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