Author: rcritten
Update of /cvs/dirsec/mod_nss
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv21038
Modified Files:
mod_nss.c mod_nss.h nss_engine_config.c nss_engine_init.c
Log Message:
Add proxy support to mod_nss. Most of the changes are related to
adding new configuration directives. For the others we need to
initialize an NSS socket differently whether we will be acting as a
client or a server.
Index: mod_nss.c
===================================================================
RCS file: /cvs/dirsec/mod_nss/mod_nss.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- mod_nss.c 6 Sep 2005 14:51:43 -0000 1.7
+++ mod_nss.c 29 Sep 2005 19:35:43 -0000 1.8
@@ -15,6 +15,7 @@
#include "mod_nss.h"
#include <assert.h>
+#include "sslerr.h"
/*
* the table of configuration directives we provide
@@ -101,7 +102,6 @@
SSL_CMD_DIR(Require, AUTHCFG, RAW_ARGS,
"Require a boolean expression to evaluate to true for granting access"
"(arbitrary complex boolean expression - see manual)")
-#ifdef PROXY
/*
* Proxy configuration for remote SSL connections
*/
@@ -114,31 +114,11 @@
SSL_CMD_SRV(ProxyCipherSuite, TAKE1,
"SSL Proxy: colon-delimited list of permitted SSL ciphers "
"(`XXX:...:XXX' - see manual)")
- SSL_CMD_SRV(ProxyVerify, TAKE1,
- "SSL Proxy: whether to verify the remote certificate "
- "(`on' or `off')")
- SSL_CMD_SRV(ProxyVerifyDepth, TAKE1,
- "SSL Proxy: maximum certificate verification depth "
- "(`N' - number of intermediate certificates)")
- SSL_CMD_SRV(ProxyCACertificateFile, TAKE1,
- "SSL Proxy: file containing server certificates "
- "(`/path/to/file' - PEM encoded certificates)")
- SSL_CMD_SRV(ProxyCACertificatePath, TAKE1,
- "SSL Proxy: directory containing server certificates "
- "(`/path/to/dir' - contains PEM encoded certificates)")
- SSL_CMD_SRV(ProxyCARevocationPath, TAKE1,
- "SSL Proxy: CA Certificate Revocation List (CRL) path "
- "(`/path/to/dir' - contains PEM encoded files)")
- SSL_CMD_SRV(ProxyCARevocationFile, TAKE1,
- "SSL Proxy: CA Certificate Revocation List (CRL) file "
- "(`/path/to/file' - PEM encoded)")
- SSL_CMD_SRV(ProxyMachineCertificateFile, TAKE1,
- "SSL Proxy: file containing client certificates "
- "(`/path/to/file' - PEM encoded certificates)")
- SSL_CMD_SRV(ProxyMachineCertificatePath, TAKE1,
- "SSL Proxy: directory containing client certificates "
- "(`/path/to/dir' - contains PEM encoded certificates)")
+ SSL_CMD_SRV(ProxyNickname, TAKE1,
+ "SSL Proxy: client certificate Nickname to be for proxy connections "
+ "(`nickname')")
+#ifdef IGNORE
/* Deprecated directives. */
AP_INIT_RAW_ARGS("NSSLog", ap_set_deprecated, NULL, OR_ALL,
"SSLLog directive is no longer supported - use ErrorLog."),
@@ -183,7 +163,6 @@
return sslconn;
}
-#ifdef PROXY
int nss_proxy_enable(conn_rec *c)
{
SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
@@ -193,7 +172,7 @@
if (!sc->proxy_enabled) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
"SSL Proxy requested for %s but not enabled "
- "[Hint: SSLProxyEngine]", sc->vhost_id);
+ "[Hint: NSSProxyEngine]", sc->vhost_id);
return 0;
}
@@ -203,7 +182,6 @@
return 1;
}
-#endif
int nss_engine_disable(conn_rec *c)
{
@@ -222,6 +200,76 @@
return 1;
}
+/* Callback for an incoming certificate that is not valid */
+
+SECStatus NSSBadCertHandler(void *arg, PRFileDesc * socket)
+{
+ conn_rec *c = (conn_rec *)arg;
+ PRErrorCode err = PR_GetError();
+ SECStatus rv = SECFailure;
+ CERTCertificate *peerCert = SSL_PeerCertificate(socket);
+
+ switch (err) {
+ case SSL_ERROR_BAD_CERT_DOMAIN:
+ if (c->remote_host != NULL) {
+ rv = CERT_VerifyCertName(peerCert, c->remote_host);
+ if (rv != SECSuccess) {
+ char *remote = CERT_GetCommonName(&peerCert->subject);
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+ "SSL Proxy: Possible man-in-the-middle attack. The remove server is %s, we expected %s", remote, c->remote_host, rv);
+ PORT_Free(remote);
+ }
+ } else {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+ "SSL Proxy: I don't have the name of the host we're supposed to connect to so I can't verify that we are connecting to who we think we should be. Giving up. Hint: See Apache bug 36468.");
+ }
+ break;
+ default:
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+ "Bad remote server certificate.", err);
+ nss_log_nss_error(APLOG_MARK, APLOG_ERR, NULL);
+ break;
+ }
+ return rv;
+}
+
+/* Callback to pull the client certificate upon server request */
+
+static SECStatus NSSGetClientAuthData(void *arg, PRFileDesc *socket,
+ CERTDistNames *caNames,
+ CERTCertificate **pRetCert,/*return */
+ SECKEYPrivateKey **pRetKey)
+{
+ CERTCertificate * cert;
+ SECKEYPrivateKey * privKey;
+ void * proto_win = NULL;
+ SECStatus rv = SECFailure;
+ char * localNickName = (char *)arg;
+
+ proto_win = SSL_RevealPinArg(socket);
+
+ if (localNickName) {
+ cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
+ localNickName, certUsageSSLClient,
+ PR_FALSE, proto_win);
+ if (cert) {
+ privKey = PK11_FindKeyByAnyCert(cert, proto_win);
+ if (privKey) {
+ rv = SECSuccess;
+ } else {
+ CERT_DestroyCertificate(cert);
+ }
+ }
+
+ if (rv == SECSuccess) {
+ *pRetCert = cert;
+ *pRetKey = privKey;
+ }
+ }
+
+ return rv;
+}
+
static int nss_hook_pre_connection(conn_rec *c, void *csd)
{
SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
@@ -285,7 +333,28 @@
nss_io_filter_init(c, ssl);
- SSL_ResetHandshake(ssl, PR_TRUE);
+ SSL_ResetHandshake(ssl, mctx->as_server);
+
+ /* If we are doing a client connection, set our own bad certificate
+ * handler and register the nickname we want to use in case client
+ * authentication is requested.
+ */
+ if (!mctx->as_server) {
+ if (SSL_BadCertHook(ssl, (SSLBadCertHandler) NSSBadCertHandler, c) != SECSuccess)
+ {
+ /* errors are reported in the certificate handler */
+ return DECLINED;
+ }
+ if (mctx->nickname) {
+ if (SSL_GetClientAuthDataHook(ssl, NSSGetClientAuthData,
+ (void*)mctx->nickname) != SECSuccess)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
+ "Unable to register client authentication callback");
+ return DECLINED;
+ }
+ }
+ }
return APR_SUCCESS;
}
@@ -335,9 +404,7 @@
nss_var_register();
-#ifdef PROXY
APR_REGISTER_OPTIONAL_FN(nss_proxy_enable);
-#endif
APR_REGISTER_OPTIONAL_FN(nss_engine_disable);
}
Index: mod_nss.h
===================================================================
RCS file: /cvs/dirsec/mod_nss/mod_nss.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- mod_nss.h 6 Sep 2005 14:51:43 -0000 1.6
+++ mod_nss.h 29 Sep 2005 19:35:43 -0000 1.7
@@ -238,6 +238,8 @@
char *cipherSuite;
+ int as_server;
+
int ssl2;
int ssl3;
int tls;
@@ -278,9 +280,7 @@
int nOptionsAdd;
int nOptionsDel;
const char *szCipherSuite;
- nss_verify_t nVerifyClient;
- const char *szCACertificatePath;
- const char *szCACertificateFile;
+ nss_verify_t nVerifyClient;
const char *szUserName;
} SSLDirConfigRec;
@@ -333,6 +333,11 @@
const char *nss_cmd_NSSRequireSSL(cmd_parms *cmd, void *dcfg);
const char *nss_cmd_NSSRequire(cmd_parms *, void *, const char *);
+const char *nss_cmd_NSSProxyEngine(cmd_parms *cmd, void *dcfg, int flag);
+const char *nss_cmd_NSSProxyProtocol(cmd_parms *, void *, const char *);
+const char *nss_cmd_NSSProxyCipherSuite(cmd_parms *, void *, const char *);
+const char *nss_cmd_NSSProxyNickname(cmd_parms *cmd, void *dcfg, const char *arg);
+
/* module initialization */
int nss_init_Module(apr_pool_t *, apr_pool_t *, apr_pool_t *, server_rec *);
void nss_init_Child(apr_pool_t *, server_rec *);
@@ -363,8 +368,11 @@
APR_DECLARE_OPTIONAL_FN(int, nss_is_https, (conn_rec *));
/* Proxy Support */
+int nss_proxy_enable(conn_rec *c);
int nss_engine_disable(conn_rec *c);
+APR_DECLARE_OPTIONAL_FN(int, nss_proxy_enable, (conn_rec *));
+
APR_DECLARE_OPTIONAL_FN(int, nss_engine_disable, (conn_rec *));
/* I/O */
Index: nss_engine_config.c
===================================================================
RCS file: /cvs/dirsec/mod_nss/nss_engine_config.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- nss_engine_config.c 6 Sep 2005 14:51:43 -0000 1.7
+++ nss_engine_config.c 29 Sep 2005 19:35:43 -0000 1.8
@@ -69,6 +69,8 @@
{
mctx->sc = NULL; /* set during module init */
+ mctx->as_server = PR_TRUE;
+
mctx->ssl2 = PR_FALSE;
mctx->ssl3 = PR_FALSE;
mctx->tls = PR_FALSE;
@@ -87,6 +89,18 @@
}
+static void modnss_ctx_init_proxy(SSLSrvConfigRec *sc,
+ apr_pool_t *p)
+{
+ modnss_ctx_t *mctx;
+
+ mctx = sc->proxy = apr_palloc(p, sizeof(*sc->proxy));
+
+ modnss_ctx_init(mctx);
+
+ mctx->as_server = PR_FALSE;
+}
+
static void modnss_ctx_init_server(SSLSrvConfigRec *sc,
apr_pool_t *p)
{
@@ -95,6 +109,8 @@
mctx = sc->server = apr_palloc(p, sizeof(*sc->server));
modnss_ctx_init(mctx);
+
+ mctx->as_server = PR_TRUE;
}
static SSLSrvConfigRec *nss_config_server_new(apr_pool_t *p)
@@ -111,9 +127,7 @@
sc->proxy = NULL;
sc->server = NULL;
-#ifdef PROXY
modnss_ctx_init_proxy(sc, p);
-#endif
modnss_ctx_init_server(sc, p);
@@ -149,6 +163,13 @@
cfgMerge(enforce, PR_TRUE);
}
+static void modnss_ctx_cfg_merge_proxy(modnss_ctx_t *base,
+ modnss_ctx_t *add,
+ modnss_ctx_t *mrg)
+{
+ modnss_ctx_cfg_merge(base, add, mrg);
+}
+
static void modnss_ctx_cfg_merge_server(modnss_ctx_t *base,
modnss_ctx_t *add,
modnss_ctx_t *mrg)
@@ -170,9 +191,7 @@
cfgMergeBool(enabled);
cfgMergeBool(proxy_enabled);
-#ifdef PROXY
modnss_ctx_cfg_merge_proxy(base->proxy, add->proxy, mrg->proxy);
-#endif
modnss_ctx_cfg_merge_server(base->server, add->server, mrg->server);
@@ -270,7 +289,7 @@
const char *nss_cmd_NSSFIPS(cmd_parms *cmd, void *dcfg, int flag)
{
SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
-
+
sc->fips = flag ? TRUE : FALSE;
return NULL;
@@ -281,7 +300,7 @@
SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
sc->ocsp = flag ? TRUE : FALSE;
-
+
return NULL;
}
@@ -395,6 +414,46 @@
return NULL;
}
+const char *nss_cmd_NSSProxyEngine(cmd_parms *cmd, void *dcfg, int flag)
+{
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+
+ sc->proxy_enabled = flag ? TRUE : FALSE;
+
+ return NULL;
+}
+
+const char *nss_cmd_NSSProxyProtocol(cmd_parms *cmd,
+ void *dcfg,
+ const char *arg)
+{
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+
+ sc->proxy->auth.protocols = arg;
+}
+
+const char *nss_cmd_NSSProxyCipherSuite(cmd_parms *cmd,
+ void *dcfg,
+ const char *arg)
+{
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+
+ sc->proxy->auth.cipher_suite = arg;
+
+ return NULL;
+}
+
+const char *nss_cmd_NSSProxyNickname(cmd_parms *cmd,
+ void *dcfg,
+ const char *arg)
+{
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+
+ sc->proxy->nickname = arg;
+
+ return NULL;
+}
+
const char *nss_cmd_NSSEnforceValidCerts(cmd_parms *cmd,
void *dcfg,
int flag)
Index: nss_engine_init.c
===================================================================
RCS file: /cvs/dirsec/mod_nss/nss_engine_init.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- nss_engine_init.c 13 Sep 2005 19:34:39 -0000 1.12
+++ nss_engine_init.c 29 Sep 2005 19:35:43 -0000 1.13
@@ -16,7 +16,9 @@
#include "mod_nss.h"
#include "apr_thread_proc.h"
#include "ap_mpm.h"
-#include <secmod.h>
+#include "secmod.h"
+#include "sslerr.h"
+#include "pk11func.h"
static SECStatus ownBadCertHandler(void *arg, PRFileDesc * socket);
static SECStatus ownHandshakeCallback(PRFileDesc * socket, void *arg);
@@ -111,6 +113,7 @@
SSLModConfigRec *mc = myModConfig(s);
SSLSrvConfigRec *sc;
int forked = 0;
+ char cwd[PATH_MAX];
sc = mySrvConfig(s);
@@ -172,8 +175,14 @@
/* Set the PKCS #11 strings for the internal token. */
PK11_ConfigurePKCS11(NULL,NULL,NULL, INTERNAL_TOKEN_NAME, NULL, NULL,NULL,NULL,8,1);
+ /* We need to be in the same directory as libnssckbi.so to load the
+ * root certificates properly.
+ */
+ getcwd(cwd, PATH_MAX);
+ chdir(mc->pCertificateDatabase);
/* Initialize NSS and open the certificate database read-only. */
rv = NSS_Initialize(mc->pCertificateDatabase, mc->pDBPrefix, mc->pDBPrefix, "secmod.db", NSS_INIT_READONLY);
+ chdir(cwd);
/* Assuming everything is ok so far, check the cert database password(s). */
if (sslenabled && (rv != SECSuccess)) {
@@ -287,11 +296,9 @@
sc->server->sc = sc;
}
-#ifdef PROXY
if (sc->proxy) {
sc->proxy->sc = sc;
}
-#endif
/*
* Create the server host:port string because we need it a lot
@@ -366,8 +373,8 @@
/*
- * Announce mod_ssl and SSL library in HTTP Server field
- * as ``mod_ssl/X.X.X OpenSSL/X.X.X''
+ * Announce mod_nss and SSL library in HTTP Server field
+ * as ``mod_nss/X.X.X NSS/X.X.X''
*/
nss_add_version_components(p, base_server);
@@ -391,20 +398,28 @@
nss_die();
}
- if (SSL_OptionSet(mctx->model, SSL_HANDSHAKE_AS_SERVER, PR_TRUE)
+ if (SSL_OptionSet(mctx->model, SSL_HANDSHAKE_AS_SERVER, mctx->as_server)
!= SECSuccess) {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
"Unable to set SSL server handshake mode.");
nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
nss_die();
}
- if (SSL_OptionSet(mctx->model, SSL_HANDSHAKE_AS_CLIENT, PR_FALSE)
+ if (SSL_OptionSet(mctx->model, SSL_HANDSHAKE_AS_CLIENT, !mctx->as_server)
!= SECSuccess) {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
- "Unable to disable handshake as client");
+ "Unable to set handshake as client");
nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
nss_die();
}
+ if (!mctx->as_server) {
+ if ((SSL_OptionSet(mctx->model, SSL_NO_CACHE, PR_TRUE)) != SECSuccess) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+ "Unable to disable SSL client caching");
+ nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
+ nss_die();
+ }
+ }
}
static void nss_init_ctx_protocol(server_rec *s,
@@ -622,7 +637,8 @@
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
"FIPS mode enabled, permitted SSL ciphers are: [%s]",
fipsciphers);
- }
+ }
+
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
"Configuring permitted SSL ciphers [%s]",
suite);
@@ -666,7 +682,7 @@
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
"Cipher %s is enabled but this is not a FIPS cipher, disabling.", ciphers_def[i].name);
cipher_state[i] = PR_FALSE;
- }
+ }
}
}
@@ -728,18 +744,20 @@
* Get own certificate and private key.
*/
- if (mctx->nickname == NULL) {
+ if (mctx->nickname == NULL && mctx->as_server) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
"No certificate nickname provided.");
nss_die();
}
- ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
- "Using nickname %s.", mctx->nickname);
+
+ if (mctx->nickname != NULL)
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
+ "Using nickname %s.", mctx->nickname);
mctx->servercert = FindServerCertFromNickname(mctx->nickname);
/* Verify the certificate chain. */
- if (mctx->servercert != NULL) {
+ if (mctx->servercert != NULL && mctx->as_server) {
SECCertificateUsage usage = certificateUsageSSLServer;
if (CERT_VerifyCertificateNow(CERT_GetDefaultCertDB(), mctx->servercert, PR_TRUE, usage, NULL, NULL) != SECSuccess) {
@@ -754,14 +772,14 @@
}
}
- if (NULL == mctx->servercert)
+ if (NULL == mctx->servercert && mctx->as_server)
{
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
"Certificate not found: '%s'", mctx->nickname);
nss_die();
}
- if (strchr(mctx->nickname, ':'))
+ if (mctx->nickname && strchr(mctx->nickname, ':'))
{
char* token = strdup(mctx->nickname);
char* colon = strchr(token, ':');
@@ -786,17 +804,20 @@
slot = PK11_GetInternalKeySlot();
}
- mctx->serverkey = PK11_FindPrivateKeyFromCert(slot, mctx->servercert, NULL);
- PK11_FreeSlot(slot);
+ if (mctx->servercert) {
+ mctx->serverkey = PK11_FindPrivateKeyFromCert(slot, mctx->servercert, NULL);
+ PK11_FreeSlot(slot);
+ }
- if (mctx->serverkey == NULL) {
+ if (mctx->as_server && mctx->serverkey == NULL) {
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
"Key not found for: '%s'", mctx->nickname);
nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
nss_die();
}
- mctx->serverKEAType = NSS_FindCertKEAType(mctx->servercert);
+ if (mctx->as_server) {
+ mctx->serverKEAType = NSS_FindCertKEAType(mctx->servercert);
/*
* Check for certs that are expired or not yet valid and WARN about it
@@ -824,6 +845,7 @@
"Unhandled Certificate time type %d for: '%s'", certtimestatus, mctx->nickname);
break;
}
+ }
secstatus = (SECStatus)SSL_SetPKCS11PinArg(mctx->model, NULL);
if (secstatus != SECSuccess) {
@@ -832,15 +854,15 @@
nss_die();
}
-#if 1
- secstatus = SSL_ConfigSecureServer(mctx->model, mctx->servercert, mctx->serverkey, mctx->serverKEAType);
- if (secstatus != SECSuccess) {
- ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
- "SSL error configuring server: '%s'", mctx->nickname);
- nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
- nss_die();
+ if (mctx->as_server) {
+ secstatus = SSL_ConfigSecureServer(mctx->model, mctx->servercert, mctx->serverkey, mctx->serverKEAType);
+ if (secstatus != SECSuccess) {
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
+ "SSL error configuring server: '%s'", mctx->nickname);
+ nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
+ nss_die();
+ }
}
-#endif
secstatus = (SECStatus)SSL_HandshakeCallback(mctx->model, (SSLHandshakeCallback)NSSHandshakeCallback, NULL);
if (secstatus != SECSuccess)
@@ -852,6 +874,16 @@
}
}
+static void nss_init_proxy_ctx(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+ SSLSrvConfigRec *sc)
+{
+ nss_init_ctx(s, p, ptemp, sc->proxy);
+
+ nss_init_server_certs(s, p, ptemp, sc->proxy);
+}
+
static void nss_init_server_ctx(server_rec *s,
apr_pool_t *p,
apr_pool_t *ptemp,
@@ -876,11 +908,11 @@
nss_init_server_ctx(s, p, ptemp, sc);
}
-#ifdef PROXY
if (sc->proxy_enabled) {
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
+ "Enabling proxy.");
nss_init_proxy_ctx(s, p, ptemp, sc);
}
-#endif
}
void nss_init_Child(apr_pool_t *p, server_rec *s)
@@ -936,10 +968,14 @@
{
PRErrorCode err = PR_GetError();
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
- "Bad certificate: %d", err);
-
- return SECFailure;
+ switch (err) {
+ default:
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+ "Bad remote server certificate.", err);
+ nss_log_nss_error(APLOG_MARK, APLOG_ERR, NULL);
+ return SECFailure;
+ break;
+ }
}
/*
@@ -1028,6 +1064,9 @@
PRUint32 bestCertMatchedUsage = 0;
PRBool bestCertIsValid = PR_FALSE;
+ if (name == NULL)
+ return NULL;
+
clist = PK11_ListCerts(PK11CertListUser, NULL);
for (cln = CERT_LIST_HEAD(clist); !CERT_LIST_END(cln,clist);