1 /*
2 * Copyright 1999-2024 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
16 ASN1_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
22 IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME)
23
24 ASN1_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
30 IMPLEMENT_ASN1_FUNCTIONS(EDIPARTYNAME)
31
32 ASN1_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
46 IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAME)
47
48 ASN1_ITEM_TEMPLATE(GENERAL_NAMES) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, GENERAL_NAME)
49 ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES)
50
51 IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES)
52
53 GENERAL_NAME *GENERAL_NAME_dup(const GENERAL_NAME *a)
54 {
55 return (GENERAL_NAME *)ASN1_dup((i2d_of_void *)i2d_GENERAL_NAME,
56 (d2i_of_void *)d2i_GENERAL_NAME,
57 (char *)a);
58 }
59
GENERAL_NAME_set1_X509_NAME(GENERAL_NAME ** tgt,const X509_NAME * src)60 int GENERAL_NAME_set1_X509_NAME(GENERAL_NAME **tgt, const X509_NAME *src)
61 {
62 GENERAL_NAME *name;
63
64 if (tgt == NULL) {
65 ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
66 return 0;
67 }
68
69 if ((name = GENERAL_NAME_new()) == NULL)
70 return 0;
71 name->type = GEN_DIRNAME;
72
73 if (src == NULL) { /* NULL-DN */
74 if ((name->d.directoryName = X509_NAME_new()) == NULL)
75 goto err;
76 } else if (!X509_NAME_set(&name->d.directoryName, src)) {
77 goto err;
78 }
79
80 GENERAL_NAME_free(*tgt);
81 *tgt = name;
82 return 1;
83
84 err:
85 GENERAL_NAME_free(name);
86 return 0;
87 }
88
edipartyname_cmp(const EDIPARTYNAME * a,const EDIPARTYNAME * b)89 static int edipartyname_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b)
90 {
91 int res;
92
93 if (a == NULL || b == NULL) {
94 /*
95 * Shouldn't be possible in a valid GENERAL_NAME, but we handle it
96 * anyway. OTHERNAME_cmp treats NULL != NULL so we do the same here
97 */
98 return -1;
99 }
100 if (a->nameAssigner == NULL && b->nameAssigner != NULL)
101 return -1;
102 if (a->nameAssigner != NULL && b->nameAssigner == NULL)
103 return 1;
104 /* If we get here then both have nameAssigner set, or both unset */
105 if (a->nameAssigner != NULL) {
106 res = ASN1_STRING_cmp(a->nameAssigner, b->nameAssigner);
107 if (res != 0)
108 return res;
109 }
110 /*
111 * partyName is required, so these should never be NULL. We treat it in
112 * the same way as the a == NULL || b == NULL case above
113 */
114 if (a->partyName == NULL || b->partyName == NULL)
115 return -1;
116
117 return ASN1_STRING_cmp(a->partyName, b->partyName);
118 }
119
120 /* Returns 0 if they are equal, != 0 otherwise. */
GENERAL_NAME_cmp(GENERAL_NAME * a,GENERAL_NAME * b)121 int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b)
122 {
123 int result = -1;
124
125 if (!a || !b || a->type != b->type)
126 return -1;
127 switch (a->type) {
128 case GEN_X400:
129 result = ASN1_STRING_cmp(a->d.x400Address, b->d.x400Address);
130 break;
131
132 case GEN_EDIPARTY:
133 result = edipartyname_cmp(a->d.ediPartyName, b->d.ediPartyName);
134 break;
135
136 case GEN_OTHERNAME:
137 result = OTHERNAME_cmp(a->d.otherName, b->d.otherName);
138 break;
139
140 case GEN_EMAIL:
141 case GEN_DNS:
142 case GEN_URI:
143 result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5);
144 break;
145
146 case GEN_DIRNAME:
147 result = X509_NAME_cmp(a->d.dirn, b->d.dirn);
148 break;
149
150 case GEN_IPADD:
151 result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip);
152 break;
153
154 case GEN_RID:
155 result = OBJ_cmp(a->d.rid, b->d.rid);
156 break;
157 }
158 return result;
159 }
160
161 /* Returns 0 if they are equal, != 0 otherwise. */
OTHERNAME_cmp(OTHERNAME * a,OTHERNAME * b)162 int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b)
163 {
164 int result = -1;
165
166 if (!a || !b)
167 return -1;
168 /* Check their type first. */
169 if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0)
170 return result;
171 /* Check the value. */
172 result = ASN1_TYPE_cmp(a->value, b->value);
173 return result;
174 }
175
GENERAL_NAME_set0_value(GENERAL_NAME * a,int type,void * value)176 void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value)
177 {
178 switch (type) {
179 case GEN_X400:
180 a->d.x400Address = value;
181 break;
182
183 case GEN_EDIPARTY:
184 a->d.ediPartyName = value;
185 break;
186
187 case GEN_OTHERNAME:
188 a->d.otherName = value;
189 break;
190
191 case GEN_EMAIL:
192 case GEN_DNS:
193 case GEN_URI:
194 a->d.ia5 = value;
195 break;
196
197 case GEN_DIRNAME:
198 a->d.dirn = value;
199 break;
200
201 case GEN_IPADD:
202 a->d.ip = value;
203 break;
204
205 case GEN_RID:
206 a->d.rid = value;
207 break;
208 }
209 a->type = type;
210 }
211
GENERAL_NAME_get0_value(const GENERAL_NAME * a,int * ptype)212 void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype)
213 {
214 if (ptype)
215 *ptype = a->type;
216 switch (a->type) {
217 case GEN_X400:
218 return a->d.x400Address;
219
220 case GEN_EDIPARTY:
221 return a->d.ediPartyName;
222
223 case GEN_OTHERNAME:
224 return a->d.otherName;
225
226 case GEN_EMAIL:
227 case GEN_DNS:
228 case GEN_URI:
229 return a->d.ia5;
230
231 case GEN_DIRNAME:
232 return a->d.dirn;
233
234 case GEN_IPADD:
235 return a->d.ip;
236
237 case GEN_RID:
238 return a->d.rid;
239
240 default:
241 return NULL;
242 }
243 }
244
GENERAL_NAME_set0_othername(GENERAL_NAME * gen,ASN1_OBJECT * oid,ASN1_TYPE * value)245 int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
246 ASN1_OBJECT *oid, ASN1_TYPE *value)
247 {
248 OTHERNAME *oth;
249 oth = OTHERNAME_new();
250 if (oth == NULL)
251 return 0;
252 ASN1_TYPE_free(oth->value);
253 oth->type_id = oid;
254 oth->value = value;
255 GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
256 return 1;
257 }
258
GENERAL_NAME_get0_otherName(const GENERAL_NAME * gen,ASN1_OBJECT ** poid,ASN1_TYPE ** pvalue)259 int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen,
260 ASN1_OBJECT **poid, ASN1_TYPE **pvalue)
261 {
262 if (gen->type != GEN_OTHERNAME)
263 return 0;
264 if (poid)
265 *poid = gen->d.otherName->type_id;
266 if (pvalue)
267 *pvalue = gen->d.otherName->value;
268 return 1;
269 }
270