summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornelsonb%netscape.com <devnull@localhost>2004-01-29 22:45:20 +0000
committernelsonb%netscape.com <devnull@localhost>2004-01-29 22:45:20 +0000
commita6874a4fb746bab5589456b2e5a117efb065d108 (patch)
tree4c94ed3df288abf3f2cb2baded69ac730c069013
parent3992fc052de8e693a8f00bbb49fdcdaf063aa663 (diff)
downloadnss-hg-a6874a4fb746bab5589456b2e5a117efb065d108.tar.gz
Bug 132942. r=wtc
Make the following enhancements to NSS's ASN.1 printing code: - Print warning messages that are properly indendented. - PrintAsHex notices when the buffer contains entirely printable characters, and is larger than an int, and prints it as text in that case. - PrintRawString now indents the string, rather than always printing it on a separate line. - now prints decoded bit strings - now prints BMP (UCS2) strings as strings (not as hex) when they contain only printable ASCII characters. - now prints Universal (UCS4) Strings as strings (not hex) when they contain only printable ASCII characters. - Decodes certain encoded data that was previously printed as hex. - Generically decodes ASN.1 data, rather than merely printing an error, when the ASN.1 data doesn't fit a known template. - properly handles all optional components of basic constraints extensions. - Prints the names of the bits in the X509 Key Usage extension. - Prints General Names. - Print Auth Key ID extensions - Print subject and issuer alt name extensions - Print CRL distribution points extensions - format and print name constraints extensions - print Authority Information Access extensions - Print optional X509v2 subject and issuer Unique ID bit strings
-rw-r--r--security/nss/cmd/lib/manifest.mn2
-rw-r--r--security/nss/cmd/lib/moreoids.c177
-rw-r--r--security/nss/cmd/lib/pppolicy.c295
-rw-r--r--security/nss/cmd/lib/secutil.c714
-rw-r--r--security/nss/cmd/lib/secutil.h9
5 files changed, 1030 insertions, 167 deletions
diff --git a/security/nss/cmd/lib/manifest.mn b/security/nss/cmd/lib/manifest.mn
index 9df34a5df..a45e42c2d 100644
--- a/security/nss/cmd/lib/manifest.mn
+++ b/security/nss/cmd/lib/manifest.mn
@@ -45,6 +45,8 @@ EXPORTS = secutil.h \
CSRCS = secutil.c \
secpwd.c \
derprint.c \
+ moreoids.c \
+ pppolicy.c \
secerror.c \
ffs.c \
$(NULL)
diff --git a/security/nss/cmd/lib/moreoids.c b/security/nss/cmd/lib/moreoids.c
new file mode 100644
index 000000000..a7a78e8d3
--- /dev/null
+++ b/security/nss/cmd/lib/moreoids.c
@@ -0,0 +1,177 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 2004 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "secoid.h"
+#include "secmodt.h" /* for CKM_INVALID_MECHANISM */
+
+#define OI(x) { siDEROID, (unsigned char *)x, sizeof x }
+#define OD(oid,tag,desc,mech,ext) { OI(oid), tag, desc, mech, ext }
+#define ODN(oid,desc) \
+ { OI(oid), 0, desc, CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION }
+
+#define OIDT static const unsigned char
+
+/* OIW Security Special Interest Group defined algorithms. */
+#define OIWSSIG 0x2B, 13, 3, 2
+
+OIDT oiwMD5RSA[] = { OIWSSIG, 3 };
+OIDT oiwDESCBC[] = { OIWSSIG, 7 };
+OIDT oiwRSAsig[] = { OIWSSIG, 11 };
+OIDT oiwDSA [] = { OIWSSIG, 12 };
+OIDT oiwMD5RSAsig[] = { OIWSSIG, 25 };
+OIDT oiwSHA1 [] = { OIWSSIG, 26 };
+OIDT oiwDSASHA1[] = { OIWSSIG, 27 };
+OIDT oiwDSASHA1param[] = { OIWSSIG, 28 };
+OIDT oiwSHA1RSA[] = { OIWSSIG, 29 };
+
+
+/* Microsoft OIDs. (1 3 6 1 4 1 311 ... ) */
+#define MICROSOFT 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37
+
+OIDT mCTL[] = { MICROSOFT, 10, 3, 1 }; /* Cert Trust List signing */
+OIDT mTSS[] = { MICROSOFT, 10, 3, 2 }; /* Time Stamp Signing */
+OIDT mSGC[] = { MICROSOFT, 10, 3, 3 }; /* Server gated cryptography */
+OIDT mEFS[] = { MICROSOFT, 10, 3, 4 }; /* Encrypted File System */
+OIDT mSMIME[] = { MICROSOFT, 16, 4 }; /* SMIME encryption key prefs */
+
+OIDT mECRTT[] = { MICROSOFT, 20, 2 }; /* Enrollment cert type xtn */
+OIDT mEAGNT[] = { MICROSOFT, 20, 2, 1 }; /* Enrollment Agent */
+OIDT mKPSCL[] = { MICROSOFT, 20, 2, 2 }; /* KP SmartCard Logon */
+OIDT mNTPN [] = { MICROSOFT, 20, 2, 3 }; /* NT Principal Name */
+OIDT mCASRV[] = { MICROSOFT, 21, 1 }; /* CertServ CA version */
+
+/* AOL OIDs (1 3 6 1 4 1 1066 ... ) */
+#define AOL 0x2B, 0x06, 0x01, 0x04, 0x01, 0x88, 0x2A
+
+/* PKIX IDs (1 3 6 1 5 5 7 ...) */
+#define ID_PKIX 0x2B, 6, 1, 5, 5, 7
+/* PKIX Access Descriptors (methods for Authority Info Access Extns) */
+#define ID_AD ID_PKIX, 48
+
+OIDT padOCSP[] = { ID_AD, 1 }; /* OCSP method */
+OIDT padCAissuer[] = { ID_AD, 2 }; /* URI (for CRL ?) */
+OIDT padTimeStamp[] = { ID_AD, 3 }; /* time stamping */
+
+/* ISO Cert Extension type OIDs (id-ce) (2 5 29 ...) */
+#define X500 0x55
+#define X520_ATTRIBUTE_TYPE X500, 0x04
+#define X500_ALG X500, 0x08
+#define X500_ALG_ENCRYPTION X500_ALG, 0x01
+#define ID_CE X500, 29
+
+OIDT cePlcyObs[] = { ID_CE, 3 }; /* Cert policies, obsolete. */
+OIDT cePlcyCns[] = { ID_CE, 36 }; /* Cert policy constraints. */
+
+/* US Company arc (2 16 840 1 ...) */
+#define USCOM 0x60, 0x86, 0x48, 0x01
+#define USGOV USCOM, 0x65
+#define USDOD USGOV, 2
+#define ID_INFOSEC USDOD, 1
+
+/* Verisign PKI OIDs (2 16 840 1 113733 1 ...) */
+#define VERISIGN_PKI USCOM, 0x86, 0xf8, 0x45, 1
+#define VERISIGN_XTN VERISIGN_PKI, 6
+#define VERISIGN_POL VERISIGN_PKI, 7 /* Cert policies */
+#define VERISIGN_TNET VERISIGN_POL, 23 /* Verisign Trust Network */
+
+OIDT vcx7[] = { VERISIGN_XTN, 7 }; /* Cert Extension 7 (?) */
+OIDT vcp1[] = { VERISIGN_TNET, 1 }; /* class 1 cert policy */
+OIDT vcp2[] = { VERISIGN_TNET, 2 }; /* class 2 cert policy */
+OIDT vcp3[] = { VERISIGN_TNET, 3 }; /* class 3 cert policy */
+OIDT vcp4[] = { VERISIGN_TNET, 4 }; /* class 4 cert policy */
+
+
+/* ------------------------------------------------------------------- */
+static const SECOidData oids[] = {
+/* OIW Security Special Interest Group OIDs */
+ ODN( oiwMD5RSA, "OIWSecSIG MD5 with RSA"),
+ ODN( oiwDESCBC, "OIWSecSIG DES CBC"),
+ ODN( oiwRSAsig, "OIWSecSIG RSA signature"),
+ ODN( oiwDSA , "OIWSecSIG DSA"),
+ ODN( oiwMD5RSAsig, "OIWSecSIG MD5 with RSA signature"),
+ ODN( oiwSHA1 , "OIWSecSIG SHA1"),
+ ODN( oiwDSASHA1, "OIWSecSIG DSA with SHA1"),
+ ODN( oiwDSASHA1param, "OIWSecSIG DSA with SHA1 with params"),
+ ODN( oiwSHA1RSA, "OIWSecSIG MD5 with RSA"),
+
+/* Microsoft OIDs */
+ ODN( mCTL, "Microsoft Cert Trust List signing"),
+ ODN( mTSS, "Microsoft Time Stamp signing"),
+ ODN( mSGC, "Microsoft SGC SSL server"),
+ ODN( mEFS, "Microsoft Encrypted File System"),
+ ODN( mSMIME, "Microsoft SMIME preferences"),
+ ODN( mECRTT, "Microsoft Enrollment Cert Type Extension"),
+ ODN( mEAGNT, "Microsoft Enrollment Agent"),
+ ODN( mKPSCL, "Microsoft KP SmartCard Logon"),
+ ODN( mNTPN, "Microsoft NT Principal Name"),
+ ODN( mCASRV, "Microsoft CertServ CA version"),
+
+/* PKIX OIDs */
+ ODN( padOCSP, "PKIX OCSP method"),
+ ODN( padCAissuer, "PKIX CA Issuer method"),
+ ODN( padTimeStamp, "PKIX Time Stamping method"),
+
+/* ID_CE OIDs. */
+ ODN( cePlcyObs, "Certificate Policies (Obsolete)"),
+ ODN( cePlcyCns, "Certificate Policy Constraints"),
+
+/* Verisign OIDs. */
+ ODN( vcx7, "Verisign Cert Extension 7 (?)"),
+ ODN( vcp1, "Verisign Class 1 Certificate Policy"),
+ ODN( vcp2, "Verisign Class 2 Certificate Policy"),
+ ODN( vcp3, "Verisign Class 3 Certificate Policy"),
+ ODN( vcp4, "Verisign Class 4 Certificate Policy"),
+
+};
+
+static const unsigned int numOids = (sizeof oids) / (sizeof oids[0]);
+
+SECStatus
+SECU_RegisterDynamicOids(void)
+{
+ unsigned int i;
+ SECStatus rv = SECSuccess;
+
+ for (i = 0; i < numOids; ++i) {
+ SECOidTag tag = SECOID_AddEntry(&oids[i]);
+ if (tag == SEC_OID_UNKNOWN) {
+ rv = SECFailure;
+#ifdef DEBUG_DYN_OIDS
+ fprintf(stderr, "Add OID[%d] failed\n", i);
+ } else {
+ fprintf(stderr, "Add OID[%d] returned tag %d\n", i, tag);
+#endif
+ }
+ }
+ return rv;
+}
diff --git a/security/nss/cmd/lib/pppolicy.c b/security/nss/cmd/lib/pppolicy.c
new file mode 100644
index 000000000..71a036d8d
--- /dev/null
+++ b/security/nss/cmd/lib/pppolicy.c
@@ -0,0 +1,295 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 2004 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * 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);
+ }
+ 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);
+ }
+}
diff --git a/security/nss/cmd/lib/secutil.c b/security/nss/cmd/lib/secutil.c
index c21e8f56e..c76ce1894 100644
--- a/security/nss/cmd/lib/secutil.c
+++ b/security/nss/cmd/lib/secutil.c
@@ -46,6 +46,7 @@
#include "prprf.h"
#include "plgetopt.h"
#include "prenv.h"
+#include "prnetdb.h"
#include "secutil.h"
#include "secpkcs7.h"
@@ -84,6 +85,8 @@ static char consoleName[] = {
#endif
};
+static int OIDsAdded;
+
char *
SECU_GetString(int16 error_number)
@@ -95,6 +98,26 @@ SECU_GetString(int16 error_number)
}
void
+SECU_PrintErrMsg(FILE *out, int level, char *progName, char *msg, ...)
+{
+ va_list args;
+ PRErrorCode err = PORT_GetError();
+ const char * errString = SECU_Strerror(err);
+
+ va_start(args, msg);
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s: ", progName);
+ vfprintf(out, msg, args);
+ if (errString != NULL && PORT_Strlen(errString) > 0)
+ fprintf(out, ": %s\n", errString);
+ else
+ fprintf(out, ": error %d\n", (int)err);
+
+ va_end(args);
+}
+
+void
SECU_PrintError(char *progName, char *msg, ...)
{
va_list args;
@@ -531,9 +554,11 @@ secu_StdinToItem(SECItem *dst)
break;
if (dst->data) {
- /* XXX if PORT_Realloc fails, the old buffer is leaked. */
- dst->data = (unsigned char*)PORT_Realloc(dst->data,
- dst->len + numBytes);
+ unsigned char * p = dst->data;
+ dst->data = (unsigned char*)PORT_Realloc(p, dst->len + numBytes);
+ if (!dst->data) {
+ PORT_Free(p);
+ }
} else {
dst->data = (unsigned char*)PORT_Alloc(numBytes);
}
@@ -687,6 +712,7 @@ void
SECU_Indent(FILE *out, int level)
{
int i;
+
for (i = 0; i < level; i++) {
fprintf(out, " ");
}
@@ -702,7 +728,9 @@ SECU_PrintAsHex(FILE *out, SECItem *data, const char *m, int level)
{
unsigned i;
int column;
- PRBool isString = PR_TRUE;
+ PRBool isString = PR_TRUE;
+ PRBool isWhiteSpace = PR_TRUE;
+ PRBool printedHex = PR_FALSE;
unsigned int limit = 15;
if ( m ) {
@@ -711,6 +739,10 @@ SECU_PrintAsHex(FILE *out, SECItem *data, const char *m, int level)
}
SECU_Indent(out, level); column = level*INDENT_MULT;
+ if (!data->len) {
+ fprintf(out, "(empty)\n");
+ return;
+ }
/* take a pass to see if it's all printable. */
for (i = 0; i < data->len; i++) {
unsigned char val = data->data[i];
@@ -718,9 +750,18 @@ SECU_PrintAsHex(FILE *out, SECItem *data, const char *m, int level)
isString = PR_FALSE;
break;
}
+ if (isWhiteSpace && !isspace(val)) {
+ isWhiteSpace = PR_FALSE;
+ }
}
- if (!isString)
+ /* Short values, such as bit strings (which are printed with this
+ ** function) often look like strings, but we want to see the bits.
+ ** so this test assures that short values will be printed in hex,
+ ** perhaps in addition to being printed as strings.
+ ** The threshold size (4 bytes) is arbitrary.
+ */
+ if (!isString || data->len <= 4) {
for (i = 0; i < data->len; i++) {
if (i != data->len - 1) {
fprintf(out, "%02x:", data->data[i]);
@@ -736,7 +777,14 @@ SECU_PrintAsHex(FILE *out, SECItem *data, const char *m, int level)
column = level*INDENT_MULT;
limit = i % 16;
}
- } else {
+ }
+ printedHex = PR_TRUE;
+ }
+ if (isString && !isWhiteSpace) {
+ if (printedHex != PR_FALSE) {
+ secu_Newline(out);
+ SECU_Indent(out, level); column = level*INDENT_MULT;
+ }
for (i = 0; i < data->len; i++) {
unsigned char val = data->data[i];
@@ -865,11 +913,13 @@ secu_PrintRawString(FILE *out, SECItem *si, char *m, int level)
unsigned int i;
if ( m ) {
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_Indent(out, level); fprintf(out, "%s: ", m);
+ column = (level * INDENT_MULT) + strlen(m) + 2;
level++;
+ } else {
+ SECU_Indent(out, level);
+ column = level*INDENT_MULT;
}
-
- SECU_Indent(out, level); column = level*INDENT_MULT;
fprintf(out, "\""); column++;
for (i = 0; i < si->len; i++) {
@@ -1007,7 +1057,6 @@ SECU_PrintTimeChoice(FILE *out, SECItem *t, char *m, int level)
}
}
-static void secu_PrintAny(FILE *out, SECItem *i, char *m, int level);
/* This prints a SET or SEQUENCE */
void
@@ -1059,7 +1108,7 @@ SECU_PrintSet(FILE *out, SECItem *t, char *m, int level)
}
my.data += tmp.len;
my.len -= tmp.len;
- secu_PrintAny(out, &tmp, NULL, level + 1);
+ SECU_PrintAny(out, &tmp, NULL, level + 1);
}
SECU_Indent(out, level); fprintf(out, /* { */ "}\n");
}
@@ -1122,6 +1171,25 @@ secu_PrintBitString(FILE *out, SECItem *i, char *m, int level)
}
}
+/* in a decoded bit string, the len member is a bit length. */
+static void
+secu_PrintDecodedBitString(FILE *out, SECItem *i, char *m, int level)
+{
+ int unused_bits;
+ SECItem tmp = *i;
+
+
+ unused_bits = (tmp.len & 0x7) ? 8 - (tmp.len & 7) : 0;
+ DER_ConvertBitString(&tmp); /* convert length to byte length */
+
+ SECU_PrintAsHex(out, &tmp, m, level);
+ if (unused_bits) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "(%d least significant bits unused)\n", unused_bits);
+ }
+}
+
+
/* Print a DER encoded Boolean */
void
SECU_PrintEncodedBoolean(FILE *out, SECItem *i, char *m, int level)
@@ -1150,6 +1218,75 @@ SECU_PrintEncodedObjectID(FILE *out, SECItem *i, char *m, int level)
}
static void
+secu_PrintBMPString(FILE *out, SECItem *i, char *m, int level)
+{
+ unsigned char * s;
+ unsigned char * d;
+ int len;
+ SECItem tmp = {0, 0, 0};
+ SECItem my = *i;
+
+ if (SECSuccess != SECU_StripTagAndLength(&my))
+ goto loser;
+ if (my.len % 2)
+ goto loser;
+ len = (int)(my.len / 2);
+ tmp.data = (unsigned char *)PORT_Alloc(len);
+ if (!tmp.data)
+ goto loser;
+ tmp.len = len;
+ for (s = my.data, d = tmp.data ; len > 0; len--) {
+ PRUint32 bmpChar = (s[0] << 8) | s[1]; s += 2;
+ if (!isprint(bmpChar))
+ goto loser;
+ *d++ = (unsigned char)bmpChar;
+ }
+ secu_PrintRawString(out, &tmp, m, level);
+ PORT_Free(tmp.data);
+ return;
+
+loser:
+ SECU_PrintAsHex(out, i, m, level);
+ if (tmp.data)
+ PORT_Free(tmp.data);
+}
+
+static void
+secu_PrintUniversalString(FILE *out, SECItem *i, char *m, int level)
+{
+ unsigned char * s;
+ unsigned char * d;
+ int len;
+ SECItem tmp = {0, 0, 0};
+ SECItem my = *i;
+
+ if (SECSuccess != SECU_StripTagAndLength(&my))
+ goto loser;
+ if (my.len % 4)
+ goto loser;
+ len = (int)(my.len / 4);
+ tmp.data = (unsigned char *)PORT_Alloc(len);
+ if (!tmp.data)
+ goto loser;
+ tmp.len = len;
+ for (s = my.data, d = tmp.data ; len > 0; len--) {
+ PRUint32 bmpChar = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
+ s += 4;
+ if (!isprint(bmpChar))
+ goto loser;
+ *d++ = (unsigned char)bmpChar;
+ }
+ secu_PrintRawString(out, &tmp, m, level);
+ PORT_Free(tmp.data);
+ return;
+
+loser:
+ SECU_PrintAsHex(out, i, m, level);
+ if (tmp.data)
+ PORT_Free(tmp.data);
+}
+
+static void
secu_PrintUniversal(FILE *out, SECItem *i, char *m, int level)
{
switch (i->data[0] & SEC_ASN1_TAGNUM_MASK) {
@@ -1190,15 +1327,19 @@ secu_PrintUniversal(FILE *out, SECItem *i, char *m, int level)
secu_PrintBitString(out, i, m, level);
break;
case SEC_ASN1_BMP_STRING:
+ secu_PrintBMPString(out, i, m, level);
+ break;
case SEC_ASN1_UNIVERSAL_STRING:
+ secu_PrintUniversalString(out, i, m, level);
+ break;
default:
SECU_PrintAsHex(out, i, m, level);
break;
}
}
-static void
-secu_PrintAny(FILE *out, SECItem *i, char *m, int level)
+void
+SECU_PrintAny(FILE *out, SECItem *i, char *m, int level)
{
if ( i && i->len && i->data ) {
switch (i->data[0] & SEC_ASN1_CLASS_MASK) {
@@ -1290,7 +1431,7 @@ secu_PrintAttribute(FILE *out, SEC_PKCS7Attribute *attr, char *m, int level)
while ((value = attr->values[i++]) != NULL) {
sprintf(om, "Value (%d)%s", i, attr->encoded ? " (encoded)" : "");
if (attr->encoded || attr->typeTag == NULL) {
- SECU_PrintAsHex(out, value, om, level+1);
+ SECU_PrintAny(out, value, om, level+1);
} else {
switch (attr->typeTag->offset) {
default:
@@ -1311,18 +1452,14 @@ secu_PrintAttribute(FILE *out, SEC_PKCS7Attribute *attr, char *m, int level)
static void
secu_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
{
-#if 0 /*
- * um, yeah, that might be nice, but if you look at the callers
- * you will see that they do not *set* this, so this will not work!
- * Instead, somebody needs to fix the callers to be smarter about
- * public key stuff, if that is important.
- */
- PORT_Assert(pk->keyType == rsaKey);
-#endif
SECU_Indent(out, level); fprintf(out, "%s:\n", m);
SECU_PrintInteger(out, &pk->u.rsa.modulus, "Modulus", level+1);
SECU_PrintInteger(out, &pk->u.rsa.publicExponent, "Exponent", level+1);
+ if (pk->u.rsa.publicExponent.len == 1 &&
+ pk->u.rsa.publicExponent.data[0] == 1) {
+ SECU_Indent(out, level +1); fprintf(out, "Error: INVALID RSA KEY!\n");
+ }
}
static void
@@ -1355,7 +1492,7 @@ secu_PrintECPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
}
#endif /* NSS_ENABLE_ECC */
-static int
+static void
secu_PrintSubjectPublicKeyInfo(FILE *out, PRArenaPool *arena,
CERTSubjectPublicKeyInfo *i, char *msg, int level)
{
@@ -1384,18 +1521,22 @@ secu_PrintSubjectPublicKeyInfo(FILE *out, PRArenaPool *arena,
case dhKey:
case fortezzaKey:
case keaKey:
+ SECU_Indent(out, level);
fprintf(out, "unable to format this SPKI algorithm type\n");
- break;
+ goto loser;
default:
+ SECU_Indent(out, level);
fprintf(out, "unknown SPKI algorithm type\n");
- break;
+ goto loser;
}
PORT_FreeArena(pk->arena, PR_FALSE);
} else {
- SECU_PrintError("Error", "Parsing public key");
+ SECU_PrintErrMsg(out, level, "Error", "Parsing public key");
+loser:
+ if (i->subjectPublicKey.data) {
+ SECU_PrintAny(out, &i->subjectPublicKey, "Raw", level);
+ }
}
-
- return 0;
}
static SECStatus
@@ -1425,13 +1566,11 @@ secu_PrintX509InvalidDate(FILE *out, SECItem *value, char *msg, int level)
}
static SECStatus
-PrintExtKeyUsageExten (FILE *out, SECItem *value, char *msg, int level)
+PrintExtKeyUsageExtension (FILE *out, SECItem *value, char *msg, int level)
{
CERTOidSequence *os;
SECItem **op;
- SECU_Indent(out, level); fprintf(out, "Extended Key Usage Extension:\n");
-
os = CERT_DecodeOidSequence(value);
if( (CERTOidSequence *)NULL == os ) {
return SECFailure;
@@ -1444,105 +1583,6 @@ PrintExtKeyUsageExten (FILE *out, SECItem *value, char *msg, int level)
return SECSuccess;
}
-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_PrintPolicyQualifier(FILE *out,CERTPolicyQualifier *policyQualifier,char *msg,int level)
-{
- CERTUserNotice *userNotice;
- SECItem **itemList = NULL;
- char *string;
-
- SECU_PrintObjectID(out, &policyQualifier->qualifierID ,
- "Policy Qualifier Name", level);
-
- switch (policyQualifier->oid) {
- case SEC_OID_PKIX_USER_NOTICE_QUALIFIER:
- userNotice = CERT_DecodeUserNotice(&policyQualifier->qualifierValue);
- if (userNotice) {
- if (userNotice->noticeReference.organization.len != 0) {
- string=itemToString(&userNotice->noticeReference.organization);
- itemList = userNotice->noticeReference.noticeNumbers;
- while (*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);
- }
- break;
- }
- /* fall through on error */
- case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
- default:
- secu_PrintAny(out, &policyQualifier->qualifierValue,
- "Policy Qualifier Data", level+1);
- 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 != NULL) {
- secu_PrintPolicyQualifier(out,*policyQualifiers,"",level+1);
- policyQualifiers++;
- }
- return SECSuccess;
-
-}
-
-static SECStatus
-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 = CERT_DecodeCertificatePoliciesExtension(value);
- if (policies == NULL) {
- SECU_PrintAsHex(out, value, "Invalid Policy Data", level);
- return SECFailure;
- }
-
- policyInfos = policies->policyInfos;
- while (*policyInfos != NULL) {
- secu_PrintPolicyInfo(out,*policyInfos,"",level);
- policyInfos++;
- }
-
- CERT_DestroyCertificatePoliciesExtension(policies);
- return SECSuccess;
-}
-
-char *nsTypeBits[] = {
-"SSL Client","SSL Server","S/MIME","Object Signing","Reserved","SSL CA","S/MIME CA","ObjectSigning CA" };
-
static SECStatus
secu_PrintBasicConstraints(FILE *out, SECItem *value, char *msg, int level) {
CERTBasicConstraints constraints;
@@ -1554,14 +1594,29 @@ secu_PrintBasicConstraints(FILE *out, SECItem *value, char *msg, int level) {
}
rv = CERT_DecodeBasicConstraintValue(&constraints,value);
if (rv == SECSuccess && constraints.isCA) {
- fprintf(out,"Is a CA with a maximum path length of %d.\n",
- constraints.pathLenConstraint);
+ if (constraints.pathLenConstraint >= 0) {
+ fprintf(out,"Is a CA with a maximum path length of %d.\n",
+ constraints.pathLenConstraint);
+ } else {
+ fprintf(out,"Is a CA with no maximum path length.\n");
+ }
} else {
fprintf(out,"Is not a CA.\n");
}
return SECSuccess;
}
+static const char * const nsTypeBits[] = {
+ "SSL Client",
+ "SSL Server",
+ "S/MIME",
+ "Object Signing",
+ "Reserved",
+ "SSL CA",
+ "S/MIME CA",
+ "ObjectSigning CA"
+};
+
/* NSCertType is merely a bit string whose bits are displayed symbolically */
static SECStatus
secu_PrintNSCertType(FILE *out, SECItem *value, char *msg, int level)
@@ -1574,7 +1629,7 @@ secu_PrintNSCertType(FILE *out, SECItem *value, char *msg, int level)
if ((my.data[0] != SEC_ASN1_BIT_STRING) ||
SECSuccess != SECU_StripTagAndLength(&my)) {
- secu_PrintAny(out, value, "Data", level);
+ SECU_PrintAny(out, value, "Data", level);
return SECSuccess;
}
@@ -1598,6 +1653,321 @@ secu_PrintNSCertType(FILE *out, SECItem *value, char *msg, int level)
return SECSuccess;
}
+static const char * const usageBits[] = {
+ "Digital Signature", /* 0x80 */
+ "Non-Repudiation", /* 0x40 */
+ "Key Encipherment", /* 0x20 */
+ "Data Encipherment", /* 0x10 */
+ "Key Agreement", /* 0x08 */
+ "Certificate Signing", /* 0x04 */
+ "CRL Signing", /* 0x02 */
+ "Encipher Only", /* 0x01 */
+ "Decipher Only", /* 0x0080 */
+ NULL
+};
+
+/* X509KeyUsage is merely a bit string whose bits are displayed symbolically */
+static void
+secu_PrintX509KeyUsage(FILE *out, SECItem *value, char *msg, int level)
+{
+ int unused;
+ int usage;
+ int i;
+ int found = 0;
+ SECItem my = *value;
+
+ if ((my.data[0] != SEC_ASN1_BIT_STRING) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ SECU_PrintAny(out, value, "Data", level);
+ return;
+ }
+
+ unused = (my.len >= 2) ? (my.data[0] & 0x0f) : 0;
+ usage = (my.len == 2) ? (my.data[1] & (0xff << unused)) << 8
+ : (my.data[1] << 8) |
+ (my.data[2] & (0xff << unused));
+
+ SECU_Indent(out, level);
+ fprintf(out, "Usages: ");
+ for (i=0; usageBits[i]; i++) {
+ if ( (0x8000 >> i) & usage) {
+ if (found)
+ SECU_Indent(out, level + 2);
+ fprintf(out, "%s\n", usageBits[i]);
+ found = 1;
+ }
+ }
+ if (!found) {
+ fprintf(out, "(none)\n");
+ }
+}
+
+static void
+secu_PrintIPAddress(FILE *out, SECItem *value, char *msg, int level)
+{
+ PRStatus st;
+ PRNetAddr addr;
+ char addrBuf[80];
+
+ memset(&addr, 0, sizeof addr);
+ if (value->len == 4) {
+ addr.inet.family = PR_AF_INET;
+ memcpy(&addr.inet.ip, value->data, value->len);
+ } else if (value->len == 16) {
+ addr.ipv6.family = PR_AF_INET6;
+ memcpy(addr.ipv6.ip.pr_s6_addr, value->data, value->len);
+ if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped)) {
+ /* convert to IPv4. */
+ addr.inet.family = PR_AF_INET;
+ memcpy(&addr.inet.ip, &addr.ipv6.ip.pr_s6_addr[12], 4);
+ memset(&addr.inet.pad[0], 0, sizeof addr.inet.pad);
+ }
+ } else {
+ goto loser;
+ }
+
+ st = PR_NetAddrToString(&addr, addrBuf, sizeof addrBuf);
+ if (st == PR_SUCCESS) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s: %s\n", msg, addrBuf);
+ } else {
+loser:
+ SECU_PrintAsHex(out, value, msg, level);
+ }
+}
+
+
+static void
+secu_PrintGeneralName(FILE *out, CERTGeneralName *gname, char *msg, int level)
+{
+ char label[40];
+ if (msg && msg[0]) {
+ SECU_Indent(out, level++); fprintf(out, "%s: \n", msg);
+ }
+ switch (gname->type) {
+ case certOtherName :
+ SECU_PrintAny( out, &gname->name.OthName.name, "Other Name", level);
+ SECU_PrintObjectID(out, &gname->name.OthName.oid, "OID", level+1);
+ break;
+ case certDirectoryName :
+ SECU_PrintName(out, &gname->name.directoryName, "Directory Name", level);
+ break;
+ case certRFC822Name :
+ secu_PrintRawString( out, &gname->name.other, "RFC822 Name", level);
+ break;
+ case certDNSName :
+ secu_PrintRawString( out, &gname->name.other, "DNS name", level);
+ break;
+ case certURI :
+ secu_PrintRawString( out, &gname->name.other, "URI", level);
+ break;
+ case certIPAddress :
+ secu_PrintIPAddress(out, &gname->name.other, "IP Address", level);
+ break;
+ case certRegisterID :
+ SECU_PrintObjectID( out, &gname->name.other, "Registered ID", level);
+ break;
+ case certX400Address :
+ SECU_PrintAny( out, &gname->name.other, "X400 Address", level);
+ break;
+ case certEDIPartyName :
+ SECU_PrintAny( out, &gname->name.other, "EDI Party", level);
+ break;
+ default:
+ PR_snprintf(label, sizeof label, "unknown type [%d]",
+ (int)gname->type - 1);
+ SECU_PrintAsHex(out, &gname->name.other, label, level);
+ break;
+ }
+}
+
+static void
+secu_PrintAuthKeyIDExtension(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTAuthKeyID *kid = NULL;
+ PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ kid = CERT_DecodeAuthKeyID(pool, value);
+ if (!kid) {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Data", level);
+ } else {
+ int keyIDPresent = (kid->keyID.data && kid->keyID.len);
+ int issuerPresent = kid->authCertIssuer != NULL;
+ int snPresent = (kid->authCertSerialNumber.data &&
+ kid->authCertSerialNumber.len);
+
+ if ((keyIDPresent && !issuerPresent && !snPresent) ||
+ (!keyIDPresent && issuerPresent && snPresent)) {
+ /* all is well */
+ } else {
+ SECU_Indent(out, level);
+ fprintf(out,
+ "Error: KeyID OR (Issuer AND Serial) must be present, not both.\n");
+ }
+ if (keyIDPresent)
+ SECU_PrintAsHex(out, &kid->keyID, "Key ID", level);
+ if (issuerPresent)
+ secu_PrintGeneralName(out, kid->authCertIssuer, "Issuer", level);
+ if (snPresent)
+ SECU_PrintInteger(out, &kid->authCertSerialNumber,
+ "Serial Number", level);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+
+static void
+secu_PrintAltNameExtension(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTGeneralName * nameList;
+ CERTGeneralName * current;
+ PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ nameList = current = CERT_DecodeAltNameExtension(pool, value);
+ if (!current) {
+ if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) {
+ /* Decoder found empty sequence, which is invalid. */
+ PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
+ }
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Data", level);
+ } else {
+ do {
+ secu_PrintGeneralName(out, current, msg, level);
+ current = CERT_GetNextGeneralName(current);
+ } while (current != nameList);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+static void
+secu_PrintCRLDistPtsExtension(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTCrlDistributionPoints * dPoints;
+ PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ dPoints = CERT_DecodeCRLDistributionPoints(pool, value);
+ if (dPoints && dPoints->distPoints && dPoints->distPoints[0]) {
+ CRLDistributionPoint ** pPoints = dPoints->distPoints;
+ CRLDistributionPoint * pPoint;
+ while (NULL != (pPoint = *pPoints++)) {
+ if (pPoint->distPointType == generalName &&
+ pPoint->distPoint.fullName != NULL) {
+ secu_PrintGeneralName(out, pPoint->distPoint.fullName, NULL,
+ level);
+#if defined(LATER)
+ } else if (pPoint->distPointType == relativeDistinguishedName) {
+ /* print the relative name */
+#endif
+ } else if (pPoint->derDistPoint.data) {
+ SECU_PrintAny(out, &pPoint->derDistPoint, "Point", level);
+ }
+ if (pPoint->reasons.data) {
+ secu_PrintDecodedBitString(out, &pPoint->reasons, "Reasons",
+ level);
+ }
+ if (pPoint->crlIssuer) {
+ secu_PrintGeneralName(out, pPoint->crlIssuer, "Issuer", level);
+ }
+ }
+ } else {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Data", level);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+
+static void
+secu_PrintNameConstraintSubtree(FILE *out, CERTNameConstraint *value,
+ char *msg, int level)
+{
+ CERTNameConstraint *head = value;
+ SECU_Indent(out, level); fprintf(out, "%s Subtree:\n", msg);
+ level++;
+ do {
+ secu_PrintGeneralName(out, &value->name, NULL, level);
+ if (value->min.data)
+ SECU_PrintInteger(out, &value->min, "Minimum", level+1);
+ if (value->max.data)
+ SECU_PrintInteger(out, &value->max, "Maximum", level+1);
+ value = CERT_GetNextNameConstraint(value);
+ } while (value != head);
+}
+
+static void
+secu_PrintNameConstraintsExtension(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTNameConstraints * cnstrnts;
+ PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ cnstrnts = CERT_DecodeNameConstraintsExtension(pool, value);
+ if (!cnstrnts) {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Raw", level);
+ } else {
+ if (cnstrnts->permited)
+ secu_PrintNameConstraintSubtree(out, cnstrnts->permited,
+ "Permitted", level);
+ if (cnstrnts->excluded)
+ secu_PrintNameConstraintSubtree(out, cnstrnts->excluded,
+ "Excluded", level);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+
+static void
+secu_PrintAuthorityInfoAcess(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTAuthInfoAccess **infos = NULL;
+ PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ infos = CERT_DecodeAuthInfoAccessExtension(pool, value);
+ if (!infos) {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Raw", level);
+ } else {
+ CERTAuthInfoAccess *info;
+ while (NULL != (info = *infos++)) {
+ if (info->method.data) {
+ SECU_PrintObjectID(out, &info->method, "Method", level);
+ } else {
+ SECU_Indent(out,level);
+ fprintf(out, "Error: missing method\n");
+ }
+ if (info->location) {
+ secu_PrintGeneralName(out, info->location, "Location", level);
+ } else {
+ SECU_PrintAny(out, &info->derLocation, "Location", level);
+ }
+ }
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+
void
SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
char *msg, int level)
@@ -1627,7 +1997,7 @@ SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
secu_PrintX509InvalidDate(out, tmpitem, "Date", level + 1);
break;
case SEC_OID_X509_CERTIFICATE_POLICIES:
- secu_PrintPolicy(out, tmpitem, "Data", level +1);
+ SECU_PrintPolicy(out, tmpitem, "Data", level +1);
break;
case SEC_OID_NS_CERT_EXT_BASE_URL:
case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
@@ -1653,12 +2023,33 @@ SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
case SEC_OID_X509_BASIC_CONSTRAINTS:
secu_PrintBasicConstraints(out,tmpitem,"Data",level+1);
break;
-
case SEC_OID_X509_EXT_KEY_USAGE:
- PrintExtKeyUsageExten(out, tmpitem, NULL, level+1);
+ PrintExtKeyUsageExtension(out, tmpitem, NULL, level+1);
+ break;
+ case SEC_OID_X509_KEY_USAGE:
+ secu_PrintX509KeyUsage(out, tmpitem, NULL, level + 1);
+ break;
+ case SEC_OID_X509_AUTH_KEY_ID:
+ secu_PrintAuthKeyIDExtension(out, tmpitem, NULL, level + 1);
+ break;
+ case SEC_OID_X509_SUBJECT_ALT_NAME:
+ case SEC_OID_X509_ISSUER_ALT_NAME:
+ secu_PrintAltNameExtension(out, tmpitem, NULL, level + 1);
+ break;
+ case SEC_OID_X509_CRL_DIST_POINTS:
+ secu_PrintCRLDistPtsExtension(out, tmpitem, NULL, level + 1);
+ break;
+ case SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD:
+ SECU_PrintPrivKeyUsagePeriodExtension(out, tmpitem, NULL,
+ level +1);
+ break;
+ case SEC_OID_X509_NAME_CONSTRAINTS:
+ secu_PrintNameConstraintsExtension(out, tmpitem, NULL, level+1);
break;
-
case SEC_OID_X509_AUTH_INFO_ACCESS:
+ secu_PrintAuthorityInfoAcess(out, tmpitem, NULL, level+1);
+ break;
+
case SEC_OID_X509_CRL_NUMBER:
case SEC_OID_X509_REASON_CODE:
@@ -1679,38 +2070,23 @@ SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
case SEC_OID_PKIX_REGINFO_UTF8_PAIRS:
case SEC_OID_PKIX_REGINFO_CERT_REQUEST:
- case SEC_OID_EXT_KEY_USAGE_SERVER_AUTH:
- case SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH:
- case SEC_OID_EXT_KEY_USAGE_CODE_SIGN:
- case SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT:
- case SEC_OID_EXT_KEY_USAGE_TIME_STAMP:
- case SEC_OID_X509_SUBJECT_ALT_NAME:
- case SEC_OID_X509_ISSUER_ALT_NAME:
- /*
- * We should add at least some of the more interesting cases
- * here, but need to have subroutines to back them up.
- */
+
+ /* Netscape extension OIDs. */
case SEC_OID_NS_CERT_EXT_NETSCAPE_OK:
case SEC_OID_NS_CERT_EXT_ISSUER_LOGO:
case SEC_OID_NS_CERT_EXT_SUBJECT_LOGO:
case SEC_OID_NS_CERT_EXT_ENTITY_LOGO:
case SEC_OID_NS_CERT_EXT_USER_PICTURE:
- case SEC_OID_NS_KEY_USAGE_GOVT_APPROVED:
/* x.509 v3 Extensions */
case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
case SEC_OID_X509_SUBJECT_KEY_ID:
- case SEC_OID_X509_KEY_USAGE:
- case SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD:
- case SEC_OID_X509_NAME_CONSTRAINTS:
- case SEC_OID_X509_CRL_DIST_POINTS:
case SEC_OID_X509_POLICY_MAPPINGS:
case SEC_OID_X509_POLICY_CONSTRAINTS:
- case SEC_OID_X509_AUTH_KEY_ID:
default:
- secu_PrintAny(out, tmpitem, "Data", level+1);
+ SECU_PrintAny(out, tmpitem, "Data", level+1);
break;
}
@@ -1729,8 +2105,9 @@ SECU_PrintName(FILE *out, CERTName *name, char *msg, int level)
SECItem my;
str = nameStr = CERT_NameToAscii(name);
- if (!str)
+ if (!str) {
str = "!Invalid AVA!";
+ }
my.data = (unsigned char *)str;
my.len = PORT_Strlen(str);
#if 1
@@ -1835,13 +2212,11 @@ SECU_PrintCertificateRequest(FILE *out, SECItem *der, char *m, int level)
SECU_Indent(out, level); fprintf(out, "%s:\n", m);
SECU_PrintInteger(out, &cr->version, "Version", level+1);
SECU_PrintName(out, &cr->subject, "Subject", level+1);
- rv = secu_PrintSubjectPublicKeyInfo(out, arena, &cr->subjectPublicKeyInfo,
+ secu_PrintSubjectPublicKeyInfo(out, arena, &cr->subjectPublicKeyInfo,
"Subject Public Key Info", level+1);
- if (rv)
- goto loser;
if (cr->attributes)
- secu_PrintAny(out, cr->attributes[0], "Attributes", level+1);
-
+ SECU_PrintAny(out, cr->attributes[0], "Attributes", level+1);
+ rv = 0;
loser:
PORT_FreeArena(arena, PR_FALSE);
return rv;
@@ -1865,9 +2240,12 @@ SECU_PrintCertificate(FILE *out, SECItem *der, char *m, int level)
c->arena = arena;
rv = SEC_ASN1DecodeItem(arena, c,
SEC_ASN1_GET(CERT_CertificateTemplate), der);
- if (rv)
+ if (rv) {
+ SECU_Indent(out, level);
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, der, "Raw", level);
goto loser;
-
+ }
/* Pretty print it out */
SECU_Indent(out, level); fprintf(out, "%s:\n", m);
iv = c->version.len ? DER_GetInteger(&c->version) : 0; /* version is optional */
@@ -1878,10 +2256,12 @@ SECU_PrintCertificate(FILE *out, SECItem *der, char *m, int level)
SECU_PrintName(out, &c->issuer, "Issuer", level+1);
secu_PrintValidity(out, &c->validity, "Validity", level+1);
SECU_PrintName(out, &c->subject, "Subject", level+1);
- rv = secu_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo,
+ secu_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo,
"Subject Public Key Info", level+1);
- if (rv)
- goto loser;
+ if (c->issuerID.data)
+ secu_PrintDecodedBitString(out, &c->issuerID, "Issuer Unique ID", level+1);
+ if (c->subjectID.data)
+ secu_PrintDecodedBitString(out, &c->subjectID, "Subject Unique ID", level+1);
SECU_PrintExtensions(out, c->extensions, "Signed Extensions", level+1);
loser:
PORT_FreeArena(arena, PR_FALSE);
@@ -2775,7 +3155,7 @@ SECU_PrintPRandOSError(char *progName)
if (errLen > 0 && errLen < sizeof buffer) {
PR_GetErrorText(buffer);
}
- SECU_PrintError(progName, "NSS_Initialize failed");
+ SECU_PrintError(progName, "function failed");
if (errLen > 0 && errLen < sizeof buffer) {
PR_fprintf(PR_STDERR, "\t%s\n", buffer);
}
diff --git a/security/nss/cmd/lib/secutil.h b/security/nss/cmd/lib/secutil.h
index 2cc7f289e..de7876f1b 100644
--- a/security/nss/cmd/lib/secutil.h
+++ b/security/nss/cmd/lib/secutil.h
@@ -266,6 +266,13 @@ extern int SECU_PrintCrl(FILE *out, SECItem *der, char *m, int level);
extern void
SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m, int level);
+extern void SECU_PrintString(FILE *out, SECItem *si, char *m, int level);
+extern void SECU_PrintAny(FILE *out, SECItem *i, char *m, int level);
+
+extern void SECU_PrintPolicy(FILE *out, SECItem *value, char *msg, int level);
+extern void SECU_PrintPrivKeyUsagePeriodExtension(FILE *out, SECItem *value,
+ char *msg, int level);
+
extern void SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
char *msg, int level);
@@ -287,6 +294,8 @@ extern char *SECU_SECModDBName(void);
extern void SECU_PrintPRandOSError(char *progName);
+extern SECStatus SECU_RegisterDynamicOids(void);
+
/*
*
* Utilities for parsing security tools command lines