1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/lib/pppolicy.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,265 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 + * Support for various policy related extensions 1.10 + */ 1.11 + 1.12 +#include "seccomon.h" 1.13 +#include "secport.h" 1.14 +#include "secder.h" 1.15 +#include "cert.h" 1.16 +#include "secoid.h" 1.17 +#include "secasn1.h" 1.18 +#include "secerr.h" 1.19 +#include "nspr.h" 1.20 +#include "secutil.h" 1.21 + 1.22 +/* This implementation is derived from the one in nss/lib/certdb/policyxtn.c . 1.23 +** The chief difference is the addition of the OPTIONAL flag to many 1.24 +** parts. The idea is to be able to parse and print as much of the 1.25 +** policy extension as possible, even if some parts are invalid. 1.26 +** 1.27 +** If this approach still is unable to decode policy extensions that 1.28 +** contain invalid parts, then the next approach will be to parse 1.29 +** the PolicyInfos as a SEQUENCE of ANYs, and then parse each of them 1.30 +** as PolicyInfos, with the PolicyQualifiers being ANYs, and finally 1.31 +** parse each of the PolicyQualifiers. 1.32 +*/ 1.33 + 1.34 +static const SEC_ASN1Template secu_PolicyQualifierTemplate[] = { 1.35 + { SEC_ASN1_SEQUENCE, 1.36 + 0, NULL, sizeof(CERTPolicyQualifier) }, 1.37 + { SEC_ASN1_OBJECT_ID, 1.38 + offsetof(CERTPolicyQualifier, qualifierID) }, 1.39 + { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL, 1.40 + offsetof(CERTPolicyQualifier, qualifierValue) }, 1.41 + { 0 } 1.42 +}; 1.43 + 1.44 +static const SEC_ASN1Template secu_PolicyInfoTemplate[] = { 1.45 + { SEC_ASN1_SEQUENCE, 1.46 + 0, NULL, sizeof(CERTPolicyInfo) }, 1.47 + { SEC_ASN1_OBJECT_ID, 1.48 + offsetof(CERTPolicyInfo, policyID) }, 1.49 + { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_OPTIONAL, 1.50 + offsetof(CERTPolicyInfo, policyQualifiers), 1.51 + secu_PolicyQualifierTemplate }, 1.52 + { 0 } 1.53 +}; 1.54 + 1.55 +static const SEC_ASN1Template secu_CertificatePoliciesTemplate[] = { 1.56 + { SEC_ASN1_SEQUENCE_OF, 1.57 + offsetof(CERTCertificatePolicies, policyInfos), 1.58 + secu_PolicyInfoTemplate, sizeof(CERTCertificatePolicies) } 1.59 +}; 1.60 + 1.61 + 1.62 +static CERTCertificatePolicies * 1.63 +secu_DecodeCertificatePoliciesExtension(SECItem *extnValue) 1.64 +{ 1.65 + PLArenaPool *arena = NULL; 1.66 + SECStatus rv; 1.67 + CERTCertificatePolicies *policies; 1.68 + CERTPolicyInfo **policyInfos, *policyInfo; 1.69 + CERTPolicyQualifier **policyQualifiers, *policyQualifier; 1.70 + SECItem newExtnValue; 1.71 + 1.72 + /* make a new arena */ 1.73 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.74 + 1.75 + if ( !arena ) { 1.76 + goto loser; 1.77 + } 1.78 + 1.79 + /* allocate the certifiate policies structure */ 1.80 + policies = PORT_ArenaZNew(arena, CERTCertificatePolicies); 1.81 + if ( policies == NULL ) { 1.82 + goto loser; 1.83 + } 1.84 + 1.85 + policies->arena = arena; 1.86 + 1.87 + /* copy the DER into the arena, since Quick DER returns data that points 1.88 + into the DER input, which may get freed by the caller */ 1.89 + rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue); 1.90 + if ( rv != SECSuccess ) { 1.91 + goto loser; 1.92 + } 1.93 + 1.94 + /* decode the policy info */ 1.95 + rv = SEC_QuickDERDecodeItem(arena, policies, 1.96 + secu_CertificatePoliciesTemplate, 1.97 + &newExtnValue); 1.98 + 1.99 + if ( rv != SECSuccess ) { 1.100 + goto loser; 1.101 + } 1.102 + 1.103 + /* initialize the oid tags */ 1.104 + policyInfos = policies->policyInfos; 1.105 + while (policyInfos != NULL && *policyInfos != NULL ) { 1.106 + policyInfo = *policyInfos; 1.107 + policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID); 1.108 + policyQualifiers = policyInfo->policyQualifiers; 1.109 + while ( policyQualifiers && *policyQualifiers != NULL ) { 1.110 + policyQualifier = *policyQualifiers; 1.111 + policyQualifier->oid = 1.112 + SECOID_FindOIDTag(&policyQualifier->qualifierID); 1.113 + policyQualifiers++; 1.114 + } 1.115 + policyInfos++; 1.116 + } 1.117 + 1.118 + return(policies); 1.119 + 1.120 +loser: 1.121 + if ( arena != NULL ) { 1.122 + PORT_FreeArena(arena, PR_FALSE); 1.123 + } 1.124 + 1.125 + return(NULL); 1.126 +} 1.127 + 1.128 + 1.129 +static char * 1.130 +itemToString(SECItem *item) 1.131 +{ 1.132 + char *string; 1.133 + 1.134 + string = PORT_ZAlloc(item->len+1); 1.135 + if (string == NULL) return NULL; 1.136 + PORT_Memcpy(string,item->data,item->len); 1.137 + string[item->len] = 0; 1.138 + return string; 1.139 +} 1.140 + 1.141 +static SECStatus 1.142 +secu_PrintUserNoticeQualifier(FILE *out, SECItem * qualifierValue, 1.143 + char *msg, int level) 1.144 +{ 1.145 + CERTUserNotice *userNotice = NULL; 1.146 + if (qualifierValue) 1.147 + userNotice = CERT_DecodeUserNotice(qualifierValue); 1.148 + if (userNotice) { 1.149 + if (userNotice->noticeReference.organization.len != 0) { 1.150 + char *string = 1.151 + itemToString(&userNotice->noticeReference.organization); 1.152 + SECItem **itemList = userNotice->noticeReference.noticeNumbers; 1.153 + 1.154 + while (itemList && *itemList) { 1.155 + SECU_PrintInteger(out,*itemList,string,level+1); 1.156 + itemList++; 1.157 + } 1.158 + PORT_Free(string); 1.159 + } 1.160 + if (userNotice->displayText.len != 0) { 1.161 + SECU_PrintString(out,&userNotice->displayText, 1.162 + "Display Text", level+1); 1.163 + } 1.164 + CERT_DestroyUserNotice(userNotice); 1.165 + return SECSuccess; 1.166 + } 1.167 + return SECFailure; /* caller will print this value */ 1.168 +} 1.169 + 1.170 +static SECStatus 1.171 +secu_PrintPolicyQualifier(FILE *out,CERTPolicyQualifier *policyQualifier, 1.172 + char *msg,int level) 1.173 +{ 1.174 + SECStatus rv; 1.175 + SECItem * qualifierValue = &policyQualifier->qualifierValue; 1.176 + 1.177 + SECU_PrintObjectID(out, &policyQualifier->qualifierID , 1.178 + "Policy Qualifier Name", level); 1.179 + if (!qualifierValue->data) { 1.180 + SECU_Indent(out, level); 1.181 + fprintf(out,"Error: missing qualifier\n"); 1.182 + } else 1.183 + switch (policyQualifier->oid) { 1.184 + case SEC_OID_PKIX_USER_NOTICE_QUALIFIER: 1.185 + rv = secu_PrintUserNoticeQualifier(out, qualifierValue, msg, level); 1.186 + if (SECSuccess == rv) 1.187 + break; 1.188 + /* fall through on error */ 1.189 + case SEC_OID_PKIX_CPS_POINTER_QUALIFIER: 1.190 + default: 1.191 + SECU_PrintAny(out, qualifierValue, "Policy Qualifier Data", level); 1.192 + break; 1.193 + } 1.194 + return SECSuccess; 1.195 +} 1.196 + 1.197 +static SECStatus 1.198 +secu_PrintPolicyInfo(FILE *out,CERTPolicyInfo *policyInfo,char *msg,int level) 1.199 +{ 1.200 + CERTPolicyQualifier **policyQualifiers; 1.201 + 1.202 + policyQualifiers = policyInfo->policyQualifiers; 1.203 + SECU_PrintObjectID(out, &policyInfo->policyID , "Policy Name", level); 1.204 + 1.205 + while (policyQualifiers && *policyQualifiers != NULL) { 1.206 + secu_PrintPolicyQualifier(out,*policyQualifiers,"",level+1); 1.207 + policyQualifiers++; 1.208 + } 1.209 + return SECSuccess; 1.210 +} 1.211 + 1.212 +void 1.213 +SECU_PrintPolicy(FILE *out, SECItem *value, char *msg, int level) 1.214 +{ 1.215 + CERTCertificatePolicies *policies = NULL; 1.216 + CERTPolicyInfo **policyInfos; 1.217 + 1.218 + if (msg) { 1.219 + SECU_Indent(out, level); 1.220 + fprintf(out,"%s: \n",msg); 1.221 + level++; 1.222 + } 1.223 + policies = secu_DecodeCertificatePoliciesExtension(value); 1.224 + if (policies == NULL) { 1.225 + SECU_PrintAny(out, value, "Invalid Policy Data", level); 1.226 + return; 1.227 + } 1.228 + 1.229 + policyInfos = policies->policyInfos; 1.230 + while (policyInfos && *policyInfos != NULL) { 1.231 + secu_PrintPolicyInfo(out,*policyInfos,"",level); 1.232 + policyInfos++; 1.233 + } 1.234 + 1.235 + CERT_DestroyCertificatePoliciesExtension(policies); 1.236 +} 1.237 + 1.238 + 1.239 +void 1.240 +SECU_PrintPrivKeyUsagePeriodExtension(FILE *out, SECItem *value, 1.241 + char *msg, int level) 1.242 +{ 1.243 + CERTPrivKeyUsagePeriod * prd; 1.244 + PLArenaPool * arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.245 + 1.246 + if ( !arena ) { 1.247 + goto loser; 1.248 + } 1.249 + prd = CERT_DecodePrivKeyUsagePeriodExtension(arena, value); 1.250 + if (!prd) { 1.251 + goto loser; 1.252 + } 1.253 + if (prd->notBefore.data) { 1.254 + SECU_PrintGeneralizedTime(out, &prd->notBefore, "Not Before", level); 1.255 + } 1.256 + if (prd->notAfter.data) { 1.257 + SECU_PrintGeneralizedTime(out, &prd->notAfter, "Not After ", level); 1.258 + } 1.259 + if (!prd->notBefore.data && !prd->notAfter.data) { 1.260 + SECU_Indent(out, level); 1.261 + fprintf(out, "Error: notBefore or notAfter MUST be present.\n"); 1.262 +loser: 1.263 + SECU_PrintAny(out, value, msg, level); 1.264 + } 1.265 + if (arena) { 1.266 + PORT_FreeArena(arena, PR_FALSE); 1.267 + } 1.268 +}