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