155714Skris/* crypto/x509/x509name.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8280297Sjkim *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15280297Sjkim *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22280297Sjkim *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37280297Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40280297Sjkim *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52280297Sjkim *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include <openssl/stack.h>
6155714Skris#include "cryptlib.h"
6255714Skris#include <openssl/asn1.h>
6355714Skris#include <openssl/objects.h>
6455714Skris#include <openssl/evp.h>
6555714Skris#include <openssl/x509.h>
6655714Skris
6755714Skrisint X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len)
68280297Sjkim{
69280297Sjkim    ASN1_OBJECT *obj;
7055714Skris
71280297Sjkim    obj = OBJ_nid2obj(nid);
72280297Sjkim    if (obj == NULL)
73280297Sjkim        return (-1);
74280297Sjkim    return (X509_NAME_get_text_by_OBJ(name, obj, buf, len));
75280297Sjkim}
7655714Skris
7755714Skrisint X509_NAME_get_text_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, char *buf,
78280297Sjkim                              int len)
79280297Sjkim{
80280297Sjkim    int i;
81280297Sjkim    ASN1_STRING *data;
8255714Skris
83280297Sjkim    i = X509_NAME_get_index_by_OBJ(name, obj, -1);
84280297Sjkim    if (i < 0)
85280297Sjkim        return (-1);
86280297Sjkim    data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
87280297Sjkim    i = (data->length > (len - 1)) ? (len - 1) : data->length;
88280297Sjkim    if (buf == NULL)
89280297Sjkim        return (data->length);
90280297Sjkim    memcpy(buf, data->data, i);
91280297Sjkim    buf[i] = '\0';
92280297Sjkim    return (i);
93280297Sjkim}
9455714Skris
9555714Skrisint X509_NAME_entry_count(X509_NAME *name)
96280297Sjkim{
97280297Sjkim    if (name == NULL)
98280297Sjkim        return (0);
99280297Sjkim    return (sk_X509_NAME_ENTRY_num(name->entries));
100280297Sjkim}
10155714Skris
10255714Skrisint X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos)
103280297Sjkim{
104280297Sjkim    ASN1_OBJECT *obj;
10555714Skris
106280297Sjkim    obj = OBJ_nid2obj(nid);
107280297Sjkim    if (obj == NULL)
108280297Sjkim        return (-2);
109280297Sjkim    return (X509_NAME_get_index_by_OBJ(name, obj, lastpos));
110280297Sjkim}
11155714Skris
11255714Skris/* NOTE: you should be passsing -1, not 0 as lastpos */
113280297Sjkimint X509_NAME_get_index_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int lastpos)
114280297Sjkim{
115280297Sjkim    int n;
116280297Sjkim    X509_NAME_ENTRY *ne;
117280297Sjkim    STACK_OF(X509_NAME_ENTRY) *sk;
11855714Skris
119280297Sjkim    if (name == NULL)
120280297Sjkim        return (-1);
121280297Sjkim    if (lastpos < 0)
122280297Sjkim        lastpos = -1;
123280297Sjkim    sk = name->entries;
124280297Sjkim    n = sk_X509_NAME_ENTRY_num(sk);
125280297Sjkim    for (lastpos++; lastpos < n; lastpos++) {
126280297Sjkim        ne = sk_X509_NAME_ENTRY_value(sk, lastpos);
127280297Sjkim        if (OBJ_cmp(ne->object, obj) == 0)
128280297Sjkim            return (lastpos);
129280297Sjkim    }
130280297Sjkim    return (-1);
131280297Sjkim}
13255714Skris
13355714SkrisX509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc)
134280297Sjkim{
135280297Sjkim    if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
136280297Sjkim        || loc < 0)
137280297Sjkim        return (NULL);
138280297Sjkim    else
139280297Sjkim        return (sk_X509_NAME_ENTRY_value(name->entries, loc));
140280297Sjkim}
14155714Skris
14255714SkrisX509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc)
143280297Sjkim{
144280297Sjkim    X509_NAME_ENTRY *ret;
145280297Sjkim    int i, n, set_prev, set_next;
146280297Sjkim    STACK_OF(X509_NAME_ENTRY) *sk;
14755714Skris
148280297Sjkim    if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
149280297Sjkim        || loc < 0)
150280297Sjkim        return (NULL);
151280297Sjkim    sk = name->entries;
152280297Sjkim    ret = sk_X509_NAME_ENTRY_delete(sk, loc);
153280297Sjkim    n = sk_X509_NAME_ENTRY_num(sk);
154280297Sjkim    name->modified = 1;
155280297Sjkim    if (loc == n)
156280297Sjkim        return (ret);
15755714Skris
158280297Sjkim    /* else we need to fixup the set field */
159280297Sjkim    if (loc != 0)
160280297Sjkim        set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set;
161280297Sjkim    else
162280297Sjkim        set_prev = ret->set - 1;
163280297Sjkim    set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set;
16455714Skris
165280297Sjkim    /*-
166280297Sjkim     * set_prev is the previous set
167280297Sjkim     * set is the current set
168280297Sjkim     * set_next is the following
169280297Sjkim     * prev  1 1    1 1     1 1     1 1
170280297Sjkim     * set   1      1       2       2
171280297Sjkim     * next  1 1    2 2     2 2     3 2
172280297Sjkim     * so basically only if prev and next differ by 2, then
173280297Sjkim     * re-number down by 1
174280297Sjkim     */
175280297Sjkim    if (set_prev + 1 < set_next)
176280297Sjkim        for (i = loc; i < n; i++)
177280297Sjkim            sk_X509_NAME_ENTRY_value(sk, i)->set--;
178280297Sjkim    return (ret);
179280297Sjkim}
18055714Skris
18159191Skrisint X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
182280297Sjkim                               unsigned char *bytes, int len, int loc,
183280297Sjkim                               int set)
18459191Skris{
185280297Sjkim    X509_NAME_ENTRY *ne;
186280297Sjkim    int ret;
187280297Sjkim    ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
188280297Sjkim    if (!ne)
189280297Sjkim        return 0;
190280297Sjkim    ret = X509_NAME_add_entry(name, ne, loc, set);
191280297Sjkim    X509_NAME_ENTRY_free(ne);
192280297Sjkim    return ret;
19359191Skris}
19459191Skris
19559191Skrisint X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
196280297Sjkim                               unsigned char *bytes, int len, int loc,
197280297Sjkim                               int set)
19859191Skris{
199280297Sjkim    X509_NAME_ENTRY *ne;
200280297Sjkim    int ret;
201280297Sjkim    ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
202280297Sjkim    if (!ne)
203280297Sjkim        return 0;
204280297Sjkim    ret = X509_NAME_add_entry(name, ne, loc, set);
205280297Sjkim    X509_NAME_ENTRY_free(ne);
206280297Sjkim    return ret;
20759191Skris}
20859191Skris
209160814Ssimonint X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
210280297Sjkim                               const unsigned char *bytes, int len, int loc,
211280297Sjkim                               int set)
21259191Skris{
213280297Sjkim    X509_NAME_ENTRY *ne;
214280297Sjkim    int ret;
215280297Sjkim    ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
216280297Sjkim    if (!ne)
217280297Sjkim        return 0;
218280297Sjkim    ret = X509_NAME_add_entry(name, ne, loc, set);
219280297Sjkim    X509_NAME_ENTRY_free(ne);
220280297Sjkim    return ret;
22159191Skris}
22259191Skris
223280297Sjkim/*
224280297Sjkim * if set is -1, append to previous set, 0 'a new one', and 1, prepend to the
225280297Sjkim * guy we are about to stomp on.
226280297Sjkim */
22755714Skrisint X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc,
228280297Sjkim                        int set)
229280297Sjkim{
230280297Sjkim    X509_NAME_ENTRY *new_name = NULL;
231280297Sjkim    int n, i, inc;
232280297Sjkim    STACK_OF(X509_NAME_ENTRY) *sk;
23355714Skris
234280297Sjkim    if (name == NULL)
235280297Sjkim        return (0);
236280297Sjkim    sk = name->entries;
237280297Sjkim    n = sk_X509_NAME_ENTRY_num(sk);
238280297Sjkim    if (loc > n)
239280297Sjkim        loc = n;
240280297Sjkim    else if (loc < 0)
241280297Sjkim        loc = n;
24255714Skris
243280297Sjkim    name->modified = 1;
24455714Skris
245280297Sjkim    if (set == -1) {
246280297Sjkim        if (loc == 0) {
247280297Sjkim            set = 0;
248280297Sjkim            inc = 1;
249280297Sjkim        } else {
250280297Sjkim            set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set;
251280297Sjkim            inc = 0;
252280297Sjkim        }
253280297Sjkim    } else {                    /* if (set >= 0) */
25455714Skris
255280297Sjkim        if (loc >= n) {
256280297Sjkim            if (loc != 0)
257280297Sjkim                set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1;
258280297Sjkim            else
259280297Sjkim                set = 0;
260280297Sjkim        } else
261280297Sjkim            set = sk_X509_NAME_ENTRY_value(sk, loc)->set;
262280297Sjkim        inc = (set == 0) ? 1 : 0;
263280297Sjkim    }
26455714Skris
265280297Sjkim    if ((new_name = X509_NAME_ENTRY_dup(ne)) == NULL)
266280297Sjkim        goto err;
267280297Sjkim    new_name->set = set;
268280297Sjkim    if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) {
269280297Sjkim        X509err(X509_F_X509_NAME_ADD_ENTRY, ERR_R_MALLOC_FAILURE);
270280297Sjkim        goto err;
271280297Sjkim    }
272280297Sjkim    if (inc) {
273280297Sjkim        n = sk_X509_NAME_ENTRY_num(sk);
274280297Sjkim        for (i = loc + 1; i < n; i++)
275280297Sjkim            sk_X509_NAME_ENTRY_value(sk, i - 1)->set += 1;
276280297Sjkim    }
277280297Sjkim    return (1);
278280297Sjkim err:
279280297Sjkim    if (new_name != NULL)
280280297Sjkim        X509_NAME_ENTRY_free(new_name);
281280297Sjkim    return (0);
282280297Sjkim}
283280297Sjkim
28459191SkrisX509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
285280297Sjkim                                               const char *field, int type,
286280297Sjkim                                               const unsigned char *bytes,
287280297Sjkim                                               int len)
288280297Sjkim{
289280297Sjkim    ASN1_OBJECT *obj;
290280297Sjkim    X509_NAME_ENTRY *nentry;
29159191Skris
292280297Sjkim    obj = OBJ_txt2obj(field, 0);
293280297Sjkim    if (obj == NULL) {
294280297Sjkim        X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT,
295280297Sjkim                X509_R_INVALID_FIELD_NAME);
296280297Sjkim        ERR_add_error_data(2, "name=", field);
297280297Sjkim        return (NULL);
298280297Sjkim    }
299280297Sjkim    nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
300280297Sjkim    ASN1_OBJECT_free(obj);
301280297Sjkim    return nentry;
302280297Sjkim}
30359191Skris
30455714SkrisX509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
305280297Sjkim                                               int type, unsigned char *bytes,
306280297Sjkim                                               int len)
307280297Sjkim{
308280297Sjkim    ASN1_OBJECT *obj;
309280297Sjkim    X509_NAME_ENTRY *nentry;
31055714Skris
311280297Sjkim    obj = OBJ_nid2obj(nid);
312280297Sjkim    if (obj == NULL) {
313280297Sjkim        X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_NID, X509_R_UNKNOWN_NID);
314280297Sjkim        return (NULL);
315280297Sjkim    }
316280297Sjkim    nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
317280297Sjkim    ASN1_OBJECT_free(obj);
318280297Sjkim    return nentry;
319280297Sjkim}
32055714Skris
32155714SkrisX509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
322280297Sjkim                                               ASN1_OBJECT *obj, int type,
323280297Sjkim                                               const unsigned char *bytes,
324280297Sjkim                                               int len)
325280297Sjkim{
326280297Sjkim    X509_NAME_ENTRY *ret;
32755714Skris
328280297Sjkim    if ((ne == NULL) || (*ne == NULL)) {
329280297Sjkim        if ((ret = X509_NAME_ENTRY_new()) == NULL)
330280297Sjkim            return (NULL);
331280297Sjkim    } else
332280297Sjkim        ret = *ne;
33355714Skris
334280297Sjkim    if (!X509_NAME_ENTRY_set_object(ret, obj))
335280297Sjkim        goto err;
336280297Sjkim    if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len))
337280297Sjkim        goto err;
33859191Skris
339280297Sjkim    if ((ne != NULL) && (*ne == NULL))
340280297Sjkim        *ne = ret;
341280297Sjkim    return (ret);
342280297Sjkim err:
343280297Sjkim    if ((ne == NULL) || (ret != *ne))
344280297Sjkim        X509_NAME_ENTRY_free(ret);
345280297Sjkim    return (NULL);
346280297Sjkim}
34755714Skris
34855714Skrisint X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, ASN1_OBJECT *obj)
349280297Sjkim{
350280297Sjkim    if ((ne == NULL) || (obj == NULL)) {
351280297Sjkim        X509err(X509_F_X509_NAME_ENTRY_SET_OBJECT,
352280297Sjkim                ERR_R_PASSED_NULL_PARAMETER);
353280297Sjkim        return (0);
354280297Sjkim    }
355280297Sjkim    ASN1_OBJECT_free(ne->object);
356280297Sjkim    ne->object = OBJ_dup(obj);
357280297Sjkim    return ((ne->object == NULL) ? 0 : 1);
358280297Sjkim}
35955714Skris
36055714Skrisint X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
361280297Sjkim                             const unsigned char *bytes, int len)
362280297Sjkim{
363280297Sjkim    int i;
36455714Skris
365280297Sjkim    if ((ne == NULL) || ((bytes == NULL) && (len != 0)))
366280297Sjkim        return (0);
367280297Sjkim    if ((type > 0) && (type & MBSTRING_FLAG))
368280297Sjkim        return ASN1_STRING_set_by_NID(&ne->value, bytes,
369280297Sjkim                                      len, type,
370280297Sjkim                                      OBJ_obj2nid(ne->object)) ? 1 : 0;
371280297Sjkim    if (len < 0)
372280297Sjkim        len = strlen((const char *)bytes);
373280297Sjkim    i = ASN1_STRING_set(ne->value, bytes, len);
374280297Sjkim    if (!i)
375280297Sjkim        return (0);
376280297Sjkim    if (type != V_ASN1_UNDEF) {
377280297Sjkim        if (type == V_ASN1_APP_CHOOSE)
378280297Sjkim            ne->value->type = ASN1_PRINTABLE_type(bytes, len);
379280297Sjkim        else
380280297Sjkim            ne->value->type = type;
381280297Sjkim    }
382280297Sjkim    return (1);
383280297Sjkim}
38455714Skris
38555714SkrisASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne)
386280297Sjkim{
387280297Sjkim    if (ne == NULL)
388280297Sjkim        return (NULL);
389280297Sjkim    return (ne->object);
390280297Sjkim}
39155714Skris
39255714SkrisASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne)
393280297Sjkim{
394280297Sjkim    if (ne == NULL)
395280297Sjkim        return (NULL);
396280297Sjkim    return (ne->value);
397280297Sjkim}
398