1/*
2 * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License").  You may not use
5 * this file except in compliance with the License.  You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10#include <stdio.h>
11#include "internal/cryptlib.h"
12#include <openssl/asn1t.h>
13#include <openssl/conf.h>
14#include <openssl/x509v3.h>
15
16ASN1_SEQUENCE(OTHERNAME) = {
17        ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT),
18        /* Maybe have a true ANY DEFINED BY later */
19        ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0)
20} ASN1_SEQUENCE_END(OTHERNAME)
21
22IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME)
23
24ASN1_SEQUENCE(EDIPARTYNAME) = {
25        /* DirectoryString is a CHOICE type so use explicit tagging */
26        ASN1_EXP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0),
27        ASN1_EXP(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1)
28} ASN1_SEQUENCE_END(EDIPARTYNAME)
29
30IMPLEMENT_ASN1_FUNCTIONS(EDIPARTYNAME)
31
32ASN1_CHOICE(GENERAL_NAME) = {
33        ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME),
34        ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL),
35        ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS),
36        /* Don't decode this */
37        ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400),
38        /* X509_NAME is a CHOICE type so use EXPLICIT */
39        ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME),
40        ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY),
41        ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, GEN_URI),
42        ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD),
43        ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID)
44} ASN1_CHOICE_END(GENERAL_NAME)
45
46IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAME)
47
48ASN1_ITEM_TEMPLATE(GENERAL_NAMES) =
49        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, GENERAL_NAME)
50ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES)
51
52IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES)
53
54GENERAL_NAME *GENERAL_NAME_dup(const GENERAL_NAME *a)
55{
56    return (GENERAL_NAME *)ASN1_dup((i2d_of_void *)i2d_GENERAL_NAME,
57                                    (d2i_of_void *)d2i_GENERAL_NAME,
58                                    (char *)a);
59}
60
61static int edipartyname_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b)
62{
63    int res;
64
65    if (a == NULL || b == NULL) {
66        /*
67         * Shouldn't be possible in a valid GENERAL_NAME, but we handle it
68         * anyway. OTHERNAME_cmp treats NULL != NULL so we do the same here
69         */
70        return -1;
71    }
72    if (a->nameAssigner == NULL && b->nameAssigner != NULL)
73        return -1;
74    if (a->nameAssigner != NULL && b->nameAssigner == NULL)
75        return 1;
76    /* If we get here then both have nameAssigner set, or both unset */
77    if (a->nameAssigner != NULL) {
78        res = ASN1_STRING_cmp(a->nameAssigner, b->nameAssigner);
79        if (res != 0)
80            return res;
81    }
82    /*
83     * partyName is required, so these should never be NULL. We treat it in
84     * the same way as the a == NULL || b == NULL case above
85     */
86    if (a->partyName == NULL || b->partyName == NULL)
87        return -1;
88
89    return ASN1_STRING_cmp(a->partyName, b->partyName);
90}
91
92/* Returns 0 if they are equal, != 0 otherwise. */
93int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b)
94{
95    int result = -1;
96
97    if (!a || !b || a->type != b->type)
98        return -1;
99    switch (a->type) {
100    case GEN_X400:
101        result = ASN1_STRING_cmp(a->d.x400Address, b->d.x400Address);
102        break;
103
104    case GEN_EDIPARTY:
105        result = edipartyname_cmp(a->d.ediPartyName, b->d.ediPartyName);
106        break;
107
108    case GEN_OTHERNAME:
109        result = OTHERNAME_cmp(a->d.otherName, b->d.otherName);
110        break;
111
112    case GEN_EMAIL:
113    case GEN_DNS:
114    case GEN_URI:
115        result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5);
116        break;
117
118    case GEN_DIRNAME:
119        result = X509_NAME_cmp(a->d.dirn, b->d.dirn);
120        break;
121
122    case GEN_IPADD:
123        result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip);
124        break;
125
126    case GEN_RID:
127        result = OBJ_cmp(a->d.rid, b->d.rid);
128        break;
129    }
130    return result;
131}
132
133/* Returns 0 if they are equal, != 0 otherwise. */
134int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b)
135{
136    int result = -1;
137
138    if (!a || !b)
139        return -1;
140    /* Check their type first. */
141    if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0)
142        return result;
143    /* Check the value. */
144    result = ASN1_TYPE_cmp(a->value, b->value);
145    return result;
146}
147
148void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value)
149{
150    switch (type) {
151    case GEN_X400:
152        a->d.x400Address = value;
153        break;
154
155    case GEN_EDIPARTY:
156        a->d.ediPartyName = value;
157        break;
158
159    case GEN_OTHERNAME:
160        a->d.otherName = value;
161        break;
162
163    case GEN_EMAIL:
164    case GEN_DNS:
165    case GEN_URI:
166        a->d.ia5 = value;
167        break;
168
169    case GEN_DIRNAME:
170        a->d.dirn = value;
171        break;
172
173    case GEN_IPADD:
174        a->d.ip = value;
175        break;
176
177    case GEN_RID:
178        a->d.rid = value;
179        break;
180    }
181    a->type = type;
182}
183
184void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype)
185{
186    if (ptype)
187        *ptype = a->type;
188    switch (a->type) {
189    case GEN_X400:
190        return a->d.x400Address;
191
192    case GEN_EDIPARTY:
193        return a->d.ediPartyName;
194
195    case GEN_OTHERNAME:
196        return a->d.otherName;
197
198    case GEN_EMAIL:
199    case GEN_DNS:
200    case GEN_URI:
201        return a->d.ia5;
202
203    case GEN_DIRNAME:
204        return a->d.dirn;
205
206    case GEN_IPADD:
207        return a->d.ip;
208
209    case GEN_RID:
210        return a->d.rid;
211
212    default:
213        return NULL;
214    }
215}
216
217int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
218                                ASN1_OBJECT *oid, ASN1_TYPE *value)
219{
220    OTHERNAME *oth;
221    oth = OTHERNAME_new();
222    if (oth == NULL)
223        return 0;
224    ASN1_TYPE_free(oth->value);
225    oth->type_id = oid;
226    oth->value = value;
227    GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
228    return 1;
229}
230
231int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen,
232                                ASN1_OBJECT **poid, ASN1_TYPE **pvalue)
233{
234    if (gen->type != GEN_OTHERNAME)
235        return 0;
236    if (poid)
237        *poid = gen->d.otherName->type_id;
238    if (pvalue)
239        *pvalue = gen->d.otherName->value;
240    return 1;
241}
242