summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralexei.volkov.bugs%sun.com <devnull@localhost>2007-02-14 00:24:18 +0000
committeralexei.volkov.bugs%sun.com <devnull@localhost>2007-02-14 00:24:18 +0000
commitfbfb142433bb6cd99e7b12a02be9a5cadb8d3da4 (patch)
tree79c6239320ebff315bec0b11bc7feb4c299985f4
parent46e2f884561b8096458b4e02a788255138122f5e (diff)
downloadnss-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.c102
-rw-r--r--security/nss/cmd/vfyserv/vfyutil.c48
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);
+}