v3_cpols.c revision 296465
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 qual->pqualid = OBJ_nid2obj(NID_id_qt_cps); 234 qual->d.cpsuri = M_ASN1_IA5STRING_new(); 235 if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value, 236 strlen(cnf->value))) 237 goto merr; 238 } else if (!name_cmp(cnf->name, "userNotice")) { 239 STACK_OF(CONF_VALUE) *unot; 240 if (*cnf->value != '@') { 241 X509V3err(X509V3_F_POLICY_SECTION, 242 X509V3_R_EXPECTED_A_SECTION_NAME); 243 X509V3_conf_err(cnf); 244 goto err; 245 } 246 unot = X509V3_get_section(ctx, cnf->value + 1); 247 if (!unot) { 248 X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_INVALID_SECTION); 249 250 X509V3_conf_err(cnf); 251 goto err; 252 } 253 qual = notice_section(ctx, unot, ia5org); 254 X509V3_section_free(ctx, unot); 255 if (!qual) 256 goto err; 257 if (!pol->qualifiers) 258 pol->qualifiers = sk_POLICYQUALINFO_new_null(); 259 if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) 260 goto merr; 261 } else { 262 X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_INVALID_OPTION); 263 264 X509V3_conf_err(cnf); 265 goto err; 266 } 267 } 268 if (!pol->policyid) { 269 X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_NO_POLICY_IDENTIFIER); 270 goto err; 271 } 272 273 return pol; 274 275 merr: 276 X509V3err(X509V3_F_POLICY_SECTION, ERR_R_MALLOC_FAILURE); 277 278 err: 279 POLICYINFO_free(pol); 280 return NULL; 281 282} 283 284static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, 285 STACK_OF(CONF_VALUE) *unot, int ia5org) 286{ 287 int i, ret; 288 CONF_VALUE *cnf; 289 USERNOTICE *not; 290 POLICYQUALINFO *qual; 291 if (!(qual = POLICYQUALINFO_new())) 292 goto merr; 293 qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice); 294 if (!(not = USERNOTICE_new())) 295 goto merr; 296 qual->d.usernotice = not; 297 for (i = 0; i < sk_CONF_VALUE_num(unot); i++) { 298 cnf = sk_CONF_VALUE_value(unot, i); 299 if (!strcmp(cnf->name, "explicitText")) { 300 not->exptext = M_ASN1_VISIBLESTRING_new(); 301 if (!ASN1_STRING_set(not->exptext, cnf->value, 302 strlen(cnf->value))) 303 goto merr; 304 } else if (!strcmp(cnf->name, "organization")) { 305 NOTICEREF *nref; 306 if (!not->noticeref) { 307 if (!(nref = NOTICEREF_new())) 308 goto merr; 309 not->noticeref = nref; 310 } else 311 nref = not->noticeref; 312 if (ia5org) 313 nref->organization->type = V_ASN1_IA5STRING; 314 else 315 nref->organization->type = V_ASN1_VISIBLESTRING; 316 if (!ASN1_STRING_set(nref->organization, cnf->value, 317 strlen(cnf->value))) 318 goto merr; 319 } else if (!strcmp(cnf->name, "noticeNumbers")) { 320 NOTICEREF *nref; 321 STACK_OF(CONF_VALUE) *nos; 322 if (!not->noticeref) { 323 if (!(nref = NOTICEREF_new())) 324 goto merr; 325 not->noticeref = nref; 326 } else 327 nref = not->noticeref; 328 nos = X509V3_parse_list(cnf->value); 329 if (!nos || !sk_CONF_VALUE_num(nos)) { 330 X509V3err(X509V3_F_NOTICE_SECTION, X509V3_R_INVALID_NUMBERS); 331 X509V3_conf_err(cnf); 332 goto err; 333 } 334 ret = nref_nos(nref->noticenos, nos); 335 sk_CONF_VALUE_pop_free(nos, X509V3_conf_free); 336 if (!ret) 337 goto err; 338 } else { 339 X509V3err(X509V3_F_NOTICE_SECTION, X509V3_R_INVALID_OPTION); 340 X509V3_conf_err(cnf); 341 goto err; 342 } 343 } 344 345 if (not->noticeref && 346 (!not->noticeref->noticenos || !not->noticeref->organization)) { 347 X509V3err(X509V3_F_NOTICE_SECTION, 348 X509V3_R_NEED_ORGANIZATION_AND_NUMBERS); 349 goto err; 350 } 351 352 return qual; 353 354 merr: 355 X509V3err(X509V3_F_NOTICE_SECTION, ERR_R_MALLOC_FAILURE); 356 357 err: 358 POLICYQUALINFO_free(qual); 359 return NULL; 360} 361 362static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos) 363{ 364 CONF_VALUE *cnf; 365 ASN1_INTEGER *aint; 366 367 int i; 368 369 for (i = 0; i < sk_CONF_VALUE_num(nos); i++) { 370 cnf = sk_CONF_VALUE_value(nos, i); 371 if (!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) { 372 X509V3err(X509V3_F_NREF_NOS, X509V3_R_INVALID_NUMBER); 373 goto err; 374 } 375 if (!sk_ASN1_INTEGER_push(nnums, aint)) 376 goto merr; 377 } 378 return 1; 379 380 merr: 381 X509V3err(X509V3_F_NREF_NOS, ERR_R_MALLOC_FAILURE); 382 383 err: 384 sk_ASN1_INTEGER_pop_free(nnums, ASN1_STRING_free); 385 return 0; 386} 387 388static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, 389 BIO *out, int indent) 390{ 391 int i; 392 POLICYINFO *pinfo; 393 /* First print out the policy OIDs */ 394 for (i = 0; i < sk_POLICYINFO_num(pol); i++) { 395 pinfo = sk_POLICYINFO_value(pol, i); 396 BIO_printf(out, "%*sPolicy: ", indent, ""); 397 i2a_ASN1_OBJECT(out, pinfo->policyid); 398 BIO_puts(out, "\n"); 399 if (pinfo->qualifiers) 400 print_qualifiers(out, pinfo->qualifiers, indent + 2); 401 } 402 return 1; 403} 404 405static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, 406 int indent) 407{ 408 POLICYQUALINFO *qualinfo; 409 int i; 410 for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) { 411 qualinfo = sk_POLICYQUALINFO_value(quals, i); 412 switch (OBJ_obj2nid(qualinfo->pqualid)) { 413 case NID_id_qt_cps: 414 BIO_printf(out, "%*sCPS: %s\n", indent, "", 415 qualinfo->d.cpsuri->data); 416 break; 417 418 case NID_id_qt_unotice: 419 BIO_printf(out, "%*sUser Notice:\n", indent, ""); 420 print_notice(out, qualinfo->d.usernotice, indent + 2); 421 break; 422 423 default: 424 BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, ""); 425 426 i2a_ASN1_OBJECT(out, qualinfo->pqualid); 427 BIO_puts(out, "\n"); 428 break; 429 } 430 } 431} 432 433static void print_notice(BIO *out, USERNOTICE *notice, int indent) 434{ 435 int i; 436 if (notice->noticeref) { 437 NOTICEREF *ref; 438 ref = notice->noticeref; 439 BIO_printf(out, "%*sOrganization: %s\n", indent, "", 440 ref->organization->data); 441 BIO_printf(out, "%*sNumber%s: ", indent, "", 442 sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : ""); 443 for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) { 444 ASN1_INTEGER *num; 445 char *tmp; 446 num = sk_ASN1_INTEGER_value(ref->noticenos, i); 447 if (i) 448 BIO_puts(out, ", "); 449 tmp = i2s_ASN1_INTEGER(NULL, num); 450 BIO_puts(out, tmp); 451 OPENSSL_free(tmp); 452 } 453 BIO_puts(out, "\n"); 454 } 455 if (notice->exptext) 456 BIO_printf(out, "%*sExplicit Text: %s\n", indent, "", 457 notice->exptext->data); 458} 459 460void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent) 461{ 462 const X509_POLICY_DATA *dat = node->data; 463 464 BIO_printf(out, "%*sPolicy: ", indent, ""); 465 466 i2a_ASN1_OBJECT(out, dat->valid_policy); 467 BIO_puts(out, "\n"); 468 BIO_printf(out, "%*s%s\n", indent + 2, "", 469 node_data_critical(dat) ? "Critical" : "Non Critical"); 470 if (dat->qualifier_set) 471 print_qualifiers(out, dat->qualifier_set, indent + 2); 472 else 473 BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, ""); 474} 475 476IMPLEMENT_STACK_OF(X509_POLICY_NODE) 477