Fix for bug 55898 - print name of certificate causing failure in certutil . r=wtc

This commit is contained in:
jpierre%netscape.com 2003-10-08 01:00:37 +00:00
Родитель 4c74d691bd
Коммит 7f696b676c
5 изменённых файлов: 134 добавлений и 230 удалений

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

@ -2646,3 +2646,116 @@ SECU_PrintPRandOSError(char *progName)
PR_fprintf(PR_STDERR, "\t%s\n", buffer);
}
}
static char *
bestCertName(CERTCertificate *cert) {
if (cert->nickname) {
return cert->nickname;
}
if (cert->emailAddr) {
return cert->emailAddr;
}
return cert->subjectName;
}
void
SECU_printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
CERTCertificate *cert, PRBool checksig,
SECCertificateUsage certUsage, void *pinArg, PRBool verbose)
{
CERTVerifyLog log;
CERTVerifyLogNode *node = NULL;
unsigned int depth = (unsigned int)-1;
unsigned int flags = 0;
char * errstr = NULL;
PRErrorCode err = PORT_GetError();
log.arena = PORT_NewArena(512);
log.head = log.tail = NULL;
log.count = 0;
CERT_VerifyCertificate(handle, cert, checksig, certUsage, PR_Now(), pinArg, &log, NULL);
if (log.count > 0) {
fprintf(outfile,"PROBLEM WITH THE CERT CHAIN:\n");
for (node = log.head; node; node = node->next) {
if (depth != node->depth) {
depth = node->depth;
fprintf(outfile,"CERT %d. %s %s:\n", depth,
bestCertName(node->cert),
depth ? "[Certificate Authority]": "");
if (verbose) {
const char * emailAddr;
emailAddr = CERT_GetFirstEmailAddress(node->cert);
if (emailAddr) {
fprintf(outfile,"Email Address(es): ");
do {
fprintf(outfile, "%s\n", emailAddr);
emailAddr = CERT_GetNextEmailAddress(node->cert,
emailAddr);
} while (emailAddr);
}
}
}
fprintf(outfile," ERROR %d: %s\n", node->error,
SECU_Strerror(node->error));
errstr = NULL;
switch (node->error) {
case SEC_ERROR_INADEQUATE_KEY_USAGE:
flags = (unsigned int)node->arg;
switch (flags) {
case KU_DIGITAL_SIGNATURE:
errstr = "Cert cannot sign.";
break;
case KU_KEY_ENCIPHERMENT:
errstr = "Cert cannot encrypt.";
break;
case KU_KEY_CERT_SIGN:
errstr = "Cert cannot sign other certs.";
break;
default:
errstr = "[unknown usage].";
break;
}
case SEC_ERROR_INADEQUATE_CERT_TYPE:
flags = (unsigned int)node->arg;
switch (flags) {
case NS_CERT_TYPE_SSL_CLIENT:
case NS_CERT_TYPE_SSL_SERVER:
errstr = "Cert cannot be used for SSL.";
break;
case NS_CERT_TYPE_SSL_CA:
errstr = "Cert cannot be used as an SSL CA.";
break;
case NS_CERT_TYPE_EMAIL:
errstr = "Cert cannot be used for SMIME.";
break;
case NS_CERT_TYPE_EMAIL_CA:
errstr = "Cert cannot be used as an SMIME CA.";
break;
case NS_CERT_TYPE_OBJECT_SIGNING:
errstr = "Cert cannot be used for object signing.";
break;
case NS_CERT_TYPE_OBJECT_SIGNING_CA:
errstr = "Cert cannot be used as an object signing CA.";
break;
default:
errstr = "[unknown usage].";
break;
}
case SEC_ERROR_UNKNOWN_ISSUER:
case SEC_ERROR_UNTRUSTED_ISSUER:
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
errstr = node->cert->issuerName;
break;
default:
break;
}
if (errstr) {
fprintf(stderr," %s\n",errstr);
}
CERT_DestroyCertificate(node->cert);
}
}
PORT_SetError(err); /* restore original error code */
}

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

@ -161,6 +161,12 @@ extern void SECU_PrintSystemError(char *progName, char *msg, ...);
/* Return informative error string */
extern const char * SECU_Strerror(PRErrorCode errNum);
/* print information about cert verification failure */
extern void
SECU_printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
CERTCertificate *cert, PRBool checksig,
SECCertificateUsage certUsage, void *pinArg, PRBool verbose);
/* Read the contents of a file into a SECItem */
extern SECStatus SECU_FileToItem(SECItem *dst, PRFileDesc *src);
extern SECStatus SECU_TextFileToItem(SECItem *dst, PRFileDesc *src);

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

