security/nss/lib/certdb/polcyxtn.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 /*
michael@0 6 * Support for various policy related extensions
michael@0 7 */
michael@0 8
michael@0 9 #include "seccomon.h"
michael@0 10 #include "secport.h"
michael@0 11 #include "secder.h"
michael@0 12 #include "cert.h"
michael@0 13 #include "secoid.h"
michael@0 14 #include "secasn1.h"
michael@0 15 #include "secerr.h"
michael@0 16 #include "nspr.h"
michael@0 17
michael@0 18 SEC_ASN1_MKSUB(SEC_IntegerTemplate)
michael@0 19 SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
michael@0 20
michael@0 21 const SEC_ASN1Template CERT_DisplayTextTypeTemplate[] = {
michael@0 22 { SEC_ASN1_CHOICE, offsetof(SECItem, type), 0, sizeof(SECItem) },
michael@0 23 { SEC_ASN1_IA5_STRING, 0, 0, siAsciiString},
michael@0 24 { SEC_ASN1_VISIBLE_STRING , 0, 0, siVisibleString},
michael@0 25 { SEC_ASN1_BMP_STRING , 0, 0, siBMPString },
michael@0 26 { SEC_ASN1_UTF8_STRING , 0, 0, siUTF8String },
michael@0 27 { 0 }
michael@0 28 };
michael@0 29
michael@0 30 const SEC_ASN1Template CERT_NoticeReferenceTemplate[] = {
michael@0 31 { SEC_ASN1_SEQUENCE,
michael@0 32 0, NULL, sizeof(CERTNoticeReference) },
michael@0 33 { SEC_ASN1_INLINE,
michael@0 34 offsetof(CERTNoticeReference, organization),
michael@0 35 CERT_DisplayTextTypeTemplate, 0 },
michael@0 36 { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN,
michael@0 37 offsetof(CERTNoticeReference, noticeNumbers),
michael@0 38 SEC_ASN1_SUB(SEC_IntegerTemplate) },
michael@0 39 { 0 }
michael@0 40 };
michael@0 41
michael@0 42 const SEC_ASN1Template CERT_UserNoticeTemplate[] = {
michael@0 43 { SEC_ASN1_SEQUENCE,
michael@0 44 0, NULL, sizeof(CERTUserNotice) },
michael@0 45 { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL,
michael@0 46 offsetof(CERTUserNotice, noticeReference),
michael@0 47 CERT_NoticeReferenceTemplate, 0 },
michael@0 48 { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL,
michael@0 49 offsetof(CERTUserNotice, displayText),
michael@0 50 CERT_DisplayTextTypeTemplate, 0 },
michael@0 51 { 0 }
michael@0 52 };
michael@0 53
michael@0 54 const SEC_ASN1Template CERT_PolicyQualifierTemplate[] = {
michael@0 55 { SEC_ASN1_SEQUENCE,
michael@0 56 0, NULL, sizeof(CERTPolicyQualifier) },
michael@0 57 { SEC_ASN1_OBJECT_ID,
michael@0 58 offsetof(CERTPolicyQualifier, qualifierID) },
michael@0 59 { SEC_ASN1_ANY,
michael@0 60 offsetof(CERTPolicyQualifier, qualifierValue) },
michael@0 61 { 0 }
michael@0 62 };
michael@0 63
michael@0 64 const SEC_ASN1Template CERT_PolicyInfoTemplate[] = {
michael@0 65 { SEC_ASN1_SEQUENCE,
michael@0 66 0, NULL, sizeof(CERTPolicyInfo) },
michael@0 67 { SEC_ASN1_OBJECT_ID,
michael@0 68 offsetof(CERTPolicyInfo, policyID) },
michael@0 69 { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_OPTIONAL,
michael@0 70 offsetof(CERTPolicyInfo, policyQualifiers),
michael@0 71 CERT_PolicyQualifierTemplate },
michael@0 72 { 0 }
michael@0 73 };
michael@0 74
michael@0 75 const SEC_ASN1Template CERT_CertificatePoliciesTemplate[] = {
michael@0 76 { SEC_ASN1_SEQUENCE_OF,
michael@0 77 offsetof(CERTCertificatePolicies, policyInfos),
michael@0 78 CERT_PolicyInfoTemplate, sizeof(CERTCertificatePolicies) }
michael@0 79 };
michael@0 80
michael@0 81 const SEC_ASN1Template CERT_PolicyMapTemplate[] = {
michael@0 82 { SEC_ASN1_SEQUENCE,
michael@0 83 0, NULL, sizeof(CERTPolicyMap) },
michael@0 84 { SEC_ASN1_OBJECT_ID,
michael@0 85 offsetof(CERTPolicyMap, issuerDomainPolicy) },
michael@0 86 { SEC_ASN1_OBJECT_ID,
michael@0 87 offsetof(CERTPolicyMap, subjectDomainPolicy) },
michael@0 88 { 0 }
michael@0 89 };
michael@0 90
michael@0 91 const SEC_ASN1Template CERT_PolicyMappingsTemplate[] = {
michael@0 92 { SEC_ASN1_SEQUENCE_OF,
michael@0 93 offsetof(CERTCertificatePolicyMappings, policyMaps),
michael@0 94 CERT_PolicyMapTemplate, sizeof(CERTPolicyMap) }
michael@0 95 };
michael@0 96
michael@0 97 const SEC_ASN1Template CERT_PolicyConstraintsTemplate[] = {
michael@0 98 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTCertificatePolicyConstraints) },
michael@0 99 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
michael@0 100 offsetof(CERTCertificatePolicyConstraints, explicitPolicySkipCerts),
michael@0 101 SEC_ASN1_SUB(SEC_IntegerTemplate) },
michael@0 102 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1,
michael@0 103 offsetof(CERTCertificatePolicyConstraints, inhibitMappingSkipCerts),
michael@0 104 SEC_ASN1_SUB(SEC_IntegerTemplate) },
michael@0 105 { 0 }
michael@0 106 };
michael@0 107
michael@0 108 const SEC_ASN1Template CERT_InhibitAnyTemplate[] = {
michael@0 109 { SEC_ASN1_INTEGER,
michael@0 110 offsetof(CERTCertificateInhibitAny, inhibitAnySkipCerts),
michael@0 111 NULL, sizeof(CERTCertificateInhibitAny) }
michael@0 112 };
michael@0 113
michael@0 114 static void
michael@0 115 breakLines(char *string)
michael@0 116 {
michael@0 117 char *tmpstr;
michael@0 118 char *lastspace = NULL;
michael@0 119 int curlen = 0;
michael@0 120 int c;
michael@0 121
michael@0 122 tmpstr = string;
michael@0 123
michael@0 124 while ( ( c = *tmpstr ) != '\0' ) {
michael@0 125 switch ( c ) {
michael@0 126 case ' ':
michael@0 127 lastspace = tmpstr;
michael@0 128 break;
michael@0 129 case '\n':
michael@0 130 lastspace = NULL;
michael@0 131 curlen = 0;
michael@0 132 break;
michael@0 133 }
michael@0 134
michael@0 135 if ( ( curlen >= 55 ) && ( lastspace != NULL ) ) {
michael@0 136 *lastspace = '\n';
michael@0 137 curlen = ( tmpstr - lastspace );
michael@0 138 lastspace = NULL;
michael@0 139 }
michael@0 140
michael@0 141 curlen++;
michael@0 142 tmpstr++;
michael@0 143 }
michael@0 144
michael@0 145 return;
michael@0 146 }
michael@0 147
michael@0 148 CERTCertificatePolicies *
michael@0 149 CERT_DecodeCertificatePoliciesExtension(const SECItem *extnValue)
michael@0 150 {
michael@0 151 PLArenaPool *arena = NULL;
michael@0 152 SECStatus rv;
michael@0 153 CERTCertificatePolicies *policies;
michael@0 154 CERTPolicyInfo **policyInfos, *policyInfo;
michael@0 155 CERTPolicyQualifier **policyQualifiers, *policyQualifier;
michael@0 156 SECItem newExtnValue;
michael@0 157
michael@0 158 /* make a new arena */
michael@0 159 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 160
michael@0 161 if ( !arena ) {
michael@0 162 goto loser;
michael@0 163 }
michael@0 164
michael@0 165 /* allocate the certificate policies structure */
michael@0 166 policies = (CERTCertificatePolicies *)
michael@0 167 PORT_ArenaZAlloc(arena, sizeof(CERTCertificatePolicies));
michael@0 168
michael@0 169 if ( policies == NULL ) {
michael@0 170 goto loser;
michael@0 171 }
michael@0 172
michael@0 173 policies->arena = arena;
michael@0 174
michael@0 175 /* copy the DER into the arena, since Quick DER returns data that points
michael@0 176 into the DER input, which may get freed by the caller */
michael@0 177 rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue);
michael@0 178 if ( rv != SECSuccess ) {
michael@0 179 goto loser;
michael@0 180 }
michael@0 181
michael@0 182 /* decode the policy info */
michael@0 183 rv = SEC_QuickDERDecodeItem(arena, policies, CERT_CertificatePoliciesTemplate,
michael@0 184 &newExtnValue);
michael@0 185
michael@0 186 if ( rv != SECSuccess ) {
michael@0 187 goto loser;
michael@0 188 }
michael@0 189
michael@0 190 /* initialize the oid tags */
michael@0 191 policyInfos = policies->policyInfos;
michael@0 192 while (*policyInfos != NULL ) {
michael@0 193 policyInfo = *policyInfos;
michael@0 194 policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID);
michael@0 195 policyQualifiers = policyInfo->policyQualifiers;
michael@0 196 while ( policyQualifiers != NULL && *policyQualifiers != NULL ) {
michael@0 197 policyQualifier = *policyQualifiers;
michael@0 198 policyQualifier->oid =
michael@0 199 SECOID_FindOIDTag(&policyQualifier->qualifierID);
michael@0 200 policyQualifiers++;
michael@0 201 }
michael@0 202 policyInfos++;
michael@0 203 }
michael@0 204
michael@0 205 return(policies);
michael@0 206
michael@0 207 loser:
michael@0 208 if ( arena != NULL ) {
michael@0 209 PORT_FreeArena(arena, PR_FALSE);
michael@0 210 }
michael@0 211
michael@0 212 return(NULL);
michael@0 213 }
michael@0 214
michael@0 215 void
michael@0 216 CERT_DestroyCertificatePoliciesExtension(CERTCertificatePolicies *policies)
michael@0 217 {
michael@0 218 if ( policies != NULL ) {
michael@0 219 PORT_FreeArena(policies->arena, PR_FALSE);
michael@0 220 }
michael@0 221 return;
michael@0 222 }
michael@0 223
michael@0 224 CERTCertificatePolicyMappings *
michael@0 225 CERT_DecodePolicyMappingsExtension(SECItem *extnValue)
michael@0 226 {
michael@0 227 PLArenaPool *arena = NULL;
michael@0 228 SECStatus rv;
michael@0 229 CERTCertificatePolicyMappings *mappings;
michael@0 230 SECItem newExtnValue;
michael@0 231
michael@0 232 /* make a new arena */
michael@0 233 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 234 if ( !arena ) {
michael@0 235 goto loser;
michael@0 236 }
michael@0 237
michael@0 238 /* allocate the policy mappings structure */
michael@0 239 mappings = (CERTCertificatePolicyMappings *)
michael@0 240 PORT_ArenaZAlloc(arena, sizeof(CERTCertificatePolicyMappings));
michael@0 241 if ( mappings == NULL ) {
michael@0 242 goto loser;
michael@0 243 }
michael@0 244 mappings->arena = arena;
michael@0 245
michael@0 246 /* copy the DER into the arena, since Quick DER returns data that points
michael@0 247 into the DER input, which may get freed by the caller */
michael@0 248 rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue);
michael@0 249 if ( rv != SECSuccess ) {
michael@0 250 goto loser;
michael@0 251 }
michael@0 252
michael@0 253 /* decode the policy mappings */
michael@0 254 rv = SEC_QuickDERDecodeItem
michael@0 255 (arena, mappings, CERT_PolicyMappingsTemplate, &newExtnValue);
michael@0 256 if ( rv != SECSuccess ) {
michael@0 257 goto loser;
michael@0 258 }
michael@0 259
michael@0 260 return(mappings);
michael@0 261
michael@0 262 loser:
michael@0 263 if ( arena != NULL ) {
michael@0 264 PORT_FreeArena(arena, PR_FALSE);
michael@0 265 }
michael@0 266
michael@0 267 return(NULL);
michael@0 268 }
michael@0 269
michael@0 270 SECStatus
michael@0 271 CERT_DestroyPolicyMappingsExtension(CERTCertificatePolicyMappings *mappings)
michael@0 272 {
michael@0 273 if ( mappings != NULL ) {
michael@0 274 PORT_FreeArena(mappings->arena, PR_FALSE);
michael@0 275 }
michael@0 276 return SECSuccess;
michael@0 277 }
michael@0 278
michael@0 279 SECStatus
michael@0 280 CERT_DecodePolicyConstraintsExtension
michael@0 281 (CERTCertificatePolicyConstraints *decodedValue,
michael@0 282 const SECItem *encodedValue)
michael@0 283 {
michael@0 284 CERTCertificatePolicyConstraints decodeContext;
michael@0 285 PLArenaPool *arena = NULL;
michael@0 286 SECStatus rv = SECSuccess;
michael@0 287
michael@0 288 /* initialize so we can tell when an optional component is omitted */
michael@0 289 PORT_Memset(&decodeContext, 0, sizeof(decodeContext));
michael@0 290
michael@0 291 /* make a new arena */
michael@0 292 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
michael@0 293 if (!arena) {
michael@0 294 return SECFailure;
michael@0 295 }
michael@0 296
michael@0 297 do {
michael@0 298 /* decode the policy constraints */
michael@0 299 rv = SEC_QuickDERDecodeItem(arena,
michael@0 300 &decodeContext, CERT_PolicyConstraintsTemplate, encodedValue);
michael@0 301
michael@0 302 if ( rv != SECSuccess ) {
michael@0 303 break;
michael@0 304 }
michael@0 305
michael@0 306 if (decodeContext.explicitPolicySkipCerts.len == 0) {
michael@0 307 *(PRInt32 *)decodedValue->explicitPolicySkipCerts.data = -1;
michael@0 308 } else {
michael@0 309 *(PRInt32 *)decodedValue->explicitPolicySkipCerts.data =
michael@0 310 DER_GetInteger(&decodeContext.explicitPolicySkipCerts);
michael@0 311 }
michael@0 312
michael@0 313 if (decodeContext.inhibitMappingSkipCerts.len == 0) {
michael@0 314 *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data = -1;
michael@0 315 } else {
michael@0 316 *(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data =
michael@0 317 DER_GetInteger(&decodeContext.inhibitMappingSkipCerts);
michael@0 318 }
michael@0 319
michael@0 320 if ((*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data ==
michael@0 321 PR_INT32_MIN) ||
michael@0 322 (*(PRInt32 *)decodedValue->explicitPolicySkipCerts.data ==
michael@0 323 PR_INT32_MAX) ||
michael@0 324 (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data ==
michael@0 325 PR_INT32_MIN) ||
michael@0 326 (*(PRInt32 *)decodedValue->inhibitMappingSkipCerts.data ==
michael@0 327 PR_INT32_MAX)) {
michael@0 328 rv = SECFailure;
michael@0 329 }
michael@0 330
michael@0 331 } while (0);
michael@0 332
michael@0 333 PORT_FreeArena(arena, PR_FALSE);
michael@0 334 return(rv);
michael@0 335 }
michael@0 336
michael@0 337 SECStatus CERT_DecodeInhibitAnyExtension
michael@0 338 (CERTCertificateInhibitAny *decodedValue, SECItem *encodedValue)
michael@0 339 {
michael@0 340 CERTCertificateInhibitAny decodeContext;
michael@0 341 PLArenaPool *arena = NULL;
michael@0 342 SECStatus rv = SECSuccess;
michael@0 343
michael@0 344 /* make a new arena */
michael@0 345 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
michael@0 346 if ( !arena ) {
michael@0 347 return SECFailure;
michael@0 348 }
michael@0 349
michael@0 350 do {
michael@0 351
michael@0 352 /* decode the policy mappings */
michael@0 353 decodeContext.inhibitAnySkipCerts.type = siUnsignedInteger;
michael@0 354 rv = SEC_QuickDERDecodeItem(arena,
michael@0 355 &decodeContext, CERT_InhibitAnyTemplate, encodedValue);
michael@0 356
michael@0 357 if ( rv != SECSuccess ) {
michael@0 358 break;
michael@0 359 }
michael@0 360
michael@0 361 *(PRInt32 *)decodedValue->inhibitAnySkipCerts.data =
michael@0 362 DER_GetInteger(&decodeContext.inhibitAnySkipCerts);
michael@0 363
michael@0 364 } while (0);
michael@0 365
michael@0 366 PORT_FreeArena(arena, PR_FALSE);
michael@0 367 return(rv);
michael@0 368 }
michael@0 369
michael@0 370 CERTUserNotice *
michael@0 371 CERT_DecodeUserNotice(SECItem *noticeItem)
michael@0 372 {
michael@0 373 PLArenaPool *arena = NULL;
michael@0 374 SECStatus rv;
michael@0 375 CERTUserNotice *userNotice;
michael@0 376 SECItem newNoticeItem;
michael@0 377
michael@0 378 /* make a new arena */
michael@0 379 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 380
michael@0 381 if ( !arena ) {
michael@0 382 goto loser;
michael@0 383 }
michael@0 384
michael@0 385 /* allocate the userNotice structure */
michael@0 386 userNotice = (CERTUserNotice *)PORT_ArenaZAlloc(arena,
michael@0 387 sizeof(CERTUserNotice));
michael@0 388
michael@0 389 if ( userNotice == NULL ) {
michael@0 390 goto loser;
michael@0 391 }
michael@0 392
michael@0 393 userNotice->arena = arena;
michael@0 394
michael@0 395 /* copy the DER into the arena, since Quick DER returns data that points
michael@0 396 into the DER input, which may get freed by the caller */
michael@0 397 rv = SECITEM_CopyItem(arena, &newNoticeItem, noticeItem);
michael@0 398 if ( rv != SECSuccess ) {
michael@0 399 goto loser;
michael@0 400 }
michael@0 401
michael@0 402 /* decode the user notice */
michael@0 403 rv = SEC_QuickDERDecodeItem(arena, userNotice, CERT_UserNoticeTemplate,
michael@0 404 &newNoticeItem);
michael@0 405
michael@0 406 if ( rv != SECSuccess ) {
michael@0 407 goto loser;
michael@0 408 }
michael@0 409
michael@0 410 if (userNotice->derNoticeReference.data != NULL) {
michael@0 411
michael@0 412 rv = SEC_QuickDERDecodeItem(arena, &userNotice->noticeReference,
michael@0 413 CERT_NoticeReferenceTemplate,
michael@0 414 &userNotice->derNoticeReference);
michael@0 415 if (rv == SECFailure) {
michael@0 416 goto loser;
michael@0 417 }
michael@0 418 }
michael@0 419
michael@0 420 return(userNotice);
michael@0 421
michael@0 422 loser:
michael@0 423 if ( arena != NULL ) {
michael@0 424 PORT_FreeArena(arena, PR_FALSE);
michael@0 425 }
michael@0 426
michael@0 427 return(NULL);
michael@0 428 }
michael@0 429
michael@0 430 void
michael@0 431 CERT_DestroyUserNotice(CERTUserNotice *userNotice)
michael@0 432 {
michael@0 433 if ( userNotice != NULL ) {
michael@0 434 PORT_FreeArena(userNotice->arena, PR_FALSE);
michael@0 435 }
michael@0 436 return;
michael@0 437 }
michael@0 438
michael@0 439 static CERTPolicyStringCallback policyStringCB = NULL;
michael@0 440 static void *policyStringCBArg = NULL;
michael@0 441
michael@0 442 void
michael@0 443 CERT_SetCAPolicyStringCallback(CERTPolicyStringCallback cb, void *cbarg)
michael@0 444 {
michael@0 445 policyStringCB = cb;
michael@0 446 policyStringCBArg = cbarg;
michael@0 447 return;
michael@0 448 }
michael@0 449
michael@0 450 char *
michael@0 451 stringFromUserNotice(SECItem *noticeItem)
michael@0 452 {
michael@0 453 SECItem *org;
michael@0 454 unsigned int len, headerlen;
michael@0 455 char *stringbuf;
michael@0 456 CERTUserNotice *userNotice;
michael@0 457 char *policystr;
michael@0 458 char *retstr = NULL;
michael@0 459 SECItem *displayText;
michael@0 460 SECItem **noticeNumbers;
michael@0 461 unsigned int strnum;
michael@0 462
michael@0 463 /* decode the user notice */
michael@0 464 userNotice = CERT_DecodeUserNotice(noticeItem);
michael@0 465 if ( userNotice == NULL ) {
michael@0 466 return(NULL);
michael@0 467 }
michael@0 468
michael@0 469 org = &userNotice->noticeReference.organization;
michael@0 470 if ( (org->len != 0 ) && ( policyStringCB != NULL ) ) {
michael@0 471 /* has a noticeReference */
michael@0 472
michael@0 473 /* extract the org string */
michael@0 474 len = org->len;
michael@0 475 stringbuf = (char*)PORT_Alloc(len + 1);
michael@0 476 if ( stringbuf != NULL ) {
michael@0 477 PORT_Memcpy(stringbuf, org->data, len);
michael@0 478 stringbuf[len] = '\0';
michael@0 479
michael@0 480 noticeNumbers = userNotice->noticeReference.noticeNumbers;
michael@0 481 while ( *noticeNumbers != NULL ) {
michael@0 482 /* XXX - only one byte integers right now*/
michael@0 483 strnum = (*noticeNumbers)->data[0];
michael@0 484 policystr = (* policyStringCB)(stringbuf,
michael@0 485 strnum,
michael@0 486 policyStringCBArg);
michael@0 487 if ( policystr != NULL ) {
michael@0 488 if ( retstr != NULL ) {
michael@0 489 retstr = PR_sprintf_append(retstr, "\n%s", policystr);
michael@0 490 } else {
michael@0 491 retstr = PR_sprintf_append(retstr, "%s", policystr);
michael@0 492 }
michael@0 493
michael@0 494 PORT_Free(policystr);
michael@0 495 }
michael@0 496
michael@0 497 noticeNumbers++;
michael@0 498 }
michael@0 499
michael@0 500 PORT_Free(stringbuf);
michael@0 501 }
michael@0 502 }
michael@0 503
michael@0 504 if ( retstr == NULL ) {
michael@0 505 if ( userNotice->displayText.len != 0 ) {
michael@0 506 displayText = &userNotice->displayText;
michael@0 507
michael@0 508 if ( displayText->len > 2 ) {
michael@0 509 if ( displayText->data[0] == SEC_ASN1_VISIBLE_STRING ) {
michael@0 510 headerlen = 2;
michael@0 511 if ( displayText->data[1] & 0x80 ) {
michael@0 512 /* multibyte length */
michael@0 513 headerlen += ( displayText->data[1] & 0x7f );
michael@0 514 }
michael@0 515
michael@0 516 len = displayText->len - headerlen;
michael@0 517 retstr = (char*)PORT_Alloc(len + 1);
michael@0 518 if ( retstr != NULL ) {
michael@0 519 PORT_Memcpy(retstr, &displayText->data[headerlen],len);
michael@0 520 retstr[len] = '\0';
michael@0 521 }
michael@0 522 }
michael@0 523 }
michael@0 524 }
michael@0 525 }
michael@0 526
michael@0 527 CERT_DestroyUserNotice(userNotice);
michael@0 528
michael@0 529 return(retstr);
michael@0 530 }
michael@0 531
michael@0 532 char *
michael@0 533 CERT_GetCertCommentString(CERTCertificate *cert)
michael@0 534 {
michael@0 535 char *retstring = NULL;
michael@0 536 SECStatus rv;
michael@0 537 SECItem policyItem;
michael@0 538 CERTCertificatePolicies *policies = NULL;
michael@0 539 CERTPolicyInfo **policyInfos;
michael@0 540 CERTPolicyQualifier **policyQualifiers, *qualifier;
michael@0 541
michael@0 542 policyItem.data = NULL;
michael@0 543
michael@0 544 rv = CERT_FindCertExtension(cert, SEC_OID_X509_CERTIFICATE_POLICIES,
michael@0 545 &policyItem);
michael@0 546 if ( rv != SECSuccess ) {
michael@0 547 goto nopolicy;
michael@0 548 }
michael@0 549
michael@0 550 policies = CERT_DecodeCertificatePoliciesExtension(&policyItem);
michael@0 551 if ( policies == NULL ) {
michael@0 552 goto nopolicy;
michael@0 553 }
michael@0 554
michael@0 555 policyInfos = policies->policyInfos;
michael@0 556 /* search through policyInfos looking for the verisign policy */
michael@0 557 while (*policyInfos != NULL ) {
michael@0 558 if ( (*policyInfos)->oid == SEC_OID_VERISIGN_USER_NOTICES ) {
michael@0 559 policyQualifiers = (*policyInfos)->policyQualifiers;
michael@0 560 /* search through the policy qualifiers looking for user notice */
michael@0 561 while ( policyQualifiers != NULL && *policyQualifiers != NULL ) {
michael@0 562 qualifier = *policyQualifiers;
michael@0 563 if ( qualifier->oid == SEC_OID_PKIX_USER_NOTICE_QUALIFIER ) {
michael@0 564 retstring =
michael@0 565 stringFromUserNotice(&qualifier->qualifierValue);
michael@0 566 break;
michael@0 567 }
michael@0 568
michael@0 569 policyQualifiers++;
michael@0 570 }
michael@0 571 break;
michael@0 572 }
michael@0 573 policyInfos++;
michael@0 574 }
michael@0 575
michael@0 576 nopolicy:
michael@0 577 if ( policyItem.data != NULL ) {
michael@0 578 PORT_Free(policyItem.data);
michael@0 579 }
michael@0 580
michael@0 581 if ( policies != NULL ) {
michael@0 582 CERT_DestroyCertificatePoliciesExtension(policies);
michael@0 583 }
michael@0 584
michael@0 585 if ( retstring == NULL ) {
michael@0 586 retstring = CERT_FindNSStringExtension(cert,
michael@0 587 SEC_OID_NS_CERT_EXT_COMMENT);
michael@0 588 }
michael@0 589
michael@0 590 if ( retstring != NULL ) {
michael@0 591 breakLines(retstring);
michael@0 592 }
michael@0 593
michael@0 594 return(retstring);
michael@0 595 }
michael@0 596
michael@0 597
michael@0 598 const SEC_ASN1Template CERT_OidSeqTemplate[] = {
michael@0 599 { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN,
michael@0 600 offsetof(CERTOidSequence, oids),
michael@0 601 SEC_ASN1_SUB(SEC_ObjectIDTemplate) }
michael@0 602 };
michael@0 603
michael@0 604 CERTOidSequence *
michael@0 605 CERT_DecodeOidSequence(const SECItem *seqItem)
michael@0 606 {
michael@0 607 PLArenaPool *arena = NULL;
michael@0 608 SECStatus rv;
michael@0 609 CERTOidSequence *oidSeq;
michael@0 610 SECItem newSeqItem;
michael@0 611
michael@0 612 /* make a new arena */
michael@0 613 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 614
michael@0 615 if ( !arena ) {
michael@0 616 goto loser;
michael@0 617 }
michael@0 618
michael@0 619 /* allocate the userNotice structure */
michael@0 620 oidSeq = (CERTOidSequence *)PORT_ArenaZAlloc(arena,
michael@0 621 sizeof(CERTOidSequence));
michael@0 622
michael@0 623 if ( oidSeq == NULL ) {
michael@0 624 goto loser;
michael@0 625 }
michael@0 626
michael@0 627 oidSeq->arena = arena;
michael@0 628
michael@0 629 /* copy the DER into the arena, since Quick DER returns data that points
michael@0 630 into the DER input, which may get freed by the caller */
michael@0 631 rv = SECITEM_CopyItem(arena, &newSeqItem, seqItem);
michael@0 632 if ( rv != SECSuccess ) {
michael@0 633 goto loser;
michael@0 634 }
michael@0 635
michael@0 636 /* decode the user notice */
michael@0 637 rv = SEC_QuickDERDecodeItem(arena, oidSeq, CERT_OidSeqTemplate, &newSeqItem);
michael@0 638
michael@0 639 if ( rv != SECSuccess ) {
michael@0 640 goto loser;
michael@0 641 }
michael@0 642
michael@0 643 return(oidSeq);
michael@0 644
michael@0 645 loser:
michael@0 646 if (arena) {
michael@0 647 PORT_FreeArena(arena, PR_FALSE);
michael@0 648 }
michael@0 649 return(NULL);
michael@0 650 }
michael@0 651
michael@0 652
michael@0 653 void
michael@0 654 CERT_DestroyOidSequence(CERTOidSequence *oidSeq)
michael@0 655 {
michael@0 656 if ( oidSeq != NULL ) {
michael@0 657 PORT_FreeArena(oidSeq->arena, PR_FALSE);
michael@0 658 }
michael@0 659 return;
michael@0 660 }
michael@0 661
michael@0 662 PRBool
michael@0 663 CERT_GovtApprovedBitSet(CERTCertificate *cert)
michael@0 664 {
michael@0 665 SECStatus rv;
michael@0 666 SECItem extItem;
michael@0 667 CERTOidSequence *oidSeq = NULL;
michael@0 668 PRBool ret;
michael@0 669 SECItem **oids;
michael@0 670 SECItem *oid;
michael@0 671 SECOidTag oidTag;
michael@0 672
michael@0 673 extItem.data = NULL;
michael@0 674 rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem);
michael@0 675 if ( rv != SECSuccess ) {
michael@0 676 goto loser;
michael@0 677 }
michael@0 678
michael@0 679 oidSeq = CERT_DecodeOidSequence(&extItem);
michael@0 680 if ( oidSeq == NULL ) {
michael@0 681 goto loser;
michael@0 682 }
michael@0 683
michael@0 684 oids = oidSeq->oids;
michael@0 685 while ( oids != NULL && *oids != NULL ) {
michael@0 686 oid = *oids;
michael@0 687
michael@0 688 oidTag = SECOID_FindOIDTag(oid);
michael@0 689
michael@0 690 if ( oidTag == SEC_OID_NS_KEY_USAGE_GOVT_APPROVED ) {
michael@0 691 goto success;
michael@0 692 }
michael@0 693
michael@0 694 oids++;
michael@0 695 }
michael@0 696
michael@0 697 loser:
michael@0 698 ret = PR_FALSE;
michael@0 699 goto done;
michael@0 700 success:
michael@0 701 ret = PR_TRUE;
michael@0 702 done:
michael@0 703 if ( oidSeq != NULL ) {
michael@0 704 CERT_DestroyOidSequence(oidSeq);
michael@0 705 }
michael@0 706 if (extItem.data != NULL) {
michael@0 707 PORT_Free(extItem.data);
michael@0 708 }
michael@0 709 return(ret);
michael@0 710 }
michael@0 711
michael@0 712
michael@0 713 SECStatus
michael@0 714 CERT_EncodePolicyConstraintsExtension(PLArenaPool *arena,
michael@0 715 CERTCertificatePolicyConstraints *constr,
michael@0 716 SECItem *dest)
michael@0 717 {
michael@0 718 SECStatus rv = SECSuccess;
michael@0 719
michael@0 720 PORT_Assert(constr != NULL && dest != NULL);
michael@0 721 if (constr == NULL || dest == NULL) {
michael@0 722 return SECFailure;
michael@0 723 }
michael@0 724
michael@0 725 if (SEC_ASN1EncodeItem (arena, dest, constr,
michael@0 726 CERT_PolicyConstraintsTemplate) == NULL) {
michael@0 727 rv = SECFailure;
michael@0 728 }
michael@0 729 return(rv);
michael@0 730 }
michael@0 731
michael@0 732 SECStatus
michael@0 733 CERT_EncodePolicyMappingExtension(PLArenaPool *arena,
michael@0 734 CERTCertificatePolicyMappings *mapping,
michael@0 735 SECItem *dest)
michael@0 736 {
michael@0 737 SECStatus rv = SECSuccess;
michael@0 738
michael@0 739 PORT_Assert(mapping != NULL && dest != NULL);
michael@0 740 if (mapping == NULL || dest == NULL) {
michael@0 741 return SECFailure;
michael@0 742 }
michael@0 743
michael@0 744 if (SEC_ASN1EncodeItem (arena, dest, mapping,
michael@0 745 CERT_PolicyMappingsTemplate) == NULL) {
michael@0 746 rv = SECFailure;
michael@0 747 }
michael@0 748 return(rv);
michael@0 749 }
michael@0 750
michael@0 751
michael@0 752
michael@0 753 SECStatus
michael@0 754 CERT_EncodeCertPoliciesExtension(PLArenaPool *arena,
michael@0 755 CERTPolicyInfo **info,
michael@0 756 SECItem *dest)
michael@0 757 {
michael@0 758 SECStatus rv = SECSuccess;
michael@0 759
michael@0 760 PORT_Assert(info != NULL && dest != NULL);
michael@0 761 if (info == NULL || dest == NULL) {
michael@0 762 return SECFailure;
michael@0 763 }
michael@0 764
michael@0 765 if (SEC_ASN1EncodeItem (arena, dest, info,
michael@0 766 CERT_CertificatePoliciesTemplate) == NULL) {
michael@0 767 rv = SECFailure;
michael@0 768 }
michael@0 769 return(rv);
michael@0 770 }
michael@0 771
michael@0 772 SECStatus
michael@0 773 CERT_EncodeUserNotice(PLArenaPool *arena,
michael@0 774 CERTUserNotice *notice,
michael@0 775 SECItem *dest)
michael@0 776 {
michael@0 777 SECStatus rv = SECSuccess;
michael@0 778
michael@0 779 PORT_Assert(notice != NULL && dest != NULL);
michael@0 780 if (notice == NULL || dest == NULL) {
michael@0 781 return SECFailure;
michael@0 782 }
michael@0 783
michael@0 784 if (SEC_ASN1EncodeItem(arena, dest,
michael@0 785 notice, CERT_UserNoticeTemplate) == NULL) {
michael@0 786 rv = SECFailure;
michael@0 787 }
michael@0 788
michael@0 789 return(rv);
michael@0 790 }
michael@0 791
michael@0 792 SECStatus
michael@0 793 CERT_EncodeNoticeReference(PLArenaPool *arena,
michael@0 794 CERTNoticeReference *reference,
michael@0 795 SECItem *dest)
michael@0 796 {
michael@0 797 SECStatus rv = SECSuccess;
michael@0 798
michael@0 799 PORT_Assert(reference != NULL && dest != NULL);
michael@0 800 if (reference == NULL || dest == NULL) {
michael@0 801 return SECFailure;
michael@0 802 }
michael@0 803
michael@0 804 if (SEC_ASN1EncodeItem (arena, dest, reference,
michael@0 805 CERT_NoticeReferenceTemplate) == NULL) {
michael@0 806 rv = SECFailure;
michael@0 807 }
michael@0 808
michael@0 809 return(rv);
michael@0 810 }
michael@0 811
michael@0 812 SECStatus
michael@0 813 CERT_EncodeInhibitAnyExtension(PLArenaPool *arena,
michael@0 814 CERTCertificateInhibitAny *certInhibitAny,
michael@0 815 SECItem *dest)
michael@0 816 {
michael@0 817 SECStatus rv = SECSuccess;
michael@0 818
michael@0 819 PORT_Assert(certInhibitAny != NULL && dest != NULL);
michael@0 820 if (certInhibitAny == NULL || dest == NULL) {
michael@0 821 return SECFailure;
michael@0 822 }
michael@0 823
michael@0 824 if (SEC_ASN1EncodeItem (arena, dest, certInhibitAny,
michael@0 825 CERT_InhibitAnyTemplate) == NULL) {
michael@0 826 rv = SECFailure;
michael@0 827 }
michael@0 828 return(rv);
michael@0 829 }

mercurial