159191Skris/* a_strnid.c */
2280297Sjkim/*
3280297Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4280297Sjkim * 1999.
559191Skris */
659191Skris/* ====================================================================
759191Skris * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
859191Skris *
959191Skris * Redistribution and use in source and binary forms, with or without
1059191Skris * modification, are permitted provided that the following conditions
1159191Skris * are met:
1259191Skris *
1359191Skris * 1. Redistributions of source code must retain the above copyright
14280297Sjkim *    notice, this list of conditions and the following disclaimer.
1559191Skris *
1659191Skris * 2. Redistributions in binary form must reproduce the above copyright
1759191Skris *    notice, this list of conditions and the following disclaimer in
1859191Skris *    the documentation and/or other materials provided with the
1959191Skris *    distribution.
2059191Skris *
2159191Skris * 3. All advertising materials mentioning features or use of this
2259191Skris *    software must display the following acknowledgment:
2359191Skris *    "This product includes software developed by the OpenSSL Project
2459191Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2559191Skris *
2659191Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2759191Skris *    endorse or promote products derived from this software without
2859191Skris *    prior written permission. For written permission, please contact
2959191Skris *    licensing@OpenSSL.org.
3059191Skris *
3159191Skris * 5. Products derived from this software may not be called "OpenSSL"
3259191Skris *    nor may "OpenSSL" appear in their names without prior written
3359191Skris *    permission of the OpenSSL Project.
3459191Skris *
3559191Skris * 6. Redistributions of any form whatsoever must retain the following
3659191Skris *    acknowledgment:
3759191Skris *    "This product includes software developed by the OpenSSL Project
3859191Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3959191Skris *
4059191Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4159191Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4259191Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4359191Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4459191Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4559191Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4659191Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4759191Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4859191Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4959191Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5059191Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5159191Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
5259191Skris * ====================================================================
5359191Skris *
5459191Skris * This product includes cryptographic software written by Eric Young
5559191Skris * (eay@cryptsoft.com).  This product includes software written by Tim
5659191Skris * Hudson (tjh@cryptsoft.com).
5759191Skris *
5859191Skris */
5959191Skris
6059191Skris#include <stdio.h>
6159191Skris#include <ctype.h>
6259191Skris#include "cryptlib.h"
6359191Skris#include <openssl/asn1.h>
6459191Skris#include <openssl/objects.h>
6559191Skris
6659191Skrisstatic STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
6759191Skrisstatic void st_free(ASN1_STRING_TABLE *tbl);
68280297Sjkimstatic int sk_table_cmp(const ASN1_STRING_TABLE *const *a,
69280297Sjkim                        const ASN1_STRING_TABLE *const *b);
7059191Skris
71280297Sjkim/*
72280297Sjkim * This is the global mask for the mbstring functions: this is use to mask
73280297Sjkim * out certain types (such as BMPString and UTF8String) because certain
74280297Sjkim * software (e.g. Netscape) has problems with them.
7559191Skris */
7659191Skris
77267256Sjkimstatic unsigned long global_mask = B_ASN1_UTF8STRING;
7859191Skris
7959191Skrisvoid ASN1_STRING_set_default_mask(unsigned long mask)
8059191Skris{
81280297Sjkim    global_mask = mask;
8259191Skris}
8359191Skris
8459191Skrisunsigned long ASN1_STRING_get_default_mask(void)
8559191Skris{
86280297Sjkim    return global_mask;
8759191Skris}
8859191Skris
89280297Sjkim/*-
90280297Sjkim * This function sets the default to various "flavours" of configuration.
9159191Skris * based on an ASCII string. Currently this is:
9259191Skris * MASK:XXXX : a numerical mask value.
9359191Skris * nobmp : Don't use BMPStrings (just Printable, T61).
9459191Skris * pkix : PKIX recommendation in RFC2459.
9559191Skris * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004).
9659191Skris * default:   the default value, Printable, T61, BMP.
9759191Skris */
9859191Skris
99237657Sjkimint ASN1_STRING_set_default_mask_asc(const char *p)
10059191Skris{
101280297Sjkim    unsigned long mask;
102280297Sjkim    char *end;
103280297Sjkim    if (!strncmp(p, "MASK:", 5)) {
104280297Sjkim        if (!p[5])
105280297Sjkim            return 0;
106280297Sjkim        mask = strtoul(p + 5, &end, 0);
107280297Sjkim        if (*end)
108280297Sjkim            return 0;
109280297Sjkim    } else if (!strcmp(p, "nombstr"))
110280297Sjkim        mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING));
111280297Sjkim    else if (!strcmp(p, "pkix"))
112280297Sjkim        mask = ~((unsigned long)B_ASN1_T61STRING);
113280297Sjkim    else if (!strcmp(p, "utf8only"))
114280297Sjkim        mask = B_ASN1_UTF8STRING;
115280297Sjkim    else if (!strcmp(p, "default"))
116280297Sjkim        mask = 0xFFFFFFFFL;
117280297Sjkim    else
118280297Sjkim        return 0;
119280297Sjkim    ASN1_STRING_set_default_mask(mask);
120280297Sjkim    return 1;
12159191Skris}
12259191Skris
123280297Sjkim/*
124280297Sjkim * The following function generates an ASN1_STRING based on limits in a
125280297Sjkim * table. Frequently the types and length of an ASN1_STRING are restricted by
126280297Sjkim * a corresponding OID. For example certificates and certificate requests.
12759191Skris */
12859191Skris
129280297SjkimASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
130280297Sjkim                                    const unsigned char *in, int inlen,
131280297Sjkim                                    int inform, int nid)
13259191Skris{
133280297Sjkim    ASN1_STRING_TABLE *tbl;
134280297Sjkim    ASN1_STRING *str = NULL;
135280297Sjkim    unsigned long mask;
136280297Sjkim    int ret;
137280297Sjkim    if (!out)
138280297Sjkim        out = &str;
139280297Sjkim    tbl = ASN1_STRING_TABLE_get(nid);
140280297Sjkim    if (tbl) {
141280297Sjkim        mask = tbl->mask;
142280297Sjkim        if (!(tbl->flags & STABLE_NO_MASK))
143280297Sjkim            mask &= global_mask;
144280297Sjkim        ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
145280297Sjkim                                  tbl->minsize, tbl->maxsize);
146280297Sjkim    } else
147280297Sjkim        ret =
148280297Sjkim            ASN1_mbstring_copy(out, in, inlen, inform,
149280297Sjkim                               DIRSTRING_TYPE & global_mask);
150280297Sjkim    if (ret <= 0)
151280297Sjkim        return NULL;
152280297Sjkim    return *out;
15359191Skris}
15459191Skris
155280297Sjkim/*
156280297Sjkim * Now the tables and helper functions for the string table:
15759191Skris */
15859191Skris
159120631Snectar/* size limits: this stuff is taken straight from RFC3280 */
16059191Skris
161280297Sjkim#define ub_name                         32768
162280297Sjkim#define ub_common_name                  64
163280297Sjkim#define ub_locality_name                128
164280297Sjkim#define ub_state_name                   128
165280297Sjkim#define ub_organization_name            64
166280297Sjkim#define ub_organization_unit_name       64
167280297Sjkim#define ub_title                        64
168280297Sjkim#define ub_email_address                128
169280297Sjkim#define ub_serial_number                64
17059191Skris
17159191Skris/* This table must be kept in NID order */
17259191Skris
173238405Sjkimstatic const ASN1_STRING_TABLE tbl_standard[] = {
174280297Sjkim    {NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0},
175280297Sjkim    {NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
176280297Sjkim    {NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0},
177280297Sjkim    {NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0},
178280297Sjkim    {NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0},
179280297Sjkim    {NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE,
180280297Sjkim     0},
181280297Sjkim    {NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING,
182280297Sjkim     STABLE_NO_MASK},
183280297Sjkim    {NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0},
184280297Sjkim    {NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0},
185280297Sjkim    {NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0},
186280297Sjkim    {NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0},
187280297Sjkim    {NID_surname, 1, ub_name, DIRSTRING_TYPE, 0},
188280297Sjkim    {NID_initials, 1, ub_name, DIRSTRING_TYPE, 0},
189280297Sjkim    {NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING,
190280297Sjkim     STABLE_NO_MASK},
191280297Sjkim    {NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
192280297Sjkim    {NID_name, 1, ub_name, DIRSTRING_TYPE, 0},
193280297Sjkim    {NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
194280297Sjkim    {NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},
195325335Sjkim    {NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
196325335Sjkim    {NID_jurisdictionCountryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}
19759191Skris};
19859191Skris
199280297Sjkimstatic int sk_table_cmp(const ASN1_STRING_TABLE *const *a,
200280297Sjkim                        const ASN1_STRING_TABLE *const *b)
20159191Skris{
202280297Sjkim    return (*a)->nid - (*b)->nid;
20359191Skris}
20459191Skris
205238405SjkimDECLARE_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table);
206238405Sjkim
207238405Sjkimstatic int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b)
20859191Skris{
209280297Sjkim    return a->nid - b->nid;
21059191Skris}
21159191Skris
212238405SjkimIMPLEMENT_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table);
213238405Sjkim
21459191SkrisASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
21559191Skris{
216280297Sjkim    int idx;
217280297Sjkim    ASN1_STRING_TABLE *ttmp;
218280297Sjkim    ASN1_STRING_TABLE fnd;
219280297Sjkim    fnd.nid = nid;
220280297Sjkim    ttmp = OBJ_bsearch_table(&fnd, tbl_standard,
221280297Sjkim                             sizeof(tbl_standard) /
222280297Sjkim                             sizeof(ASN1_STRING_TABLE));
223280297Sjkim    if (ttmp)
224280297Sjkim        return ttmp;
225280297Sjkim    if (!stable)
226280297Sjkim        return NULL;
227280297Sjkim    idx = sk_ASN1_STRING_TABLE_find(stable, &fnd);
228280297Sjkim    if (idx < 0)
229280297Sjkim        return NULL;
230280297Sjkim    return sk_ASN1_STRING_TABLE_value(stable, idx);
23159191Skris}
232280297Sjkim
23359191Skrisint ASN1_STRING_TABLE_add(int nid,
234280297Sjkim                          long minsize, long maxsize, unsigned long mask,
235280297Sjkim                          unsigned long flags)
23659191Skris{
237280297Sjkim    ASN1_STRING_TABLE *tmp;
238280297Sjkim    char new_nid = 0;
239280297Sjkim    flags &= ~STABLE_FLAGS_MALLOC;
240280297Sjkim    if (!stable)
241280297Sjkim        stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
242280297Sjkim    if (!stable) {
243280297Sjkim        ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE);
244280297Sjkim        return 0;
245280297Sjkim    }
246280297Sjkim    if (!(tmp = ASN1_STRING_TABLE_get(nid))) {
247280297Sjkim        tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE));
248280297Sjkim        if (!tmp) {
249280297Sjkim            ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE);
250280297Sjkim            return 0;
251280297Sjkim        }
252280297Sjkim        tmp->flags = flags | STABLE_FLAGS_MALLOC;
253280297Sjkim        tmp->nid = nid;
254306195Sjkim        tmp->minsize = tmp->maxsize = -1;
255280297Sjkim        new_nid = 1;
256280297Sjkim    } else
257280297Sjkim        tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
258280297Sjkim    if (minsize != -1)
259280297Sjkim        tmp->minsize = minsize;
260280297Sjkim    if (maxsize != -1)
261280297Sjkim        tmp->maxsize = maxsize;
262280297Sjkim    tmp->mask = mask;
263280297Sjkim    if (new_nid)
264280297Sjkim        sk_ASN1_STRING_TABLE_push(stable, tmp);
265280297Sjkim    return 1;
26659191Skris}
26759191Skris
26859191Skrisvoid ASN1_STRING_TABLE_cleanup(void)
26959191Skris{
270280297Sjkim    STACK_OF(ASN1_STRING_TABLE) *tmp;
271280297Sjkim    tmp = stable;
272280297Sjkim    if (!tmp)
273280297Sjkim        return;
274280297Sjkim    stable = NULL;
275280297Sjkim    sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
27659191Skris}
27759191Skris
27859191Skrisstatic void st_free(ASN1_STRING_TABLE *tbl)
27959191Skris{
280280297Sjkim    if (tbl->flags & STABLE_FLAGS_MALLOC)
281280297Sjkim        OPENSSL_free(tbl);
28259191Skris}
28359191Skris
284120631Snectar
28559191SkrisIMPLEMENT_STACK_OF(ASN1_STRING_TABLE)
286120631Snectar
287120631Snectar#ifdef STRING_TABLE_TEST
288120631Snectar
289120631Snectarmain()
290120631Snectar{
291280297Sjkim    ASN1_STRING_TABLE *tmp;
292280297Sjkim    int i, last_nid = -1;
293120631Snectar
294280297Sjkim    for (tmp = tbl_standard, i = 0;
295280297Sjkim         i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++) {
296280297Sjkim        if (tmp->nid < last_nid) {
297280297Sjkim            last_nid = 0;
298280297Sjkim            break;
299280297Sjkim        }
300280297Sjkim        last_nid = tmp->nid;
301280297Sjkim    }
302120631Snectar
303280297Sjkim    if (last_nid != 0) {
304280297Sjkim        printf("Table order OK\n");
305280297Sjkim        exit(0);
306280297Sjkim    }
307120631Snectar
308280297Sjkim    for (tmp = tbl_standard, i = 0;
309280297Sjkim         i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++)
310280297Sjkim        printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
311280297Sjkim               OBJ_nid2ln(tmp->nid));
312120631Snectar
313120631Snectar}
314120631Snectar
315120631Snectar#endif
316