v3_cpols.c 16.1 KB
Newer Older
1
/*
M
Matt Caswell 已提交
2
 * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
3
 *
R
Rich Salz 已提交
4 5 6 7
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
8 9 10
 */

#include <stdio.h>
11
#include "internal/cryptlib.h"
12 13
#include <openssl/conf.h>
#include <openssl/asn1.h>
D
 
Dr. Stephen Henson 已提交
14
#include <openssl/asn1t.h>
15
#include <openssl/x509v3.h>
16

17
#include "pcy_local.h"
18
#include "ext_dat.h"
19

20 21
/* Certificate policies extension support: this one is a bit complex... */

22 23 24
static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
                       BIO *out, int indent);
static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
25
                                         X509V3_CTX *ctx, const char *value);
26 27
static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
                             int indent);
28
static void print_notice(BIO *out, USERNOTICE *notice, int indent);
29
static POLICYINFO *policy_section(X509V3_CTX *ctx,
30
                                  STACK_OF(CONF_VALUE) *polstrs, int ia5org);
31
static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
32
                                      STACK_OF(CONF_VALUE) *unot, int ia5org);
D
PR: 627  
Dr. Stephen Henson 已提交
33
static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos);
M
Marek Klein 已提交
34 35
static int displaytext_str2tag(const char *tagstr, unsigned int *tag_len);
static int displaytext_get_tag_len(const char *tagstr);
36

37
const X509V3_EXT_METHOD v3_cpols = {
38 39 40 41 42 43 44
    NID_certificate_policies, 0, ASN1_ITEM_ref(CERTIFICATEPOLICIES),
    0, 0, 0, 0,
    0, 0,
    0, 0,
    (X509V3_EXT_I2R)i2r_certpol,
    (X509V3_EXT_R2I)r2i_certpol,
    NULL
45 46
};

47 48
ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) =
        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO)
49
ASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES)
D
 
Dr. Stephen Henson 已提交
50 51 52 53

IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)

ASN1_SEQUENCE(POLICYINFO) = {
54 55
        ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT),
        ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO)
56
} ASN1_SEQUENCE_END(POLICYINFO)
D
 
Dr. Stephen Henson 已提交
57 58 59 60 61 62

IMPLEMENT_ASN1_FUNCTIONS(POLICYINFO)

ASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other, ASN1_ANY);

ASN1_ADB(POLICYQUALINFO) = {
63 64
        ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)),
        ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE))
D
 
Dr. Stephen Henson 已提交
65 66 67
} ASN1_ADB_END(POLICYQUALINFO, 0, pqualid, 0, &policydefault_tt, NULL);

ASN1_SEQUENCE(POLICYQUALINFO) = {
68 69
        ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT),
        ASN1_ADB_OBJECT(POLICYQUALINFO)
70
} ASN1_SEQUENCE_END(POLICYQUALINFO)
D
 
Dr. Stephen Henson 已提交
71 72 73 74

IMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO)

ASN1_SEQUENCE(USERNOTICE) = {
75 76
        ASN1_OPT(USERNOTICE, noticeref, NOTICEREF),
        ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT)
77
} ASN1_SEQUENCE_END(USERNOTICE)
D
 
Dr. Stephen Henson 已提交
78 79 80 81

IMPLEMENT_ASN1_FUNCTIONS(USERNOTICE)

ASN1_SEQUENCE(NOTICEREF) = {
82 83
        ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT),
        ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER)
84
} ASN1_SEQUENCE_END(NOTICEREF)
D
 
Dr. Stephen Henson 已提交
85 86

IMPLEMENT_ASN1_FUNCTIONS(NOTICEREF)
87

U
Ulf Möller 已提交
88
static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
89
                                         X509V3_CTX *ctx, const char *value)
