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
This commit is contained in:
nelsonb%netscape.com 2004-01-29 22:45:20 +00:00
Родитель 449a23e66c
Коммит 792e8d1e9e
5 изменённых файлов: 1030 добавлений и 167 удалений

Просмотреть файл

@ -45,6 +45,8 @@ EXPORTS = secutil.h \
CSRCS = secutil.c \
secpwd.c \
derprint.c \
moreoids.c \
pppolicy.c \
secerror.c \
ffs.c \
$(NULL)

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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: pppolicy.c,v 1.1 2004/01/29 22:45:20 nelsonb%netscape.com Exp $
*/
#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);
}
}

Просмотреть файл

@ -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)
@ -94,6 +97,26 @@ SECU_GetString(int16 error_number)
return errString;
}
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, ...)
{
@ -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)
@ -1149,6 +1217,75 @@ SECU_PrintEncodedObjectID(FILE *out, SECItem *i, char *m, int level)
SECU_PrintObjectID(out, &my, m, 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)
{
@ -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_AUTH_INFO_ACCESS:
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);
}

Просмотреть файл

@ -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