1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/ssl/libcrypto/src/crypto/x509/x509name.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,383 @@
1.4 +/* crypto/x509/x509name.c */
1.5 +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
1.6 + * All rights reserved.
1.7 + *
1.8 + * This package is an SSL implementation written
1.9 + * by Eric Young (eay@cryptsoft.com).
1.10 + * The implementation was written so as to conform with Netscapes SSL.
1.11 + *
1.12 + * This library is free for commercial and non-commercial use as long as
1.13 + * the following conditions are aheared to. The following conditions
1.14 + * apply to all code found in this distribution, be it the RC4, RSA,
1.15 + * lhash, DES, etc., code; not just the SSL code. The SSL documentation
1.16 + * included with this distribution is covered by the same copyright terms
1.17 + * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1.18 + *
1.19 + * Copyright remains Eric Young's, and as such any Copyright notices in
1.20 + * the code are not to be removed.
1.21 + * If this package is used in a product, Eric Young should be given attribution
1.22 + * as the author of the parts of the library used.
1.23 + * This can be in the form of a textual message at program startup or
1.24 + * in documentation (online or textual) provided with the package.
1.25 + *
1.26 + * Redistribution and use in source and binary forms, with or without
1.27 + * modification, are permitted provided that the following conditions
1.28 + * are met:
1.29 + * 1. Redistributions of source code must retain the copyright
1.30 + * notice, this list of conditions and the following disclaimer.
1.31 + * 2. Redistributions in binary form must reproduce the above copyright
1.32 + * notice, this list of conditions and the following disclaimer in the
1.33 + * documentation and/or other materials provided with the distribution.
1.34 + * 3. All advertising materials mentioning features or use of this software
1.35 + * must display the following acknowledgement:
1.36 + * "This product includes cryptographic software written by
1.37 + * Eric Young (eay@cryptsoft.com)"
1.38 + * The word 'cryptographic' can be left out if the rouines from the library
1.39 + * being used are not cryptographic related :-).
1.40 + * 4. If you include any Windows specific code (or a derivative thereof) from
1.41 + * the apps directory (application code) you must include an acknowledgement:
1.42 + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
1.43 + *
1.44 + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
1.45 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1.46 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1.47 + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1.48 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1.49 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1.50 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1.51 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1.52 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1.53 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1.54 + * SUCH DAMAGE.
1.55 + *
1.56 + * The licence and distribution terms for any publically available version or
1.57 + * derivative of this code cannot be changed. i.e. this code cannot simply be
1.58 + * copied and put under another distribution licence
1.59 + * [including the GNU Public Licence.]
1.60 + */
1.61 +
1.62 +#include <stdio.h>
1.63 +#include <openssl/stack.h>
1.64 +#include "cryptlib.h"
1.65 +#include <openssl/asn1.h>
1.66 +#include <openssl/objects.h>
1.67 +#include <openssl/evp.h>
1.68 +#include <openssl/x509.h>
1.69 +
1.70 +EXPORT_C int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len)
1.71 + {
1.72 + ASN1_OBJECT *obj;
1.73 +
1.74 + obj=OBJ_nid2obj(nid);
1.75 + if (obj == NULL) return(-1);
1.76 + return(X509_NAME_get_text_by_OBJ(name,obj,buf,len));
1.77 + }
1.78 +
1.79 +EXPORT_C int X509_NAME_get_text_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, char *buf,
1.80 + int len)
1.81 + {
1.82 + int i;
1.83 + ASN1_STRING *data;
1.84 +
1.85 + i=X509_NAME_get_index_by_OBJ(name,obj,-1);
1.86 + if (i < 0) return(-1);
1.87 + data=X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name,i));
1.88 + i=(data->length > (len-1))?(len-1):data->length;
1.89 + if (buf == NULL) return(data->length);
1.90 + memcpy(buf,data->data,i);
1.91 + buf[i]='\0';
1.92 + return(i);
1.93 + }
1.94 +
1.95 +EXPORT_C int X509_NAME_entry_count(X509_NAME *name)
1.96 + {
1.97 + if (name == NULL) return(0);
1.98 + return(sk_X509_NAME_ENTRY_num(name->entries));
1.99 + }
1.100 +
1.101 +EXPORT_C int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos)
1.102 + {
1.103 + ASN1_OBJECT *obj;
1.104 +
1.105 + obj=OBJ_nid2obj(nid);
1.106 + if (obj == NULL) return(-2);
1.107 + return(X509_NAME_get_index_by_OBJ(name,obj,lastpos));
1.108 + }
1.109 +
1.110 +/* NOTE: you should be passsing -1, not 0 as lastpos */
1.111 +EXPORT_C int X509_NAME_get_index_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj,
1.112 + int lastpos)
1.113 + {
1.114 + int n;
1.115 + X509_NAME_ENTRY *ne;
1.116 + STACK_OF(X509_NAME_ENTRY) *sk;
1.117 +
1.118 + if (name == NULL) return(-1);
1.119 + if (lastpos < 0)
1.120 + lastpos= -1;
1.121 + sk=name->entries;
1.122 + n=sk_X509_NAME_ENTRY_num(sk);
1.123 + for (lastpos++; lastpos < n; lastpos++)
1.124 + {
1.125 + ne=sk_X509_NAME_ENTRY_value(sk,lastpos);
1.126 + if (OBJ_cmp(ne->object,obj) == 0)
1.127 + return(lastpos);
1.128 + }
1.129 + return(-1);
1.130 + }
1.131 +
1.132 +EXPORT_C X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc)
1.133 + {
1.134 + if(name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
1.135 + || loc < 0)
1.136 + return(NULL);
1.137 + else
1.138 + return(sk_X509_NAME_ENTRY_value(name->entries,loc));
1.139 + }
1.140 +
1.141 +EXPORT_C X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc)
1.142 + {
1.143 + X509_NAME_ENTRY *ret;
1.144 + int i,n,set_prev,set_next;
1.145 + STACK_OF(X509_NAME_ENTRY) *sk;
1.146 +
1.147 + if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
1.148 + || loc < 0)
1.149 + return(NULL);
1.150 + sk=name->entries;
1.151 + ret=sk_X509_NAME_ENTRY_delete(sk,loc);
1.152 + n=sk_X509_NAME_ENTRY_num(sk);
1.153 + name->modified=1;
1.154 + if (loc == n) return(ret);
1.155 +
1.156 + /* else we need to fixup the set field */
1.157 + if (loc != 0)
1.158 + set_prev=(sk_X509_NAME_ENTRY_value(sk,loc-1))->set;
1.159 + else
1.160 + set_prev=ret->set-1;
1.161 + set_next=sk_X509_NAME_ENTRY_value(sk,loc)->set;
1.162 +
1.163 + /* set_prev is the previous set
1.164 + * set is the current set
1.165 + * set_next is the following
1.166 + * prev 1 1 1 1 1 1 1 1
1.167 + * set 1 1 2 2
1.168 + * next 1 1 2 2 2 2 3 2
1.169 + * so basically only if prev and next differ by 2, then
1.170 + * re-number down by 1 */
1.171 + if (set_prev+1 < set_next)
1.172 + for (i=loc; i<n; i++)
1.173 + sk_X509_NAME_ENTRY_value(sk,i)->set--;
1.174 + return(ret);
1.175 + }
1.176 +
1.177 +EXPORT_C int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
1.178 + unsigned char *bytes, int len, int loc, int set)
1.179 +{
1.180 + X509_NAME_ENTRY *ne;
1.181 + int ret;
1.182 + ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
1.183 + if(!ne) return 0;
1.184 + ret = X509_NAME_add_entry(name, ne, loc, set);
1.185 + X509_NAME_ENTRY_free(ne);
1.186 + return ret;
1.187 +}
1.188 +
1.189 +EXPORT_C int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
1.190 + unsigned char *bytes, int len, int loc, int set)
1.191 +{
1.192 + X509_NAME_ENTRY *ne;
1.193 + int ret;
1.194 + ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
1.195 + if(!ne) return 0;
1.196 + ret = X509_NAME_add_entry(name, ne, loc, set);
1.197 + X509_NAME_ENTRY_free(ne);
1.198 + return ret;
1.199 +}
1.200 +
1.201 +EXPORT_C int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
1.202 + const unsigned char *bytes, int len, int loc, int set)
1.203 +{
1.204 + X509_NAME_ENTRY *ne;
1.205 + int ret;
1.206 + ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
1.207 + if(!ne) return 0;
1.208 + ret = X509_NAME_add_entry(name, ne, loc, set);
1.209 + X509_NAME_ENTRY_free(ne);
1.210 + return ret;
1.211 +}
1.212 +
1.213 +/* if set is -1, append to previous set, 0 'a new one', and 1,
1.214 + * prepend to the guy we are about to stomp on. */
1.215 +EXPORT_C int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc,
1.216 + int set)
1.217 + {
1.218 + X509_NAME_ENTRY *new_name=NULL;
1.219 + int n,i,inc;
1.220 + STACK_OF(X509_NAME_ENTRY) *sk;
1.221 +
1.222 + if (name == NULL) return(0);
1.223 + sk=name->entries;
1.224 + n=sk_X509_NAME_ENTRY_num(sk);
1.225 + if (loc > n) loc=n;
1.226 + else if (loc < 0) loc=n;
1.227 +
1.228 + name->modified=1;
1.229 +
1.230 + if (set == -1)
1.231 + {
1.232 + if (loc == 0)
1.233 + {
1.234 + set=0;
1.235 + inc=1;
1.236 + }
1.237 + else
1.238 + {
1.239 + set=sk_X509_NAME_ENTRY_value(sk,loc-1)->set;
1.240 + inc=0;
1.241 + }
1.242 + }
1.243 + else /* if (set >= 0) */
1.244 + {
1.245 + if (loc >= n)
1.246 + {
1.247 + if (loc != 0)
1.248 + set=sk_X509_NAME_ENTRY_value(sk,loc-1)->set+1;
1.249 + else
1.250 + set=0;
1.251 + }
1.252 + else
1.253 + set=sk_X509_NAME_ENTRY_value(sk,loc)->set;
1.254 + inc=(set == 0)?1:0;
1.255 + }
1.256 +
1.257 + if ((new_name=X509_NAME_ENTRY_dup(ne)) == NULL)
1.258 + goto err;
1.259 + new_name->set=set;
1.260 + if (!sk_X509_NAME_ENTRY_insert(sk,new_name,loc))
1.261 + {
1.262 + X509err(X509_F_X509_NAME_ADD_ENTRY,ERR_R_MALLOC_FAILURE);
1.263 + goto err;
1.264 + }
1.265 + if (inc)
1.266 + {
1.267 + n=sk_X509_NAME_ENTRY_num(sk);
1.268 + for (i=loc+1; i<n; i++)
1.269 + sk_X509_NAME_ENTRY_value(sk,i-1)->set+=1;
1.270 + }
1.271 + return(1);
1.272 +err:
1.273 + if (new_name != NULL)
1.274 + X509_NAME_ENTRY_free(new_name);
1.275 + return(0);
1.276 + }
1.277 +
1.278 +EXPORT_C X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
1.279 + const char *field, int type, const unsigned char *bytes, int len)
1.280 + {
1.281 + ASN1_OBJECT *obj;
1.282 + X509_NAME_ENTRY *nentry;
1.283 +
1.284 + obj=OBJ_txt2obj(field, 0);
1.285 + if (obj == NULL)
1.286 + {
1.287 + X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT,
1.288 + X509_R_INVALID_FIELD_NAME);
1.289 + ERR_add_error_data(2, "name=", field);
1.290 + return(NULL);
1.291 + }
1.292 + nentry = X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len);
1.293 + ASN1_OBJECT_free(obj);
1.294 + return nentry;
1.295 + }
1.296 +
1.297 +EXPORT_C X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
1.298 + int type, unsigned char *bytes, int len)
1.299 + {
1.300 + ASN1_OBJECT *obj;
1.301 + X509_NAME_ENTRY *nentry;
1.302 +
1.303 + obj=OBJ_nid2obj(nid);
1.304 + if (obj == NULL)
1.305 + {
1.306 + X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_NID,X509_R_UNKNOWN_NID);
1.307 + return(NULL);
1.308 + }
1.309 + nentry = X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len);
1.310 + ASN1_OBJECT_free(obj);
1.311 + return nentry;
1.312 + }
1.313 +
1.314 +EXPORT_C X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
1.315 + ASN1_OBJECT *obj, int type, const unsigned char *bytes, int len)
1.316 + {
1.317 + X509_NAME_ENTRY *ret;
1.318 +
1.319 + if ((ne == NULL) || (*ne == NULL))
1.320 + {
1.321 + if ((ret=X509_NAME_ENTRY_new()) == NULL)
1.322 + return(NULL);
1.323 + }
1.324 + else
1.325 + ret= *ne;
1.326 +
1.327 + if (!X509_NAME_ENTRY_set_object(ret,obj))
1.328 + goto err;
1.329 + if (!X509_NAME_ENTRY_set_data(ret,type,bytes,len))
1.330 + goto err;
1.331 +
1.332 + if ((ne != NULL) && (*ne == NULL)) *ne=ret;
1.333 + return(ret);
1.334 +err:
1.335 + if ((ne == NULL) || (ret != *ne))
1.336 + X509_NAME_ENTRY_free(ret);
1.337 + return(NULL);
1.338 + }
1.339 +
1.340 +EXPORT_C int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, ASN1_OBJECT *obj)
1.341 + {
1.342 + if ((ne == NULL) || (obj == NULL))
1.343 + {
1.344 + X509err(X509_F_X509_NAME_ENTRY_SET_OBJECT,ERR_R_PASSED_NULL_PARAMETER);
1.345 + return(0);
1.346 + }
1.347 + ASN1_OBJECT_free(ne->object);
1.348 + ne->object=OBJ_dup(obj);
1.349 + return((ne->object == NULL)?0:1);
1.350 + }
1.351 +
1.352 +EXPORT_C int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
1.353 + const unsigned char *bytes, int len)
1.354 + {
1.355 + int i;
1.356 +
1.357 + if ((ne == NULL) || ((bytes == NULL) && (len != 0))) return(0);
1.358 + if((type > 0) && (type & MBSTRING_FLAG))
1.359 + return ASN1_STRING_set_by_NID(&ne->value, bytes,
1.360 + len, type,
1.361 + OBJ_obj2nid(ne->object)) ? 1 : 0;
1.362 + if (len < 0) len=strlen((char *)bytes);
1.363 + i=ASN1_STRING_set(ne->value,bytes,len);
1.364 + if (!i) return(0);
1.365 + if (type != V_ASN1_UNDEF)
1.366 + {
1.367 + if (type == V_ASN1_APP_CHOOSE)
1.368 + ne->value->type=ASN1_PRINTABLE_type(bytes,len);
1.369 + else
1.370 + ne->value->type=type;
1.371 + }
1.372 + return(1);
1.373 + }
1.374 +
1.375 +EXPORT_C ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne)
1.376 + {
1.377 + if (ne == NULL) return(NULL);
1.378 + return(ne->object);
1.379 + }
1.380 +
1.381 +EXPORT_C ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne)
1.382 + {
1.383 + if (ne == NULL) return(NULL);
1.384 + return(ne->value);
1.385 + }
1.386 +