1 /* v3_pci.c -*- mode:C; c-file-style: "eay" -*- */
2 /* Contributed to the OpenSSL Project 2004
3 * by Richard Levitte (richard@levitte.org)
4 */
5 /* Copyright (c) 2004 Kungliga Tekniska Högskolan
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
i2r_pci(X509V3_EXT_METHOD * method,PROXY_CERT_INFO_EXTENSION * pci,BIO * out,int indent)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
process_pci_value(CONF_VALUE * val,ASN1_OBJECT ** language,ASN1_INTEGER ** pathlen,ASN1_OCTET_STRING ** policy)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
r2i_pci(X509V3_EXT_METHOD * method,X509V3_CTX * ctx,char * value)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