1/*
2 * Copyright 1995-2020 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/safestack.h>
13#include <openssl/asn1.h>
14#include <openssl/objects.h>
15#include <openssl/evp.h>
16#include <openssl/x509.h>
17#include "crypto/x509.h"
18
19int X509_NAME_get_text_by_NID(const X509_NAME *name, int nid,
20                              char *buf, int len)
21{
22    ASN1_OBJECT *obj;
23
24    obj = OBJ_nid2obj(nid);
25    if (obj == NULL)
26        return -1;
27    return X509_NAME_get_text_by_OBJ(name, obj, buf, len);
28}
29
30int X509_NAME_get_text_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj,
31                              char *buf, int len)
32{
33    int i;
34    const ASN1_STRING *data;
35
36    i = X509_NAME_get_index_by_OBJ(name, obj, -1);
37    if (i < 0)
38        return -1;
39    data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
40    if (buf == NULL)
41        return data->length;
42    if (len <= 0)
43        return 0;
44    i = (data->length > (len - 1)) ? (len - 1) : data->length;
45    memcpy(buf, data->data, i);
46    buf[i] = '\0';
47    return i;
48}
49
50int X509_NAME_entry_count(const X509_NAME *name)
51{
52    int ret;
53
54    if (name == NULL)
55        return 0;
56    ret = sk_X509_NAME_ENTRY_num(name->entries);
57    return ret > 0 ? ret : 0;
58}
59
60int X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, int lastpos)
61{
62    ASN1_OBJECT *obj;
63
64    obj = OBJ_nid2obj(nid);
65    if (obj == NULL)
66        return -2;
67    return X509_NAME_get_index_by_OBJ(name, obj, lastpos);
68}
69
70/* NOTE: you should be passing -1, not 0 as lastpos */
71int X509_NAME_get_index_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj,
72                               int lastpos)
73{
74    int n;
75    X509_NAME_ENTRY *ne;
76    STACK_OF(X509_NAME_ENTRY) *sk;
77
78    if (name == NULL)
79        return -1;
80    if (lastpos < 0)
81        lastpos = -1;
82    sk = name->entries;
83    n = sk_X509_NAME_ENTRY_num(sk);
84    for (lastpos++; lastpos < n; lastpos++) {
85        ne = sk_X509_NAME_ENTRY_value(sk, lastpos);
86        if (OBJ_cmp(ne->object, obj) == 0)
87            return lastpos;
88    }
89    return -1;
90}
91
92X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc)
93{
94    if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
95        || loc < 0)
96        return NULL;
97
98    return sk_X509_NAME_ENTRY_value(name->entries, loc);
99}
100
101X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc)
102{
103    X509_NAME_ENTRY *ret;
104    int i, n, set_prev, set_next;
105    STACK_OF(X509_NAME_ENTRY) *sk;
106
107    if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
108        || loc < 0)
109        return NULL;
110
111    sk = name->entries;
112    ret = sk_X509_NAME_ENTRY_delete(sk, loc);
113    n = sk_X509_NAME_ENTRY_num(sk);
114    name->modified = 1;
115    if (loc == n)
116        return ret;
117
118    /* else we need to fixup the set field */
119    if (loc != 0)
120        set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set;
121    else
122        set_prev = ret->set - 1;
123    set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set;
124
125    /*-
126     * set_prev is the previous set
127     * set is the current set
128     * set_next is the following
129     * prev  1 1    1 1     1 1     1 1
130     * set   1      1       2       2
131     * next  1 1    2 2     2 2     3 2
132     * so basically only if prev and next differ by 2, then
133     * re-number down by 1
134     */
135    if (set_prev + 1 < set_next)
136        for (i = loc; i < n; i++)
137            sk_X509_NAME_ENTRY_value(sk, i)->set--;
138    return ret;
139}
140
141int X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int type,
142                               const unsigned char *bytes, int len, int loc,
143                               int set)
144{
145    X509_NAME_ENTRY *ne;
146    int ret;
147
148    ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
149    if (!ne)
150        return 0;
151    ret = X509_NAME_add_entry(name, ne, loc, set);
152    X509_NAME_ENTRY_free(ne);
153    return ret;
154}
155
156int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
157                               const unsigned char *bytes, int len, int loc,
158                               int set)
159{
160    X509_NAME_ENTRY *ne;
161    int ret;
162    ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
163    if (!ne)
164        return 0;
165    ret = X509_NAME_add_entry(name, ne, loc, set);
166    X509_NAME_ENTRY_free(ne);
167    return ret;
168}
169
170int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
171                               const unsigned char *bytes, int len, int loc,
172                               int set)
173{
174    X509_NAME_ENTRY *ne;
175    int ret;
176    ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
177    if (!ne)
178        return 0;
179    ret = X509_NAME_add_entry(name, ne, loc, set);
180    X509_NAME_ENTRY_free(ne);
181    return ret;
182}
183
184/*
185 * if set is -1, append to previous set, 0 'a new one', and 1, prepend to the
186 * guy we are about to stomp on.
187 */
188int X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne, int loc,
189                        int set)
190{
191    X509_NAME_ENTRY *new_name = NULL;
192    int n, i, inc;
193    STACK_OF(X509_NAME_ENTRY) *sk;
194
195    if (name == NULL)
196        return 0;
197    sk = name->entries;
198    n = sk_X509_NAME_ENTRY_num(sk);
199    if (loc > n)
200        loc = n;
201    else if (loc < 0)
202        loc = n;
203    inc = (set == 0);
204    name->modified = 1;
205
206    if (set == -1) {
207        if (loc == 0) {
208            set = 0;
209            inc = 1;
210        } else {
211            set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set;
212        }
213    } else {                    /* if (set >= 0) */
214
215        if (loc >= n) {
216            if (loc != 0)
217                set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1;
218            else
219                set = 0;
220        } else
221            set = sk_X509_NAME_ENTRY_value(sk, loc)->set;
222    }
223
224    if ((new_name = X509_NAME_ENTRY_dup(ne)) == NULL)
225        goto err;
226    new_name->set = set;
227    if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) {
228        ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
229        goto err;
230    }
231    if (inc) {
232        n = sk_X509_NAME_ENTRY_num(sk);
233        for (i = loc + 1; i < n; i++)
234            sk_X509_NAME_ENTRY_value(sk, i)->set += 1;
235    }
236    return 1;
237 err:
238    X509_NAME_ENTRY_free(new_name);
239    return 0;
240}
241
242X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
243                                               const char *field, int type,
244                                               const unsigned char *bytes,
245                                               int len)
246{
247    ASN1_OBJECT *obj;
248    X509_NAME_ENTRY *nentry;
249
250    obj = OBJ_txt2obj(field, 0);
251    if (obj == NULL) {
252        ERR_raise_data(ERR_LIB_X509, X509_R_INVALID_FIELD_NAME,
253                       "name=%s", field);
254        return NULL;
255    }
256    nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
257    ASN1_OBJECT_free(obj);
258    return nentry;
259}
260
261X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
262                                               int type,
263                                               const unsigned char *bytes,
264                                               int len)
265{
266    ASN1_OBJECT *obj;
267    X509_NAME_ENTRY *nentry;
268
269    obj = OBJ_nid2obj(nid);
270    if (obj == NULL) {
271        ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_NID);
272        return NULL;
273    }
274    nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
275    ASN1_OBJECT_free(obj);
276    return nentry;
277}
278
279X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
280                                               const ASN1_OBJECT *obj, int type,
281                                               const unsigned char *bytes,
282                                               int len)
283{
284    X509_NAME_ENTRY *ret;
285
286    if ((ne == NULL) || (*ne == NULL)) {
287        if ((ret = X509_NAME_ENTRY_new()) == NULL)
288            return NULL;
289    } else
290        ret = *ne;
291
292    if (!X509_NAME_ENTRY_set_object(ret, obj))
293        goto err;
294    if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len))
295        goto err;
296
297    if ((ne != NULL) && (*ne == NULL))
298        *ne = ret;
299    return ret;
300 err:
301    if ((ne == NULL) || (ret != *ne))
302        X509_NAME_ENTRY_free(ret);
303    return NULL;
304}
305
306int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj)
307{
308    if ((ne == NULL) || (obj == NULL)) {
309        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
310        return 0;
311    }
312    ASN1_OBJECT_free(ne->object);
313    ne->object = OBJ_dup(obj);
314    return ((ne->object == NULL) ? 0 : 1);
315}
316
317int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
318                             const unsigned char *bytes, int len)
319{
320    int i;
321
322    if ((ne == NULL) || ((bytes == NULL) && (len != 0)))
323        return 0;
324    if ((type > 0) && (type & MBSTRING_FLAG))
325        return ASN1_STRING_set_by_NID(&ne->value, bytes,
326                                      len, type,
327                                      OBJ_obj2nid(ne->object)) ? 1 : 0;
328    if (len < 0)
329        len = strlen((const char *)bytes);
330    i = ASN1_STRING_set(ne->value, bytes, len);
331    if (!i)
332        return 0;
333    if (type != V_ASN1_UNDEF) {
334        if (type == V_ASN1_APP_CHOOSE)
335            ne->value->type = ASN1_PRINTABLE_type(bytes, len);
336        else
337            ne->value->type = type;
338    }
339    return 1;
340}
341
342ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne)
343{
344    if (ne == NULL)
345        return NULL;
346    return ne->object;
347}
348
349ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne)
350{
351    if (ne == NULL)
352        return NULL;
353    return ne->value;
354}
355
356int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne)
357{
358    return ne->set;
359}
360