90
{
F
FdaSilvaYY 已提交
91
    STACK_OF(POLICYINFO) *pols;
92 93 94
    char *pstr;
    POLICYINFO *pol;
    ASN1_OBJECT *pobj;
F
FdaSilvaYY 已提交
95
    STACK_OF(CONF_VALUE) *vals = X509V3_parse_list(value);
96
    CONF_VALUE *cnf;
F
FdaSilvaYY 已提交
97
    const int num = sk_CONF_VALUE_num(vals);
98
    int i, ia5org;
F
FdaSilvaYY 已提交
99

100 101
    if (vals == NULL) {
        X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_X509V3_LIB);
F
FdaSilvaYY 已提交
102 103 104
        return NULL;
    }

P
Paul Yang 已提交
105 106
    pols = sk_POLICYINFO_new_reserve(NULL, num);
    if (pols == NULL) {
F
FdaSilvaYY 已提交
107
        X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
108 109
        goto err;
    }
F
FdaSilvaYY 已提交
110

111
    ia5org = 0;
F
FdaSilvaYY 已提交
112
    for (i = 0; i < num; i++) {
113
        cnf = sk_CONF_VALUE_value(vals, i);
F
FdaSilvaYY 已提交
114

115 116 117 118 119 120 121
        if (cnf->value || !cnf->name) {
            X509V3err(X509V3_F_R2I_CERTPOL,
                      X509V3_R_INVALID_POLICY_IDENTIFIER);
            X509V3_conf_err(cnf);
            goto err;
        }
        pstr = cnf->name;
R
Rich Salz 已提交
122
        if (strcmp(pstr, "ia5org") == 0) {
123 124 125 126 127 128 129 130 131 132 133 134 135
            ia5org = 1;
            continue;
        } else if (*pstr == '@') {
            STACK_OF(CONF_VALUE) *polsect;
            polsect = X509V3_get_section(ctx, pstr + 1);
            if (!polsect) {
                X509V3err(X509V3_F_R2I_CERTPOL, X509V3_R_INVALID_SECTION);

                X509V3_conf_err(cnf);
                goto err;
            }
            pol = policy_section(ctx, polsect, ia5org);
            X509V3_section_free(ctx, polsect);
136
            if (pol == NULL)
137 138
                goto err;
        } else {
139
            if ((pobj = OBJ_txt2obj(cnf->name, 0)) == NULL) {
140 141 142 143 144 145
                X509V3err(X509V3_F_R2I_CERTPOL,
                          X509V3_R_INVALID_OBJECT_IDENTIFIER);
                X509V3_conf_err(cnf);
                goto err;
            }
            pol = POLICYINFO_new();
146
            if (pol == NULL) {
147
                ASN1_OBJECT_free(pobj);
148
                X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
149 150
                goto err;
            }
151 152 153 154 155 156 157 158 159 160 161 162 163 164
            pol->policyid = pobj;
        }
        if (!sk_POLICYINFO_push(pols, pol)) {
            POLICYINFO_free(pol);
            X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
            goto err;
        }
    }
    sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
    return pols;
 err:
    sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
    sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
    return NULL;
165 166
}

167
static POLICYINFO *policy_section(X509V3_CTX *ctx,
168
                                  STACK_OF(CONF_VALUE) *polstrs, int ia5org)
