In OpenSSL builds, declare STACK for datatypes ...
[openssl.git] / crypto / asn1 / a_strnid.c
1 /*
2  * Copyright 1999-2018 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/asn1.h>
13 #include <openssl/objects.h>
14
15 DEFINE_STACK_OF(ASN1_STRING_TABLE)
16
17 static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
18 static void st_free(ASN1_STRING_TABLE *tbl);
19 static int sk_table_cmp(const ASN1_STRING_TABLE *const *a,
20                         const ASN1_STRING_TABLE *const *b);
21
22 /*
23  * This is the global mask for the mbstring functions: this is use to mask
24  * out certain types (such as BMPString and UTF8String) because certain
25  * software (e.g. Netscape) has problems with them.
26  */
27
28 static unsigned long global_mask = B_ASN1_UTF8STRING;
29
30 void ASN1_STRING_set_default_mask(unsigned long mask)
31 {
32     global_mask = mask;
33 }
34
35 unsigned long ASN1_STRING_get_default_mask(void)
36 {
37     return global_mask;
38 }
39
40 /*-
41  * This function sets the default to various "flavours" of configuration.
42  * based on an ASCII string. Currently this is:
43  * MASK:XXXX : a numerical mask value.
44  * nobmp : Don't use BMPStrings (just Printable, T61).
45  * pkix : PKIX recommendation in RFC2459.
46  * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004).
47  * default:   the default value, Printable, T61, BMP.
48  */
49
50 int ASN1_STRING_set_default_mask_asc(const char *p)
51 {
52     unsigned long mask;
53     char *end;
54
55     if (strncmp(p, "MASK:", 5) == 0) {
56         if (p[5] == '\0')
57             return 0;
58         mask = strtoul(p + 5, &end, 0);
59         if (*end)
60             return 0;
61     } else if (strcmp(p, "nombstr") == 0)
62         mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING));
63     else if (strcmp(p, "pkix") == 0)
64         mask = ~((unsigned long)B_ASN1_T61STRING);
65     else if (strcmp(p, "utf8only") == 0)
66         mask = B_ASN1_UTF8STRING;
67     else if (strcmp(p, "default") == 0)
68         mask = 0xFFFFFFFFL;
69     else
70         return 0;
71     ASN1_STRING_set_default_mask(mask);
72     return 1;
73 }
74
75 /*
76  * The following function generates an ASN1_STRING based on limits in a
77  * table. Frequently the types and length of an ASN1_STRING are restricted by
78  * a corresponding OID. For example certificates and certificate requests.
79  */
80
81 ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
82                                     const unsigned char *in, int inlen,
83                                     int inform, int nid)
84 {
85     ASN1_STRING_TABLE *tbl;
86     ASN1_STRING *str = NULL;
87     unsigned long mask;
88     int ret;
89
90     if (out == NULL)
91         out = &str;
92     tbl = ASN1_STRING_TABLE_get(nid);
93     if (tbl != NULL) {
94         mask = tbl->mask;
95         if (!(tbl->flags & STABLE_NO_MASK))
96             mask &= global_mask;
97         ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
98                                   tbl->minsize, tbl->maxsize);
99     } else {
100         ret = ASN1_mbstring_copy(out, in, inlen, inform,
101                                  DIRSTRING_TYPE & global_mask);
102     }
103     if (ret <= 0)
104         return NULL;
105     return *out;
106 }
107
108 /*
109  * Now the tables and helper functions for the string table:
110  */
111
112 #include "tbl_standard.h"
113
114 static int sk_table_cmp(const ASN1_STRING_TABLE *const *a,
115                         const ASN1_STRING_TABLE *const *b)
116 {
117     return (*a)->nid - (*b)->nid;
118 }
119
120 DECLARE_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table);
121
122 static int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b)
123 {
124     return a->nid - b->nid;
125 }
126
127 IMPLEMENT_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table);
128
129 ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
130 {
131     int idx;
132     ASN1_STRING_TABLE fnd;
133
134     /* "stable" can be impacted by config, so load the config file first */
135     OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
136
137     fnd.nid = nid;
138     if (stable) {
139         idx = sk_ASN1_STRING_TABLE_find(stable, &fnd);
140         if (idx >= 0)
141             return sk_ASN1_STRING_TABLE_value(stable, idx);
142     }
143     return OBJ_bsearch_table(&fnd, tbl_standard, OSSL_NELEM(tbl_standard));
144 }
145
146 /*
147  * Return a string table pointer which can be modified: either directly from
148  * table or a copy of an internal value added to the table.
149  */
150
151 static ASN1_STRING_TABLE *stable_get(int nid)
152 {
153     ASN1_STRING_TABLE *tmp, *rv;
154
155     /* Always need a string table so allocate one if NULL */
156     if (stable == NULL) {
157         stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
158         if (stable == NULL)
159             return NULL;
160     }
161     tmp = ASN1_STRING_TABLE_get(nid);
162     if (tmp != NULL && tmp->flags & STABLE_FLAGS_MALLOC)
163         return tmp;
164     if ((rv = OPENSSL_zalloc(sizeof(*rv))) == NULL) {
165         ASN1err(ASN1_F_STABLE_GET, ERR_R_MALLOC_FAILURE);
166         return NULL;
167     }
168     if (!sk_ASN1_STRING_TABLE_push(stable, rv)) {
169         OPENSSL_free(rv);
170         return NULL;
171     }
172     if (tmp != NULL) {
173         rv->nid = tmp->nid;
174         rv->minsize = tmp->minsize;
175         rv->maxsize = tmp->maxsize;
176         rv->mask = tmp->mask;
177         rv->flags = tmp->flags | STABLE_FLAGS_MALLOC;
178     } else {
179         rv->nid = nid;
180         rv->minsize = -1;
181         rv->maxsize = -1;
182         rv->flags = STABLE_FLAGS_MALLOC;
183     }
184     return rv;
185 }
186
187 int ASN1_STRING_TABLE_add(int nid,
188                           long minsize, long maxsize, unsigned long mask,
189                           unsigned long flags)
190 {
191     ASN1_STRING_TABLE *tmp;
192
193     tmp = stable_get(nid);
194     if (tmp == NULL) {
195         ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE);
196         return 0;
197     }
198     if (minsize >= 0)
199         tmp->minsize = minsize;
200     if (maxsize >= 0)
201         tmp->maxsize = maxsize;
202     if (mask)
203         tmp->mask = mask;
204     if (flags)
205         tmp->flags = STABLE_FLAGS_MALLOC | flags;
206     return 1;
207 }
208
209 void ASN1_STRING_TABLE_cleanup(void)
210 {
211     STACK_OF(ASN1_STRING_TABLE) *tmp;
212
213     tmp = stable;
214     if (tmp == NULL)
215         return;
216     stable = NULL;
217     sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
218 }
219
220 static void st_free(ASN1_STRING_TABLE *tbl)
221 {
222     if (tbl->flags & STABLE_FLAGS_MALLOC)
223         OPENSSL_free(tbl);
224 }