363476(vfyserv needs OCSP option) and 363477(vfyserv needs option to save server certs to local files. sr=kengert, r=neil.williams

This commit is contained in:
alexei.volkov.bugs%sun.com 2007-02-14 00:39:34 +00:00
parent d492a46e5d
commit 911502366b
2 changed files with 143 additions and 7 deletions

View File

@ -68,6 +68,7 @@
#include "prnetdb.h"
#include "nss.h"
#include "secutil.h"
#include "ocsp.h"
#include "vfyserv.h"
@ -81,14 +82,48 @@ char *certNickname = NULL;
char *hostName = NULL;
char *password = NULL;
unsigned short port = 0;
PRBool dumpChain;
static void
Usage(const char *progName)
{
fprintf(stderr,
"Usage: %s [-p port] [-c connections] [-d dbdir] [-w password]\n"
"\t\t[-C cipher(s)] hostname\n",
progName);
PRFileDesc *pr_stderr;
pr_stderr = PR_STDERR;
PR_fprintf(pr_stderr, "Usage:\n"
" %s [-c ] [-o] [-p port] [-d dbdir] [-w password]\n"
" \t\t[-C cipher(s)] [-l <url> -t <nickname> ] hostname",
progName);
PR_fprintf (pr_stderr, "\nWhere:\n");
PR_fprintf (pr_stderr,
" %-13s dump server cert chain into files\n",
"-c");
PR_fprintf (pr_stderr,
" %-13s perform server cert OCSP check\n",
"-o");
PR_fprintf (pr_stderr,
" %-13s server port to be used\n",
"-p");
PR_fprintf (pr_stderr,
" %-13s use security databases in \"dbdir\"\n",
"-d dbdir");
PR_fprintf (pr_stderr,
" %-13s key database password\n",
"-w password");
PR_fprintf (pr_stderr,
" %-13s communication cipher list\n",
"-C cipher(s)");
PR_fprintf (pr_stderr,
" %-13s OCSP responder location. This location is used to\n"
" %-13s check status of a server certificate. If not \n"
" %-13s specified, location will be taken from the AIA\n"
" %-13s server certificate extension.\n",
"-l url", "", "", "");
PR_fprintf (pr_stderr,
" %-13s OCSP Trusted Responder Cert nickname\n\n",
"-t nickname");
exit(1);
}
@ -388,9 +423,12 @@ main(int argc, char **argv)
char * progName = NULL;
int connections = 1;
char * cipherString = NULL;
char * respUrl = NULL;
char * respCertName = NULL;
SECStatus secStatus;
PLOptState * optstate;
PLOptStatus status;
PRBool doOcspCheck = PR_FALSE;
/* Call the NSPR initialization routines */
PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
@ -398,14 +436,17 @@ main(int argc, char **argv)
progName = PORT_Strdup(argv[0]);
hostName = NULL;
optstate = PL_CreateOptState(argc, argv, "C:c:d:n:p:w:");
optstate = PL_CreateOptState(argc, argv, "C:cd:l:n:p:ot:w:");
while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
switch(optstate->option) {
case 'C' : cipherString = PL_strdup(optstate->value); break;
case 'c' : connections = PORT_Atoi(optstate->value); break;
case 'c' : dumpChain = PR_TRUE; break;
case 'd' : certDir = PL_strdup(optstate->value); break;
case 'l' : respUrl = PL_strdup(optstate->value); break;
case 'p' : port = PORT_Atoi(optstate->value); break;
case 'w' : password = PL_strdup(optstate->value); break;
case 'o' : doOcspCheck = PR_TRUE; break;
case 't' : respCertName = PL_strdup(optstate->value); break;
case 'w' : password = PL_strdup(optstate->value); break;
case '\0': hostName = PL_strdup(optstate->value); break;
default : Usage(progName);
}
@ -418,6 +459,14 @@ main(int argc, char **argv)
if (port == 0 || hostName == NULL)
Usage(progName);
if (doOcspCheck &&
((respCertName != NULL && respUrl == NULL) ||
(respUrl != NULL && respCertName == NULL))) {
SECU_PrintError (progName, "options -l <url> and -t "
"<responder> must be used together");
Usage(progName);
}
/* Set our password function callback. */
PK11_SetPasswordFunc(myPasswd);
@ -436,6 +485,38 @@ main(int argc, char **argv)
}
SECU_RegisterDynamicOids();
if (doOcspCheck == PR_TRUE) {
SECStatus rv;
CERTCertDBHandle *handle = CERT_GetDefaultCertDB();
if (handle == NULL) {
SECU_PrintError (progName, "problem getting certdb handle");
goto cleanup;
}
rv = CERT_EnableOCSPChecking (handle);
if (rv != SECSuccess) {
SECU_PrintError (progName, "error enabling OCSP checking");
goto cleanup;
}
if (respUrl != NULL) {
rv = CERT_SetOCSPDefaultResponder (handle, respUrl,
respCertName);
if (rv != SECSuccess) {
SECU_PrintError (progName,
"error setting default responder");
goto cleanup;
}
rv = CERT_EnableOCSPDefaultResponder (handle);
if (rv != SECSuccess) {
SECU_PrintError (progName,
"error enabling default responder");
goto cleanup;
}
}
}
/* All cipher suites except RSA_NULL_MD5 are enabled by
* Domestic Policy. */
NSS_SetDomesticPolicy();
@ -485,6 +566,13 @@ main(int argc, char **argv)
client_main(port, connections, hostName);
cleanup:
if (doOcspCheck) {
CERTCertDBHandle *handle = CERT_GetDefaultCertDB();
CERT_DisableOCSPDefaultResponder(handle);
CERT_DisableOCSPChecking (handle);
}
if (NSS_Shutdown() != SECSuccess) {
exit(1);
}

