x509name.c revision 296465
1/* crypto/x509/x509name.c */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to.  The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 *    notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 *    notice, this list of conditions and the following disclaimer in the
30 *    documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 *    must display the following acknowledgement:
33 *    "This product includes cryptographic software written by
34 *     Eric Young (eay@cryptsoft.com)"
35 *    The word 'cryptographic' can be left out if the rouines from the library
36 *    being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 *    the apps directory (application code) you must include an acknowledgement:
39 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed.  i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59#include <stdio.h>
60#include <openssl/stack.h>
61#include "cryptlib.h"
62#include <openssl/asn1.h>
63#include <openssl/objects.h>
64#include <openssl/evp.h>
65#include <openssl/x509.h>
66
67int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len)
68{
69    ASN1_OBJECT *obj;
70
71    obj = OBJ_nid2obj(nid);
72    if (obj == NULL)
73        return (-1);
74    return (X509_NAME_get_text_by_OBJ(name, obj, buf, len));
75}
76
77int X509_NAME_get_text_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, char *buf,
78                              int len)
79{
80    int i;
81    ASN1_STRING *data;
82
83    i = X509_NAME_get_index_by_OBJ(name, obj, -1);
84    if (i < 0)
85        return (-1);
86    data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
87    i = (data->length > (len - 1)) ? (len - 1) : data->length;
88    if (buf == NULL)
89        return (data->length);
90    memcpy(buf, data->data, i);
91    buf[i] = '\0';
92    return (i);
93}
94
95int X509_NAME_entry_count(X509_NAME *name)
96{
97    if (name == NULL)
98        return (0);
99    return (sk_X509_NAME_ENTRY_num(name->entries));
100}
101
102int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos)
103{
104    ASN1_OBJECT *obj;
105
106    obj = OBJ_nid2obj(nid);
107    if (obj == NULL)
108        return (-2);
109    return (X509_NAME_get_index_by_OBJ(name, obj, lastpos));
110}
111
112/* NOTE: you should be passsing -1, not 0 as lastpos */
113int X509_NAME_get_index_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int lastpos)
114{
115    int n;
116    X509_NAME_ENTRY *ne;
117    STACK_OF(X509_NAME_ENTRY) *sk;
118
119    if (name == NULL)
120        return (-1);
121    if (lastpos < 0)
122        lastpos = -1;
123    sk = name->entries;
124    n = sk_X509_NAME_ENTRY_num(sk);
125    for (lastpos++; lastpos < n; lastpos++) {
126        ne = sk_X509_NAME_ENTRY_value(sk, lastpos);
127        if (OBJ_cmp(ne->object, obj) == 0)
128            return (lastpos);
129    }
130    return (-1);
131}
132
133X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc)
134{
135    if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
136        || loc < 0)
137        return (NULL);
138    else
139        return (sk_X509_NAME_ENTRY_value(name->entries, loc));
140}
141
142X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc)
143{
144    X509_NAME_ENTRY *ret;
145    int i, n, set_prev, set_next;
146    STACK_OF(X509_NAME_ENTRY) *sk;
147
148    if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
149        || loc < 0)
150        return (NULL);
151    sk = name->entries;
152    ret = sk_X509_NAME_ENTRY_delete(sk, loc);
153    n = sk_X509_NAME_ENTRY_num(sk);
154    name->modified = 1;
155    if (loc == n)
156        return (ret);
157
158    /* else we need to fixup the set field */
159    if (loc != 0)
160        set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set;
161    else
162        set_prev = ret->set - 1;
163    set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set;
164
165    /*-
166     * set_prev is the previous set
167     * set is the current set
168     * set_next is the following
169     * prev  1 1    1 1     1 1     1 1
170     * set   1      1       2       2
171     * next  1 1    2 2     2 2     3 2
172     * so basically only if prev and next differ by 2, then
173     * re-number down by 1
174     */
175    if (set_prev + 1 < set_next)
176        for (i = loc; i < n; i++)
177            sk_X509_NAME_ENTRY_value(sk, i)->set--;
178    return (ret);
179}
180
181int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
182                               unsigned char *bytes, int len, int loc,
183                               int set)
184{
185    X509_NAME_ENTRY *ne;
186    int ret;
187    ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
188    if (!ne)
189        return 0;
190    ret = X509_NAME_add_entry(name, ne, loc, set);
191    X509_NAME_ENTRY_free(ne);
192    return ret;
193}
194
195int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
196                               unsigned char *bytes, int len, int loc,
197                               int set)
198{
199    X509_NAME_ENTRY *ne;
200    int ret;
201    ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
202    if (!ne)
203        return 0;
204    ret = X509_NAME_add_entry(name, ne, loc, set);
205    X509_NAME_ENTRY_free(ne);
206    return ret;
207}
208
209int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
210                               const unsigned char *bytes, int len, int loc,
211                               int set)
212{
213    X509_NAME_ENTRY *ne;
214    int ret;
215    ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
216    if (!ne)
217        return 0;
218    ret = X509_NAME_add_entry(name, ne, loc, set);
219    X509_NAME_ENTRY_free(ne);
220    return ret;
221}
222
223/*
224 * if set is -1, append to previous set, 0 'a new one', and 1, prepend to the
225 * guy we are about to stomp on.
226 */
227int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc,
228                        int set)
229{
230    X509_NAME_ENTRY *new_name = NULL;
231    int n, i, inc;
232    STACK_OF(X509_NAME_ENTRY) *sk;
233
234    if (name == NULL)
235        return (0);
236    sk = name->entries;
237    n = sk_X509_NAME_ENTRY_num(sk);
238    if (loc > n)
239        loc = n;
240    else if (loc < 0)
241        loc = n;
242
243    name->modified = 1;
244
245    if (set == -1) {
246        if (loc == 0) {
247            set = 0;
248            inc = 1;
249        } else {
250            set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set;
251            inc = 0;
252        }
253    } else {                    /* if (set >= 0) */
254
255        if (loc >= n) {
256            if (loc != 0)
257                set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1;
258            else
259                set = 0;
260        } else
261            set = sk_X509_NAME_ENTRY_value(sk, loc)->set;
262        inc = (set == 0) ? 1 : 0;
263    }
264
265    if ((new_name = X509_NAME_ENTRY_dup(ne)) == NULL)
266        goto err;
267    new_name->set = set;
268    if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) {
269        X509err(X509_F_X509_NAME_ADD_ENTRY, ERR_R_MALLOC_FAILURE);
270        goto err;
271    }
272    if (inc) {
273        n = sk_X509_NAME_ENTRY_num(sk);
274        for (i = loc + 1; i < n; i++)
275            sk_X509_NAME_ENTRY_value(sk, i - 1)->set += 1;
276    }
277    return (1);
278 err:
279    if (new_name != NULL)
280        X509_NAME_ENTRY_free(new_name);
281    return (0);
282}
283
284X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
285                                               const char *field, int type,
286                                               const unsigned char *bytes,
287                                               int len)
288{
289    ASN1_OBJECT *obj;
290    X509_NAME_ENTRY *nentry;
291
292    obj = OBJ_txt2obj(field, 0);
293    if (obj == NULL) {
294        X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT,
295                X509_R_INVALID_FIELD_NAME);
296        ERR_add_error_data(2, "name=", field);
297        return (NULL);
298    }
299    nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
300    ASN1_OBJECT_free(obj);
301    return nentry;
302}
303
304X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
305                                               int type, unsigned char *bytes,
306                                               int len)
307{
308    ASN1_OBJECT *obj;
309    X509_NAME_ENTRY *nentry;
310
311    obj = OBJ_nid2obj(nid);
312    if (obj == NULL) {
313        X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_NID, X509_R_UNKNOWN_NID);
314        return (NULL);
315    }
316    nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
317    ASN1_OBJECT_free(obj);
318    return nentry;
319}
320
321X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
322                                               ASN1_OBJECT *obj, int type,
323                                               const unsigned char *bytes,
324                                               int len)
325{
326    X509_NAME_ENTRY *ret;
327
328    if ((ne == NULL) || (*ne == NULL)) {
329        if ((ret = X509_NAME_ENTRY_new()) == NULL)
330            return (NULL);
331    } else
332        ret = *ne;
333
334    if (!X509_NAME_ENTRY_set_object(ret, obj))
335        goto err;
336    if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len))
337        goto err;
338
339    if ((ne != NULL) && (*ne == NULL))
340        *ne = ret;
341    return (ret);
342 err:
343    if ((ne == NULL) || (ret != *ne))
344        X509_NAME_ENTRY_free(ret);
345    return (NULL);
346}
347
348int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, ASN1_OBJECT *obj)
349{
350    if ((ne == NULL) || (obj == NULL)) {
351        X509err(X509_F_X509_NAME_ENTRY_SET_OBJECT,
352                ERR_R_PASSED_NULL_PARAMETER);
353        return (0);
354    }
355    ASN1_OBJECT_free(ne->object);
356    ne->object = OBJ_dup(obj);
357    return ((ne->object == NULL) ? 0 : 1);
358}
359
360int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
361                             const unsigned char *bytes, int len)
362{
363    int i;
364
365    if ((ne == NULL) || ((bytes == NULL) && (len != 0)))
366        return (0);
367    if ((type > 0) && (type & MBSTRING_FLAG))
368        return ASN1_STRING_set_by_NID(&ne->value, bytes,
369                                      len, type,
370                                      OBJ_obj2nid(ne->object)) ? 1 : 0;
371    if (len < 0)
372        len = strlen((char *)bytes);
373    i = ASN1_STRING_set(ne->value, bytes, len);
374    if (!i)
375        return (0);
376    if (type != V_ASN1_UNDEF) {
377        if (type == V_ASN1_APP_CHOOSE)
378            ne->value->type = ASN1_PRINTABLE_type(bytes, len);
379        else
380            ne->value->type = type;
381    }
382    return (1);
383}
384
385ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne)
386{
387    if (ne == NULL)
388        return (NULL);
389    return (ne->object);
390}
391
392ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne)
393{
394    if (ne == NULL)
395        return (NULL);
396    return (ne->value);
397}
398