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