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.
8296465Sdelphij *
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).
15296465Sdelphij *
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.
22296465Sdelphij *
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 :-).
37296465Sdelphij * 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)"
40296465Sdelphij *
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.
52296465Sdelphij *
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)
68296465Sdelphij{
69296465Sdelphij    ASN1_OBJECT *obj;
7055714Skris
71296465Sdelphij    obj = OBJ_nid2obj(nid);
72296465Sdelphij    if (obj == NULL)
73296465Sdelphij        return (-1);
74296465Sdelphij    return (X509_NAME_get_text_by_OBJ(name, obj, buf, len));
75296465Sdelphij}
7655714Skris
7755714Skrisint X509_NAME_get_text_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, char *buf,
78296465Sdelphij                              int len)
79296465Sdelphij{
80296465Sdelphij    int i;
81296465Sdelphij    ASN1_STRING *data;
8255714Skris
83296465Sdelphij    i = X509_NAME_get_index_by_OBJ(name, obj, -1);
84296465Sdelphij    if (i < 0)
85296465Sdelphij        return (-1);
86296465Sdelphij    data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
87296465Sdelphij    i = (data->length > (len - 1)) ? (len - 1) : data->length;
88296465Sdelphij    if (buf == NULL)
89296465Sdelphij        return (data->length);
90296465Sdelphij    memcpy(buf, data->data, i);
91296465Sdelphij    buf[i] = '\0';
92296465Sdelphij    return (i);
93296465Sdelphij}
9455714Skris
9555714Skrisint X509_NAME_entry_count(X509_NAME *name)
96296465Sdelphij{
97296465Sdelphij    if (name == NULL)
98296465Sdelphij        return (0);
99296465Sdelphij    return (sk_X509_NAME_ENTRY_num(name->entries));
100296465Sdelphij}
10155714Skris
10255714Skrisint X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos)
103296465Sdelphij{
104296465Sdelphij    ASN1_OBJECT *obj;
10555714Skris
106296465Sdelphij    obj = OBJ_nid2obj(nid);
107296465Sdelphij    if (obj == NULL)
108296465Sdelphij        return (-2);
109296465Sdelphij    return (X509_NAME_get_index_by_OBJ(name, obj, lastpos));
110296465Sdelphij}
11155714Skris
11255714Skris/* NOTE: you should be passsing -1, not 0 as lastpos */
113296465Sdelphijint X509_NAME_get_index_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int lastpos)
114296465Sdelphij{
115296465Sdelphij    int n;
116296465Sdelphij    X509_NAME_ENTRY *ne;
117296465Sdelphij    STACK_OF(X509_NAME_ENTRY) *sk;
11855714Skris
119296465Sdelphij    if (name == NULL)
120296465Sdelphij        return (-1);
121296465Sdelphij    if (lastpos < 0)
122296465Sdelphij        lastpos = -1;
123296465Sdelphij    sk = name->entries;
124296465Sdelphij    n = sk_X509_NAME_ENTRY_num(sk);
125296465Sdelphij    for (lastpos++; lastpos < n; lastpos++) {
126296465Sdelphij        ne = sk_X509_NAME_ENTRY_value(sk, lastpos);
127296465Sdelphij        if (OBJ_cmp(ne->object, obj) == 0)
128296465Sdelphij            return (lastpos);
129296465Sdelphij    }
130296465Sdelphij    return (-1);
131296465Sdelphij}
13255714Skris
13355714SkrisX509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc)
134296465Sdelphij{
135296465Sdelphij    if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
136296465Sdelphij        || loc < 0)
137296465Sdelphij        return (NULL);
138296465Sdelphij    else
139296465Sdelphij        return (sk_X509_NAME_ENTRY_value(name->entries, loc));
140296465Sdelphij}
14155714Skris
14255714SkrisX509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc)
143296465Sdelphij{
144296465Sdelphij    X509_NAME_ENTRY *ret;
145296465Sdelphij    int i, n, set_prev, set_next;
146296465Sdelphij    STACK_OF(X509_NAME_ENTRY) *sk;
14755714Skris
148296465Sdelphij    if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
149296465Sdelphij        || loc < 0)
150296465Sdelphij        return (NULL);
151296465Sdelphij    sk = name->entries;
152296465Sdelphij    ret = sk_X509_NAME_ENTRY_delete(sk, loc);
153296465Sdelphij    n = sk_X509_NAME_ENTRY_num(sk);
154296465Sdelphij    name->modified = 1;
155296465Sdelphij    if (loc == n)
156296465Sdelphij        return (ret);
15755714Skris
158296465Sdelphij    /* else we need to fixup the set field */
159296465Sdelphij    if (loc != 0)
160296465Sdelphij        set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set;
161296465Sdelphij    else
162296465Sdelphij        set_prev = ret->set - 1;
163296465Sdelphij    set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set;
16455714Skris
165296465Sdelphij    /*-
166296465Sdelphij     * set_prev is the previous set
167296465Sdelphij     * set is the current set
168296465Sdelphij     * set_next is the following
169296465Sdelphij     * prev  1 1    1 1     1 1     1 1
170296465Sdelphij     * set   1      1       2       2
171296465Sdelphij     * next  1 1    2 2     2 2     3 2
172296465Sdelphij     * so basically only if prev and next differ by 2, then
173296465Sdelphij     * re-number down by 1
174296465Sdelphij     */
175296465Sdelphij    if (set_prev + 1 < set_next)
176296465Sdelphij        for (i = loc; i < n; i++)
177296465Sdelphij            sk_X509_NAME_ENTRY_value(sk, i)->set--;
178296465Sdelphij    return (ret);
179296465Sdelphij}
18055714Skris
18159191Skrisint X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
182296465Sdelphij                               unsigned char *bytes, int len, int loc,
183296465Sdelphij                               int set)
18459191Skris{
185296465Sdelphij    X509_NAME_ENTRY *ne;
186296465Sdelphij    int ret;
187296465Sdelphij    ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
188296465Sdelphij    if (!ne)
189296465Sdelphij        return 0;
190296465Sdelphij    ret = X509_NAME_add_entry(name, ne, loc, set);
191296465Sdelphij    X509_NAME_ENTRY_free(ne);
192296465Sdelphij    return ret;
19359191Skris}
19459191Skris
19559191Skrisint X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
196296465Sdelphij                               unsigned char *bytes, int len, int loc,
197296465Sdelphij                               int set)
19859191Skris{
199296465Sdelphij    X509_NAME_ENTRY *ne;
200296465Sdelphij    int ret;
201296465Sdelphij    ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
202296465Sdelphij    if (!ne)
203296465Sdelphij        return 0;
204296465Sdelphij    ret = X509_NAME_add_entry(name, ne, loc, set);
205296465Sdelphij    X509_NAME_ENTRY_free(ne);
206296465Sdelphij    return ret;
20759191Skris}
20859191Skris
209160814Ssimonint X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
210296465Sdelphij                               const unsigned char *bytes, int len, int loc,
211296465Sdelphij                               int set)
21259191Skris{
213296465Sdelphij    X509_NAME_ENTRY *ne;
214296465Sdelphij    int ret;
215296465Sdelphij    ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
216296465Sdelphij    if (!ne)
217296465Sdelphij        return 0;
218296465Sdelphij    ret = X509_NAME_add_entry(name, ne, loc, set);
219296465Sdelphij    X509_NAME_ENTRY_free(ne);
220296465Sdelphij    return ret;
22159191Skris}
22259191Skris
223296465Sdelphij/*
224296465Sdelphij * if set is -1, append to previous set, 0 'a new one', and 1, prepend to the
225296465Sdelphij * guy we are about to stomp on.
226296465Sdelphij */
22755714Skrisint X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc,
228296465Sdelphij                        int set)
229296465Sdelphij{
230296465Sdelphij    X509_NAME_ENTRY *new_name = NULL;
231296465Sdelphij    int n, i, inc;
232296465Sdelphij    STACK_OF(X509_NAME_ENTRY) *sk;
23355714Skris
234296465Sdelphij    if (name == NULL)
235296465Sdelphij        return (0);
236296465Sdelphij    sk = name->entries;
237296465Sdelphij    n = sk_X509_NAME_ENTRY_num(sk);
238296465Sdelphij    if (loc > n)
239296465Sdelphij        loc = n;
240296465Sdelphij    else if (loc < 0)
241296465Sdelphij        loc = n;
24255714Skris
243296465Sdelphij    name->modified = 1;
24455714Skris
245296465Sdelphij    if (set == -1) {
246296465Sdelphij        if (loc == 0) {
247296465Sdelphij            set = 0;
248296465Sdelphij            inc = 1;
249296465Sdelphij        } else {
250296465Sdelphij            set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set;
251296465Sdelphij            inc = 0;
252296465Sdelphij        }
253296465Sdelphij    } else {                    /* if (set >= 0) */
25455714Skris
255296465Sdelphij        if (loc >= n) {
256296465Sdelphij            if (loc != 0)
257296465Sdelphij                set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1;
258296465Sdelphij            else
259296465Sdelphij                set = 0;
260296465Sdelphij        } else
261296465Sdelphij            set = sk_X509_NAME_ENTRY_value(sk, loc)->set;
262296465Sdelphij        inc = (set == 0) ? 1 : 0;
263296465Sdelphij    }
26455714Skris
265296465Sdelphij    if ((new_name = X509_NAME_ENTRY_dup(ne)) == NULL)
266296465Sdelphij        goto err;
267296465Sdelphij    new_name->set = set;
268296465Sdelphij    if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) {
269296465Sdelphij        X509err(X509_F_X509_NAME_ADD_ENTRY, ERR_R_MALLOC_FAILURE);
270296465Sdelphij        goto err;
271296465Sdelphij    }
272296465Sdelphij    if (inc) {
273296465Sdelphij        n = sk_X509_NAME_ENTRY_num(sk);
274296465Sdelphij        for (i = loc + 1; i < n; i++)
275296465Sdelphij            sk_X509_NAME_ENTRY_value(sk, i - 1)->set += 1;
276296465Sdelphij    }
277296465Sdelphij    return (1);
278296465Sdelphij err:
279296465Sdelphij    if (new_name != NULL)
280296465Sdelphij        X509_NAME_ENTRY_free(new_name);
281296465Sdelphij    return (0);
282296465Sdelphij}
283296465Sdelphij
28459191SkrisX509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
285296465Sdelphij                                               const char *field, int type,
286296465Sdelphij                                               const unsigned char *bytes,
287296465Sdelphij                                               int len)
288296465Sdelphij{
289296465Sdelphij    ASN1_OBJECT *obj;
290296465Sdelphij    X509_NAME_ENTRY *nentry;
29159191Skris
292296465Sdelphij    obj = OBJ_txt2obj(field, 0);
293296465Sdelphij    if (obj == NULL) {
294296465Sdelphij        X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT,
295296465Sdelphij                X509_R_INVALID_FIELD_NAME);
296296465Sdelphij        ERR_add_error_data(2, "name=", field);
297296465Sdelphij        return (NULL);
298296465Sdelphij    }
299296465Sdelphij    nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
300296465Sdelphij    ASN1_OBJECT_free(obj);
301296465Sdelphij    return nentry;
302296465Sdelphij}
30359191Skris
30455714SkrisX509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
305296465Sdelphij                                               int type, unsigned char *bytes,
306296465Sdelphij                                               int len)
307296465Sdelphij{
308296465Sdelphij    ASN1_OBJECT *obj;
309296465Sdelphij    X509_NAME_ENTRY *nentry;
31055714Skris
311296465Sdelphij    obj = OBJ_nid2obj(nid);
312296465Sdelphij    if (obj == NULL) {
313296465Sdelphij        X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_NID, X509_R_UNKNOWN_NID);
314296465Sdelphij        return (NULL);
315296465Sdelphij    }
316296465Sdelphij    nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
317296465Sdelphij    ASN1_OBJECT_free(obj);
318296465Sdelphij    return nentry;
319296465Sdelphij}
32055714Skris
32155714SkrisX509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
322296465Sdelphij                                               ASN1_OBJECT *obj, int type,
323296465Sdelphij                                               const unsigned char *bytes,
324296465Sdelphij                                               int len)
325296465Sdelphij{
326296465Sdelphij    X509_NAME_ENTRY *ret;
32755714Skris
328296465Sdelphij    if ((ne == NULL) || (*ne == NULL)) {
329296465Sdelphij        if ((ret = X509_NAME_ENTRY_new()) == NULL)
330296465Sdelphij            return (NULL);
331296465Sdelphij    } else
332296465Sdelphij        ret = *ne;
33355714Skris
334296465Sdelphij    if (!X509_NAME_ENTRY_set_object(ret, obj))
335296465Sdelphij        goto err;
336296465Sdelphij    if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len))
337296465Sdelphij        goto err;
33859191Skris
339296465Sdelphij    if ((ne != NULL) && (*ne == NULL))
340296465Sdelphij        *ne = ret;
341296465Sdelphij    return (ret);
342296465Sdelphij err:
343296465Sdelphij    if ((ne == NULL) || (ret != *ne))
344296465Sdelphij        X509_NAME_ENTRY_free(ret);
345296465Sdelphij    return (NULL);
346296465Sdelphij}
34755714Skris
34855714Skrisint X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, ASN1_OBJECT *obj)
349296465Sdelphij{
350296465Sdelphij    if ((ne == NULL) || (obj == NULL)) {
351296465Sdelphij        X509err(X509_F_X509_NAME_ENTRY_SET_OBJECT,
352296465Sdelphij                ERR_R_PASSED_NULL_PARAMETER);
353296465Sdelphij        return (0);
354296465Sdelphij    }
355296465Sdelphij    ASN1_OBJECT_free(ne->object);
356296465Sdelphij    ne->object = OBJ_dup(obj);
357296465Sdelphij    return ((ne->object == NULL) ? 0 : 1);
358296465Sdelphij}
35955714Skris
36055714Skrisint X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
361296465Sdelphij                             const unsigned char *bytes, int len)
362296465Sdelphij{
363296465Sdelphij    int i;
36455714Skris
365296465Sdelphij    if ((ne == NULL) || ((bytes == NULL) && (len != 0)))
366296465Sdelphij        return (0);
367296465Sdelphij    if ((type > 0) && (type & MBSTRING_FLAG))
368296465Sdelphij        return ASN1_STRING_set_by_NID(&ne->value, bytes,
369296465Sdelphij                                      len, type,
370296465Sdelphij                                      OBJ_obj2nid(ne->object)) ? 1 : 0;
371296465Sdelphij    if (len < 0)
372296465Sdelphij        len = strlen((char *)bytes);
373296465Sdelphij    i = ASN1_STRING_set(ne->value, bytes, len);
374296465Sdelphij    if (!i)
375296465Sdelphij        return (0);
376296465Sdelphij    if (type != V_ASN1_UNDEF) {
377296465Sdelphij        if (type == V_ASN1_APP_CHOOSE)
378296465Sdelphij            ne->value->type = ASN1_PRINTABLE_type(bytes, len);
379296465Sdelphij        else
380296465Sdelphij            ne->value->type = type;
381296465Sdelphij    }
382296465Sdelphij    return (1);
383296465Sdelphij}
38455714Skris
38555714SkrisASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne)
386296465Sdelphij{
387296465Sdelphij    if (ne == NULL)
388296465Sdelphij        return (NULL);
389296465Sdelphij    return (ne->object);
390296465Sdelphij}
39155714Skris
39255714SkrisASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne)
393296465Sdelphij{
394296465Sdelphij    if (ne == NULL)
395296465Sdelphij        return (NULL);
396296465Sdelphij    return (ne->value);
397296465Sdelphij}
398