169
{
170 171 172 173
    int i;
    CONF_VALUE *cnf;
    POLICYINFO *pol;
    POLICYQUALINFO *qual;
174 175

    if ((pol = POLICYINFO_new()) == NULL)
176 177 178
        goto merr;
    for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) {
        cnf = sk_CONF_VALUE_value(polstrs, i);
R
Rich Salz 已提交
179
        if (strcmp(cnf->name, "policyIdentifier") == 0) {
180
            ASN1_OBJECT *pobj;
181
            if ((pobj = OBJ_txt2obj(cnf->value, 0)) == NULL) {
182 183 184 185 186 187 188 189
                X509V3err(X509V3_F_POLICY_SECTION,
                          X509V3_R_INVALID_OBJECT_IDENTIFIER);
                X509V3_conf_err(cnf);
                goto err;
            }
            pol->policyid = pobj;

        } else if (!name_cmp(cnf->name, "CPS")) {
190
            if (pol->qualifiers == NULL)
191
                pol->qualifiers = sk_POLICYQUALINFO_new_null();
192
            if ((qual = POLICYQUALINFO_new()) == NULL)
193 194 195
                goto merr;
            if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
                goto merr;
196
            if ((qual->pqualid = OBJ_nid2obj(NID_id_qt_cps)) == NULL) {
197 198 199
                X509V3err(X509V3_F_POLICY_SECTION, ERR_R_INTERNAL_ERROR);
                goto err;
            }
200
            if ((qual->d.cpsuri = ASN1_IA5STRING_new()) == NULL)
201
                goto merr;
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
            if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value,
                                 strlen(cnf->value)))
                goto merr;
        } else if (!name_cmp(cnf->name, "userNotice")) {
            STACK_OF(CONF_VALUE) *unot;
            if (*cnf->value != '@') {
                X509V3err(X509V3_F_POLICY_SECTION,
                          X509V3_R_EXPECTED_A_SECTION_NAME);
                X509V3_conf_err(cnf);
                goto err;
            }
            unot = X509V3_get_section(ctx, cnf->value + 1);
            if (!unot) {
                X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_INVALID_SECTION);

                X509V3_conf_err(cnf);
                goto err;
            }
            qual = notice_section(ctx, unot, ia5org);
            X509V3_section_free(ctx, unot);
            if (!qual)
                goto err;
            if (!pol->qualifiers)
                pol->qualifiers = sk_POLICYQUALINFO_new_null();
            if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
                goto merr;
        } else {
            X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_INVALID_OPTION);

            X509V3_conf_err(cnf);
            goto err;
        }
    }
    if (!pol->policyid) {
        X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_NO_POLICY_IDENTIFIER);
        goto err;
    }

    return pol;

 merr:
    X509V3err(X509V3_F_POLICY_SECTION, ERR_R_MALLOC_FAILURE);

 err:
    POLICYINFO_free(pol);
    return NULL;
248 249
}

M
Marek Klein 已提交
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
static int displaytext_get_tag_len(const char *tagstr)
{
    char *colon = strchr(tagstr, ':');

    return (colon == NULL) ? -1 : colon - tagstr;
}

static int displaytext_str2tag(const char *tagstr, unsigned int *tag_len)
{
    int len;

    *tag_len = 0;
    len = displaytext_get_tag_len(tagstr);

    if (len == -1)
        return V_ASN1_VISIBLESTRING;
    *tag_len = len;
    if (len == sizeof("UTF8") - 1 && strncmp(tagstr, "UTF8", len) == 0)
        return V_ASN1_UTF8STRING;
    if (len == sizeof("UTF8String") - 1 && strncmp(tagstr, "UTF8String", len) == 0)
        return V_ASN1_UTF8STRING;
    if (len == sizeof("BMP") - 1 && strncmp(tagstr, "BMP", len) == 0)
        return V_ASN1_BMPSTRING;
    if (len == sizeof("BMPSTRING") - 1 && strncmp(tagstr, "BMPSTRING", len) == 0)
        return V_ASN1_BMPSTRING;
    if (len == sizeof("VISIBLE") - 1 && strncmp(tagstr, "VISIBLE", len) == 0)
        return V_ASN1_VISIBLESTRING;
    if (len == sizeof("VISIBLESTRING") - 1 && strncmp(tagstr, "VISIBLESTRING", len) == 0)
        return V_ASN1_VISIBLESTRING;
    *tag_len = 0;
    return V_ASN1_VISIBLESTRING;
}

283
static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
284
                                      STACK_OF(CONF_VALUE) *unot, int ia5org)
285
{
M
Marek Klein 已提交
286 287
    int i, ret, len, tag;
    unsigned int tag_len;
288 289 290
    CONF_VALUE *cnf;
    USERNOTICE *not;
    POLICYQUALINFO *qual;
M
Marek Klein 已提交
291
    char *value = NULL;
292 293

    if ((qual = POLICYQUALINFO_new()) == NULL)
294
        goto merr;
295
    if ((qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice)) == NULL) {
296 297 298
        X509V3err(X509V3_F_NOTICE_SECTION, ERR_R_INTERNAL_ERROR);
        goto err;
    }
