1/* v3_crld.c */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 1999.
4 */
5/* ====================================================================
6 * Copyright (c) 1999-2008 The OpenSSL Project.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in
17 *    the documentation and/or other materials provided with the
18 *    distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 *    software must display the following acknowledgment:
22 *    "This product includes software developed by the OpenSSL Project
23 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 *    endorse or promote products derived from this software without
27 *    prior written permission. For written permission, please contact
28 *    licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 *    nor may "OpenSSL" appear in their names without prior written
32 *    permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 *    acknowledgment:
36 *    "This product includes software developed by the OpenSSL Project
37 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com).  This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59#include <stdio.h>
60#include "cryptlib.h"
61#include <openssl/conf.h>
62#include <openssl/asn1.h>
63#include <openssl/asn1t.h>
64#include <openssl/x509v3.h>
65
66static void *v2i_crld(const X509V3_EXT_METHOD *method,
67		      X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
68static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
69		     int indent);
70
71const X509V3_EXT_METHOD v3_crld =
72	{
73	NID_crl_distribution_points, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
74	0,0,0,0,
75	0,0,
76	0,
77	v2i_crld,
78	i2r_crldp,0,
79	NULL
80	};
81
82const X509V3_EXT_METHOD v3_freshest_crl =
83	{
84	NID_freshest_crl, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
85	0,0,0,0,
86	0,0,
87	0,
88	v2i_crld,
89	i2r_crldp,0,
90	NULL
91	};
92
93static STACK_OF(GENERAL_NAME) *gnames_from_sectname(X509V3_CTX *ctx, char *sect)
94	{
95	STACK_OF(CONF_VALUE) *gnsect;
96	STACK_OF(GENERAL_NAME) *gens;
97	if (*sect == '@')
98		gnsect = X509V3_get_section(ctx, sect + 1);
99	else
100		gnsect = X509V3_parse_list(sect);
101	if (!gnsect)
102		{
103		X509V3err(X509V3_F_GNAMES_FROM_SECTNAME,
104						X509V3_R_SECTION_NOT_FOUND);
105		return NULL;
106		}
107	gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect);
108	if (*sect == '@')
109		X509V3_section_free(ctx, gnsect);
110	else
111		sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free);
112	return gens;
113	}
114
115static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx,
116							CONF_VALUE *cnf)
117	{
118	STACK_OF(GENERAL_NAME) *fnm = NULL;
119	STACK_OF(X509_NAME_ENTRY) *rnm = NULL;
120	if (!strncmp(cnf->name, "fullname", 9))
121		{
122		fnm = gnames_from_sectname(ctx, cnf->value);
123		if (!fnm)
124			goto err;
125		}
126	else if (!strcmp(cnf->name, "relativename"))
127		{
128		int ret;
129		STACK_OF(CONF_VALUE) *dnsect;
130		X509_NAME *nm;
131		nm = X509_NAME_new();
132		if (!nm)
133			return -1;
134		dnsect = X509V3_get_section(ctx, cnf->value);
135		if (!dnsect)
136			{
137			X509V3err(X509V3_F_SET_DIST_POINT_NAME,
138						X509V3_R_SECTION_NOT_FOUND);
139			return -1;
140			}
141		ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC);
142		X509V3_section_free(ctx, dnsect);
143		rnm = nm->entries;
144		nm->entries = NULL;
145		X509_NAME_free(nm);
146		if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0)
147			goto err;
148		/* Since its a name fragment can't have more than one
149		 * RDNSequence
150		 */
151		if (sk_X509_NAME_ENTRY_value(rnm,
152				sk_X509_NAME_ENTRY_num(rnm) - 1)->set)
153			{
154			X509V3err(X509V3_F_SET_DIST_POINT_NAME,
155						X509V3_R_INVALID_MULTIPLE_RDNS);
156			goto err;
157			}
158		}
159	else
160		return 0;
161
162	if (*pdp)
163		{
164		X509V3err(X509V3_F_SET_DIST_POINT_NAME,
165						X509V3_R_DISTPOINT_ALREADY_SET);
166		goto err;
167		}
168
169	*pdp = DIST_POINT_NAME_new();
170	if (!*pdp)
171		goto err;
172	if (fnm)
173		{
174		(*pdp)->type = 0;
175		(*pdp)->name.fullname = fnm;
176		}
177	else
178		{
179		(*pdp)->type = 1;
180		(*pdp)->name.relativename = rnm;
181		}
182
183	return 1;
184
185	err:
186	if (fnm)
187		sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free);
188	if (rnm)
189		sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free);
190	return -1;
191	}
192
193static const BIT_STRING_BITNAME reason_flags[] = {
194{0, "Unused", "unused"},
195{1, "Key Compromise", "keyCompromise"},
196{2, "CA Compromise", "CACompromise"},
197{3, "Affiliation Changed", "affiliationChanged"},
198{4, "Superseded", "superseded"},
199{5, "Cessation Of Operation", "cessationOfOperation"},
200{6, "Certificate Hold", "certificateHold"},
201{7, "Privilege Withdrawn", "privilegeWithdrawn"},
202{8, "AA Compromise", "AACompromise"},
203{-1, NULL, NULL}
204};
205
206static int set_reasons(ASN1_BIT_STRING **preas, char *value)
207	{
208	STACK_OF(CONF_VALUE) *rsk = NULL;
209	const BIT_STRING_BITNAME *pbn;
210	const char *bnam;
211	int i, ret = 0;
212	rsk = X509V3_parse_list(value);
213	if (!rsk)
214		return 0;
215	if (*preas)
216		return 0;
217	for (i = 0; i < sk_CONF_VALUE_num(rsk); i++)
218		{
219		bnam = sk_CONF_VALUE_value(rsk, i)->name;
220		if (!*preas)
221			{
222			*preas = ASN1_BIT_STRING_new();
223			if (!*preas)
224				goto err;
225			}
226		for (pbn = reason_flags; pbn->lname; pbn++)
227			{
228			if (!strcmp(pbn->sname, bnam))
229				{
230				if (!ASN1_BIT_STRING_set_bit(*preas,
231							pbn->bitnum, 1))
232					goto err;
233				break;
234				}
235			}
236		if (!pbn->lname)
237			goto err;
238		}
239	ret = 1;
240
241	err:
242	sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free);
243	return ret;
244	}
245
246static int print_reasons(BIO *out, const char *rname,
247			ASN1_BIT_STRING *rflags, int indent)
248	{
249	int first = 1;
250	const BIT_STRING_BITNAME *pbn;
251	BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, "");
252	for (pbn = reason_flags; pbn->lname; pbn++)
253		{
254		if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum))
255			{
256			if (first)
257				first = 0;
258			else
259				BIO_puts(out, ", ");
260			BIO_puts(out, pbn->lname);
261			}
262		}
263	if (first)
264		BIO_puts(out, "<EMPTY>\n");
265	else
266		BIO_puts(out, "\n");
267	return 1;
268	}
269
270static DIST_POINT *crldp_from_section(X509V3_CTX *ctx,
271						STACK_OF(CONF_VALUE) *nval)
272	{
273	int i;
274	CONF_VALUE *cnf;
275	DIST_POINT *point = NULL;
276	point = DIST_POINT_new();
277	if (!point)
278		goto err;
279	for(i = 0; i < sk_CONF_VALUE_num(nval); i++)
280		{
281		int ret;
282		cnf = sk_CONF_VALUE_value(nval, i);
283		ret = set_dist_point_name(&point->distpoint, ctx, cnf);
284		if (ret > 0)
285			continue;
286		if (ret < 0)
287			goto err;
288		if (!strcmp(cnf->name, "reasons"))
289			{
290			if (!set_reasons(&point->reasons, cnf->value))
291				goto err;
292			}
293		else if (!strcmp(cnf->name, "CRLissuer"))
294			{
295			point->CRLissuer =
296				gnames_from_sectname(ctx, cnf->value);
297			if (!point->CRLissuer)
298				goto err;
299			}
300		}
301
302	return point;
303
304
305	err:
306	if (point)
307		DIST_POINT_free(point);
308	return NULL;
309	}
310
311static void *v2i_crld(const X509V3_EXT_METHOD *method,
312		      X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
313	{
314	STACK_OF(DIST_POINT) *crld = NULL;
315	GENERAL_NAMES *gens = NULL;
316	GENERAL_NAME *gen = NULL;
317	CONF_VALUE *cnf;
318	int i;
319	if(!(crld = sk_DIST_POINT_new_null())) goto merr;
320	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
321		DIST_POINT *point;
322		cnf = sk_CONF_VALUE_value(nval, i);
323		if (!cnf->value)
324			{
325			STACK_OF(CONF_VALUE) *dpsect;
326			dpsect = X509V3_get_section(ctx, cnf->name);
327			if (!dpsect)
328				goto err;
329			point = crldp_from_section(ctx, dpsect);
330			X509V3_section_free(ctx, dpsect);
331			if (!point)
332				goto err;
333			if(!sk_DIST_POINT_push(crld, point))
334				{
335				DIST_POINT_free(point);
336				goto merr;
337				}
338			}
339		else
340			{
341			if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
342				goto err;
343			if(!(gens = GENERAL_NAMES_new()))
344				goto merr;
345			if(!sk_GENERAL_NAME_push(gens, gen))
346				goto merr;
347			gen = NULL;
348			if(!(point = DIST_POINT_new()))
349				goto merr;
350			if(!sk_DIST_POINT_push(crld, point))
351				{
352				DIST_POINT_free(point);
353				goto merr;
354				}
355			if(!(point->distpoint = DIST_POINT_NAME_new()))
356				goto merr;
357			point->distpoint->name.fullname = gens;
358			point->distpoint->type = 0;
359			gens = NULL;
360			}
361	}
362	return crld;
363
364	merr:
365	X509V3err(X509V3_F_V2I_CRLD,ERR_R_MALLOC_FAILURE);
366	err:
367	GENERAL_NAME_free(gen);
368	GENERAL_NAMES_free(gens);
369	sk_DIST_POINT_pop_free(crld, DIST_POINT_free);
370	return NULL;
371}
372
373IMPLEMENT_STACK_OF(DIST_POINT)
374IMPLEMENT_ASN1_SET_OF(DIST_POINT)
375
376static int dpn_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
377								void *exarg)
378	{
379	DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval;
380
381	switch(operation)
382		{
383		case ASN1_OP_NEW_POST:
384		dpn->dpname = NULL;
385		break;
386
387		case ASN1_OP_FREE_POST:
388		if (dpn->dpname)
389			X509_NAME_free(dpn->dpname);
390		break;
391		}
392	return 1;
393	}
394
395
396ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = {
397	ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0),
398	ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1)
399} ASN1_CHOICE_END_cb(DIST_POINT_NAME, DIST_POINT_NAME, type)
400
401
402IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME)
403
404ASN1_SEQUENCE(DIST_POINT) = {
405	ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0),
406	ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1),
407	ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2)
408} ASN1_SEQUENCE_END(DIST_POINT)
409
410IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT)
411
412ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) =
413	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CRLDistributionPoints, DIST_POINT)
414ASN1_ITEM_TEMPLATE_END(CRL_DIST_POINTS)
415
416IMPLEMENT_ASN1_FUNCTIONS(CRL_DIST_POINTS)
417
418ASN1_SEQUENCE(ISSUING_DIST_POINT) = {
419	ASN1_EXP_OPT(ISSUING_DIST_POINT, distpoint, DIST_POINT_NAME, 0),
420	ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyuser, ASN1_FBOOLEAN, 1),
421	ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyCA, ASN1_FBOOLEAN, 2),
422	ASN1_IMP_OPT(ISSUING_DIST_POINT, onlysomereasons, ASN1_BIT_STRING, 3),
423	ASN1_IMP_OPT(ISSUING_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 4),
424	ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyattr, ASN1_FBOOLEAN, 5)
425} ASN1_SEQUENCE_END(ISSUING_DIST_POINT)
426
427IMPLEMENT_ASN1_FUNCTIONS(ISSUING_DIST_POINT)
428
429static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
430		   int indent);
431static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
432		     STACK_OF(CONF_VALUE) *nval);
433
434const X509V3_EXT_METHOD v3_idp =
435	{
436	NID_issuing_distribution_point, X509V3_EXT_MULTILINE,
437	ASN1_ITEM_ref(ISSUING_DIST_POINT),
438	0,0,0,0,
439	0,0,
440	0,
441	v2i_idp,
442	i2r_idp,0,
443	NULL
444	};
445
446static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
447		     STACK_OF(CONF_VALUE) *nval)
448	{
449	ISSUING_DIST_POINT *idp = NULL;
450	CONF_VALUE *cnf;
451	char *name, *val;
452	int i, ret;
453	idp = ISSUING_DIST_POINT_new();
454	if (!idp)
455		goto merr;
456	for(i = 0; i < sk_CONF_VALUE_num(nval); i++)
457		{
458		cnf = sk_CONF_VALUE_value(nval, i);
459		name = cnf->name;
460		val = cnf->value;
461		ret = set_dist_point_name(&idp->distpoint, ctx, cnf);
462		if (ret > 0)
463			continue;
464		if (ret < 0)
465			goto err;
466		if (!strcmp(name, "onlyuser"))
467			{
468			if (!X509V3_get_value_bool(cnf, &idp->onlyuser))
469				goto err;
470			}
471		else if (!strcmp(name, "onlyCA"))
472			{
473			if (!X509V3_get_value_bool(cnf, &idp->onlyCA))
474				goto err;
475			}
476		else if (!strcmp(name, "onlyAA"))
477			{
478			if (!X509V3_get_value_bool(cnf, &idp->onlyattr))
479				goto err;
480			}
481		else if (!strcmp(name, "indirectCRL"))
482			{
483			if (!X509V3_get_value_bool(cnf, &idp->indirectCRL))
484				goto err;
485			}
486		else if (!strcmp(name, "onlysomereasons"))
487			{
488			if (!set_reasons(&idp->onlysomereasons, val))
489				goto err;
490			}
491		else
492			{
493                        X509V3err(X509V3_F_V2I_IDP, X509V3_R_INVALID_NAME);
494                        X509V3_conf_err(cnf);
495                        goto err;
496			}
497		}
498	return idp;
499
500	merr:
501	X509V3err(X509V3_F_V2I_IDP,ERR_R_MALLOC_FAILURE);
502	err:
503	ISSUING_DIST_POINT_free(idp);
504	return NULL;
505	}
506
507static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent)
508	{
509	int i;
510	for (i = 0; i < sk_GENERAL_NAME_num(gens); i++)
511		{
512		BIO_printf(out, "%*s", indent + 2, "");
513		GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i));
514		BIO_puts(out, "\n");
515		}
516	return 1;
517	}
518
519static int print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent)
520	{
521	if (dpn->type == 0)
522		{
523		BIO_printf(out, "%*sFull Name:\n", indent, "");
524		print_gens(out, dpn->name.fullname, indent);
525		}
526	else
527		{
528		X509_NAME ntmp;
529		ntmp.entries = dpn->name.relativename;
530		BIO_printf(out, "%*sRelative Name:\n%*s",
531						indent, "", indent + 2, "");
532		X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE);
533		BIO_puts(out, "\n");
534		}
535	return 1;
536	}
537
538static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
539		   int indent)
540	{
541	ISSUING_DIST_POINT *idp = pidp;
542	if (idp->distpoint)
543		print_distpoint(out, idp->distpoint, indent);
544	if (idp->onlyuser > 0)
545		BIO_printf(out, "%*sOnly User Certificates\n", indent, "");
546	if (idp->onlyCA > 0)
547		BIO_printf(out, "%*sOnly CA Certificates\n", indent, "");
548	if (idp->indirectCRL > 0)
549		BIO_printf(out, "%*sIndirect CRL\n", indent, "");
550	if (idp->onlysomereasons)
551		print_reasons(out, "Only Some Reasons",
552				idp->onlysomereasons, indent);
553	if (idp->onlyattr > 0)
554		BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, "");
555	if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0)
556		&& (idp->indirectCRL <= 0) && !idp->onlysomereasons
557		&& (idp->onlyattr <= 0))
558		BIO_printf(out, "%*s<EMPTY>\n", indent, "");
559
560	return 1;
561	}
562
563static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
564		     int indent)
565	{
566	STACK_OF(DIST_POINT) *crld = pcrldp;
567	DIST_POINT *point;
568	int i;
569	for(i = 0; i < sk_DIST_POINT_num(crld); i++)
570		{
571		BIO_puts(out, "\n");
572		point = sk_DIST_POINT_value(crld, i);
573		if(point->distpoint)
574			print_distpoint(out, point->distpoint, indent);
575		if(point->reasons)
576			print_reasons(out, "Reasons", point->reasons,
577								indent);
578		if(point->CRLissuer)
579			{
580			BIO_printf(out, "%*sCRL Issuer:\n", indent, "");
581			print_gens(out, point->CRLissuer, indent);
582			}
583		}
584	return 1;
585	}
586
587int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname)
588	{
589	int i;
590	STACK_OF(X509_NAME_ENTRY) *frag;
591	X509_NAME_ENTRY *ne;
592	if (!dpn || (dpn->type != 1))
593		return 1;
594	frag = dpn->name.relativename;
595	dpn->dpname = X509_NAME_dup(iname);
596	if (!dpn->dpname)
597		return 0;
598	for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++)
599		{
600		ne = sk_X509_NAME_ENTRY_value(frag, i);
601		if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1))
602			{
603			X509_NAME_free(dpn->dpname);
604			dpn->dpname = NULL;
605			return 0;
606			}
607		}
608	/* generate cached encoding of name */
609	if (i2d_X509_NAME(dpn->dpname, NULL) < 0)
610		{
611		X509_NAME_free(dpn->dpname);
612		dpn->dpname = NULL;
613		return 0;
614		}
615	return 1;
616	}
617