Sorry for long response, I was on holyday...

On Monday 25 August 2008 03:53:25 Kalle Olavi Niemitalo wrote:
> Although it is listed in TODO, I am not sure it is a good idea.
> Current versions of ELinks do not check the subject names of
> certificates (bug 1024), do not display detailed error messages
> when SSL or TLS fails, and do not provide a way to temporarily
> trust a certificate.  I fear fixing these and maintaining the
> resulting code will be more difficult if there are more
> alternative libraries.
I think the patch is really small. It is more concerned on auto-tools files 
and documentation rather then the source code. 99% of source code works for 
OpenSSL and nss_compat_ossl without any change.

> Does NSS enable ELinks to share the CA trust and client
> certificate settings of Mozilla browsers?  If so, that would be
> a reason to support NSS.
Sure. You need to set SSL_DIR environment variable to directory containing its 
NSS database, in my case ~/.mozilla/firefox/kkkp326c.default - maybe we 
should more document this feature.

> > From: Kamil Dudka <[EMAIL PROTECTED]>
>
> Do you give permission to add this name and email address to our
> public Git repository?  Please note the cia.vc and ohloh.net web
> sites already collect profiles of people and others can do so in
> the future.
Of course, permitted. I am already collected by ohloh.net :-)

> ELinks was originally licensed under GNU GPL v2 or later, but
> since ELinks 0.10.0, only GPLv2 is allowed.  If we ever want to
> change the license back (e.g. because of LGPLv3 libraries), we'll
> need permission from all copyright holders, I suppose.  Do you
> give such permission?
Yes.

> > @@ -79,6 +83,8 @@ ssl_set_no_tls(struct socket *socket)
> >
> >             gnutls_protocol_set_priority(*(ssl_t *) socket->ssl,
> > protocol_priority); }
> > +#elif defined(CONFIG_NSS_COMPAT_OSSL)
> > +#warning "ssl_setno_tls is not implemented while using nss_compat_ossl"
> >  #endif
> >  }
>
> configure --enable-debug adds -Werror to CFLAGS if using GCC;
> does this #warning then break the build?  Also, it's a
> nonstandard directive and may hurt users of other compilers.
> (There is a #warning in osdep/system.h too but it's in an #if
> whose condition should never be true.)
Well, this patch was just a sketch and subject for discussion. This 
compile-time warning is no longer included in attached patch.

> If ssl_set_no_tls is not necessary because NSS automatically
> selects the right protocol version (more reliably than GnuTLS),
> then I don't think the warning should be there either.
> Otherwise, ssl_set_no_tls should be implemented... or is it
> impossible to implement with nss_compat_ossl?
As it was just a workaround (maybe for OpenSSL bug) I think this is not 
necessary while using NSS, but I haven't tested it for now.