@ -128,119 +128,6 @@ exitErr(char *function)
exit(1);
}
static char *
bestCertName(CERTCertificate *cert) {
if (cert->nickname) {
return cert->nickname;
}
if (cert->emailAddr) {
return cert->emailAddr;
}
return cert->subjectName;
}
void
printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
CERTCertificate *cert, PRBool checksig,
SECCertUsage certUsage, void *pinArg)
{
CERTVerifyLog log;
CERTVerifyLogNode *node = NULL;
unsigned int depth = (unsigned int)-1;
unsigned int flags = 0;
char * errstr = NULL;
PRErrorCode err = PORT_GetError();
log.arena = PORT_NewArena(512);
log.head = log.tail = NULL;
log.count = 0;
CERT_VerifyCert(handle, cert, checksig, certUsage,
PR_Now(), pinArg, &log);
if (log.count > 0) {
fprintf(outfile,"PROBLEM WITH THE CERT CHAIN:\n");
for (node = log.head; node; node = node->next) {
if (depth != node->depth) {
depth = node->depth;
fprintf(outfile,"CERT %d. %s %s:\n", depth,
bestCertName(node->cert),
depth ? "[Certificate Authority]": "");
if (verbose) {
const char * emailAddr;
emailAddr = CERT_GetFirstEmailAddress(node->cert);
if (emailAddr) {
fprintf(outfile,"Email Address(es): ");
do {
fprintf(outfile, "%s\n", emailAddr);
emailAddr = CERT_GetNextEmailAddress(node->cert,
emailAddr);
} while (emailAddr);
}
}
}
fprintf(outfile," ERROR %d: %s\n", node->error,
SECU_Strerror(node->error));
errstr = NULL;
switch (node->error) {
case SEC_ERROR_INADEQUATE_KEY_USAGE:
flags = (unsigned int)node->arg;
switch (flags) {
case KU_DIGITAL_SIGNATURE:
errstr = "Cert cannot sign.";
break;
case KU_KEY_ENCIPHERMENT:
errstr = "Cert cannot encrypt.";
break;
case KU_KEY_CERT_SIGN:
errstr = "Cert cannot sign other certs.";
break;
default:
errstr = "[unknown usage].";
break;
}
case SEC_ERROR_INADEQUATE_CERT_TYPE:
flags = (unsigned int)node->arg;
switch (flags) {
case NS_CERT_TYPE_SSL_CLIENT:
case NS_CERT_TYPE_SSL_SERVER:
errstr = "Cert cannot be used for SSL.";
break;
case NS_CERT_TYPE_SSL_CA:
errstr = "Cert cannot be used as an SSL CA.";
break;
case NS_CERT_TYPE_EMAIL:
errstr = "Cert cannot be used for SMIME.";
break;
case NS_CERT_TYPE_EMAIL_CA:
errstr = "Cert cannot be used as an SMIME CA.";
break;
case NS_CERT_TYPE_OBJECT_SIGNING:
errstr = "Cert cannot be used for object signing.";
break;
case NS_CERT_TYPE_OBJECT_SIGNING_CA:
errstr = "Cert cannot be used as an object signing CA.";
break;
default:
errstr = "[unknown usage].";
break;
}
case SEC_ERROR_UNKNOWN_ISSUER:
case SEC_ERROR_UNTRUSTED_ISSUER:
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
errstr = node->cert->issuerName;
break;
default:
break;
}
if (errstr) {
fprintf(stderr," %s\n",errstr);
}
CERT_DestroyCertificate(node->cert);
}
}
PORT_SetError(err); /* restore original error code */
}
typedef struct certMemStr {
struct certMemStr * next;
CERTCertificate * cert;
@ -349,7 +236,7 @@ main(int argc, char *argv[], char *envp[])
CERTCertDBHandle * defaultDB = NULL;
PRBool isAscii = PR_FALSE;
SECStatus secStatus;
SECCertUsage certUsage = certUsageSSLServer;
SECCertificateUsage certUsage = certificateUsageSSLServer;
PLOptState * optstate;
PLOptStatus status;
@ -364,7 +251,7 @@ main(int argc, char *argv[], char *envp[])
case 'a' : isAscii = PR_TRUE; break;
case 'd' : certDir = PL_strdup(optstate->value); break;
case 'r' : isAscii = PR_FALSE; break;
case 'u' : certUsage = (SECCertUsage)PORT_Atoi(optstate->value); break;
case 'u' : certUsage = ((SECCertificateUsage) 1) << PORT_Atoi(optstate->value); break;
case 'w' : password = PL_strdup(optstate->value); break;
case 'v' : verbose++; break;
default : Usage(progName); break;
@ -412,25 +299,26 @@ breakout:
/* NOW, verify the cert chain. */
defaultDB = CERT_GetDefaultCertDB();
secStatus = CERT_VerifyCert(defaultDB, firstCert,
secStatus = CERT_VerifyCertificate(defaultDB, firstCert,
PR_TRUE /* check sig */,
certUsage,
PR_Now(),
NULL, /* wincx */
NULL); /* error log */
NULL, /* error log */
NULL); /* returned usages */
if (secStatus != SECSuccess) {
PRIntn err = PR_GetError();
fprintf(stderr, "Chain is bad, %d = %s\n", err, SECU_Strerror(err));
printCertProblems(stderr, defaultDB, firstCert,
PR_TRUE, certUsage, NULL);
SECU_printCertProblems(stderr, defaultDB, firstCert,
PR_TRUE, certUsage, NULL, verbose);
} else {
fprintf(stderr, "Chain is good!\n");
}
punt:
forgetCerts();
if (NSS_Shutdown != SECSuccess) {
if (NSS_Shutdown() != SECSuccess) {
exit(1);
}
PR_Cleanup();

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

@ -108,10 +108,6 @@ void exitErr(char *function);
void printSecurityInfo(FILE *outfile, PRFileDesc *fd);
void printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
CERTCertificate *cert, PRBool checksig,
SECCertUsage certUsage, void *pinArg);
/* Some simple thread management routines. */
#define MAX_THREADS 32

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

@ -115,7 +115,7 @@ myAuthCertificate(void *arg, PRFileDesc *socket,
PRBool checksig, PRBool isServer)
{
SECCertUsage certUsage;
SECCertificateUsage certUsage;
CERTCertificate * cert;
void * pinArg;
char * hostName;
@ -128,22 +128,23 @@ myAuthCertificate(void *arg, PRFileDesc *socket,
/* Define how the cert is being used based upon the isServer flag. */
certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;
certUsage = isServer ? certificateUsageSSLClient : certificateUsageSSLServer;
cert = SSL_PeerCertificate(socket);
pinArg = SSL_RevealPinArg(socket);
secStatus = CERT_VerifyCertNow((CERTCertDBHandle *)arg,
secStatus = CERT_VerifyCertificateNow((CERTCertDBHandle *)arg,
cert,
checksig,
certUsage,
pinArg);
pinArg,
NULL);
/* If this is a server, we're finished. */
if (isServer || secStatus != SECSuccess) {
printCertProblems(stderr, (CERTCertDBHandle *)arg, cert,
checksig, certUsage, pinArg);
SECU_printCertProblems(stderr, (CERTCertDBHandle *)arg, cert,
checksig, certUsage, pinArg, PR_FALSE);
CERT_DestroyCertificate(cert);
return secStatus;
}
@ -612,103 +613,3 @@ lockedVars_AddToCount(lockedVars * lv, int addend)
return rv;
}
static char *
bestCertName(CERTCertificate *cert) {
if (cert->nickname) {
return cert->nickname;
}
if (cert->emailAddr) {
return cert->emailAddr;
}
return cert->subjectName;
}
void
printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
CERTCertificate *cert, PRBool checksig,
SECCertUsage certUsage, void *pinArg)
{
CERTVerifyLog log;
CERTVerifyLogNode *node = NULL;
unsigned int depth = (unsigned int)-1;
unsigned int flags = 0;
char * errstr = NULL;
PRErrorCode err = PORT_GetError();
log.arena = PORT_NewArena(512);
log.head = log.tail = NULL;
log.count = 0;
CERT_VerifyCert(handle, cert, checksig, certUsage,
PR_Now(), pinArg, &log);
if (log.count > 0) {
fprintf(outfile,"PROBLEM WITH THE CERT CHAIN:\n");
for (node = log.head; node; node = node->next) {
if (depth != node->depth) {
depth = node->depth;
fprintf(outfile,"CERT %d. %s %s:\n", depth,
bestCertName(node->cert),
depth ? "[Certificate Authority]": "");
}
fprintf(outfile," ERROR %d: %s\n", node->error,
SECU_Strerror(node->error));
errstr = NULL;
switch (node->error) {
case SEC_ERROR_INADEQUATE_KEY_USAGE:
flags = (unsigned int)node->arg;
switch (flags) {
case KU_DIGITAL_SIGNATURE:
errstr = "Cert cannot sign.";
break;
case KU_KEY_ENCIPHERMENT:
errstr = "Cert cannot encrypt.";
break;
case KU_KEY_CERT_SIGN:
errstr = "Cert cannot sign other certs.";
break;
default:
errstr = "[unknown usage].";
break;
}
case SEC_ERROR_INADEQUATE_CERT_TYPE:
flags = (unsigned int)node->arg;
switch (flags) {
case NS_CERT_TYPE_SSL_CLIENT:
case NS_CERT_TYPE_SSL_SERVER:
errstr = "Cert cannot be used for SSL.";
break;
case NS_CERT_TYPE_SSL_CA:
errstr = "Cert cannot be used as an SSL CA.";
break;
case NS_CERT_TYPE_EMAIL:
errstr = "Cert cannot be used for SMIME.";
break;
case NS_CERT_TYPE_EMAIL_CA:
errstr = "Cert cannot be used as an SMIME CA.";
break;
case NS_CERT_TYPE_OBJECT_SIGNING:
errstr = "Cert cannot be used for object signing.";
break;
case NS_CERT_TYPE_OBJECT_SIGNING_CA:
errstr = "Cert cannot be used as an object signing CA.";
break;
default:
errstr = "[unknown usage].";
break;
}
case SEC_ERROR_UNKNOWN_ISSUER:
case SEC_ERROR_UNTRUSTED_ISSUER:
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
errstr = node->cert->issuerName;
break;
default:
break;
}
if (errstr) {
fprintf(stderr," %s\n",errstr);
}
CERT_DestroyCertificate(node->cert);
}
}
PR_SetError(err, 0); /* restore original error code */
}