1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Mozilla Public License Version
5
* 1.1 (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
7
* http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* The Original Code is the Netscape security libraries.
16
* The Initial Developer of the Original Code is
17
* Netscape Communications Corporation.
18
* Portions created by the Initial Developer are Copyright (C) 1994-2000
19
* the Initial Developer. All Rights Reserved.
23
* Alternatively, the contents of this file may be used under the terms of
24
* either the GNU General Public License Version 2 or later (the "GPL"), or
25
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26
* in which case the provisions of the GPL or the LGPL are applicable instead
27
* of those above. If you wish to allow use of your version of this file only
28
* under the terms of either the GPL or the LGPL, and not to allow others to
29
* use your version of this file under the terms of the MPL, indicate your
30
* decision by deleting the provisions above and replace them with the notice
31
* and other provisions required by the GPL or the LGPL. If you do not delete
32
* the provisions above, a recipient may use your version of this file under
33
* the terms of any one of the MPL, the GPL or the LGPL.
35
* ***** END LICENSE BLOCK ***** */
38
* Support for various policy related extensions
40
* $Id: polcyxtn.c,v 1.6 2004/04/25 15:03:03 gerv%gerv.net Exp $
52
const SEC_ASN1Template CERT_NoticeReferenceTemplate[] = {
54
0, NULL, sizeof(CERTNoticeReference) },
55
/* NOTE: this should be a choice */
56
{ SEC_ASN1_IA5_STRING,
57
offsetof(CERTNoticeReference, organization) },
58
{ SEC_ASN1_SEQUENCE_OF,
59
offsetof(CERTNoticeReference, noticeNumbers),
60
SEC_IntegerTemplate },
64
/* this template can not be encoded because of the option inline */
65
const SEC_ASN1Template CERT_UserNoticeTemplate[] = {
67
0, NULL, sizeof(CERTUserNotice) },
68
{ SEC_ASN1_OPTIONAL | SEC_ASN1_SEQUENCE | SEC_ASN1_CONSTRUCTED,
69
offsetof(CERTUserNotice, derNoticeReference) },
70
{ SEC_ASN1_OPTIONAL | SEC_ASN1_ANY,
71
offsetof(CERTUserNotice, displayText) },
75
const SEC_ASN1Template CERT_PolicyQualifierTemplate[] = {
77
0, NULL, sizeof(CERTPolicyQualifier) },
79
offsetof(CERTPolicyQualifier, qualifierID) },
81
offsetof(CERTPolicyQualifier, qualifierValue) },
85
const SEC_ASN1Template CERT_PolicyInfoTemplate[] = {
87
0, NULL, sizeof(CERTPolicyInfo) },
89
offsetof(CERTPolicyInfo, policyID) },
90
{ SEC_ASN1_SEQUENCE_OF | SEC_ASN1_OPTIONAL,
91
offsetof(CERTPolicyInfo, policyQualifiers),
92
CERT_PolicyQualifierTemplate },
96
const SEC_ASN1Template CERT_CertificatePoliciesTemplate[] = {
97
{ SEC_ASN1_SEQUENCE_OF,
98
offsetof(CERTCertificatePolicies, policyInfos),
99
CERT_PolicyInfoTemplate, sizeof(CERTCertificatePolicies) }
103
breakLines(char *string)
106
char *lastspace = NULL;
112
while ( ( c = *tmpstr ) != '\0' ) {
123
if ( ( curlen >= 55 ) && ( lastspace != NULL ) ) {
125
curlen = ( tmpstr - lastspace );
136
CERTCertificatePolicies *
137
CERT_DecodeCertificatePoliciesExtension(SECItem *extnValue)
139
PRArenaPool *arena = NULL;
141
CERTCertificatePolicies *policies;
142
CERTPolicyInfo **policyInfos, *policyInfo;
143
CERTPolicyQualifier **policyQualifiers, *policyQualifier;
144
SECItem newExtnValue;
146
/* make a new arena */
147
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
153
/* allocate the certifiate policies structure */
154
policies = (CERTCertificatePolicies *)
155
PORT_ArenaZAlloc(arena, sizeof(CERTCertificatePolicies));
157
if ( policies == NULL ) {
161
policies->arena = arena;
163
/* copy the DER into the arena, since Quick DER returns data that points
164
into the DER input, which may get freed by the caller */
165
rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue);
166
if ( rv != SECSuccess ) {
170
/* decode the policy info */
171
rv = SEC_QuickDERDecodeItem(arena, policies, CERT_CertificatePoliciesTemplate,
174
if ( rv != SECSuccess ) {
178
/* initialize the oid tags */
179
policyInfos = policies->policyInfos;
180
while (*policyInfos != NULL ) {
181
policyInfo = *policyInfos;
182
policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID);
183
policyQualifiers = policyInfo->policyQualifiers;
184
while ( policyQualifiers != NULL && *policyQualifiers != NULL ) {
185
policyQualifier = *policyQualifiers;
186
policyQualifier->oid =
187
SECOID_FindOIDTag(&policyQualifier->qualifierID);
196
if ( arena != NULL ) {
197
PORT_FreeArena(arena, PR_FALSE);
204
CERT_DestroyCertificatePoliciesExtension(CERTCertificatePolicies *policies)
206
if ( policies != NULL ) {
207
PORT_FreeArena(policies->arena, PR_FALSE);
214
CERT_DecodeUserNotice(SECItem *noticeItem)
216
PRArenaPool *arena = NULL;
218
CERTUserNotice *userNotice;
219
SECItem newNoticeItem;
221
/* make a new arena */
222
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
228
/* allocate the userNotice structure */
229
userNotice = (CERTUserNotice *)PORT_ArenaZAlloc(arena,
230
sizeof(CERTUserNotice));
232
if ( userNotice == NULL ) {
236
userNotice->arena = arena;
238
/* copy the DER into the arena, since Quick DER returns data that points
239
into the DER input, which may get freed by the caller */
240
rv = SECITEM_CopyItem(arena, &newNoticeItem, noticeItem);
241
if ( rv != SECSuccess ) {
245
/* decode the user notice */
246
rv = SEC_QuickDERDecodeItem(arena, userNotice, CERT_UserNoticeTemplate,
249
if ( rv != SECSuccess ) {
253
if (userNotice->derNoticeReference.data != NULL) {
254
/* sigh, the asn1 parser stripped the sequence encoding, re add it
260
newBytes = SEC_ASN1LengthLength(userNotice->derNoticeReference.len)+1;
261
tmpbuf.len = newBytes + userNotice->derNoticeReference.len;
262
tmpbuf.data = PORT_ArenaZAlloc(arena, tmpbuf.len);
263
if (tmpbuf.data == NULL) {
266
tmpbuf.data[0] = SEC_ASN1_SEQUENCE | SEC_ASN1_CONSTRUCTED;
267
SEC_ASN1EncodeLength(&tmpbuf.data[1],userNotice->derNoticeReference.len);
268
PORT_Memcpy(&tmpbuf.data[newBytes],userNotice->derNoticeReference.data,
269
userNotice->derNoticeReference.len);
271
/* OK, no decode it */
272
rv = SEC_QuickDERDecodeItem(arena, &userNotice->noticeReference,
273
CERT_NoticeReferenceTemplate, &tmpbuf);
275
PORT_Free(tmpbuf.data); tmpbuf.data = NULL;
276
if ( rv != SECSuccess ) {
284
if ( arena != NULL ) {
285
PORT_FreeArena(arena, PR_FALSE);
292
CERT_DestroyUserNotice(CERTUserNotice *userNotice)
294
if ( userNotice != NULL ) {
295
PORT_FreeArena(userNotice->arena, PR_FALSE);
300
static CERTPolicyStringCallback policyStringCB = NULL;
301
static void *policyStringCBArg = NULL;
304
CERT_SetCAPolicyStringCallback(CERTPolicyStringCallback cb, void *cbarg)
307
policyStringCBArg = cbarg;
312
stringFromUserNotice(SECItem *noticeItem)
315
unsigned int len, headerlen;
317
CERTUserNotice *userNotice;
320
SECItem *displayText;
321
SECItem **noticeNumbers;
324
/* decode the user notice */
325
userNotice = CERT_DecodeUserNotice(noticeItem);
326
if ( userNotice == NULL ) {
330
org = &userNotice->noticeReference.organization;
331
if ( (org->len != 0 ) && ( policyStringCB != NULL ) ) {
332
/* has a noticeReference */
334
/* extract the org string */
336
stringbuf = (char*)PORT_Alloc(len + 1);
337
if ( stringbuf != NULL ) {
338
PORT_Memcpy(stringbuf, org->data, len);
339
stringbuf[len] = '\0';
341
noticeNumbers = userNotice->noticeReference.noticeNumbers;
342
while ( *noticeNumbers != NULL ) {
343
/* XXX - only one byte integers right now*/
344
strnum = (*noticeNumbers)->data[0];
345
policystr = (* policyStringCB)(stringbuf,
348
if ( policystr != NULL ) {
349
if ( retstr != NULL ) {
350
retstr = PR_sprintf_append(retstr, "\n%s", policystr);
352
retstr = PR_sprintf_append(retstr, "%s", policystr);
355
PORT_Free(policystr);
361
PORT_Free(stringbuf);
365
if ( retstr == NULL ) {
366
if ( userNotice->displayText.len != 0 ) {
367
displayText = &userNotice->displayText;
369
if ( displayText->len > 2 ) {
370
if ( displayText->data[0] == SEC_ASN1_VISIBLE_STRING ) {
372
if ( displayText->data[1] & 0x80 ) {
373
/* multibyte length */
374
headerlen += ( displayText->data[1] & 0x7f );
377
len = displayText->len - headerlen;
378
retstr = (char*)PORT_Alloc(len + 1);
379
if ( retstr != NULL ) {
380
PORT_Memcpy(retstr, &displayText->data[headerlen],len);
388
CERT_DestroyUserNotice(userNotice);
394
CERT_GetCertCommentString(CERTCertificate *cert)
396
char *retstring = NULL;
399
CERTCertificatePolicies *policies = NULL;
400
CERTPolicyInfo **policyInfos;
401
CERTPolicyQualifier **policyQualifiers, *qualifier;
403
policyItem.data = NULL;
405
rv = CERT_FindCertExtension(cert, SEC_OID_X509_CERTIFICATE_POLICIES,
407
if ( rv != SECSuccess ) {
411
policies = CERT_DecodeCertificatePoliciesExtension(&policyItem);
412
if ( policies == NULL ) {
416
policyInfos = policies->policyInfos;
417
/* search through policyInfos looking for the verisign policy */
418
while (*policyInfos != NULL ) {
419
if ( (*policyInfos)->oid == SEC_OID_VERISIGN_USER_NOTICES ) {
420
policyQualifiers = (*policyInfos)->policyQualifiers;
421
/* search through the policy qualifiers looking for user notice */
422
while ( policyQualifiers != NULL && *policyQualifiers != NULL ) {
423
qualifier = *policyQualifiers;
424
if ( qualifier->oid == SEC_OID_PKIX_USER_NOTICE_QUALIFIER ) {
426
stringFromUserNotice(&qualifier->qualifierValue);
438
if ( policyItem.data != NULL ) {
439
PORT_Free(policyItem.data);
442
if ( policies != NULL ) {
443
CERT_DestroyCertificatePoliciesExtension(policies);
446
if ( retstring == NULL ) {
447
retstring = CERT_FindNSStringExtension(cert,
448
SEC_OID_NS_CERT_EXT_COMMENT);
451
if ( retstring != NULL ) {
452
breakLines(retstring);
459
const SEC_ASN1Template CERT_OidSeqTemplate[] = {
460
{ SEC_ASN1_SEQUENCE_OF,
461
offsetof(CERTOidSequence, oids),
462
SEC_ObjectIDTemplate }
466
CERT_DecodeOidSequence(SECItem *seqItem)
468
PRArenaPool *arena = NULL;
470
CERTOidSequence *oidSeq;
473
/* make a new arena */
474
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
480
/* allocate the userNotice structure */
481
oidSeq = (CERTOidSequence *)PORT_ArenaZAlloc(arena,
482
sizeof(CERTOidSequence));
484
if ( oidSeq == NULL ) {
488
oidSeq->arena = arena;
490
/* copy the DER into the arena, since Quick DER returns data that points
491
into the DER input, which may get freed by the caller */
492
rv = SECITEM_CopyItem(arena, &newSeqItem, seqItem);
493
if ( rv != SECSuccess ) {
497
/* decode the user notice */
498
rv = SEC_QuickDERDecodeItem(arena, oidSeq, CERT_OidSeqTemplate, &newSeqItem);
500
if ( rv != SECSuccess ) {
512
CERT_DestroyOidSequence(CERTOidSequence *oidSeq)
514
if ( oidSeq != NULL ) {
515
PORT_FreeArena(oidSeq->arena, PR_FALSE);
521
CERT_GovtApprovedBitSet(CERTCertificate *cert)
525
CERTOidSequence *oidSeq = NULL;
532
rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem);
533
if ( rv != SECSuccess ) {
537
oidSeq = CERT_DecodeOidSequence(&extItem);
538
if ( oidSeq == NULL ) {
543
while ( oids != NULL && *oids != NULL ) {
546
oidTag = SECOID_FindOIDTag(oid);
548
if ( oidTag == SEC_OID_NS_KEY_USAGE_GOVT_APPROVED ) {
561
if ( oidSeq != NULL ) {
562
CERT_DestroyOidSequence(oidSeq);
564
if (extItem.data != NULL) {
565
PORT_Free(extItem.data);