improved error checking and some fixes
[openssl.git] / crypto / x509v3 / v3_alt.c
index 64e51d6129ca294c7a8ac289a921602c3186c740..b38b3dbfe62baffd7a4c8e956e4e16442f886f59 100644 (file)
@@ -66,6 +66,7 @@ static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
 static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
 static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
+static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
 
 X509V3_EXT_METHOD v3_alt[] = {
 { NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
@@ -136,13 +137,15 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
                case GEN_IPADD:
                p = gen->d.ip->data;
                if(gen->d.ip->length == 4)
-                       sprintf(oline, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+                       BIO_snprintf(oline, sizeof oline,
+                                    "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
                else if(gen->d.ip->length == 16)
                        {
                        oline[0] = 0;
                        for (i = 0; i < 8; i++)
                                {
-                               sprintf(htmp, "%X", p[0] << 8 | p[1]);
+                               BIO_snprintf(htmp, sizeof htmp,
+                                            "%X", p[0] << 8 | p[1]);
                                p += 2;
                                strcat(oline, htmp);
                                if (i != 7)
@@ -238,7 +241,7 @@ static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
        CONF_VALUE *cnf;
        int i;
        if(!(gens = sk_GENERAL_NAME_new_null())) {
-               X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE);
+               X509V3err(X509V3_F_V2I_ISSUER_ALT,ERR_R_MALLOC_FAILURE);
                return NULL;
        }
        for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
@@ -303,7 +306,7 @@ static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
        CONF_VALUE *cnf;
        int i;
        if(!(gens = sk_GENERAL_NAME_new_null())) {
-               X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE);
+               X509V3err(X509V3_F_V2I_SUBJECT_ALT,ERR_R_MALLOC_FAILURE);
                return NULL;
        }
        for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
@@ -338,7 +341,8 @@ static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
        X509_NAME_ENTRY *ne;
        GENERAL_NAME *gen = NULL;
        int i;
-       if(ctx->flags == CTX_TEST) return 1;
+       if(ctx != NULL && ctx->flags == CTX_TEST)
+               return 1;
        if(!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
                X509V3err(X509V3_F_COPY_EMAIL,X509V3_R_NO_SUBJECT_DETAILS);
                goto err;
@@ -406,82 +410,126 @@ GENERAL_NAMES *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method,
 
 GENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
                                                         CONF_VALUE *cnf)
-{
-char is_string = 0;
-int type;
-GENERAL_NAME *gen = NULL;
+       {
+       return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
+       }
 
-char *name, *value;
+GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
+                               X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+                                                CONF_VALUE *cnf, int is_nc)
+       {
+       char is_string = 0;
+       int type;
+       GENERAL_NAME *gen = NULL;
 
-name = cnf->name;
-value = cnf->value;
+       char *name, *value;
 
-if(!value) {
-       X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_MISSING_VALUE);
-       return NULL;
-}
+       name = cnf->name;
+       value = cnf->value;
 
-if(!(gen = GENERAL_NAME_new())) {
-       X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE);
-       return NULL;
-}
+       if(!value)
+               {
+               X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_MISSING_VALUE);
+               return NULL;
+               }
 
-if(!name_cmp(name, "email")) {
-       is_string = 1;
-       type = GEN_EMAIL;
-} else if(!name_cmp(name, "URI")) {
-       is_string = 1;
-       type = GEN_URI;
-} else if(!name_cmp(name, "DNS")) {
-       is_string = 1;
-       type = GEN_DNS;
-} else if(!name_cmp(name, "RID")) {
-       ASN1_OBJECT *obj;
-       if(!(obj = OBJ_txt2obj(value,0))) {
-               X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_OBJECT);
-               ERR_add_error_data(2, "value=", value);
-               goto err;
-       }
-       gen->d.rid = obj;
-       type = GEN_RID;
-} else if(!name_cmp(name, "IP")) {
-       if(!(gen->d.ip = a2i_IPADDRESS(value)))
+       if (out)
+               gen = out;
+       else
                {
-               X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_IP_ADDRESS);
-               ERR_add_error_data(2, "value=", value);
-               goto err;
+               gen = GENERAL_NAME_new();
+               if(gen == NULL)
+                       {
+                       X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,ERR_R_MALLOC_FAILURE);
+                       return NULL;
+                       }
+               }
+
+       if(!name_cmp(name, "email"))
+               {
+               is_string = 1;
+               type = GEN_EMAIL;
+               }
+       else if(!name_cmp(name, "URI"))
+               {
+               is_string = 1;
+               type = GEN_URI;
+               }
+       else if(!name_cmp(name, "DNS"))
+               {
+               is_string = 1;
+               type = GEN_DNS;
+               }
+       else if(!name_cmp(name, "RID"))
+               {
+               ASN1_OBJECT *obj;
+               if(!(obj = OBJ_txt2obj(value,0)))
+                       {
+                       X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_BAD_OBJECT);
+                       ERR_add_error_data(2, "value=", value);
+                       goto err;
+                       }
+               gen->d.rid = obj;
+               type = GEN_RID;
                }
