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