Home | History | Annotate | Download | only in x509v3
      1 /* v3_conf.c */
      2 /*
      3  * Written by Dr Stephen N Henson (steve (at) openssl.org) for the OpenSSL project
      4  * 1999.
      5  */
      6 /* ====================================================================
      7  * Copyright (c) 1999-2002 The OpenSSL Project.  All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  *
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  *
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in
     18  *    the documentation and/or other materials provided with the
     19  *    distribution.
     20  *
     21  * 3. All advertising materials mentioning features or use of this
     22  *    software must display the following acknowledgment:
     23  *    "This product includes software developed by the OpenSSL Project
     24  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
     25  *
     26  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     27  *    endorse or promote products derived from this software without
     28  *    prior written permission. For written permission, please contact
     29  *    licensing (at) OpenSSL.org.
     30  *
     31  * 5. Products derived from this software may not be called "OpenSSL"
     32  *    nor may "OpenSSL" appear in their names without prior written
     33  *    permission of the OpenSSL Project.
     34  *
     35  * 6. Redistributions of any form whatsoever must retain the following
     36  *    acknowledgment:
     37  *    "This product includes software developed by the OpenSSL Project
     38  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
     39  *
     40  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     41  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     46  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     47  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     49  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     51  * OF THE POSSIBILITY OF SUCH DAMAGE.
     52  * ====================================================================
     53  *
     54  * This product includes cryptographic software written by Eric Young
     55  * (eay (at) cryptsoft.com).  This product includes software written by Tim
     56  * Hudson (tjh (at) cryptsoft.com). */
     57 
     58 /* extension creation utilities */
     59 
     60 #include <ctype.h>
     61 #include <stdio.h>
     62 #include <string.h>
     63 
     64 #include <openssl/conf.h>
     65 #include <openssl/err.h>
     66 #include <openssl/mem.h>
     67 #include <openssl/obj.h>
     68 #include <openssl/x509.h>
     69 #include <openssl/x509v3.h>
     70 
     71 #include "../internal.h"
     72 #include "internal.h"
     73 
     74 static int v3_check_critical(char **value);
     75 static int v3_check_generic(char **value);
     76 static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
     77                                     int crit, char *value);
     78 static X509_EXTENSION *v3_generic_extension(const char *ext, char *value,
     79                                             int crit, int type,
     80                                             X509V3_CTX *ctx);
     81 static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method,
     82                                   int ext_nid, int crit, void *ext_struc);
     83 static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx,
     84                                    long *ext_len);
     85 /* CONF *conf:  Config file    */
     86 /* char *name:  Name    */
     87 /* char *value:  Value    */
     88 X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name,
     89                                  char *value)
     90 {
     91     int crit;
     92     int ext_type;
     93     X509_EXTENSION *ret;
     94     crit = v3_check_critical(&value);
     95     if ((ext_type = v3_check_generic(&value)))
     96         return v3_generic_extension(name, value, crit, ext_type, ctx);
     97     ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value);
     98     if (!ret) {
     99         OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_IN_EXTENSION);
    100         ERR_add_error_data(4, "name=", name, ", value=", value);
    101     }
    102     return ret;
    103 }
    104 
    105 /* CONF *conf:  Config file    */
    106 /* char *value:  Value    */
    107 X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid,
    108                                      char *value)
    109 {
    110     int crit;
    111     int ext_type;
    112     crit = v3_check_critical(&value);
    113     if ((ext_type = v3_check_generic(&value)))
    114         return v3_generic_extension(OBJ_nid2sn(ext_nid),
    115                                     value, crit, ext_type, ctx);
    116     return do_ext_nconf(conf, ctx, ext_nid, crit, value);
    117 }
    118 
    119 /* CONF *conf:  Config file    */
    120 /* char *value:  Value    */
    121 static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
    122                                     int crit, char *value)
    123 {
    124     const X509V3_EXT_METHOD *method;
    125     X509_EXTENSION *ext;
    126     STACK_OF(CONF_VALUE) *nval;
    127     void *ext_struc;
    128     if (ext_nid == NID_undef) {
    129         OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION_NAME);
    130         return NULL;
    131     }
    132     if (!(method = X509V3_EXT_get_nid(ext_nid))) {
    133         OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION);
    134         return NULL;
    135     }
    136     /* Now get internal extension representation based on type */
    137     if (method->v2i) {
    138         if (*value == '@')
    139             nval = NCONF_get_section(conf, value + 1);
    140         else
    141             nval = X509V3_parse_list(value);
    142         if (nval == NULL || sk_CONF_VALUE_num(nval) <= 0) {
    143             OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_EXTENSION_STRING);
    144             ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=",
    145                                value);
    146             if (*value != '@')
    147                 sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
    148             return NULL;
    149         }
    150         ext_struc = method->v2i(method, ctx, nval);
    151         if (*value != '@')
    152             sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
    153         if (!ext_struc)
    154             return NULL;
    155     } else if (method->s2i) {
    156         if (!(ext_struc = method->s2i(method, ctx, value)))
    157             return NULL;
    158     } else if (method->r2i) {
    159         if (!ctx->db || !ctx->db_meth) {
    160             OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_CONFIG_DATABASE);
    161             return NULL;
    162         }
    163         if (!(ext_struc = method->r2i(method, ctx, value)))
    164             return NULL;
    165     } else {
    166         OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED);
    167         ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid));
    168         return NULL;
    169     }
    170 
    171     ext = do_ext_i2d(method, ext_nid, crit, ext_struc);
    172     if (method->it)
    173         ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it));
    174     else
    175         method->ext_free(ext_struc);
    176     return ext;
    177 
    178 }
    179 
    180 static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method,
    181                                   int ext_nid, int crit, void *ext_struc)
    182 {
    183     unsigned char *ext_der;
    184     int ext_len;
    185     ASN1_OCTET_STRING *ext_oct;
    186     X509_EXTENSION *ext;
    187     /* Convert internal representation to DER */
    188     if (method->it) {
    189         ext_der = NULL;
    190         ext_len =
    191             ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it));
    192         if (ext_len < 0)
    193             goto merr;
    194     } else {
    195         unsigned char *p;
    196         ext_len = method->i2d(ext_struc, NULL);
    197         if (!(ext_der = OPENSSL_malloc(ext_len)))
    198             goto merr;
    199         p = ext_der;
    200         method->i2d(ext_struc, &p);
    201     }
    202     if (!(ext_oct = M_ASN1_OCTET_STRING_new()))
    203         goto merr;
    204     ext_oct->data = ext_der;
    205     ext_oct->length = ext_len;
    206 
    207     ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct);
    208     if (!ext)
    209         goto merr;
    210     M_ASN1_OCTET_STRING_free(ext_oct);
    211 
    212     return ext;
    213 
    214  merr:
    215     OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
    216     return NULL;
    217 
    218 }
    219 
    220 /* Given an internal structure, nid and critical flag create an extension */
    221 
    222 X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc)
    223 {
    224     const X509V3_EXT_METHOD *method;
    225     if (!(method = X509V3_EXT_get_nid(ext_nid))) {
    226         OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION);
    227         return NULL;
    228     }
    229     return do_ext_i2d(method, ext_nid, crit, ext_struc);
    230 }
    231 
    232 /* Check the extension string for critical flag */
    233 static int v3_check_critical(char **value)
    234 {
    235     char *p = *value;
    236     if ((strlen(p) < 9) || strncmp(p, "critical,", 9))
    237         return 0;
    238     p += 9;
    239     while (isspace((unsigned char)*p))
    240         p++;
    241     *value = p;
    242     return 1;
    243 }
    244 
    245 /* Check extension string for generic extension and return the type */
    246 static int v3_check_generic(char **value)
    247 {
    248     int gen_type = 0;
    249     char *p = *value;
    250     if ((strlen(p) >= 4) && !strncmp(p, "DER:", 4)) {
    251         p += 4;
    252         gen_type = 1;
    253     } else if ((strlen(p) >= 5) && !strncmp(p, "ASN1:", 5)) {
    254         p += 5;
    255         gen_type = 2;
    256     } else
    257         return 0;
    258 
    259     while (isspace((unsigned char)*p))
    260         p++;
    261     *value = p;
    262     return gen_type;
    263 }
    264 
    265 /* Create a generic extension: for now just handle DER type */
    266 static X509_EXTENSION *v3_generic_extension(const char *ext, char *value,
    267                                             int crit, int gen_type,
    268                                             X509V3_CTX *ctx)
    269 {
    270     unsigned char *ext_der = NULL;
    271     long ext_len = 0;
    272     ASN1_OBJECT *obj = NULL;
    273     ASN1_OCTET_STRING *oct = NULL;
    274     X509_EXTENSION *extension = NULL;
    275     if (!(obj = OBJ_txt2obj(ext, 0))) {
    276         OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NAME_ERROR);
    277         ERR_add_error_data(2, "name=", ext);
    278         goto err;
    279     }
    280 
    281     if (gen_type == 1)
    282         ext_der = x509v3_hex_to_bytes(value, &ext_len);
    283     else if (gen_type == 2)
    284         ext_der = generic_asn1(value, ctx, &ext_len);
    285 
    286     if (ext_der == NULL) {
    287         OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
    288         ERR_add_error_data(2, "value=", value);
    289         goto err;
    290     }
    291 
    292     if (!(oct = M_ASN1_OCTET_STRING_new())) {
    293         OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
    294         goto err;
    295     }
    296 
    297     oct->data = ext_der;
    298     oct->length = ext_len;
    299     ext_der = NULL;
    300 
    301     extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct);
    302 
    303  err:
    304     ASN1_OBJECT_free(obj);
    305     M_ASN1_OCTET_STRING_free(oct);
    306     if (ext_der)
    307         OPENSSL_free(ext_der);
    308     return extension;
    309 
    310 }
    311 
    312 static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx,
    313                                    long *ext_len)
    314 {
    315     ASN1_TYPE *typ;
    316     unsigned char *ext_der = NULL;
    317     typ = ASN1_generate_v3(value, ctx);
    318     if (typ == NULL)
    319         return NULL;
    320     *ext_len = i2d_ASN1_TYPE(typ, &ext_der);
    321     ASN1_TYPE_free(typ);
    322     return ext_der;
    323 }
    324 
    325 /*
    326  * This is the main function: add a bunch of extensions based on a config
    327  * file section to an extension STACK.
    328  */
    329 
    330 int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section,
    331                             STACK_OF(X509_EXTENSION) **sk)
    332 {
    333     X509_EXTENSION *ext;
    334     STACK_OF(CONF_VALUE) *nval;
    335     CONF_VALUE *val;
    336     size_t i;
    337     if (!(nval = NCONF_get_section(conf, section)))
    338         return 0;
    339     for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
    340         val = sk_CONF_VALUE_value(nval, i);
    341         if (!(ext = X509V3_EXT_nconf(conf, ctx, val->name, val->value)))
    342             return 0;
    343         if (sk)
    344             X509v3_add_ext(sk, ext, -1);
    345         X509_EXTENSION_free(ext);
    346     }
    347     return 1;
    348 }
    349 
    350 /*
    351  * Convenience functions to add extensions to a certificate, CRL and request
    352  */
    353 
    354 int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section,
    355                          X509 *cert)
    356 {
    357     STACK_OF(X509_EXTENSION) **sk = NULL;
    358     if (cert)
    359         sk = &cert->cert_info->extensions;
    360     return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
    361 }
    362 
    363 /* Same as above but for a CRL */
    364 
    365 int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section,
    366                              X509_CRL *crl)
    367 {
    368     STACK_OF(X509_EXTENSION) **sk = NULL;
    369     if (crl)
    370         sk = &crl->crl->extensions;
    371     return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
    372 }
    373 
    374 /* Add extensions to certificate request */
    375 
    376 int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section,
    377                              X509_REQ *req)
    378 {
    379     STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL;
    380     int i;
    381     if (req)
    382         sk = &extlist;
    383     i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
    384     if (!i || !sk)
    385         return i;
    386     i = X509_REQ_add_extensions(req, extlist);
    387     sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free);
    388     return i;
    389 }
    390 
    391 /* Config database functions */
    392 
    393 char *X509V3_get_string(X509V3_CTX *ctx, char *name, char *section)
    394 {
    395     if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_string) {
    396         OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED);
    397         return NULL;
    398     }
    399     if (ctx->db_meth->get_string)
    400         return ctx->db_meth->get_string(ctx->db, name, section);
    401     return NULL;
    402 }
    403 
    404 STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, char *section)
    405 {
    406     if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section) {
    407         OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED);
    408         return NULL;
    409     }
    410     if (ctx->db_meth->get_section)
    411         return ctx->db_meth->get_section(ctx->db, section);
    412     return NULL;
    413 }
    414 
    415 void X509V3_string_free(X509V3_CTX *ctx, char *str)
    416 {
    417     if (!str)
    418         return;
    419     if (ctx->db_meth->free_string)
    420         ctx->db_meth->free_string(ctx->db, str);
    421 }
    422 
    423 void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section)
    424 {
    425     if (!section)
    426         return;
    427     if (ctx->db_meth->free_section)
    428         ctx->db_meth->free_section(ctx->db, section);
    429 }
    430 
    431 static char *nconf_get_string(void *db, char *section, char *value)
    432 {
    433     /* TODO(fork): this should return a const value. */
    434     return (char *)NCONF_get_string(db, section, value);
    435 }
    436 
    437 static STACK_OF(CONF_VALUE) *nconf_get_section(void *db, char *section)
    438 {
    439     return NCONF_get_section(db, section);
    440 }
    441 
    442 static const X509V3_CONF_METHOD nconf_method = {
    443     nconf_get_string,
    444     nconf_get_section,
    445     NULL,
    446     NULL
    447 };
    448 
    449 void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf)
    450 {
    451     ctx->db_meth = &nconf_method;
    452     ctx->db = conf;
    453 }
    454 
    455 void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req,
    456                     X509_CRL *crl, int flags)
    457 {
    458     ctx->issuer_cert = issuer;
    459     ctx->subject_cert = subj;
    460     ctx->crl = crl;
    461     ctx->subject_req = req;
    462     ctx->flags = flags;
    463 }
    464