155714Skris/* v3_cpols.c */
2296465Sdelphij/*
3296465Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4296465Sdelphij * 1999.
555714Skris */
655714Skris/* ====================================================================
7160814Ssimon * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
855714Skris *
955714Skris * Redistribution and use in source and binary forms, with or without
1055714Skris * modification, are permitted provided that the following conditions
1155714Skris * are met:
1255714Skris *
1355714Skris * 1. Redistributions of source code must retain the above copyright
14296465Sdelphij *    notice, this list of conditions and the following disclaimer.
1555714Skris *
1655714Skris * 2. Redistributions in binary form must reproduce the above copyright
1755714Skris *    notice, this list of conditions and the following disclaimer in
1855714Skris *    the documentation and/or other materials provided with the
1955714Skris *    distribution.
2055714Skris *
2155714Skris * 3. All advertising materials mentioning features or use of this
2255714Skris *    software must display the following acknowledgment:
2355714Skris *    "This product includes software developed by the OpenSSL Project
2455714Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2555714Skris *
2655714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2755714Skris *    endorse or promote products derived from this software without
2855714Skris *    prior written permission. For written permission, please contact
2955714Skris *    licensing@OpenSSL.org.
3055714Skris *
3155714Skris * 5. Products derived from this software may not be called "OpenSSL"
3255714Skris *    nor may "OpenSSL" appear in their names without prior written
3355714Skris *    permission of the OpenSSL Project.
3455714Skris *
3555714Skris * 6. Redistributions of any form whatsoever must retain the following
3655714Skris *    acknowledgment:
3755714Skris *    "This product includes software developed by the OpenSSL Project
3855714Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3955714Skris *
4055714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4155714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4255714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4355714Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4455714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4555714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4655714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4755714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4955714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5055714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5155714Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
5255714Skris * ====================================================================
5355714Skris *
5455714Skris * This product includes cryptographic software written by Eric Young
5555714Skris * (eay@cryptsoft.com).  This product includes software written by Tim
5655714Skris * Hudson (tjh@cryptsoft.com).
5755714Skris *
5855714Skris */
5955714Skris
6055714Skris#include <stdio.h>
6155714Skris#include "cryptlib.h"
6255714Skris#include <openssl/conf.h>
6355714Skris#include <openssl/asn1.h>
64109998Smarkm#include <openssl/asn1t.h>
6555714Skris#include <openssl/x509v3.h>
6655714Skris
67160814Ssimon#include "pcy_int.h"
68160814Ssimon
6955714Skris/* Certificate policies extension support: this one is a bit complex... */
7055714Skris
71296465Sdelphijstatic int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
72296465Sdelphij                       BIO *out, int indent);
73296465Sdelphijstatic STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
74296465Sdelphij                                         X509V3_CTX *ctx, char *value);
75296465Sdelphijstatic void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
76296465Sdelphij                             int indent);
7755714Skrisstatic void print_notice(BIO *out, USERNOTICE *notice, int indent);
7855714Skrisstatic POLICYINFO *policy_section(X509V3_CTX *ctx,
79296465Sdelphij                                  STACK_OF(CONF_VALUE) *polstrs, int ia5org);
8055714Skrisstatic POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
81296465Sdelphij                                      STACK_OF(CONF_VALUE) *unot, int ia5org);
82120631Snectarstatic int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos);
8355714Skris
84167612Ssimonconst X509V3_EXT_METHOD v3_cpols = {
85296465Sdelphij    NID_certificate_policies, 0, ASN1_ITEM_ref(CERTIFICATEPOLICIES),
86296465Sdelphij    0, 0, 0, 0,
87296465Sdelphij    0, 0,
88296465Sdelphij    0, 0,
89296465Sdelphij    (X509V3_EXT_I2R)i2r_certpol,
90296465Sdelphij    (X509V3_EXT_R2I)r2i_certpol,
91296465Sdelphij    NULL
9255714Skris};
9355714Skris
94296465SdelphijASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) =
95296465Sdelphij        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO)
96109998SmarkmASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES)
9755714Skris
98109998SmarkmIMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
99109998Smarkm
100109998SmarkmASN1_SEQUENCE(POLICYINFO) = {
101296465Sdelphij        ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT),
102296465Sdelphij        ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO)
103109998Smarkm} ASN1_SEQUENCE_END(POLICYINFO)
104109998Smarkm
105109998SmarkmIMPLEMENT_ASN1_FUNCTIONS(POLICYINFO)
106109998Smarkm
107109998SmarkmASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other, ASN1_ANY);
108109998Smarkm
109109998SmarkmASN1_ADB(POLICYQUALINFO) = {
110296465Sdelphij        ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)),
111296465Sdelphij        ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE))
112109998Smarkm} ASN1_ADB_END(POLICYQUALINFO, 0, pqualid, 0, &policydefault_tt, NULL);
113109998Smarkm
114109998SmarkmASN1_SEQUENCE(POLICYQUALINFO) = {
115296465Sdelphij        ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT),
116296465Sdelphij        ASN1_ADB_OBJECT(POLICYQUALINFO)
117109998Smarkm} ASN1_SEQUENCE_END(POLICYQUALINFO)
118109998Smarkm
119109998SmarkmIMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO)
120109998Smarkm
121109998SmarkmASN1_SEQUENCE(USERNOTICE) = {
122296465Sdelphij        ASN1_OPT(USERNOTICE, noticeref, NOTICEREF),
123296465Sdelphij        ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT)
124109998Smarkm} ASN1_SEQUENCE_END(USERNOTICE)
125109998Smarkm
126109998SmarkmIMPLEMENT_ASN1_FUNCTIONS(USERNOTICE)
127109998Smarkm
128109998SmarkmASN1_SEQUENCE(NOTICEREF) = {
129296465Sdelphij        ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT),
130296465Sdelphij        ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER)
131109998Smarkm} ASN1_SEQUENCE_END(NOTICEREF)
132109998Smarkm
133109998SmarkmIMPLEMENT_ASN1_FUNCTIONS(NOTICEREF)
134109998Smarkm
13555714Skrisstatic STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
136296465Sdelphij                                         X509V3_CTX *ctx, char *value)
13755714Skris{
138296465Sdelphij    STACK_OF(POLICYINFO) *pols = NULL;
139296465Sdelphij    char *pstr;
140296465Sdelphij    POLICYINFO *pol;
141296465Sdelphij    ASN1_OBJECT *pobj;
142296465Sdelphij    STACK_OF(CONF_VALUE) *vals;
143296465Sdelphij    CONF_VALUE *cnf;
144296465Sdelphij    int i, ia5org;
145296465Sdelphij    pols = sk_POLICYINFO_new_null();
146296465Sdelphij    if (pols == NULL) {
147296465Sdelphij        X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
148296465Sdelphij        return NULL;
149296465Sdelphij    }
150296465Sdelphij    vals = X509V3_parse_list(value);
151296465Sdelphij    if (vals == NULL) {
152296465Sdelphij        X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_X509V3_LIB);
153296465Sdelphij        goto err;
154296465Sdelphij    }
155296465Sdelphij    ia5org = 0;
156296465Sdelphij    for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
157296465Sdelphij        cnf = sk_CONF_VALUE_value(vals, i);
158296465Sdelphij        if (cnf->value || !cnf->name) {
159296465Sdelphij            X509V3err(X509V3_F_R2I_CERTPOL,
160296465Sdelphij                      X509V3_R_INVALID_POLICY_IDENTIFIER);
161296465Sdelphij            X509V3_conf_err(cnf);
162296465Sdelphij            goto err;
163296465Sdelphij        }
164296465Sdelphij        pstr = cnf->name;
165296465Sdelphij        if (!strcmp(pstr, "ia5org")) {
166296465Sdelphij            ia5org = 1;
167296465Sdelphij            continue;
168296465Sdelphij        } else if (*pstr == '@') {
169296465Sdelphij            STACK_OF(CONF_VALUE) *polsect;
170296465Sdelphij            polsect = X509V3_get_section(ctx, pstr + 1);
171296465Sdelphij            if (!polsect) {
172296465Sdelphij                X509V3err(X509V3_F_R2I_CERTPOL, X509V3_R_INVALID_SECTION);
17355714Skris
174296465Sdelphij                X509V3_conf_err(cnf);
175296465Sdelphij                goto err;
176296465Sdelphij            }
177296465Sdelphij            pol = policy_section(ctx, polsect, ia5org);
178296465Sdelphij            X509V3_section_free(ctx, polsect);
179296465Sdelphij            if (!pol)
180296465Sdelphij                goto err;
181296465Sdelphij        } else {
182296465Sdelphij            if (!(pobj = OBJ_txt2obj(cnf->name, 0))) {
183296465Sdelphij                X509V3err(X509V3_F_R2I_CERTPOL,
184296465Sdelphij                          X509V3_R_INVALID_OBJECT_IDENTIFIER);
185296465Sdelphij                X509V3_conf_err(cnf);
186296465Sdelphij                goto err;
187296465Sdelphij            }
188296465Sdelphij            pol = POLICYINFO_new();
189296465Sdelphij            pol->policyid = pobj;
190296465Sdelphij        }
191296465Sdelphij        if (!sk_POLICYINFO_push(pols, pol)) {
192296465Sdelphij            POLICYINFO_free(pol);
193296465Sdelphij            X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
194296465Sdelphij            goto err;
195296465Sdelphij        }
196296465Sdelphij    }
197296465Sdelphij    sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
198296465Sdelphij    return pols;
199296465Sdelphij err:
200296465Sdelphij    sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
201296465Sdelphij    sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
202296465Sdelphij    return NULL;
20355714Skris}
20455714Skris
20555714Skrisstatic POLICYINFO *policy_section(X509V3_CTX *ctx,
206296465Sdelphij                                  STACK_OF(CONF_VALUE) *polstrs, int ia5org)
20755714Skris{
208296465Sdelphij    int i;
209296465Sdelphij    CONF_VALUE *cnf;
210296465Sdelphij    POLICYINFO *pol;
211296465Sdelphij    POLICYQUALINFO *qual;
212296465Sdelphij    if (!(pol = POLICYINFO_new()))
213296465Sdelphij        goto merr;
214296465Sdelphij    for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) {
215296465Sdelphij        cnf = sk_CONF_VALUE_value(polstrs, i);
216296465Sdelphij        if (!strcmp(cnf->name, "policyIdentifier")) {
217296465Sdelphij            ASN1_OBJECT *pobj;
218296465Sdelphij            if (!(pobj = OBJ_txt2obj(cnf->value, 0))) {
219296465Sdelphij                X509V3err(X509V3_F_POLICY_SECTION,
220296465Sdelphij                          X509V3_R_INVALID_OBJECT_IDENTIFIER);
221296465Sdelphij                X509V3_conf_err(cnf);
222296465Sdelphij                goto err;
223296465Sdelphij            }
224296465Sdelphij            pol->policyid = pobj;
22555714Skris
226296465Sdelphij        } else if (!name_cmp(cnf->name, "CPS")) {
227296465Sdelphij            if (!pol->qualifiers)
228296465Sdelphij                pol->qualifiers = sk_POLICYQUALINFO_new_null();
229296465Sdelphij            if (!(qual = POLICYQUALINFO_new()))
230296465Sdelphij                goto merr;
231296465Sdelphij            if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
232296465Sdelphij                goto merr;
233296465Sdelphij            qual->pqualid = OBJ_nid2obj(NID_id_qt_cps);
234296465Sdelphij            qual->d.cpsuri = M_ASN1_IA5STRING_new();
235296465Sdelphij            if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value,
236296465Sdelphij                                 strlen(cnf->value)))
237296465Sdelphij                goto merr;
238296465Sdelphij        } else if (!name_cmp(cnf->name, "userNotice")) {
239296465Sdelphij            STACK_OF(CONF_VALUE) *unot;
240296465Sdelphij            if (*cnf->value != '@') {
241296465Sdelphij                X509V3err(X509V3_F_POLICY_SECTION,
242296465Sdelphij                          X509V3_R_EXPECTED_A_SECTION_NAME);
243296465Sdelphij                X509V3_conf_err(cnf);
244296465Sdelphij                goto err;
245296465Sdelphij            }
246296465Sdelphij            unot = X509V3_get_section(ctx, cnf->value + 1);
247296465Sdelphij            if (!unot) {
248296465Sdelphij                X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_INVALID_SECTION);
24955714Skris
250296465Sdelphij                X509V3_conf_err(cnf);
251296465Sdelphij                goto err;
252296465Sdelphij            }
253296465Sdelphij            qual = notice_section(ctx, unot, ia5org);
254296465Sdelphij            X509V3_section_free(ctx, unot);
255296465Sdelphij            if (!qual)
256296465Sdelphij                goto err;
257296465Sdelphij            if (!pol->qualifiers)
258296465Sdelphij                pol->qualifiers = sk_POLICYQUALINFO_new_null();
259296465Sdelphij            if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
260296465Sdelphij                goto merr;
261296465Sdelphij        } else {
262296465Sdelphij            X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_INVALID_OPTION);
26355714Skris
264296465Sdelphij            X509V3_conf_err(cnf);
265296465Sdelphij            goto err;
266296465Sdelphij        }
267296465Sdelphij    }
268296465Sdelphij    if (!pol->policyid) {
269296465Sdelphij        X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_NO_POLICY_IDENTIFIER);
270296465Sdelphij        goto err;
271296465Sdelphij    }
27255714Skris
273296465Sdelphij    return pol;
27455714Skris
275296465Sdelphij merr:
276296465Sdelphij    X509V3err(X509V3_F_POLICY_SECTION, ERR_R_MALLOC_FAILURE);
27755714Skris
278296465Sdelphij err:
279296465Sdelphij    POLICYINFO_free(pol);
280296465Sdelphij    return NULL;
281296465Sdelphij
28255714Skris}
28355714Skris
28455714Skrisstatic POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
285296465Sdelphij                                      STACK_OF(CONF_VALUE) *unot, int ia5org)
28655714Skris{
287296465Sdelphij    int i, ret;
288296465Sdelphij    CONF_VALUE *cnf;
289296465Sdelphij    USERNOTICE *not;
290296465Sdelphij    POLICYQUALINFO *qual;
291296465Sdelphij    if (!(qual = POLICYQUALINFO_new()))
292296465Sdelphij        goto merr;
293296465Sdelphij    qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice);
294296465Sdelphij    if (!(not = USERNOTICE_new()))
295296465Sdelphij        goto merr;
296296465Sdelphij    qual->d.usernotice = not;
297296465Sdelphij    for (i = 0; i < sk_CONF_VALUE_num(unot); i++) {
298296465Sdelphij        cnf = sk_CONF_VALUE_value(unot, i);
299296465Sdelphij        if (!strcmp(cnf->name, "explicitText")) {
300296465Sdelphij            not->exptext = M_ASN1_VISIBLESTRING_new();
301296465Sdelphij            if (!ASN1_STRING_set(not->exptext, cnf->value,
302296465Sdelphij                                 strlen(cnf->value)))
303296465Sdelphij                goto merr;
304296465Sdelphij        } else if (!strcmp(cnf->name, "organization")) {
305296465Sdelphij            NOTICEREF *nref;
306296465Sdelphij            if (!not->noticeref) {
307296465Sdelphij                if (!(nref = NOTICEREF_new()))
308296465Sdelphij                    goto merr;
309296465Sdelphij                not->noticeref = nref;
310296465Sdelphij            } else
311296465Sdelphij                nref = not->noticeref;
312296465Sdelphij            if (ia5org)
313296465Sdelphij                nref->organization->type = V_ASN1_IA5STRING;
314296465Sdelphij            else
315296465Sdelphij                nref->organization->type = V_ASN1_VISIBLESTRING;
316296465Sdelphij            if (!ASN1_STRING_set(nref->organization, cnf->value,
317296465Sdelphij                                 strlen(cnf->value)))
318296465Sdelphij                goto merr;
319296465Sdelphij        } else if (!strcmp(cnf->name, "noticeNumbers")) {
320296465Sdelphij            NOTICEREF *nref;
321296465Sdelphij            STACK_OF(CONF_VALUE) *nos;
322296465Sdelphij            if (!not->noticeref) {
323296465Sdelphij                if (!(nref = NOTICEREF_new()))
324296465Sdelphij                    goto merr;
325296465Sdelphij                not->noticeref = nref;
326296465Sdelphij            } else
327296465Sdelphij                nref = not->noticeref;
328296465Sdelphij            nos = X509V3_parse_list(cnf->value);
329296465Sdelphij            if (!nos || !sk_CONF_VALUE_num(nos)) {
330296465Sdelphij                X509V3err(X509V3_F_NOTICE_SECTION, X509V3_R_INVALID_NUMBERS);
331296465Sdelphij                X509V3_conf_err(cnf);
332296465Sdelphij                goto err;
333296465Sdelphij            }
334296465Sdelphij            ret = nref_nos(nref->noticenos, nos);
335296465Sdelphij            sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
336296465Sdelphij            if (!ret)
337296465Sdelphij                goto err;
338296465Sdelphij        } else {
339296465Sdelphij            X509V3err(X509V3_F_NOTICE_SECTION, X509V3_R_INVALID_OPTION);
340296465Sdelphij            X509V3_conf_err(cnf);
341296465Sdelphij            goto err;
342296465Sdelphij        }
343296465Sdelphij    }
34455714Skris
345296465Sdelphij    if (not->noticeref &&
346296465Sdelphij        (!not->noticeref->noticenos || !not->noticeref->organization)) {
347296465Sdelphij        X509V3err(X509V3_F_NOTICE_SECTION,
348296465Sdelphij                  X509V3_R_NEED_ORGANIZATION_AND_NUMBERS);
349296465Sdelphij        goto err;
350296465Sdelphij    }
35155714Skris
352296465Sdelphij    return qual;
35355714Skris
354296465Sdelphij merr:
355296465Sdelphij    X509V3err(X509V3_F_NOTICE_SECTION, ERR_R_MALLOC_FAILURE);
35655714Skris
357296465Sdelphij err:
358296465Sdelphij    POLICYQUALINFO_free(qual);
359296465Sdelphij    return NULL;
36055714Skris}
36155714Skris
362120631Snectarstatic int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos)
36355714Skris{
364296465Sdelphij    CONF_VALUE *cnf;
365296465Sdelphij    ASN1_INTEGER *aint;
36668651Skris
367296465Sdelphij    int i;
36868651Skris
369296465Sdelphij    for (i = 0; i < sk_CONF_VALUE_num(nos); i++) {
370296465Sdelphij        cnf = sk_CONF_VALUE_value(nos, i);
371296465Sdelphij        if (!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) {
372296465Sdelphij            X509V3err(X509V3_F_NREF_NOS, X509V3_R_INVALID_NUMBER);
373296465Sdelphij            goto err;
374296465Sdelphij        }
375296465Sdelphij        if (!sk_ASN1_INTEGER_push(nnums, aint))
376296465Sdelphij            goto merr;
377296465Sdelphij    }
378296465Sdelphij    return 1;
37955714Skris
380296465Sdelphij merr:
381296465Sdelphij    X509V3err(X509V3_F_NREF_NOS, ERR_R_MALLOC_FAILURE);
38255714Skris
383296465Sdelphij err:
384296465Sdelphij    sk_ASN1_INTEGER_pop_free(nnums, ASN1_STRING_free);
385296465Sdelphij    return 0;
38655714Skris}
38755714Skris
38855714Skrisstatic int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
389296465Sdelphij                       BIO *out, int indent)
39055714Skris{
391296465Sdelphij    int i;
392296465Sdelphij    POLICYINFO *pinfo;
393296465Sdelphij    /* First print out the policy OIDs */
394296465Sdelphij    for (i = 0; i < sk_POLICYINFO_num(pol); i++) {
395296465Sdelphij        pinfo = sk_POLICYINFO_value(pol, i);
396296465Sdelphij        BIO_printf(out, "%*sPolicy: ", indent, "");
397296465Sdelphij        i2a_ASN1_OBJECT(out, pinfo->policyid);
398296465Sdelphij        BIO_puts(out, "\n");
399296465Sdelphij        if (pinfo->qualifiers)
400296465Sdelphij            print_qualifiers(out, pinfo->qualifiers, indent + 2);
401296465Sdelphij    }
402296465Sdelphij    return 1;
40355714Skris}
40455714Skris
40555714Skrisstatic void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
406296465Sdelphij                             int indent)
40755714Skris{
408296465Sdelphij    POLICYQUALINFO *qualinfo;
409296465Sdelphij    int i;
410296465Sdelphij    for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) {
411296465Sdelphij        qualinfo = sk_POLICYQUALINFO_value(quals, i);
412296465Sdelphij        switch (OBJ_obj2nid(qualinfo->pqualid)) {
413296465Sdelphij        case NID_id_qt_cps:
414296465Sdelphij            BIO_printf(out, "%*sCPS: %s\n", indent, "",
415296465Sdelphij                       qualinfo->d.cpsuri->data);
416296465Sdelphij            break;
41755714Skris
418296465Sdelphij        case NID_id_qt_unotice:
419296465Sdelphij            BIO_printf(out, "%*sUser Notice:\n", indent, "");
420296465Sdelphij            print_notice(out, qualinfo->d.usernotice, indent + 2);
421296465Sdelphij            break;
422296465Sdelphij
423296465Sdelphij        default:
424296465Sdelphij            BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, "");
425296465Sdelphij
426296465Sdelphij            i2a_ASN1_OBJECT(out, qualinfo->pqualid);
427296465Sdelphij            BIO_puts(out, "\n");
428296465Sdelphij            break;
429296465Sdelphij        }
430296465Sdelphij    }
43155714Skris}
43255714Skris
43355714Skrisstatic void print_notice(BIO *out, USERNOTICE *notice, int indent)
43455714Skris{
435296465Sdelphij    int i;
436296465Sdelphij    if (notice->noticeref) {
437296465Sdelphij        NOTICEREF *ref;
438296465Sdelphij        ref = notice->noticeref;
439296465Sdelphij        BIO_printf(out, "%*sOrganization: %s\n", indent, "",
440296465Sdelphij                   ref->organization->data);
441296465Sdelphij        BIO_printf(out, "%*sNumber%s: ", indent, "",
442296465Sdelphij                   sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : "");
443296465Sdelphij        for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) {
444296465Sdelphij            ASN1_INTEGER *num;
445296465Sdelphij            char *tmp;
446296465Sdelphij            num = sk_ASN1_INTEGER_value(ref->noticenos, i);
447296465Sdelphij            if (i)
448296465Sdelphij                BIO_puts(out, ", ");
449296465Sdelphij            tmp = i2s_ASN1_INTEGER(NULL, num);
450296465Sdelphij            BIO_puts(out, tmp);
451296465Sdelphij            OPENSSL_free(tmp);
452296465Sdelphij        }
453296465Sdelphij        BIO_puts(out, "\n");
454296465Sdelphij    }
455296465Sdelphij    if (notice->exptext)
456296465Sdelphij        BIO_printf(out, "%*sExplicit Text: %s\n", indent, "",
457296465Sdelphij                   notice->exptext->data);
45855714Skris}
45955714Skris
460160814Ssimonvoid X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent)
461296465Sdelphij{
462296465Sdelphij    const X509_POLICY_DATA *dat = node->data;
463160814Ssimon
464296465Sdelphij    BIO_printf(out, "%*sPolicy: ", indent, "");
465296465Sdelphij
466296465Sdelphij    i2a_ASN1_OBJECT(out, dat->valid_policy);
467296465Sdelphij    BIO_puts(out, "\n");
468296465Sdelphij    BIO_printf(out, "%*s%s\n", indent + 2, "",
469296465Sdelphij               node_data_critical(dat) ? "Critical" : "Non Critical");
470296465Sdelphij    if (dat->qualifier_set)
471296465Sdelphij        print_qualifiers(out, dat->qualifier_set, indent + 2);
472296465Sdelphij    else
473296465Sdelphij        BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, "");
474296465Sdelphij}
475296465Sdelphij
476194206SsimonIMPLEMENT_STACK_OF(X509_POLICY_NODE)
477