> > +#ifdef CONFIG_NSS_COMPAT_OSSL
> > +   INIT_OPT_STRING("connection.ssl.client_cert", N_("Certificate
> > nickname"), +               "file", 0, "",
> > +            N_("The nickname of the client certificate stored in NSS\n"
> > +               "database. If this value is unset, the file pointed to\n"
> > +               "by the X509_CLIENT_CERT variable is used instead. If\n"
> > +               "you have a PKCS#12 file containing client certificate,\n"
> > +               "you can import it into your NSS database with:\n"
> > +               "$ pk12util -i mycert.p12 -d /path/to/database\n\n"
> > +               "The NSS database location can be changed by SSL_DIR\n"
> > +               "environment variable.")),
> > +#else
> >     INIT_OPT_STRING("connection.ssl.client_cert", N_("Certificate File"),
> >             "file", 0, "",
> >              N_("The location of a file containing the client certificate\n"
> >                 "and unencrypted private key in PEM format. If unset, the\n"
> >                 "file pointed to by the X509_CLIENT_CERT variable is used\n"
> >                 "instead.")),
> > +#endif
>
> You make connection.ssl.client_cert.file mean a file name if
> using OpenSSL, but a nickname if using NSS.  Can the user set up
> an elinks.conf that works correctly under both interpretations?
> (For example, by defining a nickname that looks like a file
> name.)  If not, I think it would be better to use a different
> name for the nickname option.  (An elinks binary built with NSS
> might then warn about unrecognized connection.ssl.client_cert.file
> in elinks.conf.  That could be fixed either by unconditionally
> compiling the option definitions in ELinks, or by changing the
> elinks.conf parser not to warn about unrecognized options by
> default.  The latter solution seems nicer because it avoids bloat
> and removes annoying warnings also when SSL support or some other
> module is entirely disabled.)
Good idea. New configure option connection.ssl.client_cert.nickname is used 
for NSS client certificate nickname.

> Your current documentation string claims that X509_CLIENT_CERT
> is a file name even with NSS.  However, the code seems to use
> the value of X509_CLIENT_CERT simply as a default for the option,
> thus as a nickname.
Sorry for that, I've made a mistake while copy-pasting. Fixed. New patch in 
attachment.


Kamil
From 618e17449c8a0ed697577682c2234f5671130585 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <[EMAIL PROTECTED]>
Date: Wed, 27 Aug 2008 11:47:36 +0200
Subject: [PATCH] add support for nss_compat_ossl library (OpenSSL replacement)

* configure.in: Detection of nss_compat_ossl library.
New configure parameters --with-nss_compat_ossl, --without-nss_compat_ossl.
* socket.c: New configure option connection.ssl.client_cert.nickname.
* ssl.h: Handle CONFIG_NSS_COMPAT_OSSL macro.
* ssl.c: Add support for nss_compat_ossl.
* TODO: Remove completed task.
* NEWS: Mention the change.
---
 NEWS                     |    2 ++
 configure.in             |   35 ++++++++++++++++++++++++++++++++++-
 src/network/ssl/TODO     |    4 ----
 src/network/ssl/socket.c |   29 ++++++++++++++++++++++-------
 src/network/ssl/ssl.c    |   32 +++++++++++++++++++++++++-------
 src/network/ssl/ssl.h    |    2 +-
 6 files changed, 84 insertions(+), 20 deletions(-)

diff --git a/NEWS b/NEWS
index f13e441..2e9f8c6 100644
--- a/NEWS
+++ b/NEWS
@@ -46,6 +46,8 @@ Miscellaneous:
 * enhancement: Add a new entry Link Info under Link main menu.
 * enhancement: New option protocol.http.compression.
 * enhancement: Indicate backgrounded downloads using an unused led.
+* enhancement: Add support for nss_compat_ossl library (OpenSSL
+  replacement).
 
 //////////////////////////////////////////////////////////////////////
 The following changes should be removed from NEWS before ELinks 0.13.0
diff --git a/configure.in b/configure.in
index be0b64a..ff83218 100644
--- a/configure.in
+++ b/configure.in
@@ -988,6 +988,7 @@ gnutls_withval="$withval"
 
 if test "$enable_gnutls" = yes; then
 	disable_openssl=yes;
+	with_nss_compat_ossl=no;
 fi
 
 AC_ARG_WITH(openssl, [  --without-openssl       disable OpenSSL support],
@@ -995,6 +996,37 @@ AC_ARG_WITH(openssl, [  --without-openssl       disable OpenSSL support],
 AC_ARG_WITH(openssl, [  --with-openssl[=DIR]    enable OpenSSL support (default)])
 openssl_withval="$withval"
 
+AC_ARG_WITH(nss_compat_ossl, AC_HELP_STRING([--with-nss_compat_ossl[=DIR]],
+	    [NSS compatibility SSL libraries/include files]))
+
+# nss_compat_ossl
+if test "$with_nss_compat_ossl" != "no"; then
+	if test -z "$with_nss_compat_ossl"; then
+		if pkg-config nss; then
+			CFLAGS="$CFLAGS_X `pkg-config --cflags nss`"
+			LIBS="$LIBS_X `pkg-config --libs nss`"
+		else
+			with_nss_compat_ossl=no
+		fi
+	else
+		# Without pkg-config, we'll kludge in some defaults
+		CFLAGS="$CFLAGS_X -I$with_nss_compat_ossl/include -I/usr/include/nss3 -I/usr/include/nspr4"
+		LIBS="$LIBS_X -L$with_nss_compat_ossl/lib -lssl3 -lsmime3 -lnss3 -lplds4 -lplc4 -lnspr4 -lpthread -ldl"
+	fi
+	AC_CHECK_HEADERS(nss_compat_ossl/nss_compat_ossl.h,, [with_nss_compat_ossl=no], [#define NSS_COMPAT_OSSL_H])
+	AC_CHECK_LIB(nss_compat_ossl, X509_free,, [with_nss_compat_ossl=no])
+fi
+
+if  test "$with_nss_compat_ossl" != "no"; then
+	LIBS="$LIBS -lnss_compat_ossl"
+	EL_CONFIG(CONFIG_NSS_COMPAT_OSSL, [nss_compat_ossl])
+	disable_openssl="yes"
+	disable_gnutls="yes"
+
+	# TODO: Mark this as non-warning when it becomes stable
+	AC_MSG_WARN([Using nss_compat_ossl library for SSL.])
+fi
+
 # ---- OpenSSL
 
 AC_MSG_CHECKING([for OpenSSL])
@@ -1113,10 +1145,11 @@ AC_MSG_RESULT($cf_result)
 
 # Final SSL setup
 
-EL_CONFIG_DEPENDS(CONFIG_SSL, [CONFIG_OPENSSL CONFIG_GNUTLS], [SSL])
+EL_CONFIG_DEPENDS(CONFIG_SSL, [CONFIG_OPENSSL CONFIG_GNUTLS CONFIG_NSS_COMPAT_OSSL], [SSL])
 AC_SUBST(CONFIG_GNUTLS_OPENSSL_COMPAT)
 AC_SUBST(CONFIG_OPENSSL)
 AC_SUBST(CONFIG_GNUTLS)
+AC_SUBST(CONFIG_NSS_COMPAT_OSSL)
 
 #endif
 
diff --git a/src/network/ssl/TODO b/src/network/ssl/TODO
index dad2835..3079e34 100644
--- a/src/network/ssl/TODO
+++ b/src/network/ssl/TODO
@@ -5,10 +5,6 @@ We could add also support for:
  format conviently readable for me; however, they say it is damn fast and very
  easy to use)
 
-* NSS (http://www.mozilla.org/projects/security/pki/nss/ - it could be pretty
- widespread and nicely tested by mozilla, however it scares me, it looks to be
- pretty complex and already needing some certificates db generated etc)
-
 Possibly, we should drop support for native GnuTLS and use their OpenSSL
 wrapper instead, since I happen to feel very unsure about GnuTLS interface -
 OpenSSL is not much better, but we can steal code from other applications ;-).
diff --git a/src/network/ssl/socket.c b/src/network/ssl/socket.c
index 74c43b8..1acf9d5 100644
--- a/src/network/ssl/socket.c
+++ b/src/network/ssl/socket.c
@@ -6,6 +6,10 @@
 
 #ifdef CONFIG_OPENSSL
 #include <openssl/ssl.h>
+#define USE_OPENSSL
+#elif defined(CONFIG_NSS_COMPAT_OSSL)
+#include <nss_compat_ossl/nss_compat_ossl.h>
+#define USE_OPENSSL
 #elif defined(CONFIG_GNUTLS)
 #include <gnutls/gnutls.h>
 #else
@@ -26,7 +30,7 @@
 
 
 /* SSL errors */
-#ifdef CONFIG_OPENSSL
+#ifdef USE_OPENSSL
 #define	SSL_ERROR_WANT_READ2	9999 /* XXX */
 #define	SSL_ERROR_WANT_WRITE2	SSL_ERROR_WANT_WRITE
 #define	SSL_ERROR_SYSCALL2	SSL_ERROR_SYSCALL
@@ -40,7 +44,7 @@
 #define	SSL_ERROR_SYSCALL2	GNUTLS_E_PULL_ERROR
 #endif
 
-#ifdef CONFIG_OPENSSL
+#ifdef USE_OPENSSL
 
 #define ssl_do_connect(socket)		SSL_get_error(socket->ssl, SSL_connect(socket->ssl))
 #define ssl_do_write(socket, data, len)	SSL_write(socket->ssl, data, len)
@@ -126,7 +130,7 @@ ssl_connect(struct socket *socket)
 	if (socket->no_tls)
 		ssl_set_no_tls(socket);
 
-#ifdef CONFIG_OPENSSL
+#ifdef USE_OPENSSL
 	SSL_set_fd(socket->ssl, socket->fd);
 
 	if (get_opt_bool("connection.ssl.cert_verify", NULL))
@@ -137,8 +141,13 @@ ssl_connect(struct socket *socket)
 	if (get_opt_bool("connection.ssl.client_cert.enable", NULL)) {
 		unsigned char *client_cert;
 
-		client_cert = get_opt_str("connection.ssl.client_cert.file",
-		                          NULL);
+#ifdef CONFIG_NSS_COMPAT_OSSL
+		client_cert = get_opt_str(
+				"connection.ssl.client_cert.nickname", NULL);
+#else
+		client_cert = get_opt_str(
+				"connection.ssl.client_cert.file", NULL);
+#endif
 		if (!*client_cert) {
 			client_cert = getenv("X509_CLIENT_CERT");
 			if (client_cert && !*client_cert)
@@ -146,11 +155,17 @@ ssl_connect(struct socket *socket)
 		}
 
 		if (client_cert) {
+#ifdef CONFIG_NSS_COMPAT_OSSL
+			SSL_CTX_use_certificate_chain_file(
+					(SSL *) socket->ssl,
+					client_cert);
+#else
 			SSL_CTX *ctx = ((SSL *) socket->ssl)->ctx;
 
 			SSL_CTX_use_certificate_chain_file(ctx, client_cert);
 			SSL_CTX_use_PrivateKey_file(ctx, client_cert,
 						    SSL_FILETYPE_PEM);
+#endif
 		}
 	}
 
@@ -207,7 +222,7 @@ ssl_write(struct socket *socket, unsigned char *data, int len)
 	ssize_t wr = ssl_do_write(socket, data, len);
 
 	if (wr <= 0) {
-#ifdef CONFIG_OPENSSL
+#ifdef USE_OPENSSL
 		int err = SSL_get_error(socket->ssl, wr);
 #elif defined(CONFIG_GNUTLS)
 		int err = wr;
@@ -236,7 +251,7 @@ ssl_read(struct socket *socket, unsigned char *data, int len)
 	ssize_t rd = ssl_do_read(socket, data, len);
 
 	if (rd <= 0) {
-#ifdef CONFIG_OPENSSL
+#ifdef USE_OPENSSL
 		int err = SSL_get_error(socket->ssl, rd);
 #elif defined(CONFIG_GNUTLS)
 		int err = rd;
diff --git a/src/network/ssl/ssl.c b/src/network/ssl/ssl.c
index 8777f3c..84aaa58 100644
--- a/src/network/ssl/ssl.c
+++ b/src/network/ssl/ssl.c
@@ -7,6 +7,10 @@
 #ifdef CONFIG_OPENSSL
 #include <openssl/ssl.h>
 #include <openssl/rand.h>
+#define USE_OPENSSL
+#elif defined(CONFIG_NSS_COMPAT_OSSL)
+#include <nss_compat_ossl/nss_compat_ossl.h>
+#define USE_OPENSSL
 #elif defined(CONFIG_GNUTLS)
 #include <gcrypt.h>
 #include <gnutls/gnutls.h>
@@ -35,7 +39,7 @@
 /* FIXME: As you can see, SSL is currently implemented in very, erm,
  * decentralized manner. */
 
-#ifdef CONFIG_OPENSSL
+#ifdef USE_OPENSSL
 
 #ifndef PATH_MAX
 #define	PATH_MAX	256 /* according to my /usr/include/bits/posix1_lim.h */
@@ -85,12 +89,26 @@ static struct option_info openssl_options[] = {
 		 N_("Enable or not the sending of X509 client certificates\n"
 		    "to servers which request them.")),
 
+#ifdef CONFIG_NSS_COMPAT_OSSL
+	INIT_OPT_STRING("connection.ssl.client_cert", N_("Certificate nickname"),
+		"nickname", 0, "",
+		 N_("The nickname of the client certificate stored in NSS\n"
+		    "database. If this value is unset, the nickname from\n"
+		    "the X509_CLIENT_CERT variable is used instead. If you\n"
+		    "have a PKCS#12 file containing client certificate, you\n"
+		    "can import it into your NSS database with:\n"
+		    "$ pk12util -i mycert.p12 -d /path/to/database\n\n"
+		    "The NSS database location can be changed by SSL_DIR\n"
+		    "environment variable. The database can be also shared\n"
+		    "with Mozilla browsers.")),
+#else
 	INIT_OPT_STRING("connection.ssl.client_cert", N_("Certificate File"),
 		"file", 0, "",
 		 N_("The location of a file containing the client certificate\n"
 		    "and unencrypted private key in PEM format. If unset, the\n"
 		    "file pointed to by the X509_CLIENT_CERT variable is used\n"
 		    "instead.")),
+#endif
 
 	NULL_OPTION_INFO,
 };
@@ -196,7 +214,7 @@ static struct module gnutls_module = struct_module(
 	/* done: */		done_gnutls
 );
 
-#endif /* CONFIG_OPENSSL or CONFIG_GNUTLS */
+#endif /* USE_OPENSSL or CONFIG_GNUTLS */
 
 static struct option_info ssl_options[] = {
 	INIT_OPT_TREE("connection", N_("SSL"),
@@ -207,7 +225,7 @@ static struct option_info ssl_options[] = {
 };
 
 static struct module *ssl_modules[] = {
-#ifdef CONFIG_OPENSSL
+#ifdef USE_OPENSSL
 	&openssl_module,
 #elif defined(CONFIG_GNUTLS)
 	&gnutls_module,
@@ -228,7 +246,7 @@ struct module ssl_module = struct_module(
 int
 init_ssl_connection(struct socket *socket)
 {
-#ifdef CONFIG_OPENSSL
+#ifdef USE_OPENSSL
 	socket->ssl = SSL_new(context);
 	if (!socket->ssl) return S_SSL_ERROR;
 #elif defined(CONFIG_GNUTLS)
@@ -277,7 +295,7 @@ done_ssl_connection(struct socket *socket)
 	ssl_t *ssl = socket->ssl;
 
 	if (!ssl) return;
-#ifdef CONFIG_OPENSSL
+#ifdef USE_OPENSSL
 	SSL_free(ssl);
 #elif defined(CONFIG_GNUTLS)
 	gnutls_deinit(*ssl);
@@ -294,7 +312,7 @@ get_ssl_connection_cipher(struct socket *socket)
 
 	if (!init_string(&str)) return NULL;
 
-#ifdef CONFIG_OPENSSL
+#ifdef USE_OPENSSL
 	add_format_to_string(&str, "%ld-bit %s %s",
 		SSL_get_cipher_bits(ssl, NULL),
 		SSL_get_cipher_version(ssl),
@@ -318,7 +336,7 @@ get_ssl_connection_cipher(struct socket *socket)
 void
 random_nonce(unsigned char buf[], size_t size)
 {
-#ifdef CONFIG_OPENSSL
+#ifdef USE_OPENSSL
 	RAND_pseudo_bytes(buf, size);
 #elif defined(CONFIG_GNUTLS)
 	gcry_create_nonce(buf, size);
diff --git a/src/network/ssl/ssl.h b/src/network/ssl/ssl.h
index 7c54a7a..21ca142 100644
--- a/src/network/ssl/ssl.h
+++ b/src/network/ssl/ssl.h
@@ -22,7 +22,7 @@ unsigned char *get_ssl_connection_cipher(struct socket *socket);
 
 /* Internal type used in ssl module. */
 
-#ifdef CONFIG_OPENSSL
+#if defined(CONFIG_OPENSSL) || defined(CONFIG_NSS_COMPAT_OSSL)
 #define	ssl_t	SSL
 #elif defined(CONFIG_GNUTLS)
 #define	ssl_t	gnutls_session_t
-- 
1.5.4.1

_______________________________________________
elinks-dev mailing list
[email protected]
http://linuxfromscratch.org/mailman/listinfo/elinks-dev

Reply via email to