299
    if ((not = USERNOTICE_new()) == NULL)
300 301 302 303
        goto merr;
    qual->d.usernotice = not;
    for (i = 0; i < sk_CONF_VALUE_num(unot); i++) {
        cnf = sk_CONF_VALUE_value(unot, i);
M
Marek Klein 已提交
304
        value = cnf->value;
R
Rich Salz 已提交
305
        if (strcmp(cnf->name, "explicitText") == 0) {
M
Marek Klein 已提交
306 307
            tag = displaytext_str2tag(value, &tag_len);
            if ((not->exptext = ASN1_STRING_type_new(tag)) == NULL)
308
                goto merr;
M
Marek Klein 已提交
309 310 311 312
            if (tag_len != 0)
                value += tag_len + 1;
            len = strlen(value);
            if (!ASN1_STRING_set(not->exptext, value, len))
313
                goto merr;
R
Rich Salz 已提交
314
        } else if (strcmp(cnf->name, "organization") == 0) {
315 316
            NOTICEREF *nref;
            if (!not->noticeref) {
317
                if ((nref = NOTICEREF_new()) == NULL)
318 319 320 321 322 323 324 325 326 327 328
                    goto merr;
                not->noticeref = nref;
            } else
                nref = not->noticeref;
            if (ia5org)
                nref->organization->type = V_ASN1_IA5STRING;
            else
                nref->organization->type = V_ASN1_VISIBLESTRING;
            if (!ASN1_STRING_set(nref->organization, cnf->value,
                                 strlen(cnf->value)))
                goto merr;
R
Rich Salz 已提交
329
        } else if (strcmp(cnf->name, "noticeNumbers") == 0) {
330 331 332
            NOTICEREF *nref;
            STACK_OF(CONF_VALUE) *nos;
            if (!not->noticeref) {
333
                if ((nref = NOTICEREF_new()) == NULL)
334 335 336 337 338 339 340 341
                    goto merr;
                not->noticeref = nref;
            } else
                nref = not->noticeref;
            nos = X509V3_parse_list(cnf->value);
            if (!nos || !sk_CONF_VALUE_num(nos)) {
                X509V3err(X509V3_F_NOTICE_SECTION, X509V3_R_INVALID_NUMBERS);
                X509V3_conf_err(cnf);
342
                sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
                goto err;
            }
            ret = nref_nos(nref->noticenos, nos);
            sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
            if (!ret)
                goto err;
        } else {
            X509V3err(X509V3_F_NOTICE_SECTION, X509V3_R_INVALID_OPTION);
            X509V3_conf_err(cnf);
            goto err;
        }
    }

    if (not->noticeref &&
        (!not->noticeref->noticenos || !not->noticeref->organization)) {
        X509V3err(X509V3_F_NOTICE_SECTION,
                  X509V3_R_NEED_ORGANIZATION_AND_NUMBERS);
        goto err;
    }

    return qual;

 merr:
    X509V3err(X509V3_F_NOTICE_SECTION, ERR_R_MALLOC_FAILURE);

 err:
    POLICYQUALINFO_free(qual);
    return NULL;
371 372
}

D
PR: 627  
Dr. Stephen Henson 已提交
373
static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos)
374
{
375 376 377 378 379 380 381
    CONF_VALUE *cnf;
    ASN1_INTEGER *aint;

    int i;

    for (i = 0; i < sk_CONF_VALUE_num(nos); i++) {
        cnf = sk_CONF_VALUE_value(nos, i);
382
        if ((aint = s2i_ASN1_INTEGER(NULL, cnf->name)) == NULL) {
383 384 385 386 387 388 389 390 391
            X509V3err(X509V3_F_NREF_NOS, X509V3_R_INVALID_NUMBER);
            goto err;
        }
        if (!sk_ASN1_INTEGER_push(nnums, aint))
            goto merr;
    }
    return 1;

 merr:
392
    ASN1_INTEGER_free(aint);
393 394 395 396
    X509V3err(X509V3_F_NREF_NOS, ERR_R_MALLOC_FAILURE);

 err:
    return 0;
397 398
}

