Line data Source code
1 : /* a_strnid.c */
2 : /*
3 : * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4 : * 1999.
5 : */
6 : /* ====================================================================
7 : * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
8 : *
9 : * Redistribution and use in source and binary forms, with or without
10 : * modification, are permitted provided that the following conditions
11 : * are met:
12 : *
13 : * 1. Redistributions of source code must retain the above copyright
14 : * notice, this list of conditions and the following disclaimer.
15 : *
16 : * 2. Redistributions in binary form must reproduce the above copyright
17 : * notice, this list of conditions and the following disclaimer in
18 : * the documentation and/or other materials provided with the
19 : * distribution.
20 : *
21 : * 3. All advertising materials mentioning features or use of this
22 : * software must display the following acknowledgment:
23 : * "This product includes software developed by the OpenSSL Project
24 : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 : *
26 : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 : * endorse or promote products derived from this software without
28 : * prior written permission. For written permission, please contact
29 : * licensing@OpenSSL.org.
30 : *
31 : * 5. Products derived from this software may not be called "OpenSSL"
32 : * nor may "OpenSSL" appear in their names without prior written
33 : * permission of the OpenSSL Project.
34 : *
35 : * 6. Redistributions of any form whatsoever must retain the following
36 : * acknowledgment:
37 : * "This product includes software developed by the OpenSSL Project
38 : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 : *
40 : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 : * OF THE POSSIBILITY OF SUCH DAMAGE.
52 : * ====================================================================
53 : *
54 : * This product includes cryptographic software written by Eric Young
55 : * (eay@cryptsoft.com). This product includes software written by Tim
56 : * Hudson (tjh@cryptsoft.com).
57 : *
58 : */
59 :
60 : #include <stdio.h>
61 : #include <ctype.h>
62 : #include "cryptlib.h"
63 : #include <openssl/asn1.h>
64 : #include <openssl/objects.h>
65 :
66 : static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
67 : static void st_free(ASN1_STRING_TABLE *tbl);
68 : static int sk_table_cmp(const ASN1_STRING_TABLE *const *a,
69 : const ASN1_STRING_TABLE *const *b);
70 :
71 : /*
72 : * This is the global mask for the mbstring functions: this is use to mask
73 : * out certain types (such as BMPString and UTF8String) because certain
74 : * software (e.g. Netscape) has problems with them.
75 : */
76 :
77 : static unsigned long global_mask = B_ASN1_UTF8STRING;
78 :
79 0 : void ASN1_STRING_set_default_mask(unsigned long mask)
80 : {
81 0 : global_mask = mask;
82 0 : }
83 :
84 0 : unsigned long ASN1_STRING_get_default_mask(void)
85 : {
86 0 : return global_mask;
87 : }
88 :
89 : /*-
90 : * This function sets the default to various "flavours" of configuration.
91 : * based on an ASCII string. Currently this is:
92 : * MASK:XXXX : a numerical mask value.
93 : * nobmp : Don't use BMPStrings (just Printable, T61).
94 : * pkix : PKIX recommendation in RFC2459.
95 : * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004).
96 : * default: the default value, Printable, T61, BMP.
97 : */
98 :
99 0 : int ASN1_STRING_set_default_mask_asc(const char *p)
100 : {
101 : unsigned long mask;
102 : char *end;
103 0 : if (!strncmp(p, "MASK:", 5)) {
104 0 : if (!p[5])
105 : return 0;
106 0 : mask = strtoul(p + 5, &end, 0);
107 0 : if (*end)
108 : return 0;
109 0 : } else if (!strcmp(p, "nombstr"))
110 : mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING));
111 0 : else if (!strcmp(p, "pkix"))
112 : mask = ~((unsigned long)B_ASN1_T61STRING);
113 0 : else if (!strcmp(p, "utf8only"))
114 : mask = B_ASN1_UTF8STRING;
115 0 : else if (!strcmp(p, "default"))
116 : mask = 0xFFFFFFFFL;
117 : else
118 : return 0;
119 : ASN1_STRING_set_default_mask(mask);
120 0 : return 1;
121 : }
122 :
123 : /*
124 : * The following function generates an ASN1_STRING based on limits in a
125 : * table. Frequently the types and length of an ASN1_STRING are restricted by
126 : * a corresponding OID. For example certificates and certificate requests.
127 : */
128 :
129 0 : ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
130 : const unsigned char *in, int inlen,
131 : int inform, int nid)
132 : {
133 : ASN1_STRING_TABLE *tbl;
134 0 : ASN1_STRING *str = NULL;
135 : unsigned long mask;
136 : int ret;
137 0 : if (!out)
138 : out = &str;
139 0 : tbl = ASN1_STRING_TABLE_get(nid);
140 0 : if (tbl) {
141 0 : mask = tbl->mask;
142 0 : if (!(tbl->flags & STABLE_NO_MASK))
143 0 : mask &= global_mask;
144 0 : ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
145 : tbl->minsize, tbl->maxsize);
146 : } else
147 0 : ret =
148 0 : ASN1_mbstring_copy(out, in, inlen, inform,
149 : DIRSTRING_TYPE & global_mask);
150 0 : if (ret <= 0)
151 : return NULL;
152 0 : return *out;
153 : }
154 :
155 : /*
156 : * Now the tables and helper functions for the string table:
157 : */
158 :
159 : /* size limits: this stuff is taken straight from RFC3280 */
160 :
161 : #define ub_name 32768
162 : #define ub_common_name 64
163 : #define ub_locality_name 128
164 : #define ub_state_name 128
165 : #define ub_organization_name 64
166 : #define ub_organization_unit_name 64
167 : #define ub_title 64
168 : #define ub_email_address 128
169 : #define ub_serial_number 64
170 :
171 : /* This table must be kept in NID order */
172 :
173 : static const ASN1_STRING_TABLE tbl_standard[] = {
174 : {NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0},
175 : {NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
176 : {NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0},
177 : {NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0},
178 : {NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0},
179 : {NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE,
180 : 0},
181 : {NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING,
182 : STABLE_NO_MASK},
183 : {NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0},
184 : {NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0},
185 : {NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0},
186 : {NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0},
187 : {NID_surname, 1, ub_name, DIRSTRING_TYPE, 0},
188 : {NID_initials, 1, ub_name, DIRSTRING_TYPE, 0},
189 : {NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING,
190 : STABLE_NO_MASK},
191 : {NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
192 : {NID_name, 1, ub_name, DIRSTRING_TYPE, 0},
193 : {NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
194 : {NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},
195 : {NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}
196 : };
197 :
198 0 : static int sk_table_cmp(const ASN1_STRING_TABLE *const *a,
199 : const ASN1_STRING_TABLE *const *b)
200 : {
201 0 : return (*a)->nid - (*b)->nid;
202 : }
203 :
204 : DECLARE_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table);
205 :
206 : static int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b)
207 : {
208 0 : return a->nid - b->nid;
209 : }
210 :
211 0 : IMPLEMENT_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table);
212 :
213 0 : ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
214 : {
215 : int idx;
216 : ASN1_STRING_TABLE *ttmp;
217 : ASN1_STRING_TABLE fnd;
218 0 : fnd.nid = nid;
219 : ttmp = OBJ_bsearch_table(&fnd, tbl_standard,
220 : sizeof(tbl_standard) /
221 : sizeof(ASN1_STRING_TABLE));
222 0 : if (ttmp)
223 : return ttmp;
224 0 : if (!stable)
225 : return NULL;
226 0 : idx = sk_ASN1_STRING_TABLE_find(stable, &fnd);
227 0 : if (idx < 0)
228 : return NULL;
229 0 : return sk_ASN1_STRING_TABLE_value(stable, idx);
230 : }
231 :
232 0 : int ASN1_STRING_TABLE_add(int nid,
233 : long minsize, long maxsize, unsigned long mask,
234 : unsigned long flags)
235 : {
236 : ASN1_STRING_TABLE *tmp;
237 : char new_nid = 0;
238 0 : flags &= ~STABLE_FLAGS_MALLOC;
239 0 : if (!stable)
240 0 : stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
241 0 : if (!stable) {
242 0 : ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE);
243 0 : return 0;
244 : }
245 0 : if (!(tmp = ASN1_STRING_TABLE_get(nid))) {
246 0 : tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE));
247 0 : if (!tmp) {
248 0 : ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE);
249 0 : return 0;
250 : }
251 0 : tmp->flags = flags | STABLE_FLAGS_MALLOC;
252 0 : tmp->nid = nid;
253 : new_nid = 1;
254 : } else
255 0 : tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
256 0 : if (minsize != -1)
257 0 : tmp->minsize = minsize;
258 0 : if (maxsize != -1)
259 0 : tmp->maxsize = maxsize;
260 0 : tmp->mask = mask;
261 0 : if (new_nid)
262 0 : sk_ASN1_STRING_TABLE_push(stable, tmp);
263 : return 1;
264 : }
265 :
266 0 : void ASN1_STRING_TABLE_cleanup(void)
267 : {
268 : STACK_OF(ASN1_STRING_TABLE) *tmp;
269 0 : tmp = stable;
270 0 : if (!tmp)
271 0 : return;
272 0 : stable = NULL;
273 0 : sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
274 : }
275 :
276 0 : static void st_free(ASN1_STRING_TABLE *tbl)
277 : {
278 0 : if (tbl->flags & STABLE_FLAGS_MALLOC)
279 0 : OPENSSL_free(tbl);
280 0 : }
281 :
282 :
283 : IMPLEMENT_STACK_OF(ASN1_STRING_TABLE)
284 :
285 : #ifdef STRING_TABLE_TEST
286 :
287 : main()
288 : {
289 : ASN1_STRING_TABLE *tmp;
290 : int i, last_nid = -1;
291 :
292 : for (tmp = tbl_standard, i = 0;
293 : i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++) {
294 : if (tmp->nid < last_nid) {
295 : last_nid = 0;
296 : break;
297 : }
298 : last_nid = tmp->nid;
299 : }
300 :
301 : if (last_nid != 0) {
302 : printf("Table order OK\n");
303 : exit(0);
304 : }
305 :
306 : for (tmp = tbl_standard, i = 0;
307 : i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++)
308 : printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
309 : OBJ_nid2ln(tmp->nid));
310 :
311 : }
312 :
313 : #endif
|