155714Skris/* v3_cpols.c */
2280297Sjkim/*
3280297Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4280297Sjkim * 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
14280297Sjkim *    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
71280297Sjkimstatic int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
72280297Sjkim                       BIO *out, int indent);
73280297Sjkimstatic STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
74280297Sjkim                                         X509V3_CTX *ctx, char *value);
75280297Sjkimstatic void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
76280297Sjkim                             int indent);
7755714Skrisstatic void print_notice(BIO *out, USERNOTICE *notice, int indent);
7855714Skrisstatic POLICYINFO *policy_section(X509V3_CTX *ctx,
79280297Sjkim                                  STACK_OF(CONF_VALUE) *polstrs, int ia5org);
8055714Skrisstatic POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
81280297Sjkim                                      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 = {
85280297Sjkim    NID_certificate_policies, 0, ASN1_ITEM_ref(CERTIFICATEPOLICIES),
86280297Sjkim    0, 0, 0, 0,
87280297Sjkim    0, 0,
88280297Sjkim    0, 0,
89280297Sjkim    (X509V3_EXT_I2R)i2r_certpol,
90280297Sjkim    (X509V3_EXT_R2I)r2i_certpol,
91280297Sjkim    NULL
9255714Skris};
9355714Skris
94280297SjkimASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) =
95280297Sjkim        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) = {
101280297Sjkim        ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT),
102280297Sjkim        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) = {
110280297Sjkim        ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)),
111280297Sjkim        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) = {
115280297Sjkim        ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT),
116280297Sjkim        ASN1_ADB_OBJECT(POLICYQUALINFO)
117109998Smarkm} ASN1_SEQUENCE_END(POLICYQUALINFO)
118109998Smarkm
119109998SmarkmIMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO)
120109998Smarkm
121109998SmarkmASN1_SEQUENCE(USERNOTICE) = {
122280297Sjkim        ASN1_OPT(USERNOTICE, noticeref, NOTICEREF),
123280297Sjkim        ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT)
124109998Smarkm} ASN1_SEQUENCE_END(USERNOTICE)
125109998Smarkm
126109998SmarkmIMPLEMENT_ASN1_FUNCTIONS(USERNOTICE)
127109998Smarkm
128109998SmarkmASN1_SEQUENCE(NOTICEREF) = {
129280297Sjkim        ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT),
130280297Sjkim        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,
136280297Sjkim                                         X509V3_CTX *ctx, char *value)
13755714Skris{
138280297Sjkim    STACK_OF(POLICYINFO) *pols = NULL;
139280297Sjkim    char *pstr;
140280297Sjkim    POLICYINFO *pol;
141280297Sjkim    ASN1_OBJECT *pobj;
142280297Sjkim    STACK_OF(CONF_VALUE) *vals;
143280297Sjkim    CONF_VALUE *cnf;
144280297Sjkim    int i, ia5org;
145280297Sjkim    pols = sk_POLICYINFO_new_null();
146280297Sjkim    if (pols == NULL) {
147280297Sjkim        X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
148280297Sjkim        return NULL;
149280297Sjkim    }
150280297Sjkim    vals = X509V3_parse_list(value);
151280297Sjkim    if (vals == NULL) {
152280297Sjkim        X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_X509V3_LIB);
153280297Sjkim        goto err;
154280297Sjkim    }
155280297Sjkim    ia5org = 0;
156280297Sjkim    for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
157280297Sjkim        cnf = sk_CONF_VALUE_value(vals, i);
158280297Sjkim        if (cnf->value || !cnf->name) {
159280297Sjkim            X509V3err(X509V3_F_R2I_CERTPOL,
160280297Sjkim                      X509V3_R_INVALID_POLICY_IDENTIFIER);
161280297Sjkim            X509V3_conf_err(cnf);
162280297Sjkim            goto err;
163280297Sjkim        }
164280297Sjkim        pstr = cnf->name;
165280297Sjkim        if (!strcmp(pstr, "ia5org")) {
166280297Sjkim            ia5org = 1;
167280297Sjkim            continue;
168280297Sjkim        } else if (*pstr == '@') {
169280297Sjkim            STACK_OF(CONF_VALUE) *polsect;
170280297Sjkim            polsect = X509V3_get_section(ctx, pstr + 1);
171280297Sjkim            if (!polsect) {
172280297Sjkim                X509V3err(X509V3_F_R2I_CERTPOL, X509V3_R_INVALID_SECTION);
17355714Skris
174280297Sjkim                X509V3_conf_err(cnf);
175280297Sjkim                goto err;
176280297Sjkim            }
177280297Sjkim            pol = policy_section(ctx, polsect, ia5org);
178280297Sjkim            X509V3_section_free(ctx, polsect);
179280297Sjkim            if (!pol)
180280297Sjkim                goto err;
181280297Sjkim        } else {
182280297Sjkim            if (!(pobj = OBJ_txt2obj(cnf->name, 0))) {
183280297Sjkim                X509V3err(X509V3_F_R2I_CERTPOL,
184280297Sjkim                          X509V3_R_INVALID_OBJECT_IDENTIFIER);
185280297Sjkim                X509V3_conf_err(cnf);
186280297Sjkim                goto err;
187280297Sjkim            }
188280297Sjkim            pol = POLICYINFO_new();
189291719Sjkim            if (pol == NULL) {
190291719Sjkim                X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
191291719Sjkim                goto err;
192291719Sjkim            }
193280297Sjkim            pol->policyid = pobj;
194280297Sjkim        }
195280297Sjkim        if (!sk_POLICYINFO_push(pols, pol)) {
196280297Sjkim            POLICYINFO_free(pol);
197280297Sjkim            X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
198280297Sjkim            goto err;
199280297Sjkim        }
200280297Sjkim    }
201280297Sjkim    sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
202280297Sjkim    return pols;
203280297Sjkim err:
204280297Sjkim    sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
205280297Sjkim    sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
206280297Sjkim    return NULL;
20755714Skris}
20855714Skris
20955714Skrisstatic POLICYINFO *policy_section(X509V3_CTX *ctx,
210280297Sjkim                                  STACK_OF(CONF_VALUE) *polstrs, int ia5org)
21155714Skris{
212280297Sjkim    int i;
213280297Sjkim    CONF_VALUE *cnf;
214280297Sjkim    POLICYINFO *pol;
215280297Sjkim    POLICYQUALINFO *qual;
216280297Sjkim    if (!(pol = POLICYINFO_new()))
217280297Sjkim        goto merr;
218280297Sjkim    for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) {
219280297Sjkim        cnf = sk_CONF_VALUE_value(polstrs, i);
220280297Sjkim        if (!strcmp(cnf->name, "policyIdentifier")) {
221280297Sjkim            ASN1_OBJECT *pobj;
222280297Sjkim            if (!(pobj = OBJ_txt2obj(cnf->value, 0))) {
223280297Sjkim                X509V3err(X509V3_F_POLICY_SECTION,
224280297Sjkim                          X509V3_R_INVALID_OBJECT_IDENTIFIER);
225280297Sjkim                X509V3_conf_err(cnf);
226280297Sjkim                goto err;
227280297Sjkim            }
228280297Sjkim            pol->policyid = pobj;
22955714Skris
230280297Sjkim        } else if (!name_cmp(cnf->name, "CPS")) {
231280297Sjkim            if (!pol->qualifiers)
232280297Sjkim                pol->qualifiers = sk_POLICYQUALINFO_new_null();
233280297Sjkim            if (!(qual = POLICYQUALINFO_new()))
234280297Sjkim                goto merr;
235280297Sjkim            if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
236280297Sjkim                goto merr;
237284283Sjkim            if (!(qual->pqualid = OBJ_nid2obj(NID_id_qt_cps))) {
238280297Sjkim                X509V3err(X509V3_F_POLICY_SECTION, ERR_R_INTERNAL_ERROR);
239280297Sjkim                goto err;
240280297Sjkim            }
241284283Sjkim            if (!(qual->d.cpsuri = M_ASN1_IA5STRING_new()))
242280297Sjkim                goto merr;
243280297Sjkim            if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value,
244280297Sjkim                                 strlen(cnf->value)))
245280297Sjkim                goto merr;
246280297Sjkim        } else if (!name_cmp(cnf->name, "userNotice")) {
247280297Sjkim            STACK_OF(CONF_VALUE) *unot;
248280297Sjkim            if (*cnf->value != '@') {
249280297Sjkim                X509V3err(X509V3_F_POLICY_SECTION,
250280297Sjkim                          X509V3_R_EXPECTED_A_SECTION_NAME);
251280297Sjkim                X509V3_conf_err(cnf);
252280297Sjkim                goto err;
253280297Sjkim            }
254280297Sjkim            unot = X509V3_get_section(ctx, cnf->value + 1);
255280297Sjkim            if (!unot) {
256280297Sjkim                X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_INVALID_SECTION);
25755714Skris
258280297Sjkim                X509V3_conf_err(cnf);
259280297Sjkim                goto err;
260280297Sjkim            }
261280297Sjkim            qual = notice_section(ctx, unot, ia5org);
262280297Sjkim            X509V3_section_free(ctx, unot);
263280297Sjkim            if (!qual)
264280297Sjkim                goto err;
265280297Sjkim            if (!pol->qualifiers)
266280297Sjkim                pol->qualifiers = sk_POLICYQUALINFO_new_null();
267280297Sjkim            if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
268280297Sjkim                goto merr;
269280297Sjkim        } else {
270280297Sjkim            X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_INVALID_OPTION);
27155714Skris
272280297Sjkim            X509V3_conf_err(cnf);
273280297Sjkim            goto err;
274280297Sjkim        }
275280297Sjkim    }
276280297Sjkim    if (!pol->policyid) {
277280297Sjkim        X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_NO_POLICY_IDENTIFIER);
278280297Sjkim        goto err;
279280297Sjkim    }
28055714Skris
281280297Sjkim    return pol;
28255714Skris
283280297Sjkim merr:
284280297Sjkim    X509V3err(X509V3_F_POLICY_SECTION, ERR_R_MALLOC_FAILURE);
28555714Skris
286280297Sjkim err:
287280297Sjkim    POLICYINFO_free(pol);
288280297Sjkim    return NULL;
289280297Sjkim
29055714Skris}
29155714Skris
29255714Skrisstatic POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
293280297Sjkim                                      STACK_OF(CONF_VALUE) *unot, int ia5org)
29455714Skris{
295280297Sjkim    int i, ret;
296280297Sjkim    CONF_VALUE *cnf;
297280297Sjkim    USERNOTICE *not;
298280297Sjkim    POLICYQUALINFO *qual;
299280297Sjkim    if (!(qual = POLICYQUALINFO_new()))
300280297Sjkim        goto merr;
301284283Sjkim    if (!(qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice))) {
302280297Sjkim        X509V3err(X509V3_F_NOTICE_SECTION, ERR_R_INTERNAL_ERROR);
303280297Sjkim        goto err;
304280297Sjkim    }
305280297Sjkim    if (!(not = USERNOTICE_new()))
306280297Sjkim        goto merr;
307280297Sjkim    qual->d.usernotice = not;
308280297Sjkim    for (i = 0; i < sk_CONF_VALUE_num(unot); i++) {
309280297Sjkim        cnf = sk_CONF_VALUE_value(unot, i);
310280297Sjkim        if (!strcmp(cnf->name, "explicitText")) {
311284283Sjkim            if (!(not->exptext = M_ASN1_VISIBLESTRING_new()))
312280297Sjkim                goto merr;
313280297Sjkim            if (!ASN1_STRING_set(not->exptext, cnf->value,
314280297Sjkim                                 strlen(cnf->value)))
315280297Sjkim                goto merr;
316280297Sjkim        } else if (!strcmp(cnf->name, "organization")) {
317280297Sjkim            NOTICEREF *nref;
318280297Sjkim            if (!not->noticeref) {
319280297Sjkim                if (!(nref = NOTICEREF_new()))
320280297Sjkim                    goto merr;
321280297Sjkim                not->noticeref = nref;
322280297Sjkim            } else
323280297Sjkim                nref = not->noticeref;
324280297Sjkim            if (ia5org)
325280297Sjkim                nref->organization->type = V_ASN1_IA5STRING;
326280297Sjkim            else
327280297Sjkim                nref->organization->type = V_ASN1_VISIBLESTRING;
328280297Sjkim            if (!ASN1_STRING_set(nref->organization, cnf->value,
329280297Sjkim                                 strlen(cnf->value)))
330280297Sjkim                goto merr;
331280297Sjkim        } else if (!strcmp(cnf->name, "noticeNumbers")) {
332280297Sjkim            NOTICEREF *nref;
333280297Sjkim            STACK_OF(CONF_VALUE) *nos;
334280297Sjkim            if (!not->noticeref) {
335280297Sjkim                if (!(nref = NOTICEREF_new()))
336280297Sjkim                    goto merr;
337280297Sjkim                not->noticeref = nref;
338280297Sjkim            } else
339280297Sjkim                nref = not->noticeref;
340280297Sjkim            nos = X509V3_parse_list(cnf->value);
341280297Sjkim            if (!nos || !sk_CONF_VALUE_num(nos)) {
342280297Sjkim                X509V3err(X509V3_F_NOTICE_SECTION, X509V3_R_INVALID_NUMBERS);
343280297Sjkim                X509V3_conf_err(cnf);
344280297Sjkim                goto err;
345280297Sjkim            }
346280297Sjkim            ret = nref_nos(nref->noticenos, nos);
347280297Sjkim            sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
348280297Sjkim            if (!ret)
349280297Sjkim                goto err;
350280297Sjkim        } else {
351280297Sjkim            X509V3err(X509V3_F_NOTICE_SECTION, X509V3_R_INVALID_OPTION);
352280297Sjkim            X509V3_conf_err(cnf);
353280297Sjkim            goto err;
354280297Sjkim        }
355280297Sjkim    }
35655714Skris
357280297Sjkim    if (not->noticeref &&
358280297Sjkim        (!not->noticeref->noticenos || !not->noticeref->organization)) {
359280297Sjkim        X509V3err(X509V3_F_NOTICE_SECTION,
360280297Sjkim                  X509V3_R_NEED_ORGANIZATION_AND_NUMBERS);
361280297Sjkim        goto err;
362280297Sjkim    }
36355714Skris
364280297Sjkim    return qual;
36555714Skris
366280297Sjkim merr:
367280297Sjkim    X509V3err(X509V3_F_NOTICE_SECTION, ERR_R_MALLOC_FAILURE);
36855714Skris
369280297Sjkim err:
370280297Sjkim    POLICYQUALINFO_free(qual);
371280297Sjkim    return NULL;
37255714Skris}
37355714Skris
374120631Snectarstatic int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos)
37555714Skris{
376280297Sjkim    CONF_VALUE *cnf;
377280297Sjkim    ASN1_INTEGER *aint;
37868651Skris
379280297Sjkim    int i;
38068651Skris
381280297Sjkim    for (i = 0; i < sk_CONF_VALUE_num(nos); i++) {
382280297Sjkim        cnf = sk_CONF_VALUE_value(nos, i);
383280297Sjkim        if (!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) {
384280297Sjkim            X509V3err(X509V3_F_NREF_NOS, X509V3_R_INVALID_NUMBER);
385280297Sjkim            goto err;
386280297Sjkim        }
387280297Sjkim        if (!sk_ASN1_INTEGER_push(nnums, aint))
388280297Sjkim            goto merr;
389280297Sjkim    }
390280297Sjkim    return 1;
39155714Skris
392280297Sjkim merr:
393325335Sjkim    ASN1_INTEGER_free(aint);
394280297Sjkim    X509V3err(X509V3_F_NREF_NOS, ERR_R_MALLOC_FAILURE);
39555714Skris
396280297Sjkim err:
397280297Sjkim    return 0;
39855714Skris}
39955714Skris
40055714Skrisstatic int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
401280297Sjkim                       BIO *out, int indent)
40255714Skris{
403280297Sjkim    int i;
404280297Sjkim    POLICYINFO *pinfo;
405280297Sjkim    /* First print out the policy OIDs */
406280297Sjkim    for (i = 0; i < sk_POLICYINFO_num(pol); i++) {
407280297Sjkim        pinfo = sk_POLICYINFO_value(pol, i);
408280297Sjkim        BIO_printf(out, "%*sPolicy: ", indent, "");
409280297Sjkim        i2a_ASN1_OBJECT(out, pinfo->policyid);
410280297Sjkim        BIO_puts(out, "\n");
411280297Sjkim        if (pinfo->qualifiers)
412280297Sjkim            print_qualifiers(out, pinfo->qualifiers, indent + 2);
413280297Sjkim    }
414280297Sjkim    return 1;
41555714Skris}
41655714Skris
41755714Skrisstatic void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
418280297Sjkim                             int indent)
41955714Skris{
420280297Sjkim    POLICYQUALINFO *qualinfo;
421280297Sjkim    int i;
422280297Sjkim    for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) {
423280297Sjkim        qualinfo = sk_POLICYQUALINFO_value(quals, i);
424280297Sjkim        switch (OBJ_obj2nid(qualinfo->pqualid)) {
425280297Sjkim        case NID_id_qt_cps:
426280297Sjkim            BIO_printf(out, "%*sCPS: %s\n", indent, "",
427280297Sjkim                       qualinfo->d.cpsuri->data);
428280297Sjkim            break;
42955714Skris
430280297Sjkim        case NID_id_qt_unotice:
431280297Sjkim            BIO_printf(out, "%*sUser Notice:\n", indent, "");
432280297Sjkim            print_notice(out, qualinfo->d.usernotice, indent + 2);
433280297Sjkim            break;
434280297Sjkim
435280297Sjkim        default:
436280297Sjkim            BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, "");
437280297Sjkim
438280297Sjkim            i2a_ASN1_OBJECT(out, qualinfo->pqualid);
439280297Sjkim            BIO_puts(out, "\n");
440280297Sjkim            break;
441280297Sjkim        }
442280297Sjkim    }
44355714Skris}
44455714Skris
44555714Skrisstatic void print_notice(BIO *out, USERNOTICE *notice, int indent)
44655714Skris{
447280297Sjkim    int i;
448280297Sjkim    if (notice->noticeref) {
449280297Sjkim        NOTICEREF *ref;
450280297Sjkim        ref = notice->noticeref;
451280297Sjkim        BIO_printf(out, "%*sOrganization: %s\n", indent, "",
452280297Sjkim                   ref->organization->data);
453280297Sjkim        BIO_printf(out, "%*sNumber%s: ", indent, "",
454280297Sjkim                   sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : "");
455280297Sjkim        for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) {
456280297Sjkim            ASN1_INTEGER *num;
457280297Sjkim            char *tmp;
458280297Sjkim            num = sk_ASN1_INTEGER_value(ref->noticenos, i);
459280297Sjkim            if (i)
460280297Sjkim                BIO_puts(out, ", ");
461325335Sjkim            if (num == NULL)
462325335Sjkim                BIO_puts(out, "(null)");
463325335Sjkim            else {
464325335Sjkim                tmp = i2s_ASN1_INTEGER(NULL, num);
465325335Sjkim                if (tmp == NULL)
466325335Sjkim                    return;
467325335Sjkim                BIO_puts(out, tmp);
468325335Sjkim                OPENSSL_free(tmp);
469325335Sjkim            }
470280297Sjkim        }
471280297Sjkim        BIO_puts(out, "\n");
472280297Sjkim    }
473280297Sjkim    if (notice->exptext)
474280297Sjkim        BIO_printf(out, "%*sExplicit Text: %s\n", indent, "",
475280297Sjkim                   notice->exptext->data);
47655714Skris}
47755714Skris
478160814Ssimonvoid X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent)
479280297Sjkim{
480280297Sjkim    const X509_POLICY_DATA *dat = node->data;
481160814Ssimon
482280297Sjkim    BIO_printf(out, "%*sPolicy: ", indent, "");
483238405Sjkim
484280297Sjkim    i2a_ASN1_OBJECT(out, dat->valid_policy);
485280297Sjkim    BIO_puts(out, "\n");
486280297Sjkim    BIO_printf(out, "%*s%s\n", indent + 2, "",
487280297Sjkim               node_data_critical(dat) ? "Critical" : "Non Critical");
488280297Sjkim    if (dat->qualifier_set)
489280297Sjkim        print_qualifiers(out, dat->qualifier_set, indent + 2);
490280297Sjkim    else
491280297Sjkim        BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, "");
492280297Sjkim}
493238405Sjkim
494280297Sjkim
495194206SsimonIMPLEMENT_STACK_OF(X509_POLICY_NODE)
496280297Sjkim
497238405SjkimIMPLEMENT_STACK_OF(X509_POLICY_DATA)
498