1 /* v3_conf.c */
2 /*
3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4 * 1999.
5 */
6 /* ====================================================================
7 * Copyright (c) 1999-2002 The OpenSSL Project. 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
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. All advertising materials mentioning features or use of this
22 * software must display the following acknowledgment:
23 * "This product includes software developed by the OpenSSL Project
24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 *
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 * endorse or promote products derived from this software without
28 * prior written permission. For written permission, please contact
29 * licensing@OpenSSL.org.
30 *
31 * 5. Products derived from this software may not be called "OpenSSL"
32 * nor may "OpenSSL" appear in their names without prior written
33 * permission of the OpenSSL Project.
34 *
35 * 6. Redistributions of any form whatsoever must retain the following
36 * acknowledgment:
37 * "This product includes software developed by the OpenSSL Project
38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
53 *
54 * This product includes cryptographic software written by Eric Young
55 * (eay@cryptsoft.com). This product includes software written by Tim
56 * Hudson (tjh@cryptsoft.com). */
57
58 /* extension creation utilities */
59
60 #include <ctype.h>
61 #include <stdio.h>
62 #include <string.h>
63
64 #include <openssl/conf.h>
65 #include <openssl/err.h>
66 #include <openssl/mem.h>
67 #include <openssl/obj.h>
68 #include <openssl/x509.h>
69 #include <openssl/x509v3.h>
70
71 #include "../internal.h"
72
73 static int v3_check_critical(char **value);
74 static int v3_check_generic(char **value);
75 static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
76 int crit, char *value);
77 static X509_EXTENSION *v3_generic_extension(const char *ext, char *value,
78 int crit, int type,
79 X509V3_CTX *ctx);
80 static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method,
81 int ext_nid, int crit, void *ext_struc);
82 static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx,
83 long *ext_len);
84 /* CONF *conf: Config file */
85 /* char *name: Name */
86 /* char *value: Value */
X509V3_EXT_nconf(CONF * conf,X509V3_CTX * ctx,char * name,char * value)87 X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name,
88 char *value)
89 {
90 int crit;
91 int ext_type;
92 X509_EXTENSION *ret;
93 crit = v3_check_critical(&value);
94 if ((ext_type = v3_check_generic(&value)))
95 return v3_generic_extension(name, value, crit, ext_type, ctx);
96 ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value);
97 if (!ret) {
98 OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_IN_EXTENSION);
99 ERR_add_error_data(4, "name=", name, ", value=", value);
100 }
101 return ret;
102 }
103
104 /* CONF *conf: Config file */
105 /* char *value: Value */
X509V3_EXT_nconf_nid(CONF * conf,X509V3_CTX * ctx,int ext_nid,char * value)106 X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid,
107 char *value)
108 {
109 int crit;
110 int ext_type;
111 crit = v3_check_critical(&value);
112 if ((ext_type = v3_check_generic(&value)))
113 return v3_generic_extension(OBJ_nid2sn(ext_nid),
114 value, crit, ext_type, ctx);
115 return do_ext_nconf(conf, ctx, ext_nid, crit, value);
116 }
117
118 /* CONF *conf: Config file */
119 /* char *value: Value */
do_ext_nconf(CONF * conf,X509V3_CTX * ctx,int ext_nid,int crit,char * value)120 static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
121 int crit, char *value)
122 {
123 const X509V3_EXT_METHOD *method;
124 X509_EXTENSION *ext;
125 STACK_OF(CONF_VALUE) *nval;
126 void *ext_struc;
127 if (ext_nid == NID_undef) {
128 OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION_NAME);
129 return NULL;
130 }
131 if (!(method = X509V3_EXT_get_nid(ext_nid))) {
132 OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION);
133 return NULL;
134 }
135 /* Now get internal extension representation based on type */
136 if (method->v2i) {
137 if (*value == '@')
138 nval = NCONF_get_section(conf, value + 1);
139 else
140 nval = X509V3_parse_list(value);
141 if (nval == NULL || sk_CONF_VALUE_num(nval) <= 0) {
142 OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_EXTENSION_STRING);
143 ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=",
144 value);
145 if (*value != '@')
146 sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
147 return NULL;
148 }
149 ext_struc = method->v2i(method, ctx, nval);
150 if (*value != '@')
151 sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
152 if (!ext_struc)
153 return NULL;
154 } else if (method->s2i) {
155 if (!(ext_struc = method->s2i(method, ctx, value)))
156 return NULL;
157 } else if (method->r2i) {
158 if (!ctx->db || !ctx->db_meth) {
159 OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_CONFIG_DATABASE);
160 return NULL;
161 }
162 if (!(ext_struc = method->r2i(method, ctx, value)))
163 return NULL;
164 } else {
165 OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED);
166 ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid));
167 return NULL;
168 }
169
170 ext = do_ext_i2d(method, ext_nid, crit, ext_struc);
171 if (method->it)
172 ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it));
173 else
174 method->ext_free(ext_struc);
175 return ext;
176
177 }
178
do_ext_i2d(const X509V3_EXT_METHOD * method,int ext_nid,int crit,void * ext_struc)179 static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method,
180 int ext_nid, int crit, void *ext_struc)
181 {
182 unsigned char *ext_der;
183 int ext_len;
184 ASN1_OCTET_STRING *ext_oct;
185 X509_EXTENSION *ext;
186 /* Convert internal representation to DER */
187 if (method->it) {
188 ext_der = NULL;
189 ext_len =
190 ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it));
191 if (ext_len < 0)
192 goto merr;
193 } else {
194 unsigned char *p;
195 ext_len = method->i2d(ext_struc, NULL);
196 if (!(ext_der = OPENSSL_malloc(ext_len)))
197 goto merr;
198 p = ext_der;
199 method->i2d(ext_struc, &p);
200 }
201 if (!(ext_oct = M_ASN1_OCTET_STRING_new()))
202 goto merr;
203 ext_oct->data = ext_der;
204 ext_oct->length = ext_len;
205
206 ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct);
207 if (!ext)
208 goto merr;
209 M_ASN1_OCTET_STRING_free(ext_oct);
210
211 return ext;
212
213 merr:
214 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
215 return NULL;
216
217 }
218
219 /* Given an internal structure, nid and critical flag create an extension */
220
X509V3_EXT_i2d(int ext_nid,int crit,void * ext_struc)221 X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc)
222 {
223 const X509V3_EXT_METHOD *method;
224 if (!(method = X509V3_EXT_get_nid(ext_nid))) {
225 OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION);
226 return NULL;
227 }
228 return do_ext_i2d(method, ext_nid, crit, ext_struc);
229 }
230
231 /* Check the extension string for critical flag */
v3_check_critical(char ** value)232 static int v3_check_critical(char **value)
233 {
234 char *p = *value;
235 if ((strlen(p) < 9) || strncmp(p, "critical,", 9))
236 return 0;
237 p += 9;
238 while (isspace((unsigned char)*p))
239 p++;
240 *value = p;
241 return 1;
242 }
243
244 /* Check extension string for generic extension and return the type */
v3_check_generic(char ** value)245 static int v3_check_generic(char **value)
246 {
247 int gen_type = 0;
248 char *p = *value;
249 if ((strlen(p) >= 4) && !strncmp(p, "DER:", 4)) {
250 p += 4;
251 gen_type = 1;
252 } else if ((strlen(p) >= 5) && !strncmp(p, "ASN1:", 5)) {
253 p += 5;
254 gen_type = 2;
255 } else
256 return 0;
257
258 while (isspace((unsigned char)*p))
259 p++;
260 *value = p;
261 return gen_type;
262 }
263
264 /* Create a generic extension: for now just handle DER type */
v3_generic_extension(const char * ext,char * value,int crit,int gen_type,X509V3_CTX * ctx)265 static X509_EXTENSION *v3_generic_extension(const char *ext, char *value,
266 int crit, int gen_type,
267 X509V3_CTX *ctx)
268 {
269 unsigned char *ext_der = NULL;
270 long ext_len = 0;
271 ASN1_OBJECT *obj = NULL;
272 ASN1_OCTET_STRING *oct = NULL;
273 X509_EXTENSION *extension = NULL;
274 if (!(obj = OBJ_txt2obj(ext, 0))) {
275 OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NAME_ERROR);
276 ERR_add_error_data(2, "name=", ext);
277 goto err;
278 }
279
280 if (gen_type == 1)
281 ext_der = string_to_hex(value, &ext_len);
282 else if (gen_type == 2)
283 ext_der = generic_asn1(value, ctx, &ext_len);
284
285 if (ext_der == NULL) {
286 OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
287 ERR_add_error_data(2, "value=", value);
288 goto err;
289 }
290
291 if (!(oct = M_ASN1_OCTET_STRING_new())) {
292 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
293 goto err;
294 }
295
296 oct->data = ext_der;
297 oct->length = ext_len;
298 ext_der = NULL;
299
300 extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct);
301
302 err:
303 ASN1_OBJECT_free(obj);
304 M_ASN1_OCTET_STRING_free(oct);
305 if (ext_der)
306 OPENSSL_free(ext_der);
307 return extension;
308
309 }
310
generic_asn1(char * value,X509V3_CTX * ctx,long * ext_len)311 static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx,
312 long *ext_len)
313 {
314 ASN1_TYPE *typ;
315 unsigned char *ext_der = NULL;
316 typ = ASN1_generate_v3(value, ctx);
317 if (typ == NULL)
318 return NULL;
319 *ext_len = i2d_ASN1_TYPE(typ, &ext_der);
320 ASN1_TYPE_free(typ);
321 return ext_der;
322 }
323
324 /*
325 * This is the main function: add a bunch of extensions based on a config
326 * file section to an extension STACK.
327 */
328
X509V3_EXT_add_nconf_sk(CONF * conf,X509V3_CTX * ctx,char * section,STACK_OF (X509_EXTENSION)** sk)329 int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section,
330 STACK_OF(X509_EXTENSION) **sk)
331 {
332 X509_EXTENSION *ext;
333 STACK_OF(CONF_VALUE) *nval;
334 CONF_VALUE *val;
335 size_t i;
336 if (!(nval = NCONF_get_section(conf, section)))
337 return 0;
338 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
339 val = sk_CONF_VALUE_value(nval, i);
340 if (!(ext = X509V3_EXT_nconf(conf, ctx, val->name, val->value)))
341 return 0;
342 if (sk)
343 X509v3_add_ext(sk, ext, -1);
344 X509_EXTENSION_free(ext);
345 }
346 return 1;
347 }
348
349 /*
350 * Convenience functions to add extensions to a certificate, CRL and request
351 */
352
X509V3_EXT_add_nconf(CONF * conf,X509V3_CTX * ctx,char * section,X509 * cert)353 int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section,
354 X509 *cert)
355 {
356 STACK_OF(X509_EXTENSION) **sk = NULL;
357 if (cert)
358 sk = &cert->cert_info->extensions;
359 return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
360 }
361
362 /* Same as above but for a CRL */
363
X509V3_EXT_CRL_add_nconf(CONF * conf,X509V3_CTX * ctx,char * section,X509_CRL * crl)364 int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section,
365 X509_CRL *crl)
366 {
367 STACK_OF(X509_EXTENSION) **sk = NULL;
368 if (crl)
369 sk = &crl->crl->extensions;
370 return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
371 }
372
373 /* Add extensions to certificate request */
374
X509V3_EXT_REQ_add_nconf(CONF * conf,X509V3_CTX * ctx,char * section,X509_REQ * req)375 int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section,
376 X509_REQ *req)
377 {
378 STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL;
379 int i;
380 if (req)
381 sk = &extlist;
382 i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
383 if (!i || !sk)
384 return i;
385 i = X509_REQ_add_extensions(req, extlist);
386 sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free);
387 return i;
388 }
389
390 /* Config database functions */
391
X509V3_get_string(X509V3_CTX * ctx,char * name,char * section)392 char *X509V3_get_string(X509V3_CTX *ctx, char *name, char *section)
393 {
394 if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_string) {
395 OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED);
396 return NULL;
397 }
398 if (ctx->db_meth->get_string)
399 return ctx->db_meth->get_string(ctx->db, name, section);
400 return NULL;
401 }
402
STACK_OF(CONF_VALUE)403 STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, char *section)
404 {
405 if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section) {
406 OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED);
407 return NULL;
408 }
409 if (ctx->db_meth->get_section)
410 return ctx->db_meth->get_section(ctx->db, section);
411 return NULL;
412 }
413
X509V3_string_free(X509V3_CTX * ctx,char * str)414 void X509V3_string_free(X509V3_CTX *ctx, char *str)
415 {
416 if (!str)
417 return;
418 if (ctx->db_meth->free_string)
419 ctx->db_meth->free_string(ctx->db, str);
420 }
421
X509V3_section_free(X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* section)422 void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section)
423 {
424 if (!section)
425 return;
426 if (ctx->db_meth->free_section)
427 ctx->db_meth->free_section(ctx->db, section);
428 }
429
nconf_get_string(void * db,char * section,char * value)430 static char *nconf_get_string(void *db, char *section, char *value)
431 {
432 /* TODO(fork): this should return a const value. */
433 return (char *)NCONF_get_string(db, section, value);
434 }
435
STACK_OF(CONF_VALUE)436 static STACK_OF(CONF_VALUE) *nconf_get_section(void *db, char *section)
437 {
438 return NCONF_get_section(db, section);
439 }
440
441 static const X509V3_CONF_METHOD nconf_method = {
442 nconf_get_string,
443 nconf_get_section,
444 NULL,
445 NULL
446 };
447
X509V3_set_nconf(X509V3_CTX * ctx,CONF * conf)448 void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf)
449 {
450 ctx->db_meth = &nconf_method;
451 ctx->db = conf;
452 }
453
X509V3_set_ctx(X509V3_CTX * ctx,X509 * issuer,X509 * subj,X509_REQ * req,X509_CRL * crl,int flags)454 void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req,
455 X509_CRL *crl, int flags)
456 {
457 ctx->issuer_cert = issuer;
458 ctx->subject_cert = subj;
459 ctx->crl = crl;
460 ctx->subject_req = req;
461 ctx->flags = flags;
462 }
463