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