v3_cpols.c revision 238405
155714Skris/* v3_cpols.c */
2194206Ssimon/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
355714Skris * project 1999.
455714Skris */
555714Skris/* ====================================================================
6160814Ssimon * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
755714Skris *
855714Skris * Redistribution and use in source and binary forms, with or without
955714Skris * modification, are permitted provided that the following conditions
1055714Skris * are met:
1155714Skris *
1255714Skris * 1. Redistributions of source code must retain the above copyright
1355714Skris *    notice, this list of conditions and the following disclaimer.
1455714Skris *
1555714Skris * 2. Redistributions in binary form must reproduce the above copyright
1655714Skris *    notice, this list of conditions and the following disclaimer in
1755714Skris *    the documentation and/or other materials provided with the
1855714Skris *    distribution.
1955714Skris *
2055714Skris * 3. All advertising materials mentioning features or use of this
2155714Skris *    software must display the following acknowledgment:
2255714Skris *    "This product includes software developed by the OpenSSL Project
2355714Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2455714Skris *
2555714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2655714Skris *    endorse or promote products derived from this software without
2755714Skris *    prior written permission. For written permission, please contact
2855714Skris *    licensing@OpenSSL.org.
2955714Skris *
3055714Skris * 5. Products derived from this software may not be called "OpenSSL"
3155714Skris *    nor may "OpenSSL" appear in their names without prior written
3255714Skris *    permission of the OpenSSL Project.
3355714Skris *
3455714Skris * 6. Redistributions of any form whatsoever must retain the following
3555714Skris *    acknowledgment:
3655714Skris *    "This product includes software developed by the OpenSSL Project
3755714Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3855714Skris *
3955714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4055714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4155714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4255714Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4355714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4455714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4555714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4655714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4755714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4855714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
4955714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5055714Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
5155714Skris * ====================================================================
5255714Skris *
5355714Skris * This product includes cryptographic software written by Eric Young
5455714Skris * (eay@cryptsoft.com).  This product includes software written by Tim
5555714Skris * Hudson (tjh@cryptsoft.com).
5655714Skris *
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include "cryptlib.h"
6155714Skris#include <openssl/conf.h>
6255714Skris#include <openssl/asn1.h>
63109998Smarkm#include <openssl/asn1t.h>
6455714Skris#include <openssl/x509v3.h>
6555714Skris
66160814Ssimon#include "pcy_int.h"
67160814Ssimon
6855714Skris/* Certificate policies extension support: this one is a bit complex... */
6955714Skris
7055714Skrisstatic int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, BIO *out, int indent);
7155714Skrisstatic STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *value);
7255714Skrisstatic void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, int indent);
7355714Skrisstatic void print_notice(BIO *out, USERNOTICE *notice, int indent);
7455714Skrisstatic POLICYINFO *policy_section(X509V3_CTX *ctx,
7555714Skris				 STACK_OF(CONF_VALUE) *polstrs, int ia5org);
7655714Skrisstatic POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
7755714Skris					STACK_OF(CONF_VALUE) *unot, int ia5org);
78120631Snectarstatic int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos);
7955714Skris
80167612Ssimonconst X509V3_EXT_METHOD v3_cpols = {
81109998SmarkmNID_certificate_policies, 0,ASN1_ITEM_ref(CERTIFICATEPOLICIES),
82109998Smarkm0,0,0,0,
83109998Smarkm0,0,
84109998Smarkm0,0,
8555714Skris(X509V3_EXT_I2R)i2r_certpol,
8655714Skris(X509V3_EXT_R2I)r2i_certpol,
8755714SkrisNULL
8855714Skris};
8955714Skris
90109998SmarkmASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) =
91109998Smarkm	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO)
92109998SmarkmASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES)
9355714Skris
94109998SmarkmIMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
95109998Smarkm
96109998SmarkmASN1_SEQUENCE(POLICYINFO) = {
97109998Smarkm	ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT),
98109998Smarkm	ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO)
99109998Smarkm} ASN1_SEQUENCE_END(POLICYINFO)
100109998Smarkm
101109998SmarkmIMPLEMENT_ASN1_FUNCTIONS(POLICYINFO)
102109998Smarkm
103109998SmarkmASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other, ASN1_ANY);
104109998Smarkm
105109998SmarkmASN1_ADB(POLICYQUALINFO) = {
106109998Smarkm	ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)),
107109998Smarkm	ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE))
108109998Smarkm} ASN1_ADB_END(POLICYQUALINFO, 0, pqualid, 0, &policydefault_tt, NULL);
109109998Smarkm
110109998SmarkmASN1_SEQUENCE(POLICYQUALINFO) = {
111109998Smarkm	ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT),
112109998Smarkm	ASN1_ADB_OBJECT(POLICYQUALINFO)
113109998Smarkm} ASN1_SEQUENCE_END(POLICYQUALINFO)
114109998Smarkm
115109998SmarkmIMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO)
116109998Smarkm
117109998SmarkmASN1_SEQUENCE(USERNOTICE) = {
118109998Smarkm	ASN1_OPT(USERNOTICE, noticeref, NOTICEREF),
119109998Smarkm	ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT)
120109998Smarkm} ASN1_SEQUENCE_END(USERNOTICE)
121109998Smarkm
122109998SmarkmIMPLEMENT_ASN1_FUNCTIONS(USERNOTICE)
123109998Smarkm
124109998SmarkmASN1_SEQUENCE(NOTICEREF) = {
125109998Smarkm	ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT),
126109998Smarkm	ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER)
127109998Smarkm} ASN1_SEQUENCE_END(NOTICEREF)
128109998Smarkm
129109998SmarkmIMPLEMENT_ASN1_FUNCTIONS(NOTICEREF)
130109998Smarkm
13155714Skrisstatic STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
13255714Skris		X509V3_CTX *ctx, char *value)
13355714Skris{
13455714Skris	STACK_OF(POLICYINFO) *pols = NULL;
13555714Skris	char *pstr;
13655714Skris	POLICYINFO *pol;
13755714Skris	ASN1_OBJECT *pobj;
13855714Skris	STACK_OF(CONF_VALUE) *vals;
13955714Skris	CONF_VALUE *cnf;
14055714Skris	int i, ia5org;
14155714Skris	pols = sk_POLICYINFO_new_null();
142160814Ssimon	if (pols == NULL) {
143160814Ssimon		X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
144160814Ssimon		return NULL;
145160814Ssimon	}
14655714Skris	vals =  X509V3_parse_list(value);
147160814Ssimon	if (vals == NULL) {
148160814Ssimon		X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_X509V3_LIB);
149160814Ssimon		goto err;
150160814Ssimon	}
15155714Skris	ia5org = 0;
15255714Skris	for(i = 0; i < sk_CONF_VALUE_num(vals); i++) {
15355714Skris		cnf = sk_CONF_VALUE_value(vals, i);
15455714Skris		if(cnf->value || !cnf->name ) {
15555714Skris			X509V3err(X509V3_F_R2I_CERTPOL,X509V3_R_INVALID_POLICY_IDENTIFIER);
15655714Skris			X509V3_conf_err(cnf);
15755714Skris			goto err;
15855714Skris		}
15955714Skris		pstr = cnf->name;
16055714Skris		if(!strcmp(pstr,"ia5org")) {
16155714Skris			ia5org = 1;
16255714Skris			continue;
16355714Skris		} else if(*pstr == '@') {
16455714Skris			STACK_OF(CONF_VALUE) *polsect;
16555714Skris			polsect = X509V3_get_section(ctx, pstr + 1);
16655714Skris			if(!polsect) {
16755714Skris				X509V3err(X509V3_F_R2I_CERTPOL,X509V3_R_INVALID_SECTION);
16855714Skris
16955714Skris				X509V3_conf_err(cnf);
17055714Skris				goto err;
17155714Skris			}
17255714Skris			pol = policy_section(ctx, polsect, ia5org);
17355714Skris			X509V3_section_free(ctx, polsect);
17455714Skris			if(!pol) goto err;
17555714Skris		} else {
17655714Skris			if(!(pobj = OBJ_txt2obj(cnf->name, 0))) {
17755714Skris				X509V3err(X509V3_F_R2I_CERTPOL,X509V3_R_INVALID_OBJECT_IDENTIFIER);
17855714Skris				X509V3_conf_err(cnf);
17955714Skris				goto err;
18055714Skris			}
18155714Skris			pol = POLICYINFO_new();
18255714Skris			pol->policyid = pobj;
18355714Skris		}
184194206Ssimon		if (!sk_POLICYINFO_push(pols, pol)){
185194206Ssimon			POLICYINFO_free(pol);
186194206Ssimon			X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
187194206Ssimon			goto err;
188194206Ssimon		}
18955714Skris	}
19055714Skris	sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
19155714Skris	return pols;
19255714Skris	err:
193160814Ssimon	sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
19455714Skris	sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
19555714Skris	return NULL;
19655714Skris}
19755714Skris
19855714Skrisstatic POLICYINFO *policy_section(X509V3_CTX *ctx,
19955714Skris				STACK_OF(CONF_VALUE) *polstrs, int ia5org)
20055714Skris{
20155714Skris	int i;
20255714Skris	CONF_VALUE *cnf;
20355714Skris	POLICYINFO *pol;
20455714Skris	POLICYQUALINFO *qual;
20555714Skris	if(!(pol = POLICYINFO_new())) goto merr;
20655714Skris	for(i = 0; i < sk_CONF_VALUE_num(polstrs); i++) {
20755714Skris		cnf = sk_CONF_VALUE_value(polstrs, i);
20855714Skris		if(!strcmp(cnf->name, "policyIdentifier")) {
20955714Skris			ASN1_OBJECT *pobj;
21055714Skris			if(!(pobj = OBJ_txt2obj(cnf->value, 0))) {
21155714Skris				X509V3err(X509V3_F_POLICY_SECTION,X509V3_R_INVALID_OBJECT_IDENTIFIER);
21255714Skris				X509V3_conf_err(cnf);
21355714Skris				goto err;
21455714Skris			}
21555714Skris			pol->policyid = pobj;
21655714Skris
21755714Skris		} else if(!name_cmp(cnf->name, "CPS")) {
21855714Skris			if(!pol->qualifiers) pol->qualifiers =
21955714Skris						 sk_POLICYQUALINFO_new_null();
22055714Skris			if(!(qual = POLICYQUALINFO_new())) goto merr;
22155714Skris			if(!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
22255714Skris								 goto merr;
22355714Skris			qual->pqualid = OBJ_nid2obj(NID_id_qt_cps);
22459191Skris			qual->d.cpsuri = M_ASN1_IA5STRING_new();
22555714Skris			if(!ASN1_STRING_set(qual->d.cpsuri, cnf->value,
22655714Skris						 strlen(cnf->value))) goto merr;
22755714Skris		} else if(!name_cmp(cnf->name, "userNotice")) {
22855714Skris			STACK_OF(CONF_VALUE) *unot;
22955714Skris			if(*cnf->value != '@') {
23055714Skris				X509V3err(X509V3_F_POLICY_SECTION,X509V3_R_EXPECTED_A_SECTION_NAME);
23155714Skris				X509V3_conf_err(cnf);
23255714Skris				goto err;
23355714Skris			}
23455714Skris			unot = X509V3_get_section(ctx, cnf->value + 1);
23555714Skris			if(!unot) {
23655714Skris				X509V3err(X509V3_F_POLICY_SECTION,X509V3_R_INVALID_SECTION);
23755714Skris
23855714Skris				X509V3_conf_err(cnf);
23955714Skris				goto err;
24055714Skris			}
24155714Skris			qual = notice_section(ctx, unot, ia5org);
24255714Skris			X509V3_section_free(ctx, unot);
24355714Skris			if(!qual) goto err;
244120631Snectar			if(!pol->qualifiers) pol->qualifiers =
245120631Snectar						 sk_POLICYQUALINFO_new_null();
24655714Skris			if(!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
24755714Skris								 goto merr;
24855714Skris		} else {
24955714Skris			X509V3err(X509V3_F_POLICY_SECTION,X509V3_R_INVALID_OPTION);
25055714Skris
25155714Skris			X509V3_conf_err(cnf);
25255714Skris			goto err;
25355714Skris		}
25455714Skris	}
25555714Skris	if(!pol->policyid) {
25655714Skris		X509V3err(X509V3_F_POLICY_SECTION,X509V3_R_NO_POLICY_IDENTIFIER);
25755714Skris		goto err;
25855714Skris	}
25955714Skris
26055714Skris	return pol;
26155714Skris
26255714Skris	merr:
26355714Skris	X509V3err(X509V3_F_POLICY_SECTION,ERR_R_MALLOC_FAILURE);
26455714Skris
26555714Skris	err:
26655714Skris	POLICYINFO_free(pol);
26755714Skris	return NULL;
26855714Skris
26955714Skris
27055714Skris}
27155714Skris
27255714Skrisstatic POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
27355714Skris					STACK_OF(CONF_VALUE) *unot, int ia5org)
27455714Skris{
275120631Snectar	int i, ret;
27655714Skris	CONF_VALUE *cnf;
27755714Skris	USERNOTICE *not;
27855714Skris	POLICYQUALINFO *qual;
27955714Skris	if(!(qual = POLICYQUALINFO_new())) goto merr;
28055714Skris	qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice);
28155714Skris	if(!(not = USERNOTICE_new())) goto merr;
28255714Skris	qual->d.usernotice = not;
28355714Skris	for(i = 0; i < sk_CONF_VALUE_num(unot); i++) {
28455714Skris		cnf = sk_CONF_VALUE_value(unot, i);
28555714Skris		if(!strcmp(cnf->name, "explicitText")) {
28659191Skris			not->exptext = M_ASN1_VISIBLESTRING_new();
28755714Skris			if(!ASN1_STRING_set(not->exptext, cnf->value,
28855714Skris						 strlen(cnf->value))) goto merr;
28955714Skris		} else if(!strcmp(cnf->name, "organization")) {
29055714Skris			NOTICEREF *nref;
29155714Skris			if(!not->noticeref) {
29255714Skris				if(!(nref = NOTICEREF_new())) goto merr;
29355714Skris				not->noticeref = nref;
29455714Skris			} else nref = not->noticeref;
295120631Snectar			if(ia5org) nref->organization->type = V_ASN1_IA5STRING;
296120631Snectar			else nref->organization->type = V_ASN1_VISIBLESTRING;
29755714Skris			if(!ASN1_STRING_set(nref->organization, cnf->value,
29855714Skris						 strlen(cnf->value))) goto merr;
29955714Skris		} else if(!strcmp(cnf->name, "noticeNumbers")) {
30055714Skris			NOTICEREF *nref;
30155714Skris			STACK_OF(CONF_VALUE) *nos;
30255714Skris			if(!not->noticeref) {
30355714Skris				if(!(nref = NOTICEREF_new())) goto merr;
30455714Skris				not->noticeref = nref;
30555714Skris			} else nref = not->noticeref;
30655714Skris			nos = X509V3_parse_list(cnf->value);
30755714Skris			if(!nos || !sk_CONF_VALUE_num(nos)) {
30855714Skris				X509V3err(X509V3_F_NOTICE_SECTION,X509V3_R_INVALID_NUMBERS);
30955714Skris				X509V3_conf_err(cnf);
31055714Skris				goto err;
31155714Skris			}
312120631Snectar			ret = nref_nos(nref->noticenos, nos);
31355714Skris			sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
314120631Snectar			if (!ret)
315120631Snectar				goto err;
31655714Skris		} else {
31755714Skris			X509V3err(X509V3_F_NOTICE_SECTION,X509V3_R_INVALID_OPTION);
31855714Skris			X509V3_conf_err(cnf);
31955714Skris			goto err;
32055714Skris		}
32155714Skris	}
32255714Skris
32355714Skris	if(not->noticeref &&
32455714Skris	      (!not->noticeref->noticenos || !not->noticeref->organization)) {
32555714Skris			X509V3err(X509V3_F_NOTICE_SECTION,X509V3_R_NEED_ORGANIZATION_AND_NUMBERS);
32655714Skris			goto err;
32755714Skris	}
32855714Skris
32955714Skris	return qual;
33055714Skris
33155714Skris	merr:
33255714Skris	X509V3err(X509V3_F_NOTICE_SECTION,ERR_R_MALLOC_FAILURE);
33355714Skris
33455714Skris	err:
33555714Skris	POLICYQUALINFO_free(qual);
33655714Skris	return NULL;
33755714Skris}
33855714Skris
339120631Snectarstatic int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos)
34055714Skris{
34155714Skris	CONF_VALUE *cnf;
34255714Skris	ASN1_INTEGER *aint;
34368651Skris
34455714Skris	int i;
34568651Skris
34655714Skris	for(i = 0; i < sk_CONF_VALUE_num(nos); i++) {
34755714Skris		cnf = sk_CONF_VALUE_value(nos, i);
34855714Skris		if(!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) {
34955714Skris			X509V3err(X509V3_F_NREF_NOS,X509V3_R_INVALID_NUMBER);
35055714Skris			goto err;
35155714Skris		}
35268651Skris		if(!sk_ASN1_INTEGER_push(nnums, aint)) goto merr;
35355714Skris	}
354120631Snectar	return 1;
35555714Skris
35655714Skris	merr:
357160814Ssimon	X509V3err(X509V3_F_NREF_NOS,ERR_R_MALLOC_FAILURE);
35855714Skris
35955714Skris	err:
36068651Skris	sk_ASN1_INTEGER_pop_free(nnums, ASN1_STRING_free);
361120631Snectar	return 0;
36255714Skris}
36355714Skris
36455714Skris
36555714Skrisstatic int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
36655714Skris		BIO *out, int indent)
36755714Skris{
36855714Skris	int i;
36955714Skris	POLICYINFO *pinfo;
37055714Skris	/* First print out the policy OIDs */
37155714Skris	for(i = 0; i < sk_POLICYINFO_num(pol); i++) {
37255714Skris		pinfo = sk_POLICYINFO_value(pol, i);
37355714Skris		BIO_printf(out, "%*sPolicy: ", indent, "");
37455714Skris		i2a_ASN1_OBJECT(out, pinfo->policyid);
37555714Skris		BIO_puts(out, "\n");
37655714Skris		if(pinfo->qualifiers)
37755714Skris			 print_qualifiers(out, pinfo->qualifiers, indent + 2);
37855714Skris	}
37955714Skris	return 1;
38055714Skris}
38155714Skris
38255714Skrisstatic void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
38355714Skris		int indent)
38455714Skris{
38555714Skris	POLICYQUALINFO *qualinfo;
38655714Skris	int i;
38755714Skris	for(i = 0; i < sk_POLICYQUALINFO_num(quals); i++) {
38855714Skris		qualinfo = sk_POLICYQUALINFO_value(quals, i);
38955714Skris		switch(OBJ_obj2nid(qualinfo->pqualid))
39055714Skris		{
39155714Skris			case NID_id_qt_cps:
39255714Skris			BIO_printf(out, "%*sCPS: %s\n", indent, "",
39355714Skris						qualinfo->d.cpsuri->data);
39455714Skris			break;
39555714Skris
39655714Skris			case NID_id_qt_unotice:
39755714Skris			BIO_printf(out, "%*sUser Notice:\n", indent, "");
39855714Skris			print_notice(out, qualinfo->d.usernotice, indent + 2);
39955714Skris			break;
40055714Skris
40155714Skris			default:
40255714Skris			BIO_printf(out, "%*sUnknown Qualifier: ",
40355714Skris							 indent + 2, "");
40455714Skris
40555714Skris			i2a_ASN1_OBJECT(out, qualinfo->pqualid);
40655714Skris			BIO_puts(out, "\n");
40755714Skris			break;
40855714Skris		}
40955714Skris	}
41055714Skris}
41155714Skris
41255714Skrisstatic void print_notice(BIO *out, USERNOTICE *notice, int indent)
41355714Skris{
41455714Skris	int i;
41555714Skris	if(notice->noticeref) {
41655714Skris		NOTICEREF *ref;
41755714Skris		ref = notice->noticeref;
41855714Skris		BIO_printf(out, "%*sOrganization: %s\n", indent, "",
41955714Skris						 ref->organization->data);
42055714Skris		BIO_printf(out, "%*sNumber%s: ", indent, "",
42168651Skris			   sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : "");
42268651Skris		for(i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) {
42355714Skris			ASN1_INTEGER *num;
42455714Skris			char *tmp;
42568651Skris			num = sk_ASN1_INTEGER_value(ref->noticenos, i);
42655714Skris			if(i) BIO_puts(out, ", ");
42755714Skris			tmp = i2s_ASN1_INTEGER(NULL, num);
42855714Skris			BIO_puts(out, tmp);
42968651Skris			OPENSSL_free(tmp);
43055714Skris		}
43155714Skris		BIO_puts(out, "\n");
43255714Skris	}
43355714Skris	if(notice->exptext)
43455714Skris		BIO_printf(out, "%*sExplicit Text: %s\n", indent, "",
43555714Skris							 notice->exptext->data);
43655714Skris}
43755714Skris
438160814Ssimonvoid X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent)
439160814Ssimon	{
440160814Ssimon	const X509_POLICY_DATA *dat = node->data;
441160814Ssimon
442160814Ssimon	BIO_printf(out, "%*sPolicy: ", indent, "");
443160814Ssimon
444160814Ssimon	i2a_ASN1_OBJECT(out, dat->valid_policy);
445160814Ssimon	BIO_puts(out, "\n");
446160814Ssimon	BIO_printf(out, "%*s%s\n", indent + 2, "",
447160814Ssimon		node_data_critical(dat) ? "Critical" : "Non Critical");
448160814Ssimon	if (dat->qualifier_set)
449160814Ssimon		print_qualifiers(out, dat->qualifier_set, indent + 2);
450160814Ssimon	else
451160814Ssimon		BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, "");
452160814Ssimon	}
453238405Sjkim
454238405Sjkim
455194206SsimonIMPLEMENT_STACK_OF(X509_POLICY_NODE)
456238405SjkimIMPLEMENT_STACK_OF(X509_POLICY_DATA)
457238405Sjkim
458