-       type = GEN_IPADD;
-} else if(!name_cmp(name, "otherName")) {
-       if (!do_othername(gen, value, ctx))
+       else if(!name_cmp(name, "IP"))
                {
-               X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_OTHERNAME_ERROR);
+               if (is_nc)
+                       gen->d.ip = a2i_IPADDRESS_NC(value);
+               else
+                       gen->d.ip = a2i_IPADDRESS(value);
+               if(gen->d.ip == NULL)
+                       {
+                       X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_BAD_IP_ADDRESS);
+                       ERR_add_error_data(2, "value=", value);
+                       goto err;
+                       }
+               type = GEN_IPADD;
+               }
+       else if(!name_cmp(name, "dirName"))
+               {
+               type = GEN_DIRNAME;
+               if (!do_dirname(gen, value, ctx))
+                       {
+                       X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_DIRNAME_ERROR);
+                       goto err;
+                       }
+               }
+       else if(!name_cmp(name, "otherName"))
+               {
+               if (!do_othername(gen, value, ctx))
+                       {
+                       X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_OTHERNAME_ERROR);
+                       goto err;
+                       }
+               type = GEN_OTHERNAME;
+               }
+       else
+               {
+               X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_UNSUPPORTED_OPTION);
+               ERR_add_error_data(2, "name=", name);
                goto err;
                }
-       type = GEN_OTHERNAME;
-} else {
-       X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_UNSUPPORTED_OPTION);
-       ERR_add_error_data(2, "name=", name);
-       goto err;
-}
 
-if(is_string) {
-       if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
-                     !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value,
-                                      strlen(value))) {
-               X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE);
-               goto err;
-       }
-}
+       if(is_string)
+               {
+               if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
+                             !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value,
+                                              strlen(value)))
+                       {
+                       X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,ERR_R_MALLOC_FAILURE);
+                       goto err;
+                       }
+               }
 
-gen->type = type;
+       gen->type = type;
 
-return gen;
+       return gen;
 
-err:
-GENERAL_NAME_free(gen);
-return NULL;
-}
+       err:
+       GENERAL_NAME_free(gen);
+       return NULL;
+       }
 
 static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
        {
@@ -507,3 +555,27 @@ static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
                return 0;
        return 1;
        }
+
+static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
+       {
+       int ret;
+       STACK_OF(CONF_VALUE) *sk;
+       X509_NAME *nm;
+       if (!(nm = X509_NAME_new()))
+               return 0;
+       sk = X509V3_get_section(ctx, value);
+       if (!sk)
+               {
+               X509V3err(X509V3_F_DO_DIRNAME,X509V3_R_SECTION_NOT_FOUND);
+               ERR_add_error_data(2, "section=", value);
+               X509_NAME_free(nm);
+               return 0;
+               }
+       /* FIXME: should allow other character types... */
+       ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC);
+       if (!ret)
+               X509_NAME_free(nm);
+       gen->d.dirn = nm;
+               
+       return ret;
+       }