diff options
author | alexei.volkov.bugs%sun.com <devnull@localhost> | 2007-02-14 00:24:18 +0000 |
---|---|---|
committer | alexei.volkov.bugs%sun.com <devnull@localhost> | 2007-02-14 00:24:18 +0000 |
commit | fbfb142433bb6cd99e7b12a02be9a5cadb8d3da4 (patch) | |
tree | 79c6239320ebff315bec0b11bc7feb4c299985f4 | |
parent | 46e2f884561b8096458b4e02a788255138122f5e (diff) | |
download | nss-hg-fbfb142433bb6cd99e7b12a02be9a5cadb8d3da4.tar.gz |
363476(vfyserv needs OCSP option) and 363477(vfyserv needs option to save server certs to local files). sr=kengert, r=neil.williams
-rw-r--r-- | security/nss/cmd/vfyserv/vfyserv.c | 102 | ||||
-rw-r--r-- | security/nss/cmd/vfyserv/vfyutil.c | 48 |
2 files changed, 143 insertions, 7 deletions
diff --git a/security/nss/cmd/vfyserv/vfyserv.c b/security/nss/cmd/vfyserv/vfyserv.c index b55db11c5..f4da4e130 100644 --- a/security/nss/cmd/vfyserv/vfyserv.c +++ b/security/nss/cmd/vfyserv/vfyserv.c @@ -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); } diff --git a/security/nss/cmd/vfyserv/vfyutil.c b/security/nss/cmd/vfyserv/vfyutil.c index 038f0194a..9db64c01f 100644 --- a/security/nss/cmd/vfyserv/vfyutil.c +++ b/security/nss/cmd/vfyserv/vfyutil.c @@ -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); +} |