Back to index

lightning-sunbird  0.9+nobinonly
pppolicy.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 2004
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 /*
00038  * Support for various policy related extensions
00039  *
00040  * $Id: pppolicy.c,v 1.3 2005/02/22 20:02:22 wtchang%redhat.com Exp $
00041  */
00042 
00043 #include "seccomon.h"
00044 #include "secport.h"
00045 #include "secder.h"
00046 #include "cert.h"
00047 #include "secoid.h"
00048 #include "secasn1.h"
00049 #include "secerr.h"
00050 #include "nspr.h"
00051 #include "secutil.h"
00052 
00053 /* This implementation is derived from the one in nss/lib/certdb/policyxtn.c .
00054 ** The chief difference is the addition of the OPTIONAL flag to many 
00055 ** parts.  The idea is to be able to parse and print as much of the 
00056 ** policy extension as possible, even if some parts are invalid.
00057 **
00058 ** If this approach still is unable to decode policy extensions that
00059 ** contain invalid parts, then the next approach will be to parse 
00060 ** the PolicyInfos as a SEQUENCE of ANYs, and then parse each of them 
00061 ** as PolicyInfos, with the PolicyQualifiers being ANYs, and finally
00062 ** parse each of the PolicyQualifiers.
00063 */
00064 
00065 static const SEC_ASN1Template secu_PolicyQualifierTemplate[] = {
00066     { SEC_ASN1_SEQUENCE,
00067          0, NULL, sizeof(CERTPolicyQualifier) },
00068     { SEC_ASN1_OBJECT_ID,
00069          offsetof(CERTPolicyQualifier, qualifierID) },
00070     { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
00071          offsetof(CERTPolicyQualifier, qualifierValue) },
00072     { 0 }
00073 };
00074 
00075 static const SEC_ASN1Template secu_PolicyInfoTemplate[] = {
00076     { SEC_ASN1_SEQUENCE,
00077          0, NULL, sizeof(CERTPolicyInfo) },
00078     { SEC_ASN1_OBJECT_ID,
00079          offsetof(CERTPolicyInfo, policyID) },
00080     { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_OPTIONAL,
00081          offsetof(CERTPolicyInfo, policyQualifiers),
00082          secu_PolicyQualifierTemplate },
00083     { 0 }
00084 };
00085 
00086 static const SEC_ASN1Template secu_CertificatePoliciesTemplate[] = {
00087     { SEC_ASN1_SEQUENCE_OF,
00088          offsetof(CERTCertificatePolicies, policyInfos),
00089          secu_PolicyInfoTemplate, sizeof(CERTCertificatePolicies)  }
00090 };
00091 
00092 
00093 static CERTCertificatePolicies *
00094 secu_DecodeCertificatePoliciesExtension(SECItem *extnValue)
00095 {
00096     PRArenaPool *arena = NULL;
00097     SECStatus rv;
00098     CERTCertificatePolicies *policies;
00099     CERTPolicyInfo **policyInfos, *policyInfo;
00100     CERTPolicyQualifier **policyQualifiers, *policyQualifier;
00101     SECItem newExtnValue;
00102     
00103     /* make a new arena */
00104     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
00105     
00106     if ( !arena ) {
00107        goto loser;
00108     }
00109 
00110     /* allocate the certifiate policies structure */
00111     policies = PORT_ArenaZNew(arena, CERTCertificatePolicies);
00112     if ( policies == NULL ) {
00113        goto loser;
00114     }
00115     
00116     policies->arena = arena;
00117 
00118     /* copy the DER into the arena, since Quick DER returns data that points
00119        into the DER input, which may get freed by the caller */
00120     rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue);
00121     if ( rv != SECSuccess ) {
00122        goto loser;
00123     }
00124 
00125     /* decode the policy info */
00126     rv = SEC_QuickDERDecodeItem(arena, policies, 
00127                                 secu_CertificatePoliciesTemplate,
00128                              &newExtnValue);
00129 
00130     if ( rv != SECSuccess ) {
00131        goto loser;
00132     }
00133 
00134     /* initialize the oid tags */
00135     policyInfos = policies->policyInfos;
00136     while (policyInfos != NULL && *policyInfos != NULL ) {
00137        policyInfo = *policyInfos;
00138        policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID);
00139        policyQualifiers = policyInfo->policyQualifiers;
00140        while ( policyQualifiers && *policyQualifiers != NULL ) {
00141            policyQualifier = *policyQualifiers;
00142            policyQualifier->oid =
00143               SECOID_FindOIDTag(&policyQualifier->qualifierID);
00144            policyQualifiers++;
00145        }
00146        policyInfos++;
00147     }
00148 
00149     return(policies);
00150     
00151 loser:
00152     if ( arena != NULL ) {
00153        PORT_FreeArena(arena, PR_FALSE);
00154     }
00155     
00156     return(NULL);
00157 }
00158 
00159 
00160 static char *
00161 itemToString(SECItem *item)
00162 {
00163     char *string;
00164 
00165     string = PORT_ZAlloc(item->len+1);
00166     if (string == NULL) return NULL;
00167     PORT_Memcpy(string,item->data,item->len);
00168     string[item->len] = 0;
00169     return string;
00170 }
00171 
00172 static SECStatus
00173 secu_PrintUserNoticeQualifier(FILE *out, SECItem * qualifierValue,
00174                               char *msg, int level)
00175 {
00176     CERTUserNotice *userNotice = NULL;
00177     if (qualifierValue)
00178        userNotice = CERT_DecodeUserNotice(qualifierValue);
00179     if (userNotice) {
00180        if (userNotice->noticeReference.organization.len != 0) {
00181             char *string = 
00182                    itemToString(&userNotice->noticeReference.organization);
00183             SECItem **itemList = userNotice->noticeReference.noticeNumbers;
00184 
00185            while (itemList && *itemList) {
00186               SECU_PrintInteger(out,*itemList,string,level+1);
00187                itemList++;
00188            }
00189            PORT_Free(string);
00190        }
00191        if (userNotice->displayText.len != 0) {
00192            SECU_PrintString(out,&userNotice->displayText,
00193                           "Display Text", level+1);
00194        }
00195        CERT_DestroyUserNotice(userNotice);
00196        return SECSuccess;
00197     }
00198     return SECFailure;      /* caller will print this value */
00199 }
00200 
00201 static SECStatus
00202 secu_PrintPolicyQualifier(FILE *out,CERTPolicyQualifier *policyQualifier,
00203                        char *msg,int level)
00204 {
00205    SECStatus rv;
00206    SECItem * qualifierValue = &policyQualifier->qualifierValue;
00207 
00208    SECU_PrintObjectID(out, &policyQualifier->qualifierID , 
00209                                    "Policy Qualifier Name", level);
00210    if (!qualifierValue->data) {
00211        SECU_Indent(out, level);
00212        fprintf(out,"Error: missing qualifier\n");
00213    } else 
00214    switch (policyQualifier->oid) {
00215    case SEC_OID_PKIX_USER_NOTICE_QUALIFIER:
00216        rv = secu_PrintUserNoticeQualifier(out, qualifierValue, msg, level);
00217        if (SECSuccess == rv)
00218           break;
00219        /* fall through on error */
00220    case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
00221    default:
00222        SECU_PrintAny(out, qualifierValue, "Policy Qualifier Data", level);
00223        break;
00224    }
00225    return SECSuccess;
00226 }
00227 
00228 static SECStatus
00229 secu_PrintPolicyInfo(FILE *out,CERTPolicyInfo *policyInfo,char *msg,int level)
00230 {
00231    CERTPolicyQualifier **policyQualifiers;
00232 
00233    policyQualifiers = policyInfo->policyQualifiers;
00234    SECU_PrintObjectID(out, &policyInfo->policyID , "Policy Name", level);
00235    
00236    while (policyQualifiers && *policyQualifiers != NULL) {
00237        secu_PrintPolicyQualifier(out,*policyQualifiers,"",level+1);
00238        policyQualifiers++;
00239    }
00240    return SECSuccess;
00241 }
00242 
00243 void
00244 SECU_PrintPolicy(FILE *out, SECItem *value, char *msg, int level)
00245 {
00246    CERTCertificatePolicies *policies = NULL;
00247    CERTPolicyInfo **policyInfos;
00248 
00249    if (msg) {
00250        SECU_Indent(out, level);
00251        fprintf(out,"%s: \n",msg);
00252        level++;
00253    }
00254    policies = secu_DecodeCertificatePoliciesExtension(value);
00255    if (policies == NULL) {
00256        SECU_PrintAny(out, value, "Invalid Policy Data", level);
00257        return;
00258    }
00259 
00260    policyInfos = policies->policyInfos;
00261    while (policyInfos && *policyInfos != NULL) {
00262        secu_PrintPolicyInfo(out,*policyInfos,"",level);
00263        policyInfos++;
00264    }
00265 
00266    CERT_DestroyCertificatePoliciesExtension(policies);
00267 }
00268 
00269 
00270 void
00271 SECU_PrintPrivKeyUsagePeriodExtension(FILE *out, SECItem *value, 
00272                                    char *msg, int level)
00273 {
00274     CERTPrivKeyUsagePeriod * prd;
00275     PLArenaPool * arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
00276 
00277     if ( !arena ) {
00278        goto loser;
00279     }
00280     prd = CERT_DecodePrivKeyUsagePeriodExtension(arena, value);
00281     if (!prd) {
00282        goto loser;
00283     }
00284     if (prd->notBefore.data) {
00285        SECU_PrintGeneralizedTime(out, &prd->notBefore, "Not Before", level);
00286     }
00287     if (prd->notAfter.data) {
00288        SECU_PrintGeneralizedTime(out, &prd->notAfter,  "Not After ", level);
00289     }
00290     if (!prd->notBefore.data && !prd->notAfter.data) {
00291        SECU_Indent(out, level);
00292        fprintf(out, "Error: notBefore or notAfter MUST be present.\n");
00293 loser:
00294        SECU_PrintAny(out, value, msg, level);
00295     }
00296     if (arena) {
00297        PORT_FreeArena(arena, PR_FALSE);
00298     }
00299 }