зеркало из https://github.com/mozilla/gecko-dev.git
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
This commit is contained in:
Родитель
449a23e66c
Коммит
792e8d1e9e
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче