Branch data Line data Source code
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 : :
67 : 0 : int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len)
68 : : {
69 : : ASN1_OBJECT *obj;
70 : :
71 : 0 : obj=OBJ_nid2obj(nid);
72 [ # # ]: 0 : if (obj == NULL) return(-1);
73 : 0 : return(X509_NAME_get_text_by_OBJ(name,obj,buf,len));
74 : : }
75 : :
76 : 0 : int X509_NAME_get_text_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, char *buf,
77 : : int len)
78 : : {
79 : : int i;
80 : : ASN1_STRING *data;
81 : :
82 : 0 : i=X509_NAME_get_index_by_OBJ(name,obj,-1);
83 [ # # ]: 0 : if (i < 0) return(-1);
84 : 0 : data=X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name,i));
85 [ # # ]: 0 : i=(data->length > (len-1))?(len-1):data->length;
86 [ # # ]: 0 : if (buf == NULL) return(data->length);
87 : 0 : memcpy(buf,data->data,i);
88 : 0 : buf[i]='\0';
89 : 0 : return(i);
90 : : }
91 : :
92 : 29 : int X509_NAME_entry_count(X509_NAME *name)
93 : : {
94 [ + - ]: 29 : if (name == NULL) return(0);
95 : 29 : return(sk_X509_NAME_ENTRY_num(name->entries));
96 : : }
97 : :
98 : 87957 : int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos)
99 : : {
100 : : ASN1_OBJECT *obj;
101 : :
102 : 87957 : obj=OBJ_nid2obj(nid);
103 [ + - ]: 87957 : if (obj == NULL) return(-2);
104 : 87957 : return(X509_NAME_get_index_by_OBJ(name,obj,lastpos));
105 : : }
106 : :
107 : : /* NOTE: you should be passsing -1, not 0 as lastpos */
108 : 87978 : int X509_NAME_get_index_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj,
109 : : int lastpos)
110 : : {
111 : : int n;
112 : : X509_NAME_ENTRY *ne;
113 : : STACK_OF(X509_NAME_ENTRY) *sk;
114 : :
115 [ + - ]: 87978 : if (name == NULL) return(-1);
116 [ + + ]: 87978 : if (lastpos < 0)
117 : 49937 : lastpos= -1;
118 : 87978 : sk=name->entries;
119 : 87978 : n=sk_X509_NAME_ENTRY_num(sk);
120 [ + + ]: 126690 : for (lastpos++; lastpos < n; lastpos++)
121 : : {
122 : 77389 : ne=sk_X509_NAME_ENTRY_value(sk,lastpos);
123 [ + + ]: 77389 : if (OBJ_cmp(ne->object,obj) == 0)
124 : : return(lastpos);
125 : : }
126 : : return(-1);
127 : : }
128 : :
129 : 38726 : X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc)
130 : : {
131 [ + - ][ + - ]: 38726 : if(name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
132 [ + - ]: 38726 : || loc < 0)
133 : : return(NULL);
134 : : else
135 : 38726 : return(sk_X509_NAME_ENTRY_value(name->entries,loc));
136 : : }
137 : :
138 : 0 : X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc)
139 : : {
140 : : X509_NAME_ENTRY *ret;
141 : : int i,n,set_prev,set_next;
142 : : STACK_OF(X509_NAME_ENTRY) *sk;
143 : :
144 [ # # ][ # # ]: 0 : if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
145 [ # # ]: 0 : || loc < 0)
146 : : return(NULL);
147 : 0 : sk=name->entries;
148 : 0 : ret=sk_X509_NAME_ENTRY_delete(sk,loc);
149 : 0 : n=sk_X509_NAME_ENTRY_num(sk);
150 : 0 : name->modified=1;
151 [ # # ]: 0 : if (loc == n) return(ret);
152 : :
153 : : /* else we need to fixup the set field */
154 [ # # ]: 0 : if (loc != 0)
155 : 0 : set_prev=(sk_X509_NAME_ENTRY_value(sk,loc-1))->set;
156 : : else
157 : 0 : set_prev=ret->set-1;
158 : 0 : set_next=sk_X509_NAME_ENTRY_value(sk,loc)->set;
159 : :
160 : : /* set_prev is the previous set
161 : : * set is the current set
162 : : * set_next is the following
163 : : * prev 1 1 1 1 1 1 1 1
164 : : * set 1 1 2 2
165 : : * next 1 1 2 2 2 2 3 2
166 : : * so basically only if prev and next differ by 2, then
167 : : * re-number down by 1 */
168 [ # # ]: 0 : if (set_prev+1 < set_next)
169 [ # # ]: 0 : for (i=loc; i<n; i++)
170 : 0 : sk_X509_NAME_ENTRY_value(sk,i)->set--;
171 : 0 : return(ret);
172 : : }
173 : :
174 : 0 : int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
175 : : unsigned char *bytes, int len, int loc, int set)
176 : : {
177 : : X509_NAME_ENTRY *ne;
178 : : int ret;
179 : 0 : ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
180 [ # # ]: 0 : if(!ne) return 0;
181 : 0 : ret = X509_NAME_add_entry(name, ne, loc, set);
182 : 0 : X509_NAME_ENTRY_free(ne);
183 : 0 : return ret;
184 : : }
185 : :
186 : 633 : int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
187 : : unsigned char *bytes, int len, int loc, int set)
188 : : {
189 : : X509_NAME_ENTRY *ne;
190 : : int ret;
191 : 633 : ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
192 [ + - ]: 633 : if(!ne) return 0;
193 : 633 : ret = X509_NAME_add_entry(name, ne, loc, set);
194 : 633 : X509_NAME_ENTRY_free(ne);
195 : 633 : return ret;
196 : : }
197 : :
198 : 15 : int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
199 : : const unsigned char *bytes, int len, int loc, int set)
200 : : {
201 : : X509_NAME_ENTRY *ne;
202 : : int ret;
203 : 15 : ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
204 [ + - ]: 15 : if(!ne) return 0;
205 : 15 : ret = X509_NAME_add_entry(name, ne, loc, set);
206 : 15 : X509_NAME_ENTRY_free(ne);
207 : 15 : return ret;
208 : : }
209 : :
210 : : /* if set is -1, append to previous set, 0 'a new one', and 1,
211 : : * prepend to the guy we are about to stomp on. */
212 : 655 : int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc,
213 : : int set)
214 : : {
215 : 655 : X509_NAME_ENTRY *new_name=NULL;
216 : : int n,i,inc;
217 : : STACK_OF(X509_NAME_ENTRY) *sk;
218 : :
219 [ + - ]: 655 : if (name == NULL) return(0);
220 : 655 : sk=name->entries;
221 : 655 : n=sk_X509_NAME_ENTRY_num(sk);
222 [ + - ]: 655 : if (loc > n) loc=n;
223 [ + - ]: 655 : else if (loc < 0) loc=n;
224 : :
225 : 655 : name->modified=1;
226 : :
227 [ - + ]: 655 : if (set == -1)
228 : : {
229 [ # # ]: 0 : if (loc == 0)
230 : : {
231 : : set=0;
232 : : inc=1;
233 : : }
234 : : else
235 : : {
236 : 0 : set=sk_X509_NAME_ENTRY_value(sk,loc-1)->set;
237 : 0 : inc=0;
238 : : }
239 : : }
240 : : else /* if (set >= 0) */
241 : : {
242 [ + - ]: 655 : if (loc >= n)
243 : : {
244 [ + + ]: 655 : if (loc != 0)
245 : 299 : set=sk_X509_NAME_ENTRY_value(sk,loc-1)->set+1;
246 : : else
247 : : set=0;
248 : : }
249 : : else
250 : 0 : set=sk_X509_NAME_ENTRY_value(sk,loc)->set;
251 : 655 : inc=(set == 0)?1:0;
252 : : }
253 : :
254 [ + - ]: 655 : if ((new_name=X509_NAME_ENTRY_dup(ne)) == NULL)
255 : : goto err;
256 : 655 : new_name->set=set;
257 [ - + ]: 655 : if (!sk_X509_NAME_ENTRY_insert(sk,new_name,loc))
258 : : {
259 : 0 : X509err(X509_F_X509_NAME_ADD_ENTRY,ERR_R_MALLOC_FAILURE);
260 : 0 : goto err;
261 : : }
262 [ + + ]: 655 : if (inc)
263 : : {
264 : 356 : n=sk_X509_NAME_ENTRY_num(sk);
265 [ - + ]: 356 : for (i=loc+1; i<n; i++)
266 : 0 : sk_X509_NAME_ENTRY_value(sk,i-1)->set+=1;
267 : : }
268 : : return(1);
269 : : err:
270 [ # # ]: 0 : if (new_name != NULL)
271 : 0 : X509_NAME_ENTRY_free(new_name);
272 : : return(0);
273 : : }
274 : :
275 : 15 : X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
276 : : const char *field, int type, const unsigned char *bytes, int len)
277 : : {
278 : : ASN1_OBJECT *obj;
279 : : X509_NAME_ENTRY *nentry;
280 : :
281 : 15 : obj=OBJ_txt2obj(field, 0);
282 [ - + ]: 15 : if (obj == NULL)
283 : : {
284 : 0 : X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT,
285 : : X509_R_INVALID_FIELD_NAME);
286 : 0 : ERR_add_error_data(2, "name=", field);
287 : 0 : return(NULL);
288 : : }
289 : 15 : nentry = X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len);
290 : 15 : ASN1_OBJECT_free(obj);
291 : 15 : return nentry;
292 : : }
293 : :
294 : 633 : X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
295 : : int type, unsigned char *bytes, int len)
296 : : {
297 : : ASN1_OBJECT *obj;
298 : : X509_NAME_ENTRY *nentry;
299 : :
300 : 633 : obj=OBJ_nid2obj(nid);
301 [ - + ]: 633 : if (obj == NULL)
302 : : {
303 : 0 : X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_NID,X509_R_UNKNOWN_NID);
304 : 0 : return(NULL);
305 : : }
306 : 633 : nentry = X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len);
307 : 633 : ASN1_OBJECT_free(obj);
308 : 633 : return nentry;
309 : : }
310 : :
311 : 648 : X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
312 : : ASN1_OBJECT *obj, int type, const unsigned char *bytes, int len)
313 : : {
314 : : X509_NAME_ENTRY *ret;
315 : :
316 [ - + ][ # # ]: 648 : if ((ne == NULL) || (*ne == NULL))
317 : : {
318 [ + - ]: 648 : if ((ret=X509_NAME_ENTRY_new()) == NULL)
319 : : return(NULL);
320 : : }
321 : : else
322 : : ret= *ne;
323 : :
324 [ + - ]: 648 : if (!X509_NAME_ENTRY_set_object(ret,obj))
325 : : goto err;
326 [ + - ]: 648 : if (!X509_NAME_ENTRY_set_data(ret,type,bytes,len))
327 : : goto err;
328 : :
329 [ - + ][ # # ]: 648 : if ((ne != NULL) && (*ne == NULL)) *ne=ret;
330 : 648 : return(ret);
331 : : err:
332 [ # # ][ # # ]: 0 : if ((ne == NULL) || (ret != *ne))
333 : 0 : X509_NAME_ENTRY_free(ret);
334 : : return(NULL);
335 : : }
336 : :
337 : 648 : int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, ASN1_OBJECT *obj)
338 : : {
339 [ - + ]: 648 : if ((ne == NULL) || (obj == NULL))
340 : : {
341 : 0 : X509err(X509_F_X509_NAME_ENTRY_SET_OBJECT,ERR_R_PASSED_NULL_PARAMETER);
342 : 0 : return(0);
343 : : }
344 : 648 : ASN1_OBJECT_free(ne->object);
345 : 648 : ne->object=OBJ_dup(obj);
346 : 648 : return((ne->object == NULL)?0:1);
347 : : }
348 : :
349 : 648 : int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
350 : : const unsigned char *bytes, int len)
351 : : {
352 : : int i;
353 : :
354 [ + - ][ + - ]: 648 : if ((ne == NULL) || ((bytes == NULL) && (len != 0))) return(0);
355 [ + - ][ + - ]: 648 : if((type > 0) && (type & MBSTRING_FLAG))
356 : 648 : return ASN1_STRING_set_by_NID(&ne->value, bytes,
357 : : len, type,
358 : 1296 : OBJ_obj2nid(ne->object)) ? 1 : 0;
359 [ # # ]: 0 : if (len < 0) len=strlen((const char *)bytes);
360 : 0 : i=ASN1_STRING_set(ne->value,bytes,len);
361 [ # # ]: 0 : if (!i) return(0);
362 [ # # ]: 0 : if (type != V_ASN1_UNDEF)
363 : : {
364 [ # # ]: 0 : if (type == V_ASN1_APP_CHOOSE)
365 : 0 : ne->value->type=ASN1_PRINTABLE_type(bytes,len);
366 : : else
367 : 0 : ne->value->type=type;
368 : : }
369 : : return(1);
370 : : }
371 : :
372 : 49 : ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne)
373 : : {
374 [ + - ]: 49 : if (ne == NULL) return(NULL);
375 : 49 : return(ne->object);
376 : : }
377 : :
378 : 38719 : ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne)
379 : : {
380 [ + - ]: 38719 : if (ne == NULL) return(NULL);
381 : 38719 : return(ne->value);
382 : : }
383 : :
|