Home | History | Annotate | Download | only in x509v3
      1 /* v3_pci.c -*- mode:C; c-file-style: "eay" -*- */
      2 /*
      3  * Contributed to the OpenSSL Project 2004 by Richard Levitte
      4  * (richard (at) levitte.org)
      5  */
      6 /* Copyright (c) 2004 Kungliga Tekniska Hgskolan
      7  * (Royal Institute of Technology, Stockholm, Sweden).
      8  * All rights reserved.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  *
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  *
     17  * 2. Redistributions in binary form must reproduce the above copyright
     18  *    notice, this list of conditions and the following disclaimer in the
     19  *    documentation and/or other materials provided with the distribution.
     20  *
     21  * 3. Neither the name of the Institute nor the names of its contributors
     22  *    may be used to endorse or promote products derived from this software
     23  *    without specific prior written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
     29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     35  * SUCH DAMAGE.
     36  */
     37 
     38 #include <string.h>
     39 
     40 #include <openssl/conf.h>
     41 #include <openssl/err.h>
     42 #include <openssl/mem.h>
     43 #include <openssl/obj.h>
     44 #include <openssl/x509v3.h>
     45 
     46 #include "../internal.h"
     47 
     48 
     49 static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *ext,
     50                    BIO *out, int indent);
     51 static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
     52                                           X509V3_CTX *ctx, char *str);
     53 
     54 const X509V3_EXT_METHOD v3_pci =
     55     { NID_proxyCertInfo, 0, ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION),
     56     0, 0, 0, 0,
     57     0, 0,
     58     NULL, NULL,
     59     (X509V3_EXT_I2R)i2r_pci,
     60     (X509V3_EXT_R2I)r2i_pci,
     61     NULL,
     62 };
     63 
     64 static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *pci,
     65                    BIO *out, int indent)
     66 {
     67     BIO_printf(out, "%*sPath Length Constraint: ", indent, "");
     68     if (pci->pcPathLengthConstraint)
     69         i2a_ASN1_INTEGER(out, pci->pcPathLengthConstraint);
     70     else
     71         BIO_printf(out, "infinite");
     72     BIO_puts(out, "\n");
     73     BIO_printf(out, "%*sPolicy Language: ", indent, "");
     74     i2a_ASN1_OBJECT(out, pci->proxyPolicy->policyLanguage);
     75     BIO_puts(out, "\n");
     76     if (pci->proxyPolicy->policy && pci->proxyPolicy->policy->data)
     77         BIO_printf(out, "%*sPolicy Text: %s\n", indent, "",
     78                    pci->proxyPolicy->policy->data);
     79     return 1;
     80 }
     81 
     82 static int process_pci_value(CONF_VALUE *val,
     83                              ASN1_OBJECT **language, ASN1_INTEGER **pathlen,
     84                              ASN1_OCTET_STRING **policy)
     85 {
     86     int free_policy = 0;
     87 
     88     if (strcmp(val->name, "language") == 0) {
     89         if (*language) {
     90             OPENSSL_PUT_ERROR(X509V3,
     91                               X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED);
     92             X509V3_conf_err(val);
     93             return 0;
     94         }
     95         if (!(*language = OBJ_txt2obj(val->value, 0))) {
     96             OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
     97             X509V3_conf_err(val);
     98             return 0;
     99         }
    100     } else if (strcmp(val->name, "pathlen") == 0) {
    101         if (*pathlen) {
    102             OPENSSL_PUT_ERROR(X509V3,
    103                               X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED);
    104             X509V3_conf_err(val);
    105             return 0;
    106         }
    107         if (!X509V3_get_value_int(val, pathlen)) {
    108             OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_PATH_LENGTH);
    109             X509V3_conf_err(val);
    110             return 0;
    111         }
    112     } else if (strcmp(val->name, "policy") == 0) {
    113         unsigned char *tmp_data = NULL;
    114         long val_len;
    115         if (!*policy) {
    116             *policy = ASN1_OCTET_STRING_new();
    117             if (!*policy) {
    118                 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
    119                 X509V3_conf_err(val);
    120                 return 0;
    121             }
    122             free_policy = 1;
    123         }
    124         if (strncmp(val->value, "hex:", 4) == 0) {
    125             unsigned char *tmp_data2 =
    126                 string_to_hex(val->value + 4, &val_len);
    127 
    128             if (!tmp_data2) {
    129                 OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT);
    130                 X509V3_conf_err(val);
    131                 goto err;
    132             }
    133 
    134             tmp_data = OPENSSL_realloc((*policy)->data,
    135                                        (*policy)->length + val_len + 1);
    136             if (tmp_data) {
    137                 (*policy)->data = tmp_data;
    138                 OPENSSL_memcpy(&(*policy)->data[(*policy)->length],
    139                        tmp_data2, val_len);
    140                 (*policy)->length += val_len;
    141                 (*policy)->data[(*policy)->length] = '\0';
    142             } else {
    143                 OPENSSL_free(tmp_data2);
    144                 /*
    145                  * realloc failure implies the original data space is b0rked
    146                  * too!
    147                  */
    148                 (*policy)->data = NULL;
    149                 (*policy)->length = 0;
    150                 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
    151                 X509V3_conf_err(val);
    152                 goto err;
    153             }
    154             OPENSSL_free(tmp_data2);
    155         } else if (strncmp(val->value, "text:", 5) == 0) {
    156             val_len = strlen(val->value + 5);
    157             tmp_data = OPENSSL_realloc((*policy)->data,
    158                                        (*policy)->length + val_len + 1);
    159             if (tmp_data) {
    160                 (*policy)->data = tmp_data;
    161                 OPENSSL_memcpy(&(*policy)->data[(*policy)->length],
    162                        val->value + 5, val_len);
    163                 (*policy)->length += val_len;
    164                 (*policy)->data[(*policy)->length] = '\0';
    165             } else {
    166                 /*
    167                  * realloc failure implies the original data space is b0rked
    168                  * too!
    169                  */
    170                 (*policy)->data = NULL;
    171                 (*policy)->length = 0;
    172                 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
    173                 X509V3_conf_err(val);
    174                 goto err;
    175             }
    176         } else {
    177             OPENSSL_PUT_ERROR(X509V3, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG);
    178             X509V3_conf_err(val);
    179             goto err;
    180         }
    181         if (!tmp_data) {
    182             OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
    183             X509V3_conf_err(val);
    184             goto err;
    185         }
    186     }
    187     return 1;
    188  err:
    189     if (free_policy) {
    190         ASN1_OCTET_STRING_free(*policy);
    191         *policy = NULL;
    192     }
    193     return 0;
    194 }
    195 
    196 static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
    197                                           X509V3_CTX *ctx, char *value)
    198 {
    199     PROXY_CERT_INFO_EXTENSION *pci = NULL;
    200     STACK_OF(CONF_VALUE) *vals;
    201     ASN1_OBJECT *language = NULL;
    202     ASN1_INTEGER *pathlen = NULL;
    203     ASN1_OCTET_STRING *policy = NULL;
    204     size_t i, j;
    205     int nid;
    206 
    207     vals = X509V3_parse_list(value);
    208     for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
    209         CONF_VALUE *cnf = sk_CONF_VALUE_value(vals, i);
    210         if (!cnf->name || (*cnf->name != '@' && !cnf->value)) {
    211             OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PROXY_POLICY_SETTING);
    212             X509V3_conf_err(cnf);
    213             goto err;
    214         }
    215         if (*cnf->name == '@') {
    216             STACK_OF(CONF_VALUE) *sect;
    217             int success_p = 1;
    218 
    219             sect = X509V3_get_section(ctx, cnf->name + 1);
    220             if (!sect) {
    221                 OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION);
    222                 X509V3_conf_err(cnf);
    223                 goto err;
    224             }
    225             for (j = 0; success_p && j < sk_CONF_VALUE_num(sect); j++) {
    226                 success_p =
    227                     process_pci_value(sk_CONF_VALUE_value(sect, j),
    228                                       &language, &pathlen, &policy);
    229             }
    230             X509V3_section_free(ctx, sect);
    231             if (!success_p)
    232                 goto err;
    233         } else {
    234             if (!process_pci_value(cnf, &language, &pathlen, &policy)) {
    235                 X509V3_conf_err(cnf);
    236                 goto err;
    237             }
    238         }
    239     }
    240 
    241     /* Language is mandatory */
    242     if (!language) {
    243         OPENSSL_PUT_ERROR(X509V3,
    244                           X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED);
    245         goto err;
    246     }
    247     nid = OBJ_obj2nid(language);
    248     if ((nid == NID_Independent || nid == NID_id_ppl_inheritAll) && policy) {
    249         OPENSSL_PUT_ERROR(X509V3,
    250                           X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY);
    251         goto err;
    252     }
    253 
    254     pci = PROXY_CERT_INFO_EXTENSION_new();
    255     if (!pci) {
    256         OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
    257         goto err;
    258     }
    259 
    260     pci->proxyPolicy->policyLanguage = language;
    261     language = NULL;
    262     pci->proxyPolicy->policy = policy;
    263     policy = NULL;
    264     pci->pcPathLengthConstraint = pathlen;
    265     pathlen = NULL;
    266     goto end;
    267  err:
    268     if (language) {
    269         ASN1_OBJECT_free(language);
    270         language = NULL;
    271     }
    272     if (pathlen) {
    273         ASN1_INTEGER_free(pathlen);
    274         pathlen = NULL;
    275     }
    276     if (policy) {
    277         ASN1_OCTET_STRING_free(policy);
    278         policy = NULL;
    279     }
    280     if (pci) {
    281         PROXY_CERT_INFO_EXTENSION_free(pci);
    282         pci = NULL;
    283     }
    284  end:
    285     sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
    286     return pci;
    287 }
    288