1 /* v3_cpols.c */ 2 /* 3 * Written by Dr Stephen N Henson (steve (at) 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 (at) 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 (at) cryptsoft.com). This product includes software written by Tim 56 * Hudson (tjh (at) cryptsoft.com). 57 * 58 */ 59 60 #include <stdio.h> 61 #include <string.h> 62 63 #include <openssl/asn1.h> 64 #include <openssl/asn1t.h> 65 #include <openssl/conf.h> 66 #include <openssl/err.h> 67 #include <openssl/mem.h> 68 #include <openssl/obj.h> 69 #include <openssl/stack.h> 70 #include <openssl/x509v3.h> 71 72 #include "pcy_int.h" 73 74 /* Certificate policies extension support: this one is a bit complex... */ 75 76 static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, 77 BIO *out, int indent); 78 static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, 79 X509V3_CTX *ctx, char *value); 80 static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, 81 int indent); 82 static void print_notice(BIO *out, USERNOTICE *notice, int indent); 83 static POLICYINFO *policy_section(X509V3_CTX *ctx, 84 STACK_OF(CONF_VALUE) *polstrs, int ia5org); 85 static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, 86 STACK_OF(CONF_VALUE) *unot, int ia5org); 87 static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos); 88 89 const X509V3_EXT_METHOD v3_cpols = { 90 NID_certificate_policies, 0, ASN1_ITEM_ref(CERTIFICATEPOLICIES), 91 0, 0, 0, 0, 92 0, 0, 93 0, 0, 94 (X509V3_EXT_I2R)i2r_certpol, 95 (X509V3_EXT_R2I)r2i_certpol, 96 NULL 97 }; 98 99 ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) = 100 ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO) 101 ASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES) 102 103 IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES) 104 105 ASN1_SEQUENCE(POLICYINFO) = { 106 ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT), 107 ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO) 108 } ASN1_SEQUENCE_END(POLICYINFO) 109 110 IMPLEMENT_ASN1_FUNCTIONS(POLICYINFO) 111 112 ASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other, ASN1_ANY); 113 114 ASN1_ADB(POLICYQUALINFO) = { 115 ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)), 116 ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE)) 117 } ASN1_ADB_END(POLICYQUALINFO, 0, pqualid, 0, &policydefault_tt, NULL); 118 119 ASN1_SEQUENCE(POLICYQUALINFO) = { 120 ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT), 121 ASN1_ADB_OBJECT(POLICYQUALINFO) 122 } ASN1_SEQUENCE_END(POLICYQUALINFO) 123 124 IMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO) 125 126 ASN1_SEQUENCE(USERNOTICE) = { 127 ASN1_OPT(USERNOTICE, noticeref, NOTICEREF), 128 ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT) 129 } ASN1_SEQUENCE_END(USERNOTICE) 130 131 IMPLEMENT_ASN1_FUNCTIONS(USERNOTICE) 132 133 ASN1_SEQUENCE(NOTICEREF) = { 134 ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT), 135 ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER) 136 } ASN1_SEQUENCE_END(NOTICEREF) 137 138 IMPLEMENT_ASN1_FUNCTIONS(NOTICEREF) 139 140 static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, 141 X509V3_CTX *ctx, char *value) 142 { 143 STACK_OF(POLICYINFO) *pols = NULL; 144 char *pstr; 145 POLICYINFO *pol; 146 ASN1_OBJECT *pobj; 147 STACK_OF(CONF_VALUE) *vals; 148 CONF_VALUE *cnf; 149 size_t i; 150 int ia5org; 151 pols = sk_POLICYINFO_new_null(); 152 if (pols == NULL) { 153 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 154 return NULL; 155 } 156 vals = X509V3_parse_list(value); 157 if (vals == NULL) { 158 OPENSSL_PUT_ERROR(X509V3, ERR_R_X509V3_LIB); 159 goto err; 160 } 161 ia5org = 0; 162 for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { 163 cnf = sk_CONF_VALUE_value(vals, i); 164 if (cnf->value || !cnf->name) { 165 OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_POLICY_IDENTIFIER); 166 X509V3_conf_err(cnf); 167 goto err; 168 } 169 pstr = cnf->name; 170 if (!strcmp(pstr, "ia5org")) { 171 ia5org = 1; 172 continue; 173 } else if (*pstr == '@') { 174 STACK_OF(CONF_VALUE) *polsect; 175 polsect = X509V3_get_section(ctx, pstr + 1); 176 if (!polsect) { 177 OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION); 178 179 X509V3_conf_err(cnf); 180 goto err; 181 } 182 pol = policy_section(ctx, polsect, ia5org); 183 X509V3_section_free(ctx, polsect); 184 if (!pol) 185 goto err; 186 } else { 187 if (!(pobj = OBJ_txt2obj(cnf->name, 0))) { 188 OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); 189 X509V3_conf_err(cnf); 190 goto err; 191 } 192 pol = POLICYINFO_new(); 193 if (pol == NULL) { 194 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 195 ASN1_OBJECT_free(pobj); 196 goto err; 197 } 198 pol->policyid = pobj; 199 } 200 if (!sk_POLICYINFO_push(pols, pol)) { 201 POLICYINFO_free(pol); 202 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 203 goto err; 204 } 205 } 206 sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); 207 return pols; 208 err: 209 sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); 210 sk_POLICYINFO_pop_free(pols, POLICYINFO_free); 211 return NULL; 212 } 213 214 static POLICYINFO *policy_section(X509V3_CTX *ctx, 215 STACK_OF(CONF_VALUE) *polstrs, int ia5org) 216 { 217 size_t i; 218 CONF_VALUE *cnf; 219 POLICYINFO *pol; 220 POLICYQUALINFO *qual; 221 if (!(pol = POLICYINFO_new())) 222 goto merr; 223 for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) { 224 cnf = sk_CONF_VALUE_value(polstrs, i); 225 if (!strcmp(cnf->name, "policyIdentifier")) { 226 ASN1_OBJECT *pobj; 227 if (!(pobj = OBJ_txt2obj(cnf->value, 0))) { 228 OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER); 229 X509V3_conf_err(cnf); 230 goto err; 231 } 232 pol->policyid = pobj; 233 234 } else if (!name_cmp(cnf->name, "CPS")) { 235 if (!pol->qualifiers) 236 pol->qualifiers = sk_POLICYQUALINFO_new_null(); 237 if (!(qual = POLICYQUALINFO_new())) 238 goto merr; 239 if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) 240 goto merr; 241 /* TODO(fork): const correctness */ 242 qual->pqualid = (ASN1_OBJECT *)OBJ_nid2obj(NID_id_qt_cps); 243 if (qual->pqualid == NULL) { 244 OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR); 245 goto err; 246 } 247 qual->d.cpsuri = M_ASN1_IA5STRING_new(); 248 if (qual->d.cpsuri == NULL) { 249 goto err; 250 } 251 if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value, 252 strlen(cnf->value))) 253 goto merr; 254 } else if (!name_cmp(cnf->name, "userNotice")) { 255 STACK_OF(CONF_VALUE) *unot; 256 if (*cnf->value != '@') { 257 OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXPECTED_A_SECTION_NAME); 258 X509V3_conf_err(cnf); 259 goto err; 260 } 261 unot = X509V3_get_section(ctx, cnf->value + 1); 262 if (!unot) { 263 OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION); 264 265 X509V3_conf_err(cnf); 266 goto err; 267 } 268 qual = notice_section(ctx, unot, ia5org); 269 X509V3_section_free(ctx, unot); 270 if (!qual) 271 goto err; 272 if (!pol->qualifiers) 273 pol->qualifiers = sk_POLICYQUALINFO_new_null(); 274 if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) 275 goto merr; 276 } else { 277 OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OPTION); 278 279 X509V3_conf_err(cnf); 280 goto err; 281 } 282 } 283 if (!pol->policyid) { 284 OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_POLICY_IDENTIFIER); 285 goto err; 286 } 287 288 return pol; 289 290 merr: 291 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 292 293 err: 294 POLICYINFO_free(pol); 295 return NULL; 296 297 } 298 299 static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, 300 STACK_OF(CONF_VALUE) *unot, int ia5org) 301 { 302 size_t i; 303 int ret; 304 CONF_VALUE *cnf; 305 USERNOTICE *not; 306 POLICYQUALINFO *qual; 307 if (!(qual = POLICYQUALINFO_new())) 308 goto merr; 309 /* TODO(fork): const correctness */ 310 qual->pqualid = (ASN1_OBJECT *)OBJ_nid2obj(NID_id_qt_unotice); 311 if (qual->pqualid == NULL) { 312 OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR); 313 goto err; 314 } 315 if (!(not = USERNOTICE_new())) 316 goto merr; 317 qual->d.usernotice = not; 318 for (i = 0; i < sk_CONF_VALUE_num(unot); i++) { 319 cnf = sk_CONF_VALUE_value(unot, i); 320 if (!strcmp(cnf->name, "explicitText")) { 321 not->exptext = M_ASN1_VISIBLESTRING_new(); 322 if (not->exptext == NULL) 323 goto merr; 324 if (!ASN1_STRING_set(not->exptext, cnf->value, 325 strlen(cnf->value))) 326 goto merr; 327 } else if (!strcmp(cnf->name, "organization")) { 328 NOTICEREF *nref; 329 if (!not->noticeref) { 330 if (!(nref = NOTICEREF_new())) 331 goto merr; 332 not->noticeref = nref; 333 } else 334 nref = not->noticeref; 335 if (ia5org) 336 nref->organization->type = V_ASN1_IA5STRING; 337 else 338 nref->organization->type = V_ASN1_VISIBLESTRING; 339 if (!ASN1_STRING_set(nref->organization, cnf->value, 340 strlen(cnf->value))) 341 goto merr; 342 } else if (!strcmp(cnf->name, "noticeNumbers")) { 343 NOTICEREF *nref; 344 STACK_OF(CONF_VALUE) *nos; 345 if (!not->noticeref) { 346 if (!(nref = NOTICEREF_new())) 347 goto merr; 348 not->noticeref = nref; 349 } else 350 nref = not->noticeref; 351 nos = X509V3_parse_list(cnf->value); 352 if (!nos || !sk_CONF_VALUE_num(nos)) { 353 OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NUMBERS); 354 X509V3_conf_err(cnf); 355 goto err; 356 } 357 ret = nref_nos(nref->noticenos, nos); 358 sk_CONF_VALUE_pop_free(nos, X509V3_conf_free); 359 if (!ret) 360 goto err; 361 } else { 362 OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OPTION); 363 X509V3_conf_err(cnf); 364 goto err; 365 } 366 } 367 368 if (not->noticeref && 369 (!not->noticeref->noticenos || !not->noticeref->organization)) { 370 OPENSSL_PUT_ERROR(X509V3, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS); 371 goto err; 372 } 373 374 return qual; 375 376 merr: 377 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 378 379 err: 380 POLICYQUALINFO_free(qual); 381 return NULL; 382 } 383 384 static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos) 385 { 386 CONF_VALUE *cnf; 387 ASN1_INTEGER *aint; 388 389 size_t i; 390 391 for (i = 0; i < sk_CONF_VALUE_num(nos); i++) { 392 cnf = sk_CONF_VALUE_value(nos, i); 393 if (!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) { 394 OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NUMBER); 395 goto err; 396 } 397 if (!sk_ASN1_INTEGER_push(nnums, aint)) 398 goto merr; 399 } 400 return 1; 401 402 merr: 403 ASN1_INTEGER_free(aint); 404 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 405 406 err: 407 return 0; 408 } 409 410 static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, 411 BIO *out, int indent) 412 { 413 size_t i; 414 POLICYINFO *pinfo; 415 /* First print out the policy OIDs */ 416 for (i = 0; i < sk_POLICYINFO_num(pol); i++) { 417 pinfo = sk_POLICYINFO_value(pol, i); 418 BIO_printf(out, "%*sPolicy: ", indent, ""); 419 i2a_ASN1_OBJECT(out, pinfo->policyid); 420 BIO_puts(out, "\n"); 421 if (pinfo->qualifiers) 422 print_qualifiers(out, pinfo->qualifiers, indent + 2); 423 } 424 return 1; 425 } 426 427 static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, 428 int indent) 429 { 430 POLICYQUALINFO *qualinfo; 431 size_t i; 432 for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) { 433 qualinfo = sk_POLICYQUALINFO_value(quals, i); 434 switch (OBJ_obj2nid(qualinfo->pqualid)) { 435 case NID_id_qt_cps: 436 BIO_printf(out, "%*sCPS: %s\n", indent, "", 437 qualinfo->d.cpsuri->data); 438 break; 439 440 case NID_id_qt_unotice: 441 BIO_printf(out, "%*sUser Notice:\n", indent, ""); 442 print_notice(out, qualinfo->d.usernotice, indent + 2); 443 break; 444 445 default: 446 BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, ""); 447 448 i2a_ASN1_OBJECT(out, qualinfo->pqualid); 449 BIO_puts(out, "\n"); 450 break; 451 } 452 } 453 } 454 455 static void print_notice(BIO *out, USERNOTICE *notice, int indent) 456 { 457 size_t i; 458 if (notice->noticeref) { 459 NOTICEREF *ref; 460 ref = notice->noticeref; 461 BIO_printf(out, "%*sOrganization: %s\n", indent, "", 462 ref->organization->data); 463 BIO_printf(out, "%*sNumber%s: ", indent, "", 464 sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : ""); 465 for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) { 466 ASN1_INTEGER *num; 467 char *tmp; 468 num = sk_ASN1_INTEGER_value(ref->noticenos, i); 469 if (i) 470 BIO_puts(out, ", "); 471 if (num == NULL) 472 BIO_puts(out, "(null)"); 473 else { 474 tmp = i2s_ASN1_INTEGER(NULL, num); 475 if (tmp == NULL) 476 return; 477 BIO_puts(out, tmp); 478 OPENSSL_free(tmp); 479 } 480 } 481 BIO_puts(out, "\n"); 482 } 483 if (notice->exptext) 484 BIO_printf(out, "%*sExplicit Text: %s\n", indent, "", 485 notice->exptext->data); 486 } 487 488 void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent) 489 { 490 const X509_POLICY_DATA *dat = node->data; 491 492 BIO_printf(out, "%*sPolicy: ", indent, ""); 493 494 i2a_ASN1_OBJECT(out, dat->valid_policy); 495 BIO_puts(out, "\n"); 496 BIO_printf(out, "%*s%s\n", indent + 2, "", 497 node_data_critical(dat) ? "Critical" : "Non Critical"); 498 if (dat->qualifier_set) 499 print_qualifiers(out, dat->qualifier_set, indent + 2); 500 else 501 BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, ""); 502 } 503