security/nss/cmd/lib/pppolicy.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial