68f3b8
 configure.in             |   34 +++++++++++++++++++++++++++++++++-
68f3b8
 src/network/ssl/socket.c |   28 ++++++++++++++++++++++------
68f3b8
 src/network/ssl/ssl.c    |   32 ++++++++++++++++++++++++++------
68f3b8
 src/network/ssl/ssl.h    |    2 +-
68f3b8
 4 files changed, 82 insertions(+), 14 deletions(-)
68f3b8
68f3b8
diff --git a/configure.in b/configure.in
68f3b8
index 0e534db..972a305 100644
68f3b8
--- a/configure.in
68f3b8
+++ b/configure.in
68f3b8
@@ -970,6 +970,37 @@ AC_ARG_WITH(openssl, [[  --with-openssl[=DIR]    enable OpenSSL support (default
68f3b8
 		*)	chosen_ssl_library="OpenSSL" ;;
68f3b8
 	     esac])
68f3b8
 
68f3b8
+AC_ARG_WITH(nss_compat_ossl, [[  --with-nss_compat_ossl[=DIR]
68f3b8
+                          NSS compatibility SSL libraries/include files]])
68f3b8
+
68f3b8
+# nss_compat_ossl
68f3b8
+if test -n "$with_nss_compat_ossl" && test "$with_nss_compat_ossl" != "no"; then
68f3b8
+	EL_SAVE_FLAGS
68f3b8
+	if test "$with_nss_compat_ossl" = yes; then
68f3b8
+		if pkg-config nss; then
68f3b8
+			CFLAGS="$CFLAGS_X `pkg-config --cflags nss`"
68f3b8
+			LIBS="$LIBS_X `pkg-config --libs nss`"
68f3b8
+		else
68f3b8
+			with_nss_compat_ossl=no
68f3b8
+		fi
68f3b8
+	else
68f3b8
+		# Without pkg-config, we'll kludge in some defaults
68f3b8
+		CFLAGS="$CFLAGS_X -I$with_nss_compat_ossl/include -I/usr/include/nss3 -I/usr/include/nspr4"
68f3b8
+		LIBS="$LIBS_X -L$with_nss_compat_ossl/lib -lssl3 -lsmime3 -lnss3 -lplds4 -lplc4 -lnspr4 -lpthread -ldl"
68f3b8
+	fi
68f3b8
+	AC_CHECK_HEADERS(nss_compat_ossl/nss_compat_ossl.h,, [with_nss_compat_ossl=no], [#define NSS_COMPAT_OSSL_H])
68f3b8
+	AC_CHECK_LIB(nss_compat_ossl, X509_free,, [with_nss_compat_ossl=no])
68f3b8
+
68f3b8
+	if test "$with_nss_compat_ossl" = "no"; then
68f3b8
+		EL_RESTORE_FLAGS
68f3b8
+	else
68f3b8
+		LIBS="$LIBS -lnss_compat_ossl"
68f3b8
+		EL_CONFIG(CONFIG_NSS_COMPAT_OSSL, [nss_compat_ossl])
68f3b8
+		disable_openssl="yes"
68f3b8
+		disable_gnutls="yes"
68f3b8
+	fi
68f3b8
+fi
68f3b8
+
68f3b8
 # ---- OpenSSL
68f3b8
 
68f3b8
 AC_MSG_CHECKING([for OpenSSL])
68f3b8
@@ -1092,10 +1123,11 @@ fi
68f3b8
 
68f3b8
 # Final SSL setup
68f3b8
 
68f3b8
-EL_CONFIG_DEPENDS(CONFIG_SSL, [CONFIG_OPENSSL CONFIG_GNUTLS], [SSL])
68f3b8
+EL_CONFIG_DEPENDS(CONFIG_SSL, [CONFIG_OPENSSL CONFIG_GNUTLS CONFIG_NSS_COMPAT_OSSL], [SSL])
68f3b8
 AC_SUBST(CONFIG_GNUTLS_OPENSSL_COMPAT)
68f3b8
 AC_SUBST(CONFIG_OPENSSL)
68f3b8
 AC_SUBST(CONFIG_GNUTLS)
68f3b8
+AC_SUBST(CONFIG_NSS_COMPAT_OSSL)
68f3b8
 
68f3b8
 #endif
68f3b8
 
68f3b8
diff --git a/src/network/ssl/socket.c b/src/network/ssl/socket.c
68f3b8
index 45b4b4a..3265107 100644
68f3b8
--- a/src/network/ssl/socket.c
68f3b8
+++ b/src/network/ssl/socket.c
68f3b8
@@ -6,6 +6,10 @@
68f3b8
 
68f3b8
 #ifdef CONFIG_OPENSSL
68f3b8
 #include <openssl/ssl.h>
68f3b8
+#define USE_OPENSSL
68f3b8
+#elif defined(CONFIG_NSS_COMPAT_OSSL)
68f3b8
+#include <nss_compat_ossl/nss_compat_ossl.h>
68f3b8
+#define USE_OPENSSL
68f3b8
 #elif defined(CONFIG_GNUTLS)
68f3b8
 #include <gnutls/gnutls.h>
68f3b8
 #else
68f3b8
@@ -26,7 +30,7 @@
68f3b8
 
68f3b8
 
68f3b8
 /* SSL errors */
68f3b8
-#ifdef CONFIG_OPENSSL
68f3b8
+#ifdef USE_OPENSSL
68f3b8
 #define	SSL_ERROR_WANT_READ2	9999 /* XXX */
68f3b8
 #define	SSL_ERROR_WANT_WRITE2	SSL_ERROR_WANT_WRITE
68f3b8
 #define	SSL_ERROR_SYSCALL2	SSL_ERROR_SYSCALL
68f3b8
@@ -40,7 +44,7 @@
68f3b8
 #define	SSL_ERROR_SYSCALL2	GNUTLS_E_PULL_ERROR
68f3b8
 #endif
68f3b8
 
68f3b8
-#ifdef CONFIG_OPENSSL
68f3b8
+#ifdef USE_OPENSSL
68f3b8
 
68f3b8
 #define ssl_do_connect(socket)		SSL_get_error(socket->ssl, SSL_connect(socket->ssl))
68f3b8
 #define ssl_do_write(socket, data, len)	SSL_write(socket->ssl, data, len)
68f3b8
@@ -126,7 +130,7 @@ ssl_connect(struct socket *socket)
68f3b8
 	if (socket->no_tls)
68f3b8
 		ssl_set_no_tls(socket);
68f3b8
 
68f3b8
-#ifdef CONFIG_OPENSSL
68f3b8
+#ifdef USE_OPENSSL
68f3b8
 	SSL_set_fd(socket->ssl, socket->fd);
68f3b8
 
68f3b8
 	if (get_opt_bool("connection.ssl.cert_verify"))
68f3b8
@@ -137,7 +141,13 @@ ssl_connect(struct socket *socket)
68f3b8
 	if (get_opt_bool("connection.ssl.client_cert.enable")) {
68f3b8
 		unsigned char *client_cert;
68f3b8
 
68f3b8
-		client_cert = get_opt_str("connection.ssl.client_cert.file");
68f3b8
+#ifdef CONFIG_NSS_COMPAT_OSSL
68f3b8
+		client_cert = get_opt_str(
68f3b8
+				"connection.ssl.client_cert.nickname");
68f3b8
+#else
68f3b8
+		client_cert = get_opt_str(
68f3b8
+				"connection.ssl.client_cert.file");
68f3b8
+#endif
68f3b8
 		if (!*client_cert) {
68f3b8
 			client_cert = getenv("X509_CLIENT_CERT");
68f3b8
 			if (client_cert && !*client_cert)
68f3b8
@@ -145,11 +155,17 @@ ssl_connect(struct socket *socket)
68f3b8
 		}
68f3b8
 
68f3b8
 		if (client_cert) {
68f3b8
+#ifdef CONFIG_NSS_COMPAT_OSSL
68f3b8
+			SSL_CTX_use_certificate_chain_file(
68f3b8
+					(SSL *) socket->ssl,
68f3b8
+					client_cert);
68f3b8
+#else
68f3b8
 			SSL_CTX *ctx = ((SSL *) socket->ssl)->ctx;
68f3b8
 
68f3b8
 			SSL_CTX_use_certificate_chain_file(ctx, client_cert);
68f3b8
 			SSL_CTX_use_PrivateKey_file(ctx, client_cert,
68f3b8
 						    SSL_FILETYPE_PEM);
68f3b8
+#endif
68f3b8
 		}
68f3b8
 	}
68f3b8
 
68f3b8
@@ -206,7 +222,7 @@ ssl_write(struct socket *socket, unsigned char *data, int len)
68f3b8
 	ssize_t wr = ssl_do_write(socket, data, len);
68f3b8
 
68f3b8
 	if (wr <= 0) {
68f3b8
-#ifdef CONFIG_OPENSSL
68f3b8
+#ifdef USE_OPENSSL
68f3b8
 		int err = SSL_get_error(socket->ssl, wr);
68f3b8
 #elif defined(CONFIG_GNUTLS)
68f3b8
 		int err = wr;
68f3b8
@@ -235,7 +251,7 @@ ssl_read(struct socket *socket, unsigned char *data, int len)
68f3b8
 	ssize_t rd = ssl_do_read(socket, data, len);
68f3b8
 
68f3b8
 	if (rd <= 0) {
68f3b8
-#ifdef CONFIG_OPENSSL
68f3b8
+#ifdef USE_OPENSSL
68f3b8
 		int err = SSL_get_error(socket->ssl, rd);
68f3b8
 #elif defined(CONFIG_GNUTLS)
68f3b8
 		int err = rd;
68f3b8
diff --git a/src/network/ssl/ssl.c b/src/network/ssl/ssl.c
68f3b8
index 685c31e..73446b5 100644
68f3b8
--- a/src/network/ssl/ssl.c
68f3b8
+++ b/src/network/ssl/ssl.c
68f3b8
@@ -7,6 +7,10 @@
68f3b8
 #ifdef CONFIG_OPENSSL
68f3b8
 #include <openssl/ssl.h>
68f3b8
 #include <openssl/rand.h>
68f3b8
+#define USE_OPENSSL
68f3b8
+#elif defined(CONFIG_NSS_COMPAT_OSSL)
68f3b8
+#include <nss_compat_ossl/nss_compat_ossl.h>
68f3b8
+#define USE_OPENSSL
68f3b8
 #elif defined(CONFIG_GNUTLS)
68f3b8
 #include <gnutls/gnutls.h>
68f3b8
 #include <gnutls/x509.h>
68f3b8
@@ -33,7 +37,7 @@
68f3b8
 /* FIXME: As you can see, SSL is currently implemented in very, erm,
68f3b8
  * decentralized manner. */
68f3b8
 
68f3b8
-#ifdef CONFIG_OPENSSL
68f3b8
+#ifdef USE_OPENSSL
68f3b8
 
68f3b8
 #ifndef PATH_MAX
68f3b8
 #define	PATH_MAX	256 /* according to my /usr/include/bits/posix1_lim.h */
68f3b8
@@ -71,12 +75,28 @@ static union option_info openssl_options[] = {
68f3b8
 		N_("Enable or not the sending of X509 client certificates "
68f3b8
 		"to servers which request them.")),
68f3b8
 
68f3b8
+#ifdef CONFIG_NSS_COMPAT_OSSL
68f3b8
+	INIT_OPT_STRING("connection.ssl.client_cert", N_("Certificate nickname"),
68f3b8
+		"nickname", 0, "",
68f3b8
+		N_("The nickname of the client certificate stored in NSS "
68f3b8
+		"database. If this value is unset, the nickname from "
68f3b8
+		"the X509_CLIENT_CERT variable is used instead. If you "
68f3b8
+		"have a PKCS#12 file containing client certificate, you "
68f3b8
+		"can import it into your NSS database with:\n"
68f3b8
+		"\n"
68f3b8
+		"$ pk12util -i mycert.p12 -d /path/to/database\n"
68f3b8
+		"\n"
68f3b8
+		"The NSS database location can be changed by SSL_DIR "
68f3b8
+		"environment variable. The database can be also shared "
68f3b8
+		"with Mozilla browsers.")),
68f3b8
+#else
68f3b8
 	INIT_OPT_STRING("connection.ssl.client_cert", N_("Certificate File"),
68f3b8
 		"file", 0, "",
68f3b8
 		N_("The location of a file containing the client certificate "
68f3b8
 		"and unencrypted private key in PEM format. If unset, the "
68f3b8
 		"file pointed to by the X509_CLIENT_CERT variable is used "
68f3b8
 		"instead.")),
68f3b8
+#endif
68f3b8
 
68f3b8
 	NULL_OPTION_INFO,
68f3b8
 };
68f3b8
@@ -182,7 +202,7 @@ static struct module gnutls_module = struct_module(
68f3b8
 	/* done: */		done_gnutls
68f3b8
 );
68f3b8
 
68f3b8
-#endif /* CONFIG_OPENSSL or CONFIG_GNUTLS */
68f3b8
+#endif /* USE_OPENSSL or CONFIG_GNUTLS */
68f3b8
 
68f3b8
 static union option_info ssl_options[] = {
68f3b8
 	INIT_OPT_TREE("connection", N_("SSL"),
68f3b8
@@ -193,7 +213,7 @@ static union option_info ssl_options[] = {
68f3b8
 };
68f3b8
 
68f3b8
 static struct module *ssl_modules[] = {
68f3b8
-#ifdef CONFIG_OPENSSL
68f3b8
+#ifdef USE_OPENSSL
68f3b8
 	&openssl_module,
68f3b8
 #elif defined(CONFIG_GNUTLS)
68f3b8
 	&gnutls_module,
68f3b8
@@ -214,7 +234,7 @@ struct module ssl_module = struct_module(
68f3b8
 int
68f3b8
 init_ssl_connection(struct socket *socket)
68f3b8
 {
68f3b8
-#ifdef CONFIG_OPENSSL
68f3b8
+#ifdef USE_OPENSSL
68f3b8
 	socket->ssl = SSL_new(context);
68f3b8
 	if (!socket->ssl) return S_SSL_ERROR;
68f3b8
 #elif defined(CONFIG_GNUTLS)
68f3b8
@@ -271,7 +291,7 @@ done_ssl_connection(struct socket *socket)
68f3b8
 	ssl_t *ssl = socket->ssl;
68f3b8
 
68f3b8
 	if (!ssl) return;
68f3b8
-#ifdef CONFIG_OPENSSL
68f3b8
+#ifdef USE_OPENSSL
68f3b8
 	SSL_free(ssl);
68f3b8
 #elif defined(CONFIG_GNUTLS)
68f3b8
 	gnutls_deinit(*ssl);
68f3b8
@@ -288,7 +308,7 @@ get_ssl_connection_cipher(struct socket *socket)
68f3b8
 
68f3b8
 	if (!init_string(&str)) return NULL;
68f3b8
 
68f3b8
-#ifdef CONFIG_OPENSSL
68f3b8
+#ifdef USE_OPENSSL
68f3b8
 	add_format_to_string(&str, "%ld-bit %s %s",
68f3b8
 		SSL_get_cipher_bits(ssl, NULL),
68f3b8
 		SSL_get_cipher_version(ssl),
68f3b8
diff --git a/src/network/ssl/ssl.h b/src/network/ssl/ssl.h
68f3b8
index 7c54a7a..21ca142 100644
68f3b8
--- a/src/network/ssl/ssl.h
68f3b8
+++ b/src/network/ssl/ssl.h
68f3b8
@@ -22,7 +22,7 @@ unsigned char *get_ssl_connection_cipher(struct socket *socket);
68f3b8
 
68f3b8
 /* Internal type used in ssl module. */
68f3b8
 
68f3b8
-#ifdef CONFIG_OPENSSL
68f3b8
+#if defined(CONFIG_OPENSSL) || defined(CONFIG_NSS_COMPAT_OSSL)
68f3b8
 #define	ssl_t	SSL
68f3b8
 #elif defined(CONFIG_GNUTLS)
68f3b8
 #define	ssl_t	gnutls_session_t