1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <stdio.h>
11e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
12e1051a39Sopenharmony_ci#include <openssl/conf.h>
13e1051a39Sopenharmony_ci#include <openssl/asn1.h>
14e1051a39Sopenharmony_ci#include <openssl/asn1t.h>
15e1051a39Sopenharmony_ci#include <openssl/x509v3.h>
16e1051a39Sopenharmony_ci
17e1051a39Sopenharmony_ci#include "x509_local.h"
18e1051a39Sopenharmony_ci#include "pcy_local.h"
19e1051a39Sopenharmony_ci#include "ext_dat.h"
20e1051a39Sopenharmony_ci
21e1051a39Sopenharmony_ci/* Certificate policies extension support: this one is a bit complex... */
22e1051a39Sopenharmony_ci
23e1051a39Sopenharmony_cistatic int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
24e1051a39Sopenharmony_ci                       BIO *out, int indent);
25e1051a39Sopenharmony_cistatic STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
26e1051a39Sopenharmony_ci                                         X509V3_CTX *ctx, const char *value);
27e1051a39Sopenharmony_cistatic void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
28e1051a39Sopenharmony_ci                             int indent);
29e1051a39Sopenharmony_cistatic void print_notice(BIO *out, USERNOTICE *notice, int indent);
30e1051a39Sopenharmony_cistatic POLICYINFO *policy_section(X509V3_CTX *ctx,
31e1051a39Sopenharmony_ci                                  STACK_OF(CONF_VALUE) *polstrs, int ia5org);
32e1051a39Sopenharmony_cistatic POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
33e1051a39Sopenharmony_ci                                      STACK_OF(CONF_VALUE) *unot, int ia5org);
34e1051a39Sopenharmony_cistatic int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos);
35e1051a39Sopenharmony_cistatic int displaytext_str2tag(const char *tagstr, unsigned int *tag_len);
36e1051a39Sopenharmony_cistatic int displaytext_get_tag_len(const char *tagstr);
37e1051a39Sopenharmony_ci
38e1051a39Sopenharmony_ciconst X509V3_EXT_METHOD ossl_v3_cpols = {
39e1051a39Sopenharmony_ci    NID_certificate_policies, 0, ASN1_ITEM_ref(CERTIFICATEPOLICIES),
40e1051a39Sopenharmony_ci    0, 0, 0, 0,
41e1051a39Sopenharmony_ci    0, 0,
42e1051a39Sopenharmony_ci    0, 0,
43e1051a39Sopenharmony_ci    (X509V3_EXT_I2R)i2r_certpol,
44e1051a39Sopenharmony_ci    (X509V3_EXT_R2I)r2i_certpol,
45e1051a39Sopenharmony_ci    NULL
46e1051a39Sopenharmony_ci};
47e1051a39Sopenharmony_ci
48e1051a39Sopenharmony_ciASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) =
49e1051a39Sopenharmony_ci        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO)
50e1051a39Sopenharmony_ciASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES)
51e1051a39Sopenharmony_ci
52e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
53e1051a39Sopenharmony_ci
54e1051a39Sopenharmony_ciASN1_SEQUENCE(POLICYINFO) = {
55e1051a39Sopenharmony_ci        ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT),
56e1051a39Sopenharmony_ci        ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO)
57e1051a39Sopenharmony_ci} ASN1_SEQUENCE_END(POLICYINFO)
58e1051a39Sopenharmony_ci
59e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(POLICYINFO)
60e1051a39Sopenharmony_ci
61e1051a39Sopenharmony_ciASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other, ASN1_ANY);
62e1051a39Sopenharmony_ci
63e1051a39Sopenharmony_ciASN1_ADB(POLICYQUALINFO) = {
64e1051a39Sopenharmony_ci        ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)),
65e1051a39Sopenharmony_ci        ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE))
66e1051a39Sopenharmony_ci} ASN1_ADB_END(POLICYQUALINFO, 0, pqualid, 0, &policydefault_tt, NULL);
67e1051a39Sopenharmony_ci
68e1051a39Sopenharmony_ciASN1_SEQUENCE(POLICYQUALINFO) = {
69e1051a39Sopenharmony_ci        ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT),
70e1051a39Sopenharmony_ci        ASN1_ADB_OBJECT(POLICYQUALINFO)
71e1051a39Sopenharmony_ci} ASN1_SEQUENCE_END(POLICYQUALINFO)
72e1051a39Sopenharmony_ci
73e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO)
74e1051a39Sopenharmony_ci
75e1051a39Sopenharmony_ciASN1_SEQUENCE(USERNOTICE) = {
76e1051a39Sopenharmony_ci        ASN1_OPT(USERNOTICE, noticeref, NOTICEREF),
77e1051a39Sopenharmony_ci        ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT)
78e1051a39Sopenharmony_ci} ASN1_SEQUENCE_END(USERNOTICE)
79e1051a39Sopenharmony_ci
80e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(USERNOTICE)
81e1051a39Sopenharmony_ci
82e1051a39Sopenharmony_ciASN1_SEQUENCE(NOTICEREF) = {
83e1051a39Sopenharmony_ci        ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT),
84e1051a39Sopenharmony_ci        ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER)
85e1051a39Sopenharmony_ci} ASN1_SEQUENCE_END(NOTICEREF)
86e1051a39Sopenharmony_ci
87e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(NOTICEREF)
88e1051a39Sopenharmony_ci
89e1051a39Sopenharmony_cistatic STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
90e1051a39Sopenharmony_ci                                         X509V3_CTX *ctx, const char *value)
91e1051a39Sopenharmony_ci{
92e1051a39Sopenharmony_ci    STACK_OF(POLICYINFO) *pols;
93e1051a39Sopenharmony_ci    char *pstr;
94e1051a39Sopenharmony_ci    POLICYINFO *pol;
95e1051a39Sopenharmony_ci    ASN1_OBJECT *pobj;
96e1051a39Sopenharmony_ci    STACK_OF(CONF_VALUE) *vals = X509V3_parse_list(value);
97e1051a39Sopenharmony_ci    CONF_VALUE *cnf;
98e1051a39Sopenharmony_ci    const int num = sk_CONF_VALUE_num(vals);
99e1051a39Sopenharmony_ci    int i, ia5org;
100e1051a39Sopenharmony_ci
101e1051a39Sopenharmony_ci    if (vals == NULL) {
102e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509V3, ERR_R_X509V3_LIB);
103e1051a39Sopenharmony_ci        return NULL;
104e1051a39Sopenharmony_ci    }
105e1051a39Sopenharmony_ci
106e1051a39Sopenharmony_ci    pols = sk_POLICYINFO_new_reserve(NULL, num);
107e1051a39Sopenharmony_ci    if (pols == NULL) {
108e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
109e1051a39Sopenharmony_ci        goto err;
110e1051a39Sopenharmony_ci    }
111e1051a39Sopenharmony_ci
112e1051a39Sopenharmony_ci    ia5org = 0;
113e1051a39Sopenharmony_ci    for (i = 0; i < num; i++) {
114e1051a39Sopenharmony_ci        cnf = sk_CONF_VALUE_value(vals, i);
115e1051a39Sopenharmony_ci        if (cnf->value != NULL || cnf->name == NULL) {
116e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_POLICY_IDENTIFIER);
117e1051a39Sopenharmony_ci            X509V3_conf_add_error_name_value(cnf);
118e1051a39Sopenharmony_ci            goto err;
119e1051a39Sopenharmony_ci        }
120e1051a39Sopenharmony_ci        pstr = cnf->name;
121e1051a39Sopenharmony_ci        if (strcmp(pstr, "ia5org") == 0) {
122e1051a39Sopenharmony_ci            ia5org = 1;
123e1051a39Sopenharmony_ci            continue;
124e1051a39Sopenharmony_ci        } else if (*pstr == '@') {
125e1051a39Sopenharmony_ci            STACK_OF(CONF_VALUE) *polsect;
126e1051a39Sopenharmony_ci
127e1051a39Sopenharmony_ci            polsect = X509V3_get_section(ctx, pstr + 1);
128e1051a39Sopenharmony_ci            if (polsect == NULL) {
129e1051a39Sopenharmony_ci                ERR_raise_data(ERR_LIB_X509V3, X509V3_R_INVALID_SECTION,
130e1051a39Sopenharmony_ci                               "%s", cnf->name);
131e1051a39Sopenharmony_ci                goto err;
132e1051a39Sopenharmony_ci            }
133e1051a39Sopenharmony_ci            pol = policy_section(ctx, polsect, ia5org);
134e1051a39Sopenharmony_ci            X509V3_section_free(ctx, polsect);
135e1051a39Sopenharmony_ci            if (pol == NULL)
136e1051a39Sopenharmony_ci                goto err;
137e1051a39Sopenharmony_ci        } else {
138e1051a39Sopenharmony_ci            if ((pobj = OBJ_txt2obj(cnf->name, 0)) == NULL) {
139e1051a39Sopenharmony_ci                ERR_raise_data(ERR_LIB_X509V3,
140e1051a39Sopenharmony_ci                               X509V3_R_INVALID_OBJECT_IDENTIFIER,
141e1051a39Sopenharmony_ci                               "%s", cnf->name);
142e1051a39Sopenharmony_ci                goto err;
143e1051a39Sopenharmony_ci            }
144e1051a39Sopenharmony_ci            pol = POLICYINFO_new();
145e1051a39Sopenharmony_ci            if (pol == NULL) {
146e1051a39Sopenharmony_ci                ASN1_OBJECT_free(pobj);
147e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
148e1051a39Sopenharmony_ci                goto err;
149e1051a39Sopenharmony_ci            }
150e1051a39Sopenharmony_ci            pol->policyid = pobj;
151e1051a39Sopenharmony_ci        }
152e1051a39Sopenharmony_ci        if (!sk_POLICYINFO_push(pols, pol)) {
153e1051a39Sopenharmony_ci            POLICYINFO_free(pol);
154e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
155e1051a39Sopenharmony_ci            goto err;
156e1051a39Sopenharmony_ci        }
157e1051a39Sopenharmony_ci    }
158e1051a39Sopenharmony_ci    sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
159e1051a39Sopenharmony_ci    return pols;
160e1051a39Sopenharmony_ci err:
161e1051a39Sopenharmony_ci    sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
162e1051a39Sopenharmony_ci    sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
163e1051a39Sopenharmony_ci    return NULL;
164e1051a39Sopenharmony_ci}
165e1051a39Sopenharmony_ci
166e1051a39Sopenharmony_cistatic POLICYINFO *policy_section(X509V3_CTX *ctx,
167e1051a39Sopenharmony_ci                                  STACK_OF(CONF_VALUE) *polstrs, int ia5org)
168e1051a39Sopenharmony_ci{
169e1051a39Sopenharmony_ci    int i;
170e1051a39Sopenharmony_ci    CONF_VALUE *cnf;
171e1051a39Sopenharmony_ci    POLICYINFO *pol;
172e1051a39Sopenharmony_ci    POLICYQUALINFO *qual;
173e1051a39Sopenharmony_ci
174e1051a39Sopenharmony_ci    if ((pol = POLICYINFO_new()) == NULL)
175e1051a39Sopenharmony_ci        goto merr;
176e1051a39Sopenharmony_ci    for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) {
177e1051a39Sopenharmony_ci        cnf = sk_CONF_VALUE_value(polstrs, i);
178e1051a39Sopenharmony_ci        if (strcmp(cnf->name, "policyIdentifier") == 0) {
179e1051a39Sopenharmony_ci            ASN1_OBJECT *pobj;
180e1051a39Sopenharmony_ci
181e1051a39Sopenharmony_ci            if ((pobj = OBJ_txt2obj(cnf->value, 0)) == NULL) {
182e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
183e1051a39Sopenharmony_ci                X509V3_conf_err(cnf);
184e1051a39Sopenharmony_ci                goto err;
185e1051a39Sopenharmony_ci            }
186e1051a39Sopenharmony_ci            pol->policyid = pobj;
187e1051a39Sopenharmony_ci
188e1051a39Sopenharmony_ci        } else if (!ossl_v3_name_cmp(cnf->name, "CPS")) {
189e1051a39Sopenharmony_ci            if (pol->qualifiers == NULL)
190e1051a39Sopenharmony_ci                pol->qualifiers = sk_POLICYQUALINFO_new_null();
191e1051a39Sopenharmony_ci            if ((qual = POLICYQUALINFO_new()) == NULL)
192e1051a39Sopenharmony_ci                goto merr;
193e1051a39Sopenharmony_ci            if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
194e1051a39Sopenharmony_ci                goto merr;
195e1051a39Sopenharmony_ci            if ((qual->pqualid = OBJ_nid2obj(NID_id_qt_cps)) == NULL) {
196e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, ERR_R_INTERNAL_ERROR);
197e1051a39Sopenharmony_ci                goto err;
198e1051a39Sopenharmony_ci            }
199e1051a39Sopenharmony_ci            if ((qual->d.cpsuri = ASN1_IA5STRING_new()) == NULL)
200e1051a39Sopenharmony_ci                goto merr;
201e1051a39Sopenharmony_ci            if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value,
202e1051a39Sopenharmony_ci                                 strlen(cnf->value)))
203e1051a39Sopenharmony_ci                goto merr;
204e1051a39Sopenharmony_ci        } else if (!ossl_v3_name_cmp(cnf->name, "userNotice")) {
205e1051a39Sopenharmony_ci            STACK_OF(CONF_VALUE) *unot;
206e1051a39Sopenharmony_ci            if (*cnf->value != '@') {
207e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, X509V3_R_EXPECTED_A_SECTION_NAME);
208e1051a39Sopenharmony_ci                X509V3_conf_err(cnf);
209e1051a39Sopenharmony_ci                goto err;
210e1051a39Sopenharmony_ci            }
211e1051a39Sopenharmony_ci            unot = X509V3_get_section(ctx, cnf->value + 1);
212e1051a39Sopenharmony_ci            if (!unot) {
213e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_SECTION);
214e1051a39Sopenharmony_ci
215e1051a39Sopenharmony_ci                X509V3_conf_err(cnf);
216e1051a39Sopenharmony_ci                goto err;
217e1051a39Sopenharmony_ci            }
218e1051a39Sopenharmony_ci            qual = notice_section(ctx, unot, ia5org);
219e1051a39Sopenharmony_ci            X509V3_section_free(ctx, unot);
220e1051a39Sopenharmony_ci            if (!qual)
221e1051a39Sopenharmony_ci                goto err;
222e1051a39Sopenharmony_ci            if (pol->qualifiers == NULL)
223e1051a39Sopenharmony_ci                pol->qualifiers = sk_POLICYQUALINFO_new_null();
224e1051a39Sopenharmony_ci            if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
225e1051a39Sopenharmony_ci                goto merr;
226e1051a39Sopenharmony_ci        } else {
227e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_OPTION);
228e1051a39Sopenharmony_ci            X509V3_conf_err(cnf);
229e1051a39Sopenharmony_ci            goto err;
230e1051a39Sopenharmony_ci        }
231e1051a39Sopenharmony_ci    }
232e1051a39Sopenharmony_ci    if (pol->policyid == NULL) {
233e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_POLICY_IDENTIFIER);
234e1051a39Sopenharmony_ci        goto err;
235e1051a39Sopenharmony_ci    }
236e1051a39Sopenharmony_ci
237e1051a39Sopenharmony_ci    return pol;
238e1051a39Sopenharmony_ci
239e1051a39Sopenharmony_ci merr:
240e1051a39Sopenharmony_ci    ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
241e1051a39Sopenharmony_ci
242e1051a39Sopenharmony_ci err:
243e1051a39Sopenharmony_ci    POLICYINFO_free(pol);
244e1051a39Sopenharmony_ci    return NULL;
245e1051a39Sopenharmony_ci}
246e1051a39Sopenharmony_ci
247e1051a39Sopenharmony_cistatic int displaytext_get_tag_len(const char *tagstr)
248e1051a39Sopenharmony_ci{
249e1051a39Sopenharmony_ci    char *colon = strchr(tagstr, ':');
250e1051a39Sopenharmony_ci
251e1051a39Sopenharmony_ci    return (colon == NULL) ? -1 : colon - tagstr;
252e1051a39Sopenharmony_ci}
253e1051a39Sopenharmony_ci
254e1051a39Sopenharmony_cistatic int displaytext_str2tag(const char *tagstr, unsigned int *tag_len)
255e1051a39Sopenharmony_ci{
256e1051a39Sopenharmony_ci    int len;
257e1051a39Sopenharmony_ci
258e1051a39Sopenharmony_ci    *tag_len = 0;
259e1051a39Sopenharmony_ci    len = displaytext_get_tag_len(tagstr);
260e1051a39Sopenharmony_ci
261e1051a39Sopenharmony_ci    if (len == -1)
262e1051a39Sopenharmony_ci        return V_ASN1_VISIBLESTRING;
263e1051a39Sopenharmony_ci    *tag_len = len;
264e1051a39Sopenharmony_ci    if (len == sizeof("UTF8") - 1 && strncmp(tagstr, "UTF8", len) == 0)
265e1051a39Sopenharmony_ci        return V_ASN1_UTF8STRING;
266e1051a39Sopenharmony_ci    if (len == sizeof("UTF8String") - 1 && strncmp(tagstr, "UTF8String", len) == 0)
267e1051a39Sopenharmony_ci        return V_ASN1_UTF8STRING;
268e1051a39Sopenharmony_ci    if (len == sizeof("BMP") - 1 && strncmp(tagstr, "BMP", len) == 0)
269e1051a39Sopenharmony_ci        return V_ASN1_BMPSTRING;
270e1051a39Sopenharmony_ci    if (len == sizeof("BMPSTRING") - 1 && strncmp(tagstr, "BMPSTRING", len) == 0)
271e1051a39Sopenharmony_ci        return V_ASN1_BMPSTRING;
272e1051a39Sopenharmony_ci    if (len == sizeof("VISIBLE") - 1 && strncmp(tagstr, "VISIBLE", len) == 0)
273e1051a39Sopenharmony_ci        return V_ASN1_VISIBLESTRING;
274e1051a39Sopenharmony_ci    if (len == sizeof("VISIBLESTRING") - 1 && strncmp(tagstr, "VISIBLESTRING", len) == 0)
275e1051a39Sopenharmony_ci        return V_ASN1_VISIBLESTRING;
276e1051a39Sopenharmony_ci    *tag_len = 0;
277e1051a39Sopenharmony_ci    return V_ASN1_VISIBLESTRING;
278e1051a39Sopenharmony_ci}
279e1051a39Sopenharmony_ci
280e1051a39Sopenharmony_cistatic POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
281e1051a39Sopenharmony_ci                                      STACK_OF(CONF_VALUE) *unot, int ia5org)
282e1051a39Sopenharmony_ci{
283e1051a39Sopenharmony_ci    int i, ret, len, tag;
284e1051a39Sopenharmony_ci    unsigned int tag_len;
285e1051a39Sopenharmony_ci    CONF_VALUE *cnf;
286e1051a39Sopenharmony_ci    USERNOTICE *not;
287e1051a39Sopenharmony_ci    POLICYQUALINFO *qual;
288e1051a39Sopenharmony_ci    char *value = NULL;
289e1051a39Sopenharmony_ci
290e1051a39Sopenharmony_ci    if ((qual = POLICYQUALINFO_new()) == NULL)
291e1051a39Sopenharmony_ci        goto merr;
292e1051a39Sopenharmony_ci    if ((qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice)) == NULL) {
293e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509V3, ERR_R_INTERNAL_ERROR);
294e1051a39Sopenharmony_ci        goto err;
295e1051a39Sopenharmony_ci    }
296e1051a39Sopenharmony_ci    if ((not = USERNOTICE_new()) == NULL)
297e1051a39Sopenharmony_ci        goto merr;
298e1051a39Sopenharmony_ci    qual->d.usernotice = not;
299e1051a39Sopenharmony_ci    for (i = 0; i < sk_CONF_VALUE_num(unot); i++) {
300e1051a39Sopenharmony_ci        cnf = sk_CONF_VALUE_value(unot, i);
301e1051a39Sopenharmony_ci
302e1051a39Sopenharmony_ci        value = cnf->value;
303e1051a39Sopenharmony_ci        if (strcmp(cnf->name, "explicitText") == 0) {
304e1051a39Sopenharmony_ci            tag = displaytext_str2tag(value, &tag_len);
305e1051a39Sopenharmony_ci            if ((not->exptext = ASN1_STRING_type_new(tag)) == NULL)
306e1051a39Sopenharmony_ci                goto merr;
307e1051a39Sopenharmony_ci            if (tag_len != 0)
308e1051a39Sopenharmony_ci                value += tag_len + 1;
309e1051a39Sopenharmony_ci            len = strlen(value);
310e1051a39Sopenharmony_ci            if (!ASN1_STRING_set(not->exptext, value, len))
311e1051a39Sopenharmony_ci                goto merr;
312e1051a39Sopenharmony_ci        } else if (strcmp(cnf->name, "organization") == 0) {
313e1051a39Sopenharmony_ci            NOTICEREF *nref;
314e1051a39Sopenharmony_ci
315e1051a39Sopenharmony_ci            if (!not->noticeref) {
316e1051a39Sopenharmony_ci                if ((nref = NOTICEREF_new()) == NULL)
317e1051a39Sopenharmony_ci                    goto merr;
318e1051a39Sopenharmony_ci                not->noticeref = nref;
319e1051a39Sopenharmony_ci            } else
320e1051a39Sopenharmony_ci                nref = not->noticeref;
321e1051a39Sopenharmony_ci            if (ia5org)
322e1051a39Sopenharmony_ci                nref->organization->type = V_ASN1_IA5STRING;
323e1051a39Sopenharmony_ci            else
324e1051a39Sopenharmony_ci                nref->organization->type = V_ASN1_VISIBLESTRING;
325e1051a39Sopenharmony_ci            if (!ASN1_STRING_set(nref->organization, cnf->value,
326e1051a39Sopenharmony_ci                                 strlen(cnf->value)))
327e1051a39Sopenharmony_ci                goto merr;
328e1051a39Sopenharmony_ci        } else if (strcmp(cnf->name, "noticeNumbers") == 0) {
329e1051a39Sopenharmony_ci            NOTICEREF *nref;
330e1051a39Sopenharmony_ci
331e1051a39Sopenharmony_ci            STACK_OF(CONF_VALUE) *nos;
332e1051a39Sopenharmony_ci            if (!not->noticeref) {
333e1051a39Sopenharmony_ci                if ((nref = NOTICEREF_new()) == NULL)
334e1051a39Sopenharmony_ci                    goto merr;
335e1051a39Sopenharmony_ci                not->noticeref = nref;
336e1051a39Sopenharmony_ci            } else
337e1051a39Sopenharmony_ci                nref = not->noticeref;
338e1051a39Sopenharmony_ci            nos = X509V3_parse_list(cnf->value);
339e1051a39Sopenharmony_ci            if (!nos || !sk_CONF_VALUE_num(nos)) {
340e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NUMBERS);
341e1051a39Sopenharmony_ci                X509V3_conf_add_error_name_value(cnf);
342e1051a39Sopenharmony_ci                sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
343e1051a39Sopenharmony_ci                goto err;
344e1051a39Sopenharmony_ci            }
345e1051a39Sopenharmony_ci            ret = nref_nos(nref->noticenos, nos);
346e1051a39Sopenharmony_ci            sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
347e1051a39Sopenharmony_ci            if (!ret)
348e1051a39Sopenharmony_ci                goto err;
349e1051a39Sopenharmony_ci        } else {
350e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_OPTION);
351e1051a39Sopenharmony_ci            X509V3_conf_add_error_name_value(cnf);
352e1051a39Sopenharmony_ci            goto err;
353e1051a39Sopenharmony_ci        }
354e1051a39Sopenharmony_ci    }
355e1051a39Sopenharmony_ci
356e1051a39Sopenharmony_ci    if (not->noticeref &&
357e1051a39Sopenharmony_ci        (!not->noticeref->noticenos || !not->noticeref->organization)) {
358e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509V3, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS);
359e1051a39Sopenharmony_ci        goto err;
360e1051a39Sopenharmony_ci    }
361e1051a39Sopenharmony_ci
362e1051a39Sopenharmony_ci    return qual;
363e1051a39Sopenharmony_ci
364e1051a39Sopenharmony_ci merr:
365e1051a39Sopenharmony_ci    ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
366e1051a39Sopenharmony_ci
367e1051a39Sopenharmony_ci err:
368e1051a39Sopenharmony_ci    POLICYQUALINFO_free(qual);
369e1051a39Sopenharmony_ci    return NULL;
370e1051a39Sopenharmony_ci}
371e1051a39Sopenharmony_ci
372e1051a39Sopenharmony_cistatic int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos)
373e1051a39Sopenharmony_ci{
374e1051a39Sopenharmony_ci    CONF_VALUE *cnf;
375e1051a39Sopenharmony_ci    ASN1_INTEGER *aint;
376e1051a39Sopenharmony_ci
377e1051a39Sopenharmony_ci    int i;
378e1051a39Sopenharmony_ci
379e1051a39Sopenharmony_ci    for (i = 0; i < sk_CONF_VALUE_num(nos); i++) {
380e1051a39Sopenharmony_ci        cnf = sk_CONF_VALUE_value(nos, i);
381e1051a39Sopenharmony_ci        if ((aint = s2i_ASN1_INTEGER(NULL, cnf->name)) == NULL) {
382e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NUMBER);
383e1051a39Sopenharmony_ci            goto err;
384e1051a39Sopenharmony_ci        }
385e1051a39Sopenharmony_ci        if (!sk_ASN1_INTEGER_push(nnums, aint))
386e1051a39Sopenharmony_ci            goto merr;
387e1051a39Sopenharmony_ci    }
388e1051a39Sopenharmony_ci    return 1;
389e1051a39Sopenharmony_ci
390e1051a39Sopenharmony_ci merr:
391e1051a39Sopenharmony_ci    ASN1_INTEGER_free(aint);
392e1051a39Sopenharmony_ci    ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
393e1051a39Sopenharmony_ci
394e1051a39Sopenharmony_ci err:
395e1051a39Sopenharmony_ci    return 0;
396e1051a39Sopenharmony_ci}
397e1051a39Sopenharmony_ci
398e1051a39Sopenharmony_cistatic int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
399e1051a39Sopenharmony_ci                       BIO *out, int indent)
400e1051a39Sopenharmony_ci{
401e1051a39Sopenharmony_ci    int i;
402e1051a39Sopenharmony_ci    POLICYINFO *pinfo;
403e1051a39Sopenharmony_ci    /* First print out the policy OIDs */
404e1051a39Sopenharmony_ci    for (i = 0; i < sk_POLICYINFO_num(pol); i++) {
405e1051a39Sopenharmony_ci        if (i > 0)
406e1051a39Sopenharmony_ci            BIO_puts(out, "\n");
407e1051a39Sopenharmony_ci        pinfo = sk_POLICYINFO_value(pol, i);
408e1051a39Sopenharmony_ci        BIO_printf(out, "%*sPolicy: ", indent, "");
409e1051a39Sopenharmony_ci        i2a_ASN1_OBJECT(out, pinfo->policyid);
410e1051a39Sopenharmony_ci        if (pinfo->qualifiers) {
411e1051a39Sopenharmony_ci            BIO_puts(out, "\n");
412e1051a39Sopenharmony_ci            print_qualifiers(out, pinfo->qualifiers, indent + 2);
413e1051a39Sopenharmony_ci        }
414e1051a39Sopenharmony_ci    }
415e1051a39Sopenharmony_ci    return 1;
416e1051a39Sopenharmony_ci}
417e1051a39Sopenharmony_ci
418e1051a39Sopenharmony_cistatic void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
419e1051a39Sopenharmony_ci                             int indent)
420e1051a39Sopenharmony_ci{
421e1051a39Sopenharmony_ci    POLICYQUALINFO *qualinfo;
422e1051a39Sopenharmony_ci    int i;
423e1051a39Sopenharmony_ci    for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) {
424e1051a39Sopenharmony_ci        if (i > 0)
425e1051a39Sopenharmony_ci            BIO_puts(out, "\n");
426e1051a39Sopenharmony_ci        qualinfo = sk_POLICYQUALINFO_value(quals, i);
427e1051a39Sopenharmony_ci        switch (OBJ_obj2nid(qualinfo->pqualid)) {
428e1051a39Sopenharmony_ci        case NID_id_qt_cps:
429e1051a39Sopenharmony_ci            BIO_printf(out, "%*sCPS: %.*s", indent, "",
430e1051a39Sopenharmony_ci                       qualinfo->d.cpsuri->length,
431e1051a39Sopenharmony_ci                       qualinfo->d.cpsuri->data);
432e1051a39Sopenharmony_ci            break;
433e1051a39Sopenharmony_ci
434e1051a39Sopenharmony_ci        case NID_id_qt_unotice:
435e1051a39Sopenharmony_ci            BIO_printf(out, "%*sUser Notice:\n", indent, "");
436e1051a39Sopenharmony_ci            print_notice(out, qualinfo->d.usernotice, indent + 2);
437e1051a39Sopenharmony_ci            break;
438e1051a39Sopenharmony_ci
439e1051a39Sopenharmony_ci        default:
440e1051a39Sopenharmony_ci            BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, "");
441e1051a39Sopenharmony_ci
442e1051a39Sopenharmony_ci            i2a_ASN1_OBJECT(out, qualinfo->pqualid);
443e1051a39Sopenharmony_ci            break;
444e1051a39Sopenharmony_ci        }
445e1051a39Sopenharmony_ci    }
446e1051a39Sopenharmony_ci}
447e1051a39Sopenharmony_ci
448e1051a39Sopenharmony_cistatic void print_notice(BIO *out, USERNOTICE *notice, int indent)
449e1051a39Sopenharmony_ci{
450e1051a39Sopenharmony_ci    int i;
451e1051a39Sopenharmony_ci    if (notice->noticeref) {
452e1051a39Sopenharmony_ci        NOTICEREF *ref;
453e1051a39Sopenharmony_ci        ref = notice->noticeref;
454e1051a39Sopenharmony_ci        BIO_printf(out, "%*sOrganization: %.*s\n", indent, "",
455e1051a39Sopenharmony_ci                   ref->organization->length,
456e1051a39Sopenharmony_ci                   ref->organization->data);
457e1051a39Sopenharmony_ci        BIO_printf(out, "%*sNumber%s: ", indent, "",
458e1051a39Sopenharmony_ci                   sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : "");
459e1051a39Sopenharmony_ci        for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) {
460e1051a39Sopenharmony_ci            ASN1_INTEGER *num;
461e1051a39Sopenharmony_ci            char *tmp;
462e1051a39Sopenharmony_ci            num = sk_ASN1_INTEGER_value(ref->noticenos, i);
463e1051a39Sopenharmony_ci            if (i)
464e1051a39Sopenharmony_ci                BIO_puts(out, ", ");
465e1051a39Sopenharmony_ci            if (num == NULL)
466e1051a39Sopenharmony_ci                BIO_puts(out, "(null)");
467e1051a39Sopenharmony_ci            else {
468e1051a39Sopenharmony_ci                tmp = i2s_ASN1_INTEGER(NULL, num);
469e1051a39Sopenharmony_ci                if (tmp == NULL)
470e1051a39Sopenharmony_ci                    return;
471e1051a39Sopenharmony_ci                BIO_puts(out, tmp);
472e1051a39Sopenharmony_ci                OPENSSL_free(tmp);
473e1051a39Sopenharmony_ci            }
474e1051a39Sopenharmony_ci        }
475e1051a39Sopenharmony_ci        if (notice->exptext)
476e1051a39Sopenharmony_ci            BIO_puts(out, "\n");
477e1051a39Sopenharmony_ci    }
478e1051a39Sopenharmony_ci    if (notice->exptext)
479e1051a39Sopenharmony_ci        BIO_printf(out, "%*sExplicit Text: %.*s", indent, "",
480e1051a39Sopenharmony_ci                   notice->exptext->length,
481e1051a39Sopenharmony_ci                   notice->exptext->data);
482e1051a39Sopenharmony_ci}
483e1051a39Sopenharmony_ci
484e1051a39Sopenharmony_civoid X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent)
485e1051a39Sopenharmony_ci{
486e1051a39Sopenharmony_ci    const X509_POLICY_DATA *dat = node->data;
487e1051a39Sopenharmony_ci
488e1051a39Sopenharmony_ci    BIO_printf(out, "%*sPolicy: ", indent, "");
489e1051a39Sopenharmony_ci
490e1051a39Sopenharmony_ci    i2a_ASN1_OBJECT(out, dat->valid_policy);
491e1051a39Sopenharmony_ci    BIO_puts(out, "\n");
492e1051a39Sopenharmony_ci    BIO_printf(out, "%*s%s\n", indent + 2, "",
493e1051a39Sopenharmony_ci               node_data_critical(dat) ? "Critical" : "Non Critical");
494e1051a39Sopenharmony_ci    if (dat->qualifier_set) {
495e1051a39Sopenharmony_ci        print_qualifiers(out, dat->qualifier_set, indent + 2);
496e1051a39Sopenharmony_ci        BIO_puts(out, "\n");
497e1051a39Sopenharmony_ci    }
498e1051a39Sopenharmony_ci    else
499e1051a39Sopenharmony_ci        BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, "");
500e1051a39Sopenharmony_ci}
501