View File

@ -40,6 +40,10 @@
#include "nspr.h"
#include "secutil.h"
extern PRBool dumpChain;
extern void dumpCertChain(CERTCertificate *, SECCertUsage);
/* Declare SSL cipher suites. */
int ssl2CipherSuites[] = {
@ -136,6 +140,10 @@ myAuthCertificate(void *arg, PRFileDesc *socket,
cert = SSL_PeerCertificate(socket);
pinArg = SSL_RevealPinArg(socket);
if (dumpChain == PR_TRUE) {
dumpCertChain(cert, certUsage);
}
secStatus = CERT_VerifyCertificateNow((CERTCertDBHandle *)arg,
cert,
@ -616,3 +624,43 @@ lockedVars_AddToCount(lockedVars * lv, int addend)
return rv;
}
/*
* Dump cert chain in to cert.* files. This function is will
* create collisions while dumping cert chains if called from
* multiple treads. But it should not be a problem since we
* consider vfyserv to be single threaded(see bug 353477).
*/
void
dumpCertChain(CERTCertificate *cert, SECCertUsage usage)
{
CERTCertificateList *certList;
int count = 0;
certList = CERT_CertChainFromCert(cert, usage, PR_TRUE);
if (certList == NULL) {
errWarn("CERT_CertChainFromCert");
return;
}
for(count = 0; count < (unsigned int)certList->len; count++) {
char certFileName[16];
PRFileDesc *cfd;
PR_snprintf(certFileName, sizeof certFileName, "cert.%03d",
count);
cfd = PR_Open(certFileName, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE,
0664);
if (!cfd) {
PR_fprintf(PR_STDOUT,
"Error: couldn't save cert der in file '%s'\n",
certFileName);
} else {
PR_Write(cfd, certList->certs[count].data, certList->certs[count].len);
PR_Close(cfd);
PR_fprintf(PR_STDOUT, "Cert file %s was created.\n", certFileName);
}
}
CERT_DestroyCertificateList(certList);
}