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