v3_cpols.c revision 296341
1/* v3_cpols.c */ 2/* 3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4 * 1999. 5 */ 6/* ==================================================================== 7 * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. All advertising materials mentioning features or use of this 22 * software must display the following acknowledgment: 23 * "This product includes software developed by the OpenSSL Project 24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25 * 26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27 * endorse or promote products derived from this software without 28 * prior written permission. For written permission, please contact 29 * licensing@OpenSSL.org. 30 * 31 * 5. Products derived from this software may not be called "OpenSSL" 32 * nor may "OpenSSL" appear in their names without prior written 33 * permission of the OpenSSL Project. 34 * 35 * 6. Redistributions of any form whatsoever must retain the following 36 * acknowledgment: 37 * "This product includes software developed by the OpenSSL Project 38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51 * OF THE POSSIBILITY OF SUCH DAMAGE. 52 * ==================================================================== 53 * 54 * This product includes cryptographic software written by Eric Young 55 * (eay@cryptsoft.com). This product includes software written by Tim 56 * Hudson (tjh@cryptsoft.com). 57 * 58 */ 59 60#include <stdio.h> 61#include "cryptlib.h" 62#include <openssl/conf.h> 63#include <openssl/asn1.h> 64#include <openssl/asn1t.h> 65#include <openssl/x509v3.h> 66 67#include "pcy_int.h" 68 69/* Certificate policies extension support: this one is a bit complex... */ 70 71static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, 72 BIO *out, int indent); 73static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, 74 X509V3_CTX *ctx, char *value); 75static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, 76 int indent); 77static void print_notice(BIO *out, USERNOTICE *notice, int indent); 78static POLICYINFO *policy_section(X509V3_CTX *ctx, 79 STACK_OF(CONF_VALUE) *polstrs, int ia5org); 80static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, 81 STACK_OF(CONF_VALUE) *unot, int ia5org); 82static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos); 83 84const X509V3_EXT_METHOD v3_cpols = { 85 NID_certificate_policies, 0, ASN1_ITEM_ref(CERTIFICATEPOLICIES), 86 0, 0, 0, 0, 87 0, 0, 88 0, 0, 89 (X509V3_EXT_I2R)i2r_certpol, 90 (X509V3_EXT_R2I)r2i_certpol, 91 NULL 92}; 93 94ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) = 95 ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO) 96ASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES) 97 98IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES) 99 100ASN1_SEQUENCE(POLICYINFO) = { 101 ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT), 102 ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO) 103} ASN1_SEQUENCE_END(POLICYINFO) 104 105IMPLEMENT_ASN1_FUNCTIONS(POLICYINFO) 106 107ASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other, ASN1_ANY); 108 109ASN1_ADB(POLICYQUALINFO) = { 110 ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)), 111 ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE)) 112} ASN1_ADB_END(POLICYQUALINFO, 0, pqualid, 0, &policydefault_tt, NULL); 113 114ASN1_SEQUENCE(POLICYQUALINFO) = { 115 ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT), 116 ASN1_ADB_OBJECT(POLICYQUALINFO) 117} ASN1_SEQUENCE_END(POLICYQUALINFO) 118 119IMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO) 120 121ASN1_SEQUENCE(USERNOTICE) = { 122 ASN1_OPT(USERNOTICE, noticeref, NOTICEREF), 123 ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT) 124} ASN1_SEQUENCE_END(USERNOTICE) 125 126IMPLEMENT_ASN1_FUNCTIONS(USERNOTICE) 127 128ASN1_SEQUENCE(NOTICEREF) = { 129 ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT), 130 ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER) 131} ASN1_SEQUENCE_END(NOTICEREF) 132 133IMPLEMENT_ASN1_FUNCTIONS(NOTICEREF) 134 135static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, 136 X509V3_CTX *ctx, char *value) 137{ 138 STACK_OF(POLICYINFO) *pols = NULL; 139 char *pstr; 140 POLICYINFO *pol; 141 ASN1_OBJECT *pobj; 142 STACK_OF(CONF_VALUE) *vals; 143 CONF_VALUE *cnf; 144 int i, ia5org; 145 pols = sk_POLICYINFO_new_null(); 146 if (pols == NULL) { 147 X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE); 148 return NULL; 149 } 150 vals = X509V3_parse_list(value); 151 if (vals == NULL) { 152 X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_X509V3_LIB); 153 goto err; 154 } 155 ia5org = 0; 156 for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { 157 cnf = sk_CONF_VALUE_value(vals, i); 158 if (cnf->value || !cnf->name) { 159 X509V3err(X509V3_F_R2I_CERTPOL, 160 X509V3_R_INVALID_POLICY_IDENTIFIER); 161 X509V3_conf_err(cnf); 162 goto err; 163 } 164 pstr = cnf->name; 165 if (!strcmp(pstr, "ia5org")) { 166 ia5org = 1; 167 continue; 168 } else if (*pstr == '@') { 169 STACK_OF(CONF_VALUE) *polsect; 170 polsect = X509V3_get_section(ctx, pstr + 1); 171 if (!polsect) { 172 X509V3err(X509V3_F_R2I_CERTPOL, X509V3_R_INVALID_SECTION); 173 174 X509V3_conf_err(cnf); 175 goto err; 176 } 177 pol = policy_section(ctx, polsect, ia5org); 178 X509V3_section_free(ctx, polsect); 179 if (!pol) 180 goto err; 181 } else { 182 if (!(pobj = OBJ_txt2obj(cnf->name, 0))) { 183 X509V3err(X509V3_F_R2I_CERTPOL, 184 X509V3_R_INVALID_OBJECT_IDENTIFIER); 185 X509V3_conf_err(cnf); 186 goto err; 187 } 188 pol = POLICYINFO_new(); 189 pol->policyid = pobj; 190 } 191 if (!sk_POLICYINFO_push(pols, pol)) { 192 POLICYINFO_free(pol); 193 X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE); 194 goto err; 195 } 196 } 197 sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); 198 return pols; 199 err: 200 sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); 201 sk_POLICYINFO_pop_free(pols, POLICYINFO_free); 202 return NULL; 203} 204 205static POLICYINFO *policy_section(X509V3_CTX *ctx, 206 STACK_OF(CONF_VALUE) *polstrs, int ia5org) 207{ 208 int i; 209 CONF_VALUE *cnf; 210 POLICYINFO *pol; 211 POLICYQUALINFO *qual; 212 if (!(pol = POLICYINFO_new())) 213 goto merr; 214 for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) { 215 cnf = sk_CONF_VALUE_value(polstrs, i); 216 if (!strcmp(cnf->name, "policyIdentifier")) { 217 ASN1_OBJECT *pobj; 218 if (!(pobj = OBJ_txt2obj(cnf->value, 0))) { 219 X509V3err(X509V3_F_POLICY_SECTION, 220 X509V3_R_INVALID_OBJECT_IDENTIFIER); 221 X509V3_conf_err(cnf); 222 goto err; 223 } 224 pol->policyid = pobj; 225 226 } else if (!name_cmp(cnf->name, "CPS")) { 227 if (!pol->qualifiers) 228 pol->qualifiers = sk_POLICYQUALINFO_new_null(); 229 if (!(qual = POLICYQUALINFO_new())) 230 goto merr; 231 if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) 232 goto merr; 233 if (!(qual->pqualid = OBJ_nid2obj(NID_id_qt_cps))) { 234 X509V3err(X509V3_F_POLICY_SECTION, ERR_R_INTERNAL_ERROR); 235 goto err; 236 } 237 if (!(qual->d.cpsuri = M_ASN1_IA5STRING_new())) 238 goto merr; 239 if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value, 240 strlen(cnf->value))) 241 goto merr; 242 } else if (!name_cmp(cnf->name, "userNotice")) { 243 STACK_OF(CONF_VALUE) *unot; 244 if (*cnf->value != '@') { 245 X509V3err(X509V3_F_POLICY_SECTION, 246 X509V3_R_EXPECTED_A_SECTION_NAME); 247 X509V3_conf_err(cnf); 248 goto err; 249 } 250 unot = X509V3_get_section(ctx, cnf->value + 1); 251 if (!unot) { 252 X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_INVALID_SECTION); 253 254 X509V3_conf_err(cnf); 255 goto err; 256 } 257 qual = notice_section(ctx, unot, ia5org); 258 X509V3_section_free(ctx, unot); 259 if (!qual) 260 goto err; 261 if (!pol->qualifiers) 262 pol->qualifiers = sk_POLICYQUALINFO_new_null(); 263 if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) 264 goto merr; 265 } else { 266 X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_INVALID_OPTION); 267 268 X509V3_conf_err(cnf); 269 goto err; 270 } 271 } 272 if (!pol->policyid) { 273 X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_NO_POLICY_IDENTIFIER); 274 goto err; 275 } 276 277 return pol; 278 279 merr: 280 X509V3err(X509V3_F_POLICY_SECTION, ERR_R_MALLOC_FAILURE); 281 282 err: 283 POLICYINFO_free(pol); 284 return NULL; 285 286} 287 288static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, 289 STACK_OF(CONF_VALUE) *unot, int ia5org) 290{ 291 int i, ret; 292 CONF_VALUE *cnf; 293 USERNOTICE *not; 294 POLICYQUALINFO *qual; 295 if (!(qual = POLICYQUALINFO_new())) 296 goto merr; 297 if (!(qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice))) { 298 X509V3err(X509V3_F_NOTICE_SECTION, ERR_R_INTERNAL_ERROR); 299 goto err; 300 } 301 if (!(not = USERNOTICE_new())) 302 goto merr; 303 qual->d.usernotice = not; 304 for (i = 0; i < sk_CONF_VALUE_num(unot); i++) { 305 cnf = sk_CONF_VALUE_value(unot, i); 306 if (!strcmp(cnf->name, "explicitText")) { 307 if (!(not->exptext = M_ASN1_VISIBLESTRING_new())) 308 goto merr; 309 if (!ASN1_STRING_set(not->exptext, cnf->value, 310 strlen(cnf->value))) 311 goto merr; 312 } else if (!strcmp(cnf->name, "organization")) { 313 NOTICEREF *nref; 314 if (!not->noticeref) { 315 if (!(nref = NOTICEREF_new())) 316 goto merr; 317 not->noticeref = nref; 318 } else 319 nref = not->noticeref; 320 if (ia5org) 321 nref->organization->type = V_ASN1_IA5STRING; 322 else 323 nref->organization->type = V_ASN1_VISIBLESTRING; 324 if (!ASN1_STRING_set(nref->organization, cnf->value, 325 strlen(cnf->value))) 326 goto merr; 327 } else if (!strcmp(cnf->name, "noticeNumbers")) { 328 NOTICEREF *nref; 329 STACK_OF(CONF_VALUE) *nos; 330 if (!not->noticeref) { 331 if (!(nref = NOTICEREF_new())) 332 goto merr; 333 not->noticeref = nref; 334 } else 335 nref = not->noticeref; 336 nos = X509V3_parse_list(cnf->value); 337 if (!nos || !sk_CONF_VALUE_num(nos)) { 338 X509V3err(X509V3_F_NOTICE_SECTION, X509V3_R_INVALID_NUMBERS); 339 X509V3_conf_err(cnf); 340 goto err; 341 } 342 ret = nref_nos(nref->noticenos, nos); 343 sk_CONF_VALUE_pop_free(nos, X509V3_conf_free); 344 if (!ret) 345 goto err; 346 } else { 347 X509V3err(X509V3_F_NOTICE_SECTION, X509V3_R_INVALID_OPTION); 348 X509V3_conf_err(cnf); 349 goto err; 350 } 351 } 352 353 if (not->noticeref && 354 (!not->noticeref->noticenos || !not->noticeref->organization)) { 355 X509V3err(X509V3_F_NOTICE_SECTION, 356 X509V3_R_NEED_ORGANIZATION_AND_NUMBERS); 357 goto err; 358 } 359 360 return qual; 361 362 merr: 363 X509V3err(X509V3_F_NOTICE_SECTION, ERR_R_MALLOC_FAILURE); 364 365 err: 366 POLICYQUALINFO_free(qual); 367 return NULL; 368} 369 370static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos) 371{ 372 CONF_VALUE *cnf; 373 ASN1_INTEGER *aint; 374 375 int i; 376 377 for (i = 0; i < sk_CONF_VALUE_num(nos); i++) { 378 cnf = sk_CONF_VALUE_value(nos, i); 379 if (!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) { 380 X509V3err(X509V3_F_NREF_NOS, X509V3_R_INVALID_NUMBER); 381 goto err; 382 } 383 if (!sk_ASN1_INTEGER_push(nnums, aint)) 384 goto merr; 385 } 386 return 1; 387 388 merr: 389 X509V3err(X509V3_F_NREF_NOS, ERR_R_MALLOC_FAILURE); 390 391 err: 392 sk_ASN1_INTEGER_pop_free(nnums, ASN1_STRING_free); 393 return 0; 394} 395 396static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, 397 BIO *out, int indent) 398{ 399 int i; 400 POLICYINFO *pinfo; 401 /* First print out the policy OIDs */ 402 for (i = 0; i < sk_POLICYINFO_num(pol); i++) { 403 pinfo = sk_POLICYINFO_value(pol, i); 404 BIO_printf(out, "%*sPolicy: ", indent, ""); 405 i2a_ASN1_OBJECT(out, pinfo->policyid); 406 BIO_puts(out, "\n"); 407 if (pinfo->qualifiers) 408 print_qualifiers(out, pinfo->qualifiers, indent + 2); 409 } 410 return 1; 411} 412 413static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, 414 int indent) 415{ 416 POLICYQUALINFO *qualinfo; 417 int i; 418 for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) { 419 qualinfo = sk_POLICYQUALINFO_value(quals, i); 420 switch (OBJ_obj2nid(qualinfo->pqualid)) { 421 case NID_id_qt_cps: 422 BIO_printf(out, "%*sCPS: %s\n", indent, "", 423 qualinfo->d.cpsuri->data); 424 break; 425 426 case NID_id_qt_unotice: 427 BIO_printf(out, "%*sUser Notice:\n", indent, ""); 428 print_notice(out, qualinfo->d.usernotice, indent + 2); 429 break; 430 431 default: 432 BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, ""); 433 434 i2a_ASN1_OBJECT(out, qualinfo->pqualid); 435 BIO_puts(out, "\n"); 436 break; 437 } 438 } 439} 440 441static void print_notice(BIO *out, USERNOTICE *notice, int indent) 442{ 443 int i; 444 if (notice->noticeref) { 445 NOTICEREF *ref; 446 ref = notice->noticeref; 447 BIO_printf(out, "%*sOrganization: %s\n", indent, "", 448 ref->organization->data); 449 BIO_printf(out, "%*sNumber%s: ", indent, "", 450 sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : ""); 451 for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) { 452 ASN1_INTEGER *num; 453 char *tmp; 454 num = sk_ASN1_INTEGER_value(ref->noticenos, i); 455 if (i) 456 BIO_puts(out, ", "); 457 tmp = i2s_ASN1_INTEGER(NULL, num); 458 BIO_puts(out, tmp); 459 OPENSSL_free(tmp); 460 } 461 BIO_puts(out, "\n"); 462 } 463 if (notice->exptext) 464 BIO_printf(out, "%*sExplicit Text: %s\n", indent, "", 465 notice->exptext->data); 466} 467 468void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent) 469{ 470 const X509_POLICY_DATA *dat = node->data; 471 472 BIO_printf(out, "%*sPolicy: ", indent, ""); 473 474 i2a_ASN1_OBJECT(out, dat->valid_policy); 475 BIO_puts(out, "\n"); 476 BIO_printf(out, "%*s%s\n", indent + 2, "", 477 node_data_critical(dat) ? "Critical" : "Non Critical"); 478 if (dat->qualifier_set) 479 print_qualifiers(out, dat->qualifier_set, indent + 2); 480 else 481 BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, ""); 482} 483 484 485IMPLEMENT_STACK_OF(X509_POLICY_NODE) 486 487IMPLEMENT_STACK_OF(X509_POLICY_DATA) 488