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 int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len)
  68         {
  69         ASN1_OBJECT *obj;
  70 
  71         obj=OBJ_nid2obj(nid);
  72         if (obj == NULL) return(-1);
  73         return(X509_NAME_get_text_by_OBJ(name,obj,buf,len));
  74         }
  75 
  76 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         i=X509_NAME_get_index_by_OBJ(name,obj,-1);
  83         if (i < 0) return(-1);
  84         data=X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name,i));
  85         i=(data->length > (len-1))?(len-1):data->length;
  86         if (buf == NULL) return(data->length);
  87         memcpy(buf,data->data,i);
  88         buf[i]='\0';
  89         return(i);
  90         }
  91 
  92 int X509_NAME_entry_count(X509_NAME *name)
  93         {
  94         if (name == NULL) return(0);
  95         return(sk_X509_NAME_ENTRY_num(name->entries));
  96         }
  97 
  98 int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos)
  99         {
 100         ASN1_OBJECT *obj;
 101 
 102         obj=OBJ_nid2obj(nid);
 103         if (obj == NULL) return(-2);
 104         return(X509_NAME_get_index_by_OBJ(name,obj,lastpos));
 105         }
 106 
 107 /* NOTE: you should be passsing -1, not 0 as lastpos */
 108 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         if (name == NULL) return(-1);
 116         if (lastpos < 0)
 117                 lastpos= -1;
 118         sk=name->entries;
 119         n=sk_X509_NAME_ENTRY_num(sk);
 120         for (lastpos++; lastpos < n; lastpos++)
 121                 {
 122                 ne=sk_X509_NAME_ENTRY_value(sk,lastpos);
 123                 if (OBJ_cmp(ne->object,obj) == 0)
 124                         return(lastpos);
 125                 }
 126         return(-1);
 127         }
 128 
 129 X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc)
 130         {
 131         if(name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
 132            || loc < 0)
 133                 return(NULL);
 134         else
 135                 return(sk_X509_NAME_ENTRY_value(name->entries,loc));
 136         }
 137 
 138 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         if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
 145             || loc < 0)
 146                 return(NULL);
 147         sk=name->entries;
 148         ret=sk_X509_NAME_ENTRY_delete(sk,loc);
 149         n=sk_X509_NAME_ENTRY_num(sk);
 150         name->modified=1;
 151         if (loc == n) return(ret);
 152 
 153         /* else we need to fixup the set field */
 154         if (loc != 0)
 155                 set_prev=(sk_X509_NAME_ENTRY_value(sk,loc-1))->set;
 156         else
 157                 set_prev=ret->set-1;
 158         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         if (set_prev+1 < set_next)
 169                 for (i=loc; i<n; i++)
 170                         sk_X509_NAME_ENTRY_value(sk,i)->set--;
 171         return(ret);
 172         }
 173 
 174 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         ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
 180         if(!ne) return 0;
 181         ret = X509_NAME_add_entry(name, ne, loc, set);
 182         X509_NAME_ENTRY_free(ne);
 183         return ret;
 184 }
 185 
 186 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         ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
 192         if(!ne) return 0;
 193         ret = X509_NAME_add_entry(name, ne, loc, set);
 194         X509_NAME_ENTRY_free(ne);
 195         return ret;
 196 }
 197 
 198 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         ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
 204         if(!ne) return 0;
 205         ret = X509_NAME_add_entry(name, ne, loc, set);
 206         X509_NAME_ENTRY_free(ne);
 207         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 int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc,
 213              int set)
 214         {
 215         X509_NAME_ENTRY *new_name=NULL;
 216         int n,i,inc;
 217         STACK_OF(X509_NAME_ENTRY) *sk;
 218 
 219         if (name == NULL) return(0);
 220         sk=name->entries;
 221         n=sk_X509_NAME_ENTRY_num(sk);
 222         if (loc > n) loc=n;
 223         else if (loc < 0) loc=n;
 224 
 225         name->modified=1;
 226 
 227         if (set == -1)
 228                 {
 229                 if (loc == 0)
 230                         {
 231                         set=0;
 232                         inc=1;
 233                         }
 234                 else
 235                         {
 236                         set=sk_X509_NAME_ENTRY_value(sk,loc-1)->set;
 237                         inc=0;
 238                         }
 239                 }
 240         else /* if (set >= 0) */
 241                 {
 242                 if (loc >= n)
 243                         {
 244                         if (loc != 0)
 245                                 set=sk_X509_NAME_ENTRY_value(sk,loc-1)->set+1;
 246                         else
 247                                 set=0;
 248                         }
 249                 else
 250                         set=sk_X509_NAME_ENTRY_value(sk,loc)->set;
 251                 inc=(set == 0)?1:0;
 252                 }
 253 
 254         if ((new_name=X509_NAME_ENTRY_dup(ne)) == NULL)
 255                 goto err;
 256         new_name->set=set;
 257         if (!sk_X509_NAME_ENTRY_insert(sk,new_name,loc))
 258                 {
 259                 X509err(X509_F_X509_NAME_ADD_ENTRY,ERR_R_MALLOC_FAILURE);
 260                 goto err;
 261                 }
 262         if (inc)
 263                 {
 264                 n=sk_X509_NAME_ENTRY_num(sk);
 265                 for (i=loc+1; i<n; i++)
 266                         sk_X509_NAME_ENTRY_value(sk,i-1)->set+=1;
 267                 }
 268         return(1);
 269 err:
 270         if (new_name != NULL)
 271                 X509_NAME_ENTRY_free(new_name);
 272         return(0);
 273         }
 274 
 275 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         obj=OBJ_txt2obj(field, 0);
 282         if (obj == NULL)
 283                 {
 284                 X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT,
 285                                                 X509_R_INVALID_FIELD_NAME);
 286                 ERR_add_error_data(2, "name=", field);
 287                 return(NULL);
 288                 }
 289         nentry = X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len);
 290         ASN1_OBJECT_free(obj);
 291         return nentry;
 292         }
 293 
 294 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         obj=OBJ_nid2obj(nid);
 301         if (obj == NULL)
 302                 {
 303                 X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_NID,X509_R_UNKNOWN_NID);
 304                 return(NULL);
 305                 }
 306         nentry = X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len);
 307         ASN1_OBJECT_free(obj);
 308         return nentry;
 309         }
 310 
 311 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         if ((ne == NULL) || (*ne == NULL))
 317                 {
 318                 if ((ret=X509_NAME_ENTRY_new()) == NULL)
 319                         return(NULL);
 320                 }
 321         else
 322                 ret= *ne;
 323 
 324         if (!X509_NAME_ENTRY_set_object(ret,obj))
 325                 goto err;
 326         if (!X509_NAME_ENTRY_set_data(ret,type,bytes,len))
 327                 goto err;
 328 
 329         if ((ne != NULL) && (*ne == NULL)) *ne=ret;
 330         return(ret);
 331 err:
 332         if ((ne == NULL) || (ret != *ne))
 333                 X509_NAME_ENTRY_free(ret);
 334         return(NULL);
 335         }
 336 
 337 int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, ASN1_OBJECT *obj)
 338         {
 339         if ((ne == NULL) || (obj == NULL))
 340                 {
 341                 X509err(X509_F_X509_NAME_ENTRY_SET_OBJECT,ERR_R_PASSED_NULL_PARAMETER);
 342                 return(0);
 343                 }
 344         ASN1_OBJECT_free(ne->object);
 345         ne->object=OBJ_dup(obj);
 346         return((ne->object == NULL)?0:1);
 347         }
 348 
 349 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         if ((ne == NULL) || ((bytes == NULL) && (len != 0))) return(0);
 355         if((type > 0) && (type & MBSTRING_FLAG))
 356                 return ASN1_STRING_set_by_NID(&ne->value, bytes,
 357                                                 len, type,
 358                                         OBJ_obj2nid(ne->object)) ? 1 : 0;
 359         if (len < 0) len=strlen((const char *)bytes);
 360         i=ASN1_STRING_set(ne->value,bytes,len);
 361         if (!i) return(0);
 362         if (type != V_ASN1_UNDEF)
 363                 {
 364                 if (type == V_ASN1_APP_CHOOSE)
 365                         ne->value->type=ASN1_PRINTABLE_type(bytes,len);
 366                 else
 367                         ne->value->type=type;
 368                 }
 369         return(1);
 370         }
 371 
 372 ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne)
 373         {
 374         if (ne == NULL) return(NULL);
 375         return(ne->object);
 376         }
 377 
 378 ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne)
 379         {
 380         if (ne == NULL) return(NULL);
 381         return(ne->value);
 382         }