summaryrefslogtreecommitdiffstats
path: root/pki/base/native-tools/src/tkstool/pppolicy.c
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/native-tools/src/tkstool/pppolicy.c')
-rw-r--r--pki/base/native-tools/src/tkstool/pppolicy.c306
1 files changed, 306 insertions, 0 deletions
diff --git a/pki/base/native-tools/src/tkstool/pppolicy.c b/pki/base/native-tools/src/tkstool/pppolicy.c
new file mode 100644
index 0000000..8b198ca
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/pppolicy.c
@@ -0,0 +1,306 @@
+/** BEGIN COPYRIGHT BLOCK
+ *
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * END COPYRIGHT BLOCK **/
+
+/* Originally obtained from:
+ *
+ * CVSROOT=:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
+ * cvs export -r NSS_3_11_3_RTM -N mozilla/security/nss/cmd/lib/pppolicy.c
+ */
+
+/*
+ * Support for various policy related extensions
+ *
+ * $Id$
+ */
+
+#include "seccomon.h"
+#include "secport.h"
+#include "secder.h"
+#include "cert.h"
+#include "secoid.h"
+#include "secasn1.h"
+#include "secerr.h"
+#include "nspr.h"
+#include "secutil.h"
+
+/* This implementation is derived from the one in nss/lib/certdb/policyxtn.c .
+** The chief difference is the addition of the OPTIONAL flag to many
+** parts. The idea is to be able to parse and print as much of the
+** policy extension as possible, even if some parts are invalid.
+**
+** If this approach still is unable to decode policy extensions that
+** contain invalid parts, then the next approach will be to parse
+** the PolicyInfos as a SEQUENCE of ANYs, and then parse each of them
+** as PolicyInfos, with the PolicyQualifiers being ANYs, and finally
+** parse each of the PolicyQualifiers.
+*/
+
+static const SEC_ASN1Template secu_PolicyQualifierTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(CERTPolicyQualifier) },
+ { SEC_ASN1_OBJECT_ID,
+ offsetof(CERTPolicyQualifier, qualifierID) },
+ { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
+ offsetof(CERTPolicyQualifier, qualifierValue) },
+ { 0 }
+};
+
+static const SEC_ASN1Template secu_PolicyInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(CERTPolicyInfo) },
+ { SEC_ASN1_OBJECT_ID,
+ offsetof(CERTPolicyInfo, policyID) },
+ { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_OPTIONAL,
+ offsetof(CERTPolicyInfo, policyQualifiers),
+ secu_PolicyQualifierTemplate },
+ { 0 }
+};
+
+static const SEC_ASN1Template secu_CertificatePoliciesTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF,
+ offsetof(CERTCertificatePolicies, policyInfos),
+ secu_PolicyInfoTemplate, sizeof(CERTCertificatePolicies) }
+};
+
+
+static CERTCertificatePolicies *
+secu_DecodeCertificatePoliciesExtension(SECItem *extnValue)
+{
+ PRArenaPool *arena = NULL;
+ SECStatus rv;
+ CERTCertificatePolicies *policies;
+ CERTPolicyInfo **policyInfos, *policyInfo;
+ CERTPolicyQualifier **policyQualifiers, *policyQualifier;
+ SECItem newExtnValue;
+
+ /* make a new arena */
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if ( !arena ) {
+ goto loser;
+ }
+
+ /* allocate the certifiate policies structure */
+ policies = PORT_ArenaZNew(arena, CERTCertificatePolicies);
+ if ( policies == NULL ) {
+ goto loser;
+ }
+
+ policies->arena = arena;
+
+ /* copy the DER into the arena, since Quick DER returns data that points
+ into the DER input, which may get freed by the caller */
+ rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ /* decode the policy info */
+ rv = SEC_QuickDERDecodeItem(arena, policies,
+ secu_CertificatePoliciesTemplate,
+ &newExtnValue);
+
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ /* initialize the oid tags */
+ policyInfos = policies->policyInfos;
+ while (policyInfos != NULL && *policyInfos != NULL ) {
+ policyInfo = *policyInfos;
+ policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID);
+ policyQualifiers = policyInfo->policyQualifiers;
+ while ( policyQualifiers && *policyQualifiers != NULL ) {
+ policyQualifier = *policyQualifiers;
+ policyQualifier->oid =
+ SECOID_FindOIDTag(&policyQualifier->qualifierID);
+ policyQualifiers++;
+ }
+ policyInfos++;
+ }
+
+ return(policies);
+
+loser:
+ if ( arena != NULL ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(NULL);
+}
+
+
+static char *
+itemToString(SECItem *item)
+{
+ char *string;
+
+ string = PORT_ZAlloc(item->len+1);
+ if (string == NULL) return NULL;
+ PORT_Memcpy(string,item->data,item->len);
+ string[item->len] = 0;
+ return string;
+}
+
+static SECStatus
+secu_PrintUserNoticeQualifier(FILE *out, SECItem * qualifierValue,
+ char *msg, int level)
+{
+ CERTUserNotice *userNotice = NULL;
+ if (qualifierValue)
+ userNotice = CERT_DecodeUserNotice(qualifierValue);
+ if (userNotice) {
+ if (userNotice->noticeReference.organization.len != 0) {
+ char *string =
+ itemToString(&userNotice->noticeReference.organization);
+ SECItem **itemList = userNotice->noticeReference.noticeNumbers;
+
+ while (itemList && *itemList) {
+ SECU_PrintInteger(out,*itemList,string,level+1);
+ itemList++;
+ }
+ PORT_Free(string);
+ }
+ if (userNotice->displayText.len != 0) {
+ SECU_PrintString(out,&userNotice->displayText,
+ "Display Text", level+1);
+ }
+ CERT_DestroyUserNotice(userNotice);
+ return SECSuccess;
+ }
+ return SECFailure; /* caller will print this value */
+}
+
+static SECStatus
+secu_PrintPolicyQualifier(FILE *out,CERTPolicyQualifier *policyQualifier,
+ char *msg,int level)
+{
+ SECStatus rv;
+ SECItem * qualifierValue = &policyQualifier->qualifierValue;
+
+ SECU_PrintObjectID(out, &policyQualifier->qualifierID ,
+ "Policy Qualifier Name", level);
+ if (!qualifierValue->data) {
+ SECU_Indent(out, level);
+ fprintf(out,"Error: missing qualifier\n");
+ } else
+ switch (policyQualifier->oid) {
+ case SEC_OID_PKIX_USER_NOTICE_QUALIFIER:
+ rv = secu_PrintUserNoticeQualifier(out, qualifierValue, msg, level);
+ if (SECSuccess == rv)
+ break;
+ /* fall through on error */
+ case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
+ default:
+ SECU_PrintAny(out, qualifierValue, "Policy Qualifier Data", level);
+ break;
+ }
+ return SECSuccess;
+}
+
+static SECStatus
+secu_PrintPolicyInfo(FILE *out,CERTPolicyInfo *policyInfo,char *msg,int level)
+{
+ CERTPolicyQualifier **policyQualifiers;
+
+ policyQualifiers = policyInfo->policyQualifiers;
+ SECU_PrintObjectID(out, &policyInfo->policyID , "Policy Name", level);
+
+ while (policyQualifiers && *policyQualifiers != NULL) {
+ secu_PrintPolicyQualifier(out,*policyQualifiers,"",level+1);
+ policyQualifiers++;
+ }
+ return SECSuccess;
+}
+
+void
+SECU_PrintPolicy(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTCertificatePolicies *policies = NULL;
+ CERTPolicyInfo **policyInfos;
+
+ if (msg) {
+ SECU_Indent(out, level);
+ fprintf(out,"%s: \n",msg);
+ level++;
+ }
+ policies = secu_DecodeCertificatePoliciesExtension(value);
+ if (policies == NULL) {
+ SECU_PrintAny(out, value, "Invalid Policy Data", level);
+ return;
+ }
+
+ policyInfos = policies->policyInfos;
+ while (policyInfos && *policyInfos != NULL) {
+ secu_PrintPolicyInfo(out,*policyInfos,"",level);
+ policyInfos++;
+ }
+
+ CERT_DestroyCertificatePoliciesExtension(policies);
+}
+
+
+void
+SECU_PrintPrivKeyUsagePeriodExtension(FILE *out, SECItem *value,
+ char *msg, int level)
+{
+ CERTPrivKeyUsagePeriod * prd;
+ PLArenaPool * arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if ( !arena ) {
+ goto loser;
+ }
+ prd = CERT_DecodePrivKeyUsagePeriodExtension(arena, value);
+ if (!prd) {
+ goto loser;
+ }
+ if (prd->notBefore.data) {
+ SECU_PrintGeneralizedTime(out, &prd->notBefore, "Not Before", level);
+ }
+ if (prd->notAfter.data) {
+ SECU_PrintGeneralizedTime(out, &prd->notAfter, "Not After ", level);
+ }
+ if (!prd->notBefore.data && !prd->notAfter.data) {
+ SECU_Indent(out, level);
+ fprintf(out, "Error: notBefore or notAfter MUST be present.\n");
+loser:
+ SECU_PrintAny(out, value, msg, level);
+ }
+ if (arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+}