U
Ulf Möller 已提交
399
static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
400
                       BIO *out, int indent)
401
{
402 403 404 405 406 407 408 409 410 411 412 413
    int i;
    POLICYINFO *pinfo;
    /* First print out the policy OIDs */
    for (i = 0; i < sk_POLICYINFO_num(pol); i++) {
        pinfo = sk_POLICYINFO_value(pol, i);
        BIO_printf(out, "%*sPolicy: ", indent, "");
        i2a_ASN1_OBJECT(out, pinfo->policyid);
        BIO_puts(out, "\n");
        if (pinfo->qualifiers)
            print_qualifiers(out, pinfo->qualifiers, indent + 2);
    }
    return 1;
414 415
}

U
Ulf Möller 已提交
416
static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
417
                             int indent)
418
{
419 420 421 422 423 424
    POLICYQUALINFO *qualinfo;
    int i;
    for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) {
        qualinfo = sk_POLICYQUALINFO_value(quals, i);
        switch (OBJ_obj2nid(qualinfo->pqualid)) {
        case NID_id_qt_cps:
425 426
            BIO_printf(out, "%*sCPS: %.*s\n", indent, "",
                       qualinfo->d.cpsuri->length,
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
                       qualinfo->d.cpsuri->data);
            break;

        case NID_id_qt_unotice:
            BIO_printf(out, "%*sUser Notice:\n", indent, "");
            print_notice(out, qualinfo->d.usernotice, indent + 2);
            break;

        default:
            BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, "");

            i2a_ASN1_OBJECT(out, qualinfo->pqualid);
            BIO_puts(out, "\n");
            break;
        }
    }
443 444
}

U
Ulf Möller 已提交
445
static void print_notice(BIO *out, USERNOTICE *notice, int indent)
446
{
447 448 449 450
    int i;
    if (notice->noticeref) {
        NOTICEREF *ref;
        ref = notice->noticeref;
451 452
        BIO_printf(out, "%*sOrganization: %.*s\n", indent, "",
                   ref->organization->length,
453 454 455 456 457 458 459 460 461
                   ref->organization->data);
        BIO_printf(out, "%*sNumber%s: ", indent, "",
                   sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : "");
        for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) {
            ASN1_INTEGER *num;
            char *tmp;
            num = sk_ASN1_INTEGER_value(ref->noticenos, i);
            if (i)
                BIO_puts(out, ", ");
B
Bernd Edlinger 已提交
462 463 464 465 466 467 468 469 470
            if (num == NULL)
                BIO_puts(out, "(null)");
            else {
                tmp = i2s_ASN1_INTEGER(NULL, num);
                if (tmp == NULL)
                    return;
                BIO_puts(out, tmp);
                OPENSSL_free(tmp);
            }
471 472 473 474
        }
        BIO_puts(out, "\n");
    }
    if (notice->exptext)
475 476
        BIO_printf(out, "%*sExplicit Text: %.*s\n", indent, "",
                   notice->exptext->length,
477
                   notice->exptext->data);
478 479
}

480
void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent)
481 482 483 484 485 486 487 488 489 490 491 492 493 494
{
    const X509_POLICY_DATA *dat = node->data;

    BIO_printf(out, "%*sPolicy: ", indent, "");

    i2a_ASN1_OBJECT(out, dat->valid_policy);
    BIO_puts(out, "\n");
    BIO_printf(out, "%*s%s\n", indent + 2, "",
               node_data_critical(dat) ? "Critical" : "Non Critical");
    if (dat->qualifier_set)
        print_qualifiers(out, dat->qualifier_set, indent + 2);
    else
        BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, "");
}