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 #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 
     47 static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *ext,
     48 	BIO *out, int indent);
     49 static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
     50 	X509V3_CTX *ctx, char *str);
     51 
     52 const X509V3_EXT_METHOD v3_pci =
     53 	{ NID_proxyCertInfo, 0, ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION),
     54 	  0,0,0,0,
     55 	  0,0,
     56 	  NULL, NULL,
     57 	  (X509V3_EXT_I2R)i2r_pci,
     58 	  (X509V3_EXT_R2I)r2i_pci,
     59 	  NULL,
     60 	};
     61 
     62 static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *pci,
     63 	BIO *out, int indent)
     64 	{
     65 	BIO_printf(out, "%*sPath Length Constraint: ", indent, "");
     66 	if (pci->pcPathLengthConstraint)
     67 	  i2a_ASN1_INTEGER(out, pci->pcPathLengthConstraint);
     68 	else
     69 	  BIO_printf(out, "infinite");
     70 	BIO_puts(out, "\n");
     71 	BIO_printf(out, "%*sPolicy Language: ", indent, "");
     72 	i2a_ASN1_OBJECT(out, pci->proxyPolicy->policyLanguage);
     73 	BIO_puts(out, "\n");
     74 	if (pci->proxyPolicy->policy && pci->proxyPolicy->policy->data)
     75 	  BIO_printf(out, "%*sPolicy Text: %s\n", indent, "",
     76 		     pci->proxyPolicy->policy->data);
     77 	return 1;
     78 	}
     79 
     80 static int process_pci_value(CONF_VALUE *val,
     81 	ASN1_OBJECT **language, ASN1_INTEGER **pathlen,
     82 	ASN1_OCTET_STRING **policy)
     83 	{
     84 	int free_policy = 0;
     85 
     86 	if (strcmp(val->name, "language") == 0)
     87 		{
     88 		if (*language)
     89 			{
     90 			OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED);
     91 			X509V3_conf_err(val);
     92 			return 0;
     93 			}
     94 		if (!(*language = OBJ_txt2obj(val->value, 0)))
     95 			{
     96 			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
     97 			X509V3_conf_err(val);
     98 			return 0;
     99 			}
    100 		}
    101 	else if (strcmp(val->name, "pathlen") == 0)
    102 		{
    103 		if (*pathlen)
    104 			{
    105 			OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED);
    106 			X509V3_conf_err(val);
    107 			return 0;
    108 			}
    109 		if (!X509V3_get_value_int(val, pathlen))
    110 			{
    111 			OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_PATH_LENGTH);
    112 			X509V3_conf_err(val);
    113 			return 0;
    114 			}
    115 		}
    116 	else if (strcmp(val->name, "policy") == 0)
    117 		{
    118 		unsigned char *tmp_data = NULL;
    119 		long val_len;
    120 		if (!*policy)
    121 			{
    122 			*policy = ASN1_OCTET_STRING_new();
    123 			if (!*policy)
    124 				{
    125 				OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
    126 				X509V3_conf_err(val);
    127 				return 0;
    128 				}
    129 			free_policy = 1;
    130 			}
    131 		if (strncmp(val->value, "hex:", 4) == 0)
    132 			{
    133 			unsigned char *tmp_data2 =
    134 				string_to_hex(val->value + 4, &val_len);
    135 
    136 			if (!tmp_data2)
    137 				{
    138 				OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT);
    139 				X509V3_conf_err(val);
    140 				goto err;
    141 				}
    142 
    143 			tmp_data = OPENSSL_realloc((*policy)->data,
    144 				(*policy)->length + val_len + 1);
    145 			if (tmp_data)
    146 				{
    147 				(*policy)->data = tmp_data;
    148 				memcpy(&(*policy)->data[(*policy)->length],
    149 					tmp_data2, val_len);
    150 				(*policy)->length += val_len;
    151 				(*policy)->data[(*policy)->length] = '\0';
    152 				}
    153 			else
    154 				{
    155 				OPENSSL_free(tmp_data2);
    156 				/* realloc failure implies the original data space is b0rked too! */
    157 				(*policy)->data = NULL;
    158 				(*policy)->length = 0;
    159 				OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
    160 				X509V3_conf_err(val);
    161 				goto err;
    162 				}
    163 			OPENSSL_free(tmp_data2);
    164 			}
    165 		else if (strncmp(val->value, "file:", 5) == 0)
    166 			{
    167 			unsigned char buf[2048];
    168 			int n;
    169 			BIO *b = BIO_new_file(val->value + 5, "r");
    170 			if (!b)
    171 				{
    172 				OPENSSL_PUT_ERROR(X509V3, ERR_R_BIO_LIB);
    173 				X509V3_conf_err(val);
    174 				goto err;
    175 				}
    176 			while((n = BIO_read(b, buf, sizeof(buf))) > 0
    177 				|| (n == 0 && BIO_should_retry(b)))
    178 				{
    179 				if (!n) continue;
    180 
    181 				tmp_data = OPENSSL_realloc((*policy)->data,
    182 					(*policy)->length + n + 1);
    183 
    184 				if (!tmp_data)
    185 					break;
    186 
    187 				(*policy)->data = tmp_data;
    188 				memcpy(&(*policy)->data[(*policy)->length],
    189 					buf, n);
    190 				(*policy)->length += n;
    191 				(*policy)->data[(*policy)->length] = '\0';
    192 				}
    193 			BIO_free_all(b);
    194 
    195 			if (n < 0)
    196 				{
    197 				OPENSSL_PUT_ERROR(X509V3, ERR_R_BIO_LIB);
    198 				X509V3_conf_err(val);
    199 				goto err;
    200 				}
    201 			}
    202 		else if (strncmp(val->value, "text:", 5) == 0)
    203 			{
    204 			val_len = strlen(val->value + 5);
    205 			tmp_data = OPENSSL_realloc((*policy)->data,
    206 				(*policy)->length + val_len + 1);
    207 			if (tmp_data)
    208 				{
    209 				(*policy)->data = tmp_data;
    210 				memcpy(&(*policy)->data[(*policy)->length],
    211 					val->value + 5, val_len);
    212 				(*policy)->length += val_len;
    213 				(*policy)->data[(*policy)->length] = '\0';
    214 				}
    215 			else
    216 				{
    217 				/* realloc failure implies the original data space is b0rked too! */
    218 				(*policy)->data = NULL;
    219 				(*policy)->length = 0;
    220 				OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
    221 				X509V3_conf_err(val);
    222 				goto err;
    223 				}
    224 			}
    225 		else
    226 			{
    227 			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG);
    228 			X509V3_conf_err(val);
    229 			goto err;
    230 			}
    231 		if (!tmp_data)
    232 			{
    233 			OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
    234 			X509V3_conf_err(val);
    235 			goto err;
    236 			}
    237 		}
    238 	return 1;
    239 err:
    240 	if (free_policy)
    241 		{
    242 		ASN1_OCTET_STRING_free(*policy);
    243 		*policy = NULL;
    244 		}
    245 	return 0;
    246 	}
    247 
    248 static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
    249 	X509V3_CTX *ctx, char *value)
    250 	{
    251 	PROXY_CERT_INFO_EXTENSION *pci = NULL;
    252 	STACK_OF(CONF_VALUE) *vals;
    253 	ASN1_OBJECT *language = NULL;
    254 	ASN1_INTEGER *pathlen = NULL;
    255 	ASN1_OCTET_STRING *policy = NULL;
    256 	size_t i, j;
    257 	int nid;
    258 
    259 	vals = X509V3_parse_list(value);
    260 	for (i = 0; i < sk_CONF_VALUE_num(vals); i++)
    261 		{
    262 		CONF_VALUE *cnf = sk_CONF_VALUE_value(vals, i);
    263 		if (!cnf->name || (*cnf->name != '@' && !cnf->value))
    264 			{
    265 			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PROXY_POLICY_SETTING);
    266 			X509V3_conf_err(cnf);
    267 			goto err;
    268 			}
    269 		if (*cnf->name == '@')
    270 			{
    271 			STACK_OF(CONF_VALUE) *sect;
    272 			int success_p = 1;
    273 
    274 			sect = X509V3_get_section(ctx, cnf->name + 1);
    275 			if (!sect)
    276 				{
    277 				OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION);
    278 				X509V3_conf_err(cnf);
    279 				goto err;
    280 				}
    281 			for (j = 0; success_p && j < sk_CONF_VALUE_num(sect); j++)
    282 				{
    283 				success_p =
    284 					process_pci_value(sk_CONF_VALUE_value(sect, j),
    285 						&language, &pathlen, &policy);
    286 				}
    287 			X509V3_section_free(ctx, sect);
    288 			if (!success_p)
    289 				goto err;
    290 			}
    291 		else
    292 			{
    293 			if (!process_pci_value(cnf,
    294 					&language, &pathlen, &policy))
    295 				{
    296 				X509V3_conf_err(cnf);
    297 				goto err;
    298 				}
    299 			}
    300 		}
    301 
    302 	/* Language is mandatory */
    303 	if (!language)
    304 		{
    305 		OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED);
    306 		goto err;
    307 		}
    308 	nid = OBJ_obj2nid(language);
    309 	if ((nid == NID_Independent || nid == NID_id_ppl_inheritAll) && policy)
    310 		{
    311 		OPENSSL_PUT_ERROR(X509V3,
    312 			X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY);
    313 		goto err;
    314 		}
    315 
    316 	pci = PROXY_CERT_INFO_EXTENSION_new();
    317 	if (!pci)
    318 		{
    319 		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
    320 		goto err;
    321 		}
    322 
    323 	pci->proxyPolicy->policyLanguage = language; language = NULL;
    324 	pci->proxyPolicy->policy = policy; policy = NULL;
    325 	pci->pcPathLengthConstraint = pathlen; pathlen = NULL;
    326 	goto end;
    327 err:
    328 	if (language) { ASN1_OBJECT_free(language); language = NULL; }
    329 	if (pathlen) { ASN1_INTEGER_free(pathlen); pathlen = NULL; }
    330 	if (policy) { ASN1_OCTET_STRING_free(policy); policy = NULL; }
    331 	if (pci) { PROXY_CERT_INFO_EXTENSION_free(pci); pci = NULL; }
    332 end:
    333 	sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
    334 	return pci;
    335 	}
    336