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