1/* v3_cpols.c */ 2/* Written by Dr Stephen N Henson (shenson@bigfoot.com) 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 80X509V3_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 sk_POLICYINFO_push(pols, pol); 185 } 186 sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); 187 return pols; 188 err: 189 sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); 190 sk_POLICYINFO_pop_free(pols, POLICYINFO_free); 191 return NULL; 192} 193 194static POLICYINFO *policy_section(X509V3_CTX *ctx, 195 STACK_OF(CONF_VALUE) *polstrs, int ia5org) 196{ 197 int i; 198 CONF_VALUE *cnf; 199 POLICYINFO *pol; 200 POLICYQUALINFO *qual; 201 if(!(pol = POLICYINFO_new())) goto merr; 202 for(i = 0; i < sk_CONF_VALUE_num(polstrs); i++) { 203 cnf = sk_CONF_VALUE_value(polstrs, i); 204 if(!strcmp(cnf->name, "policyIdentifier")) { 205 ASN1_OBJECT *pobj; 206 if(!(pobj = OBJ_txt2obj(cnf->value, 0))) { 207 X509V3err(X509V3_F_POLICY_SECTION,X509V3_R_INVALID_OBJECT_IDENTIFIER); 208 X509V3_conf_err(cnf); 209 goto err; 210 } 211 pol->policyid = pobj; 212 213 } else if(!name_cmp(cnf->name, "CPS")) { 214 if(!pol->qualifiers) pol->qualifiers = 215 sk_POLICYQUALINFO_new_null(); 216 if(!(qual = POLICYQUALINFO_new())) goto merr; 217 if(!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) 218 goto merr; 219 qual->pqualid = OBJ_nid2obj(NID_id_qt_cps); 220 qual->d.cpsuri = M_ASN1_IA5STRING_new(); 221 if(!ASN1_STRING_set(qual->d.cpsuri, cnf->value, 222 strlen(cnf->value))) goto merr; 223 } else if(!name_cmp(cnf->name, "userNotice")) { 224 STACK_OF(CONF_VALUE) *unot; 225 if(*cnf->value != '@') { 226 X509V3err(X509V3_F_POLICY_SECTION,X509V3_R_EXPECTED_A_SECTION_NAME); 227 X509V3_conf_err(cnf); 228 goto err; 229 } 230 unot = X509V3_get_section(ctx, cnf->value + 1); 231 if(!unot) { 232 X509V3err(X509V3_F_POLICY_SECTION,X509V3_R_INVALID_SECTION); 233 234 X509V3_conf_err(cnf); 235 goto err; 236 } 237 qual = notice_section(ctx, unot, ia5org); 238 X509V3_section_free(ctx, unot); 239 if(!qual) goto err; 240 if(!pol->qualifiers) pol->qualifiers = 241 sk_POLICYQUALINFO_new_null(); 242 if(!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) 243 goto merr; 244 } else { 245 X509V3err(X509V3_F_POLICY_SECTION,X509V3_R_INVALID_OPTION); 246 247 X509V3_conf_err(cnf); 248 goto err; 249 } 250 } 251 if(!pol->policyid) { 252 X509V3err(X509V3_F_POLICY_SECTION,X509V3_R_NO_POLICY_IDENTIFIER); 253 goto err; 254 } 255 256 return pol; 257 258 merr: 259 X509V3err(X509V3_F_POLICY_SECTION,ERR_R_MALLOC_FAILURE); 260 261 err: 262 POLICYINFO_free(pol); 263 return NULL; 264 265 266} 267 268static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, 269 STACK_OF(CONF_VALUE) *unot, int ia5org) 270{ 271 int i, ret; 272 CONF_VALUE *cnf; 273 USERNOTICE *not; 274 POLICYQUALINFO *qual; 275 if(!(qual = POLICYQUALINFO_new())) goto merr; 276 qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice); 277 if(!(not = USERNOTICE_new())) goto merr; 278 qual->d.usernotice = not; 279 for(i = 0; i < sk_CONF_VALUE_num(unot); i++) { 280 cnf = sk_CONF_VALUE_value(unot, i); 281 if(!strcmp(cnf->name, "explicitText")) { 282 not->exptext = M_ASN1_VISIBLESTRING_new(); 283 if(!ASN1_STRING_set(not->exptext, cnf->value, 284 strlen(cnf->value))) goto merr; 285 } else if(!strcmp(cnf->name, "organization")) { 286 NOTICEREF *nref; 287 if(!not->noticeref) { 288 if(!(nref = NOTICEREF_new())) goto merr; 289 not->noticeref = nref; 290 } else nref = not->noticeref; 291 if(ia5org) nref->organization->type = V_ASN1_IA5STRING; 292 else nref->organization->type = V_ASN1_VISIBLESTRING; 293 if(!ASN1_STRING_set(nref->organization, cnf->value, 294 strlen(cnf->value))) goto merr; 295 } else if(!strcmp(cnf->name, "noticeNumbers")) { 296 NOTICEREF *nref; 297 STACK_OF(CONF_VALUE) *nos; 298 if(!not->noticeref) { 299 if(!(nref = NOTICEREF_new())) goto merr; 300 not->noticeref = nref; 301 } else nref = not->noticeref; 302 nos = X509V3_parse_list(cnf->value); 303 if(!nos || !sk_CONF_VALUE_num(nos)) { 304 X509V3err(X509V3_F_NOTICE_SECTION,X509V3_R_INVALID_NUMBERS); 305 X509V3_conf_err(cnf); 306 goto err; 307 } 308 ret = nref_nos(nref->noticenos, nos); 309 sk_CONF_VALUE_pop_free(nos, X509V3_conf_free); 310 if (!ret) 311 goto err; 312 } else { 313 X509V3err(X509V3_F_NOTICE_SECTION,X509V3_R_INVALID_OPTION); 314 X509V3_conf_err(cnf); 315 goto err; 316 } 317 } 318 319 if(not->noticeref && 320 (!not->noticeref->noticenos || !not->noticeref->organization)) { 321 X509V3err(X509V3_F_NOTICE_SECTION,X509V3_R_NEED_ORGANIZATION_AND_NUMBERS); 322 goto err; 323 } 324 325 return qual; 326 327 merr: 328 X509V3err(X509V3_F_NOTICE_SECTION,ERR_R_MALLOC_FAILURE); 329 330 err: 331 POLICYQUALINFO_free(qual); 332 return NULL; 333} 334 335static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos) 336{ 337 CONF_VALUE *cnf; 338 ASN1_INTEGER *aint; 339 340 int i; 341 342 for(i = 0; i < sk_CONF_VALUE_num(nos); i++) { 343 cnf = sk_CONF_VALUE_value(nos, i); 344 if(!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) { 345 X509V3err(X509V3_F_NREF_NOS,X509V3_R_INVALID_NUMBER); 346 goto err; 347 } 348 if(!sk_ASN1_INTEGER_push(nnums, aint)) goto merr; 349 } 350 return 1; 351 352 merr: 353 X509V3err(X509V3_F_NREF_NOS,ERR_R_MALLOC_FAILURE); 354 355 err: 356 sk_ASN1_INTEGER_pop_free(nnums, ASN1_STRING_free); 357 return 0; 358} 359 360 361static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, 362 BIO *out, int indent) 363{ 364 int i; 365 POLICYINFO *pinfo; 366 /* First print out the policy OIDs */ 367 for(i = 0; i < sk_POLICYINFO_num(pol); i++) { 368 pinfo = sk_POLICYINFO_value(pol, i); 369 BIO_printf(out, "%*sPolicy: ", indent, ""); 370 i2a_ASN1_OBJECT(out, pinfo->policyid); 371 BIO_puts(out, "\n"); 372 if(pinfo->qualifiers) 373 print_qualifiers(out, pinfo->qualifiers, indent + 2); 374 } 375 return 1; 376} 377 378static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, 379 int indent) 380{ 381 POLICYQUALINFO *qualinfo; 382 int i; 383 for(i = 0; i < sk_POLICYQUALINFO_num(quals); i++) { 384 qualinfo = sk_POLICYQUALINFO_value(quals, i); 385 switch(OBJ_obj2nid(qualinfo->pqualid)) 386 { 387 case NID_id_qt_cps: 388 BIO_printf(out, "%*sCPS: %s\n", indent, "", 389 qualinfo->d.cpsuri->data); 390 break; 391 392 case NID_id_qt_unotice: 393 BIO_printf(out, "%*sUser Notice:\n", indent, ""); 394 print_notice(out, qualinfo->d.usernotice, indent + 2); 395 break; 396 397 default: 398 BIO_printf(out, "%*sUnknown Qualifier: ", 399 indent + 2, ""); 400 401 i2a_ASN1_OBJECT(out, qualinfo->pqualid); 402 BIO_puts(out, "\n"); 403 break; 404 } 405 } 406} 407 408static void print_notice(BIO *out, USERNOTICE *notice, int indent) 409{ 410 int i; 411 if(notice->noticeref) { 412 NOTICEREF *ref; 413 ref = notice->noticeref; 414 BIO_printf(out, "%*sOrganization: %s\n", indent, "", 415 ref->organization->data); 416 BIO_printf(out, "%*sNumber%s: ", indent, "", 417 sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : ""); 418 for(i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) { 419 ASN1_INTEGER *num; 420 char *tmp; 421 num = sk_ASN1_INTEGER_value(ref->noticenos, i); 422 if(i) BIO_puts(out, ", "); 423 tmp = i2s_ASN1_INTEGER(NULL, num); 424 BIO_puts(out, tmp); 425 OPENSSL_free(tmp); 426 } 427 BIO_puts(out, "\n"); 428 } 429 if(notice->exptext) 430 BIO_printf(out, "%*sExplicit Text: %s\n", indent, "", 431 notice->exptext->data); 432} 433 434void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent) 435 { 436 const X509_POLICY_DATA *dat = node->data; 437 438 BIO_printf(out, "%*sPolicy: ", indent, ""); 439 440 i2a_ASN1_OBJECT(out, dat->valid_policy); 441 BIO_puts(out, "\n"); 442 BIO_printf(out, "%*s%s\n", indent + 2, "", 443 node_data_critical(dat) ? "Critical" : "Non Critical"); 444 if (dat->qualifier_set) 445 print_qualifiers(out, dat->qualifier_set, indent + 2); 446 else 447 BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, ""); 448 } 449 450