security/nss/cmd/lib/pppolicy.c

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

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 #include "secutil.h"
michael@0 18
michael@0 19 /* This implementation is derived from the one in nss/lib/certdb/policyxtn.c .
michael@0 20 ** The chief difference is the addition of the OPTIONAL flag to many
michael@0 21 ** parts. The idea is to be able to parse and print as much of the
michael@0 22 ** policy extension as possible, even if some parts are invalid.
michael@0 23 **
michael@0 24 ** If this approach still is unable to decode policy extensions that
michael@0 25 ** contain invalid parts, then the next approach will be to parse
michael@0 26 ** the PolicyInfos as a SEQUENCE of ANYs, and then parse each of them
michael@0 27 ** as PolicyInfos, with the PolicyQualifiers being ANYs, and finally
michael@0 28 ** parse each of the PolicyQualifiers.
michael@0 29 */
michael@0 30
michael@0 31 static const SEC_ASN1Template secu_PolicyQualifierTemplate[] = {
michael@0 32 { SEC_ASN1_SEQUENCE,
michael@0 33 0, NULL, sizeof(CERTPolicyQualifier) },
michael@0 34 { SEC_ASN1_OBJECT_ID,
michael@0 35 offsetof(CERTPolicyQualifier, qualifierID) },
michael@0 36 { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
michael@0 37 offsetof(CERTPolicyQualifier, qualifierValue) },
michael@0 38 { 0 }
michael@0 39 };
michael@0 40
michael@0 41 static const SEC_ASN1Template secu_PolicyInfoTemplate[] = {
michael@0 42 { SEC_ASN1_SEQUENCE,
michael@0 43 0, NULL, sizeof(CERTPolicyInfo) },
michael@0 44 { SEC_ASN1_OBJECT_ID,
michael@0 45 offsetof(CERTPolicyInfo, policyID) },
michael@0 46 { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_OPTIONAL,
michael@0 47 offsetof(CERTPolicyInfo, policyQualifiers),
michael@0 48 secu_PolicyQualifierTemplate },
michael@0 49 { 0 }
michael@0 50 };
michael@0 51
michael@0 52 static const SEC_ASN1Template secu_CertificatePoliciesTemplate[] = {
michael@0 53 { SEC_ASN1_SEQUENCE_OF,
michael@0 54 offsetof(CERTCertificatePolicies, policyInfos),
michael@0 55 secu_PolicyInfoTemplate, sizeof(CERTCertificatePolicies) }
michael@0 56 };
michael@0 57
michael@0 58
michael@0 59 static CERTCertificatePolicies *
michael@0 60 secu_DecodeCertificatePoliciesExtension(SECItem *extnValue)
michael@0 61 {
michael@0 62 PLArenaPool *arena = NULL;
michael@0 63 SECStatus rv;
michael@0 64 CERTCertificatePolicies *policies;
michael@0 65 CERTPolicyInfo **policyInfos, *policyInfo;
michael@0 66 CERTPolicyQualifier **policyQualifiers, *policyQualifier;
michael@0 67 SECItem newExtnValue;
michael@0 68
michael@0 69 /* make a new arena */
michael@0 70 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 71
michael@0 72 if ( !arena ) {
michael@0 73 goto loser;
michael@0 74 }
michael@0 75
michael@0 76 /* allocate the certifiate policies structure */
michael@0 77 policies = PORT_ArenaZNew(arena, CERTCertificatePolicies);
michael@0 78 if ( policies == NULL ) {
michael@0 79 goto loser;
michael@0 80 }
michael@0 81
michael@0 82 policies->arena = arena;
michael@0 83
michael@0 84 /* copy the DER into the arena, since Quick DER returns data that points
michael@0 85 into the DER input, which may get freed by the caller */
michael@0 86 rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue);
michael@0 87 if ( rv != SECSuccess ) {
michael@0 88 goto loser;
michael@0 89 }
michael@0 90
michael@0 91 /* decode the policy info */
michael@0 92 rv = SEC_QuickDERDecodeItem(arena, policies,
michael@0 93 secu_CertificatePoliciesTemplate,
michael@0 94 &newExtnValue);
michael@0 95
michael@0 96 if ( rv != SECSuccess ) {
michael@0 97 goto loser;
michael@0 98 }
michael@0 99
michael@0 100 /* initialize the oid tags */
michael@0 101 policyInfos = policies->policyInfos;
michael@0 102 while (policyInfos != NULL && *policyInfos != NULL ) {
michael@0 103 policyInfo = *policyInfos;
michael@0 104 policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID);
michael@0 105 policyQualifiers = policyInfo->policyQualifiers;
michael@0 106 while ( policyQualifiers && *policyQualifiers != NULL ) {
michael@0 107 policyQualifier = *policyQualifiers;
michael@0 108 policyQualifier->oid =
michael@0 109 SECOID_FindOIDTag(&policyQualifier->qualifierID);
michael@0 110 policyQualifiers++;
michael@0 111 }
michael@0 112 policyInfos++;
michael@0 113 }
michael@0 114
michael@0 115 return(policies);
michael@0 116
michael@0 117 loser:
michael@0 118 if ( arena != NULL ) {
michael@0 119 PORT_FreeArena(arena, PR_FALSE);
michael@0 120 }
michael@0 121
michael@0 122 return(NULL);
michael@0 123 }
michael@0 124
michael@0 125
michael@0 126 static char *
michael@0 127 itemToString(SECItem *item)
michael@0 128 {
michael@0 129 char *string;
michael@0 130
michael@0 131 string = PORT_ZAlloc(item->len+1);
michael@0 132 if (string == NULL) return NULL;
michael@0 133 PORT_Memcpy(string,item->data,item->len);
michael@0 134 string[item->len] = 0;
michael@0 135 return string;
michael@0 136 }
michael@0 137
michael@0 138 static SECStatus
michael@0 139 secu_PrintUserNoticeQualifier(FILE *out, SECItem * qualifierValue,
michael@0 140 char *msg, int level)
michael@0 141 {
michael@0 142 CERTUserNotice *userNotice = NULL;
michael@0 143 if (qualifierValue)
michael@0 144 userNotice = CERT_DecodeUserNotice(qualifierValue);
michael@0 145 if (userNotice) {
michael@0 146 if (userNotice->noticeReference.organization.len != 0) {
michael@0 147 char *string =
michael@0 148 itemToString(&userNotice->noticeReference.organization);
michael@0 149 SECItem **itemList = userNotice->noticeReference.noticeNumbers;
michael@0 150
michael@0 151 while (itemList && *itemList) {
michael@0 152 SECU_PrintInteger(out,*itemList,string,level+1);
michael@0 153 itemList++;
michael@0 154 }
michael@0 155 PORT_Free(string);
michael@0 156 }
michael@0 157 if (userNotice->displayText.len != 0) {
michael@0 158 SECU_PrintString(out,&userNotice->displayText,
michael@0 159 "Display Text", level+1);
michael@0 160 }
michael@0 161 CERT_DestroyUserNotice(userNotice);
michael@0 162 return SECSuccess;
michael@0 163 }
michael@0 164 return SECFailure; /* caller will print this value */
michael@0 165 }
michael@0 166
michael@0 167 static SECStatus
michael@0 168 secu_PrintPolicyQualifier(FILE *out,CERTPolicyQualifier *policyQualifier,
michael@0 169 char *msg,int level)
michael@0 170 {
michael@0 171 SECStatus rv;
michael@0 172 SECItem * qualifierValue = &policyQualifier->qualifierValue;
michael@0 173
michael@0 174 SECU_PrintObjectID(out, &policyQualifier->qualifierID ,
michael@0 175 "Policy Qualifier Name", level);
michael@0 176 if (!qualifierValue->data) {
michael@0 177 SECU_Indent(out, level);
michael@0 178 fprintf(out,"Error: missing qualifier\n");
michael@0 179 } else
michael@0 180 switch (policyQualifier->oid) {
michael@0 181 case SEC_OID_PKIX_USER_NOTICE_QUALIFIER:
michael@0 182 rv = secu_PrintUserNoticeQualifier(out, qualifierValue, msg, level);
michael@0 183 if (SECSuccess == rv)
michael@0 184 break;
michael@0 185 /* fall through on error */
michael@0 186 case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
michael@0 187 default:
michael@0 188 SECU_PrintAny(out, qualifierValue, "Policy Qualifier Data", level);
michael@0 189 break;
michael@0 190 }
michael@0 191 return SECSuccess;
michael@0 192 }
michael@0 193
michael@0 194 static SECStatus
michael@0 195 secu_PrintPolicyInfo(FILE *out,CERTPolicyInfo *policyInfo,char *msg,int level)
michael@0 196 {
michael@0 197 CERTPolicyQualifier **policyQualifiers;
michael@0 198
michael@0 199 policyQualifiers = policyInfo->policyQualifiers;
michael@0 200 SECU_PrintObjectID(out, &policyInfo->policyID , "Policy Name", level);
michael@0 201
michael@0 202 while (policyQualifiers && *policyQualifiers != NULL) {
michael@0 203 secu_PrintPolicyQualifier(out,*policyQualifiers,"",level+1);
michael@0 204 policyQualifiers++;
michael@0 205 }
michael@0 206 return SECSuccess;
michael@0 207 }
michael@0 208
michael@0 209 void
michael@0 210 SECU_PrintPolicy(FILE *out, SECItem *value, char *msg, int level)
michael@0 211 {
michael@0 212 CERTCertificatePolicies *policies = NULL;
michael@0 213 CERTPolicyInfo **policyInfos;
michael@0 214
michael@0 215 if (msg) {
michael@0 216 SECU_Indent(out, level);
michael@0 217 fprintf(out,"%s: \n",msg);
michael@0 218 level++;
michael@0 219 }
michael@0 220 policies = secu_DecodeCertificatePoliciesExtension(value);
michael@0 221 if (policies == NULL) {
michael@0 222 SECU_PrintAny(out, value, "Invalid Policy Data", level);
michael@0 223 return;
michael@0 224 }
michael@0 225
michael@0 226 policyInfos = policies->policyInfos;
michael@0 227 while (policyInfos && *policyInfos != NULL) {
michael@0 228 secu_PrintPolicyInfo(out,*policyInfos,"",level);
michael@0 229 policyInfos++;
michael@0 230 }
michael@0 231
michael@0 232 CERT_DestroyCertificatePoliciesExtension(policies);
michael@0 233 }
michael@0 234
michael@0 235
michael@0 236 void
michael@0 237 SECU_PrintPrivKeyUsagePeriodExtension(FILE *out, SECItem *value,
michael@0 238 char *msg, int level)
michael@0 239 {
michael@0 240 CERTPrivKeyUsagePeriod * prd;
michael@0 241 PLArenaPool * arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 242
michael@0 243 if ( !arena ) {
michael@0 244 goto loser;
michael@0 245 }
michael@0 246 prd = CERT_DecodePrivKeyUsagePeriodExtension(arena, value);
michael@0 247 if (!prd) {
michael@0 248 goto loser;
michael@0 249 }
michael@0 250 if (prd->notBefore.data) {
michael@0 251 SECU_PrintGeneralizedTime(out, &prd->notBefore, "Not Before", level);
michael@0 252 }
michael@0 253 if (prd->notAfter.data) {
michael@0 254 SECU_PrintGeneralizedTime(out, &prd->notAfter, "Not After ", level);
michael@0 255 }
michael@0 256 if (!prd->notBefore.data && !prd->notAfter.data) {
michael@0 257 SECU_Indent(out, level);
michael@0 258 fprintf(out, "Error: notBefore or notAfter MUST be present.\n");
michael@0 259 loser:
michael@0 260 SECU_PrintAny(out, value, msg, level);
michael@0 261 }
michael@0 262 if (arena) {
michael@0 263 PORT_FreeArena(arena, PR_FALSE);
michael@0 264 }
michael@0 265 }

mercurial