Index: configure.ac
===================================================================
RCS file: /cvsroot/curl/curl/configure.ac,v
retrieving revision 1.210
diff -u -r1.210 configure.ac
--- configure.ac	3 Nov 2006 03:05:15 -0000	1.210
+++ configure.ac	12 Feb 2007 15:01:15 -0000
@@ -1188,6 +1188,7 @@
        [
        AC_DEFINE(USE_GNUTLS, 1, [if GnuTLS is enabled])
        AC_SUBST(USE_GNUTLS, [1])
+       GNUTLS_ENABLED = 1
        USE_GNUTLS="yes"
        curl_ssl_msg="enabled (GnuTLS)"
        ],
@@ -1213,13 +1214,84 @@
 
   fi dnl GNUTLS not disabled
 
-  if test X"$USE_GNUTLS" != "Xyes"; then
-    AC_MSG_WARN([SSL disabled, you will not be able to use HTTPS, FTPS, NTLM and more.])
-    AC_MSG_WARN([Use --with-ssl or --with-gnutls to address this.])
-  fi
-
 fi dnl OPENSSL != 1
 
+dnl ----------------------------------------------------
+dnl NSS. Only check if GnuTLS and OpenSSL are not enabled
+dnl ----------------------------------------------------
+
+dnl Default to compiler & linker defaults for NSS files & libraries.
+OPT_NSS=no
+
+AC_ARG_WITH(nss,dnl
+AC_HELP_STRING([--with-nss=PATH],[where to look for NSS, PATH points to the installation root (default: /usr/local/)])
+AC_HELP_STRING([--without-nss], [disable NSS detection]),
+  OPT_NSS=$withval)
+
+if test "$OPENSSL_ENABLED" != "1" -a "$GNUTLS_ENABLED" != "1"; then
+
+  if test X"$OPT_NSS" != Xno; then
+    if test "x$OPT_NSS" = "xyes"; then
+     check=`pkg-config --version 2>/dev/null`
+     if test -n "$check"; then
+       addlib=`pkg-config --libs nss`
+       addcflags=`pkg-config --cflags nss`
+       version=`pkg-config --modversion nss`
+       nssprefix=`pkg-config --variable=prefix nss`
+     fi
+    else
+      # Without pkg-config, we'll kludge in some defaults
+      addlib="-lssl3 -lsmime3 -lnss3 -lplds4 -lplc4 -lnspr4 -lpthread -ldl"
+      addcflags="-I$OPT_NSS/include" 
+      version="unknown"
+      gtlsprefix=$OPT_GNUTLS
+    fi
+    if test -n "$addlib"; then
+
+      CLEANLIBS="$LIBS"
+      CLEANCPPFLAGS="$CPPFLAGS"
+  
+      LIBS="$LIBS $addlib"
+      if test "$addcflags" != "-I/usr/include"; then
+         CPPFLAGS="$CPPFLAGS $addcflags"
+      fi
+  
+      AC_CHECK_LIB(nss3, NSS_Initialize,
+       [
+       AC_DEFINE(USE_NSS, 1, [if NSS is enabled])
+       AC_SUBST(USE_NSS, [1])
+       USE_NSS="yes"
+       curl_ssl_msg="enabled (NSS)"
+       ],
+       [
+         LIBS="$CLEANLIBS"
+         CPPFLAGS="$CLEANCPPFLAGS"
+       ])
+  
+      if test "x$USE_NSS" = "xyes"; then
+        AC_MSG_NOTICE([detected NSS version $version])
+
+        dnl when shared libs were found in a path that the run-time
+        dnl linker doesn't search through, we need to add it to
+        dnl LD_LIBRARY_PATH to prevent further configure tests to fail
+        dnl due to this
+
+        LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$nssprefix/lib$libsuff"
+        export LD_LIBRARY_PATH
+        AC_MSG_NOTICE([Added $nssprefix/lib$libsuff to LD_LIBRARY_PATH])
+      fi
+
+    fi
+
+  fi dnl NSS not disabled
+
+fi dnl OPENSSL != 1 -a GNUTLS_ENABLED != 1
+
+if test "x$OPENSSL_ENABLED" != "x1" -a "x$GNUTLS_ENABLED" != "x1" -a "x$NSS_ENABLED" != "x1"; then
+  AC_MSG_WARN([SSL disabled, you will not be able to use HTTPS, FTPS, NTLM and more.])
+  AC_MSG_WARN([Use --with-ssl, --with-gnutls or --with-nss to address this.])
+fi
+
 dnl **********************************************************************
 dnl Check for the CA bundle
 dnl **********************************************************************
Index: docs/FAQ
===================================================================
RCS file: /cvsroot/curl/curl/docs/FAQ,v
retrieving revision 1.110
diff -u -r1.110 FAQ
--- docs/FAQ	16 Jan 2006 22:14:38 -0000	1.110
+++ docs/FAQ	12 Feb 2007 15:01:16 -0000
@@ -355,10 +355,10 @@
 
   2.2 Does curl work/build with other SSL libraries?
 
-  Curl has been written to use OpenSSL or GnuTLS, although there should not be
-  many problems using a different library. If anyone does "port" curl to use a
-  different SSL library, we are of course very interested in getting the
-  patch!
+  Curl has been written to use OpenSSL, GnuTLS or NSS, although there should
+  not be many problems using a different library. If anyone does "port" curl
+  to use a different SSL library, we are of course very interested in getting
+  the patch!
 
   2.3 Where can I find a copy of LIBEAY32.DLL?
 
@@ -839,6 +839,8 @@
 
     http://www.gnu.org/software/gnutls/manual/html_node/Multi_002dthreaded-applications.html
 
+  No special locking is needed with a NSS-powered libcurl. NSS is thread-safe.
+
   5.2 How can I receive all data into a large memory chunk?
 
   [ See also the examples/getinmemory.c source ]
Index: docs/FEATURES
===================================================================
RCS file: /cvsroot/curl/curl/docs/FEATURES,v
retrieving revision 1.19
diff -u -r1.19 FEATURES
--- docs/FEATURES	12 Oct 2006 08:55:01 -0000	1.19
+++ docs/FEATURES	12 Feb 2007 15:01:16 -0000
@@ -116,10 +116,10 @@
 FOOTNOTES
 =========
 
-  *1 = requires OpenSSL or GnuTLS
+  *1 = requires OpenSSL, GnuTLS or NSS
   *2 = requires OpenLDAP
   *3 = requires a GSSAPI-compliant library, such as Heimdal or similar.
   *4 = requires FBopenssl
   *5 = requires a krb4 library, such as the MIT one or similar.
   *6 = requires c-ares
-  *7 = requires OpenSSL specificly, as GnuTLS only supports SSLv3 and TLSv1
+  *7 = requires OpenSSL or NSS, as GnuTLS only supports SSLv3 and TLSv1
Index: docs/INSTALL
===================================================================
RCS file: /cvsroot/curl/curl/docs/INSTALL,v
retrieving revision 1.69
diff -u -r1.69 INSTALL
--- docs/INSTALL	16 Aug 2006 18:48:27 -0000	1.69
+++ docs/INSTALL	12 Feb 2007 15:01:17 -0000
@@ -140,6 +140,9 @@
      yassl with its OpenSSL emulation enabled and point to that directory root
      with configure --with-ssl.
 
+     To build with NSS support instead of OpenSSL for SSL/TLS, note that
+     you need to use both --without-ssl and --with-nss.
+
 
 Win32
 =====
Index: docs/LICENSE-MIXING
===================================================================
RCS file: /cvsroot/curl/curl/docs/LICENSE-MIXING,v
retrieving revision 1.7
diff -u -r1.7 LICENSE-MIXING
--- docs/LICENSE-MIXING	7 Jul 2006 20:48:51 -0000	1.7
+++ docs/LICENSE-MIXING	12 Feb 2007 15:01:17 -0000
@@ -47,6 +47,14 @@
         (May be used for SSL/TLS support) Uses the GPL[1] license. If this is
         a problem for you, consider using OpenSSL or GnuTLS instead.
 
+NSS     http://www.mozilla.org/projects/security/pki/nss/
+
+        (May be used for SSL/TLS support) Is covered by the MPL[4] license,
+        the GPL[1] license and the LGPL[3] license. You may choose to license
+        the code under MPL terms, GPL terms, or LGPL terms. These licenses
+        grant you different permissions and impose different obligations. You
+        should select the license that best meets your needs.
+
 c-ares  http://daniel.haxx.se/projects/c-ares/license.html
 
         (Used for asynchronous name resolves) Uses an MIT license that is very
@@ -110,3 +118,5 @@
       how to write such an exception to the GPL
 [3] = LGPL - GNU Lesser General Public License:
       http://www.gnu.org/licenses/lgpl.html
+[4] = MPL - Mozilla Public License:
+      http://www.mozilla.org/MPL/
Index: docs/TODO
===================================================================
RCS file: /cvsroot/curl/curl/docs/TODO,v
retrieving revision 1.130
diff -u -r1.130 TODO
--- docs/TODO	3 Nov 2006 12:22:13 -0000	1.130
+++ docs/TODO	12 Feb 2007 15:01:17 -0000
@@ -160,19 +160,17 @@
    it be? There's so much that could be done if it were! (brought by Chris
    Clark)
 
- * Make curl's SSL layer capable of using other free SSL libraries.  Such as
-   Mozilla Security Services
-   (http://www.mozilla.org/projects/security/pki/nss/), MatrixSSL
-   (http://www.matrixssl.org/) or yaSSL (http://yassl.com/). At least the
-   latter two could be alternatives for those looking to reduce the footprint
-   of libcurl built with OpenSSL or GnuTLS.
+ * Make curl's SSL layer capable of using other free SSL libraries.  Such
+   as  MatrixSSL (http://www.matrixssl.org/) or yaSSL (http://yassl.com/).
+   These could be alternatives for those looking to reduce the footprint of
+   libcurl built with OpenSSL or GnuTLS.
 
  * Peter Sylvester's patch for SRP on the TLS layer.
    Awaits OpenSSL support for this, no need to support this in libcurl before
    there's an OpenSSL release that does it.
 
  * make the configure --with-ssl option first check for OpenSSL and then for
-   GnuTLS if OpenSSL wasn't detected.
+   GnuTLS and finally for NSS if OpenSSL wasn't detected.
 
  GnuTLS
 
Index: docs/curl.1
===================================================================
RCS file: /cvsroot/curl/curl/docs/curl.1,v
retrieving revision 1.199
diff -u -r1.199 curl.1
--- docs/curl.1	3 Nov 2006 13:45:52 -0000	1.199
+++ docs/curl.1	12 Feb 2007 15:01:18 -0000
@@ -167,6 +167,10 @@
 must be using valid ciphers. Read up on SSL cipher list details on this URL:
 \fIhttp://www.openssl.org/docs/apps/ciphers.html\fP
 
+NSS ciphers are done differently than OpenSSL and GnuTLS. The full list of
+NSS ciphers is in the NSSCipherSuite entry at this URL:
+\fIhttp://directory.fedora.redhat.com/docs/mod_nss.html#Directives\fP
+
 If this option is used several times, the last one will override the others.
 .IP "--compressed"
 (HTTP) Request a compressed response using one of the algorithms libcurl
@@ -323,6 +327,10 @@
 private certificate concatenated! See \fI--cert\P and \fI--key\fP to specify
 them independently.
 
+If curl is built against the NSS SSL library then this option tells
+curl the nickname of the certificate to use within the NSS database defined
+by --cacert.
+
 If this option is used several times, the last one will be used.
 .IP "--cert-type <type>"
 (SSL) Tells curl what certificate type the provided certificate is in. PEM,
@@ -342,6 +350,9 @@
 \'curl-ca-bundle.crt\', either in the same directory as curl.exe, or in the
 Current Working Directory, or in any folder along your PATH.
 
+If curl is built against the NSS SSL library then this option tells
+curl the directory that the NSS certificate database resides in.
+
 If this option is used several times, the last one will be used.
 .IP "--capath <CA certificate directory>"
 (SSL) Tells curl to use the specified certificate directory to verify the
Index: docs/libcurl/curl_easy_setopt.3
===================================================================
RCS file: /cvsroot/curl/curl/docs/libcurl/curl_easy_setopt.3,v
retrieving revision 1.163
diff -u -r1.163 curl_easy_setopt.3
--- docs/libcurl/curl_easy_setopt.3	2 Nov 2006 22:10:18 -0000	1.163
+++ docs/libcurl/curl_easy_setopt.3	12 Feb 2007 15:01:20 -0000
@@ -1157,6 +1157,9 @@
 Pass a pointer to a zero terminated string as parameter. The string should be
 the file name of your certificate. The default format is "PEM" and can be
 changed with \fICURLOPT_SSLCERTTYPE\fP.
+
+With NSS this is the nickname of the certificate you wish to authenticate
+with.
 .IP CURLOPT_SSLCERTTYPE
 Pass a pointer to a zero terminated string as parameter. The string should be
 the format of your certificate. Supported formats are "PEM" and "DER".  (Added
@@ -1201,8 +1204,8 @@
 The available options are:
 .RS
 .IP CURL_SSLVERSION_DEFAULT
-The default action. When libcurl built with OpenSSL, this will attempt to
-figure out the remote SSL protocol version. Unfortunately there are a lot of
+The default action. When libcurl built with OpenSSL or NSS, this will attempt
+to figure out the remote SSL protocol version. Unfortunately there are a lot of
 ancient and broken servers in use which cannot handle this technique and will
 fail to connect. When libcurl is built with GnuTLS, this will mean SSLv3.
 .IP CURL_SSLVERSION_TLSv1
@@ -1245,6 +1248,9 @@
 
 Note that option is by default set to the system path where libcurl's cacert
 bundle is assumed to be stored, as established at build time.
+
+When built against NSS this is the directory that the NSS certificate
+database resides in.
 .IP CURLOPT_CAPATH
 Pass a char * to a zero terminated string naming a directory holding
 multiple CA certificates to verify the peer with. The certificate
@@ -1294,12 +1300,23 @@
 ciphers to use for the SSL connection. The list must be syntactically correct,
 it consists of one or more cipher strings separated by colons. Commas or spaces
 are also acceptable separators but colons are normally used, \!, \- and \+ can
-be used as operators. Valid examples of cipher lists include 'RC4-SHA',
+be used as operators.
+
+For OpenSSL and GnuTLS valid examples of cipher lists include 'RC4-SHA',
 \'SHA1+DES\', 'TLSv1' and 'DEFAULT'. The default list is normally set when you
 compile OpenSSL.
 
 You'll find more details about cipher lists on this URL:
 \fIhttp://www.openssl.org/docs/apps/ciphers.html\fP
+
+For NSS valid examples of cipher lists include 'rsa_rc4_128_md5',
+\'rsa_aes_128_sha\', etc. With NSS you don't add/remove ciphers. If one uses
+this option then all known ciphers are disabled and only those passed in
+are enabled.
+
+You'll find more details about the NSS cipher lists on this URL:
+\fIhttp://directory.fedora.redhat.com/docs/mod_nss.html#Directives\fP
+
 .IP CURLOPT_SSL_SESSIONID_CACHE
 Pass a long set to 0 to disable libcurl's use of SSL session-ID caching. Set
 this to 1 to enable it. By default all transfers are done using the
Index: lib/Makefile.inc
===================================================================
RCS file: /cvsroot/curl/curl/lib/Makefile.inc,v
retrieving revision 1.14
diff -u -r1.14 Makefile.inc
--- lib/Makefile.inc	2 Nov 2006 21:56:43 -0000	1.14
+++ lib/Makefile.inc	12 Feb 2007 15:01:20 -0000
@@ -8,7 +8,7 @@
   content_encoding.c share.c http_digest.c md5.c http_negotiate.c	\
   http_ntlm.c inet_pton.c strtoofft.c strerror.c hostares.c hostasyn.c	\
   hostip4.c hostip6.c hostsyn.c hostthre.c inet_ntop.c parsedate.c	\
-  select.c gtls.c sslgen.c tftp.c splay.c strdup.c socks.c ssh.c
+  select.c gtls.c sslgen.c tftp.c splay.c strdup.c socks.c ssh.c nss.c
 
 HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h	\
   progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h	\
@@ -18,6 +18,7 @@
   share.h md5.h http_digest.h http_negotiate.h http_ntlm.h ca-bundle.h	\
   inet_pton.h strtoofft.h strerror.h inet_ntop.h curlx.h memory.h	\
   setup.h transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h   \
-  gtls.h tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h
+  gtls.h tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h  \
+  nssg.h
 
 
Index: lib/http.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/http.c,v
retrieving revision 1.303
diff -u -r1.303 http.c
--- lib/http.c	3 Nov 2006 12:43:56 -0000	1.303
+++ lib/http.c	12 Feb 2007 15:01:21 -0000
@@ -1479,6 +1479,18 @@
   (void)numsocks;
   return GETSOCK_BLANK;
 }
+#else
+#ifdef USE_NSS
+int Curl_https_getsock(struct connectdata *conn,
+                       curl_socket_t *socks,
+                       int numsocks)
+{
+  (void)conn;
+  (void)socks;
+  (void)numsocks;
+  return GETSOCK_BLANK;
+}
+#endif
 #endif
 #endif
 
Index: lib/nss.c
===================================================================
RCS file: lib/nss.c
diff -N lib/nss.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/nss.c	12 Feb 2007 15:01:21 -0000
@@ -0,0 +1,596 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * $Id: $
+ ***************************************************************************/
+
+/*
+ * Source file for all NSS-specific code for the TLS/SSL layer. No code
+ * but sslgen.c should ever call or use these functions.
+ */
+
+#include "setup.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "formdata.h" /* for the boundary function */
+#include "url.h" /* for the ssl config check function */
+#include "connect.h" /* Curl_sockerrno() proto */
+#include "strequal.h"
+#include "select.h"
+#include "sslgen.h"
+
+#define _MPRINTF_REPLACE /* use the internal *printf() functions */
+#include <curl/mprintf.h>
+
+#ifdef USE_NSS
+
+#include <nspr.h>
+#include <nss.h>
+#include <ssl.h>
+#include <sslerr.h>
+#include <secerr.h>
+#include <sslproto.h>
+#include <prtypes.h>
+#include <pk11pub.h>
+
+#include "memory.h"
+#include "easyif.h" /* for Curl_convert_from_utf8 prototype */
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+#ifndef min
+#define min(a, b)   ((a) < (b) ? (a) : (b))
+#endif
+
+PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
+
+static int initialized = 0;
+static int noverify = 0;
+
+typedef struct {
+  PRInt32 retryCount;
+  struct SessionHandle *data;
+} pphrase_arg_t;
+
+typedef struct {
+  const char *name;
+  int num;
+  PRInt32 version; /* protocol version valid for this cipher */
+} cipher_s;
+
+/* the table itself is defined in nss_engine_init.c */
+#ifdef NSS_ENABLE_ECC
+#define ciphernum 48
+#else
+#define ciphernum 23
+#endif
+
+enum sslversion { SSL2 = 1, SSL3 = 2, TLS = 4 };
+
+cipher_s cipherlist[ciphernum] = {
+  /* SSL2 cipher suites */
+  {"rc4", SSL_EN_RC4_128_WITH_MD5, SSL2},
+  {"rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5, SSL2},
+  {"rc2", SSL_EN_RC2_128_CBC_WITH_MD5, SSL2},
+  {"rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, SSL2},
+  {"des", SSL_EN_DES_64_CBC_WITH_MD5, SSL2},
+  {"desede3", SSL_EN_DES_192_EDE3_CBC_WITH_MD5, SSL2},
+  /* SSL3/TLS cipher suites */
+  {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5, SSL3 | TLS},
+  {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA, SSL3 | TLS},
+  {"rsa_3des_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL3 | TLS},
+  {"rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA, SSL3 | TLS},
+  {"rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL3 | TLS},
+  {"rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL3 | TLS},
+  {"rsa_null_md5", SSL_RSA_WITH_NULL_MD5, SSL3 | TLS},
+  {"rsa_null_sha", SSL_RSA_WITH_NULL_SHA, SSL3 | TLS},
+  {"fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL3 | TLS},
+  {"fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA, SSL3 | TLS},
+  {"fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, SSL3 | TLS},
+  {"fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, SSL3 | TLS},
+  {"fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA, SSL3 | TLS},
+  /* TLS 1.0: Exportable 56-bit Cipher Suites. */
+  {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL3 | TLS},
+  {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL3 | TLS},
+  /* AES ciphers. */
+  {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA, SSL3 | TLS},
+  {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA, SSL3 | TLS},
+#ifdef NSS_ENABLE_ECC
+  /* ECC ciphers. */
+  {"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA, TLS},
+  {"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS},
+  {"ecdh_ecdsa_3des_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS},
+  {"ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS},
+  {"ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS},
+  {"ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLS},
+  {"ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS},
+  {"ecdhe_ecdsa_3des_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS},
+  {"ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS},
+  {"ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS},
+  {"ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA, TLS},
+  {"ecdh_rsa_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA, TLS},
+  {"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, TLS},
+  {"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS},
+  {"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS},
+  {"echde_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA, TLS},
+  {"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS},
+  {"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS},
+  {"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS},
+  {"ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS},
+  {"ecdh_anon_null_sha", TLS_ECDH_anon_WITH_NULL_SHA, TLS},
+  {"ecdh_anon_rc4_128sha", TLS_ECDH_anon_WITH_RC4_128_SHA, TLS},
+  {"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, TLS},
+  {"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA, TLS},
+  {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA, TLS},
+#endif
+};
+
+SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model, char *cipher_list)
+{
+  int i;
+  PRBool cipher_state[ciphernum];
+  PRBool found;
+  char *cipher;
+  SECStatus rv;
+
+  /* First disable all ciphers. This uses a different max value in case
+   * NSS adds more ciphers later we don't want them available by
+   * accident
+   */
+  for(i=0; i<SSL_NumImplementedCiphers; i++) {
+    SSL_CipherPrefSet(model, SSL_ImplementedCiphers[i], SSL_NOT_ALLOWED);
+  }
+
+  /* Set every entry in our list to false */
+  for(i=0; i<ciphernum; i++) {
+    cipher_state[i] = PR_FALSE;
+  }
+
+  cipher = cipher_list;
+
+  while(cipher_list && (cipher_list[0])) {
+    while((*cipher) && (isspace(*cipher)))
+      ++cipher;
+
+    if((cipher_list = strchr(cipher, ','))) {
+      *cipher_list++ = '\0';
+    }
+
+    found = PR_FALSE;
+
+    for(i=0; i<ciphernum; i++) {
+      if(!strcasecmp(cipher, cipherlist[i].name)) {
+        cipher_state[i] = PR_TRUE;
+        found = PR_TRUE;
+        break;
+      }
+    }
+
+    if(found == PR_FALSE) {
+      char buf[1024];
+      snprintf(buf, 1024, "Unknown cipher in list: %s", cipher);
+      failf(data, buf);
+      return SECFailure;
+    }
+
+    if(cipher_list) {
+      cipher = cipher_list;
+    }
+  }
+
+  /* Finally actually enable the selected ciphers */
+  for(i=0; i<ciphernum; i++) {
+    rv = SSL_CipherPrefSet(model, cipherlist[i].num, cipher_state[i]);
+    if(rv != SECSuccess) {
+      failf(data, "Unknown cipher in cipher list");
+      return SECFailure;
+    }
+  }
+
+  return SECSuccess;
+}
+
+static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg)
+{
+  pphrase_arg_t *parg = (pphrase_arg_t *) arg;
+  if(parg->data->set.key_passwd)
+    return (char *)PORT_Strdup((char *)parg->data->set.key_passwd);
+  else
+    return NULL;
+}
+
+SECStatus nss_Init_Tokens(struct connectdata * conn)
+{
+  PK11SlotList *slotList;
+  PK11SlotListElement *listEntry;
+  SECStatus ret, status = SECSuccess;
+  pphrase_arg_t *parg;
+
+  parg = (pphrase_arg_t *) malloc(sizeof(*parg));
+  parg->retryCount = 0;
+  parg->data = conn->data;
+
+  PK11_SetPasswordFunc(nss_get_password);
+
+  slotList =
+    PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_TRUE, NULL);
+
+  for(listEntry = PK11_GetFirstSafe(slotList);
+      listEntry; listEntry = listEntry->next) {
+    PK11SlotInfo *slot = listEntry->slot;
+
+    if(PK11_NeedLogin(slot) && PK11_NeedUserInit(slot)) {
+      if(slot == PK11_GetInternalKeySlot()) {
+        failf(conn->data, "The NSS database has not been initialized.\n");
+      }
+      else {
+        failf(conn->data, "The token %s has not been initialized.",
+              PK11_GetTokenName(slot));
+      }
+      PK11_FreeSlot(slot);
+      continue;
+    }
+
+    ret = PK11_Authenticate(slot, PR_TRUE, parg);
+    if(SECSuccess != ret) {
+      status = SECFailure;
+      break;
+    }
+    parg->retryCount = 0; /* reset counter to 0 for the next token */
+    PK11_FreeSlot(slot);
+  }
+
+  free(parg);
+  return status;
+}
+
+static SECStatus BadCertHandler(void *arg, PRFileDesc * socket)
+{
+  SECStatus success = SECSuccess;
+  PRErrorCode err;
+
+  return success;
+}
+
+/**
+ * Inform the application that the handshake is complete.
+ */
+static SECStatus HandshakeCallback(PRFileDesc * socket, void *arg)
+{
+  return SECSuccess;
+}
+
+/**
+ *
+ * Callback to pick the SSL client certificate.
+ */
+SECStatus SelectClientCert(void *arg, PRFileDesc * socket,
+                           struct CERTDistNamesStr * caNames,
+                           struct CERTCertificateStr ** pRetCert,
+                           struct SECKEYPrivateKeyStr ** pRetKey)
+{
+  CERTCertificate *cert;
+  SECKEYPrivateKey *privKey;
+  char *nickname = (char *)arg;
+  void *proto_win = NULL;
+  SECStatus secStatus = SECFailure;
+
+  proto_win = SSL_RevealPinArg(socket);
+
+  cert = PK11_FindCertFromNickname(nickname, proto_win);
+  if(cert) {
+    privKey = PK11_FindKeyByAnyCert(cert, proto_win);
+    if(privKey) {
+      secStatus = SECSuccess;
+    }
+    else {
+      CERT_DestroyCertificate(cert);
+    }
+  }
+
+  if(secStatus == SECSuccess) {
+    *pRetCert = cert;
+    *pRetKey = privKey;
+  }
+
+  return secStatus;
+}
+
+/**
+ * Global SSL init
+ *
+ * @retval 0 error initializing SSL
+ * @retval 1 SSL initialized successfully
+ */
+int Curl_nss_init(void)
+{
+  if(!initialized)
+    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
+
+  /* We will actually initialize NSS later */
+
+  return 1;
+}
+
+/* Global cleanup */
+void Curl_nss_cleanup(void)
+{
+  NSS_Shutdown();
+  initialized = 0;
+}
+
+/*
+ * This function uses SSL_peek to determine connection status.
+ *
+ * Return codes:
+ *     1 means the connection is still in place
+ *     0 means the connection has been closed
+ *    -1 means the connection status is unknown
+ */
+int
+Curl_nss_check_cxn(struct connectdata *conn)
+{
+  int rc;
+  char buf;
+
+  rc =
+    PR_Recv(conn->ssl[FIRSTSOCKET].handle, (void *)&buf, 1, PR_MSG_PEEK,
+            PR_SecondsToInterval(1));
+  if(rc > 0)
+    return 1; /* connection still in place */
+
+  if(rc == 0)
+    return 0; /* connection has been closed */
+
+  return -1;  /* connection status unknown */
+}
+
+/*
+ * This function is called when an SSL connection is closed.
+ */
+void Curl_nss_close(struct connectdata *conn)
+{
+  int i;
+
+  for(i=0; i<2; i++) {
+    struct ssl_connect_data *connssl = &conn->ssl[i];
+
+    if(connssl->handle) {
+      PR_Close(connssl->handle);
+      connssl->handle = NULL;
+    }
+    connssl->use = FALSE; /* get back to ordinary socket usage */
+  }
+}
+
+/*
+ * This function is called when the 'data' struct is going away. Close
+ * down everything and free all resources!
+ */
+int Curl_nss_close_all(struct SessionHandle *data)
+{
+  (void)data;
+  return 0;
+}
+
+CURLcode Curl_nss_connect(struct connectdata * conn, int sockindex)
+{
+  PRInt32 err;
+  PRFileDesc *model = NULL;
+  PRBool ssl2, ssl3, tlsv1;
+  struct SessionHandle *data = conn->data;
+  curl_socket_t sockfd = conn->sock[sockindex];
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  SECStatus rv;
+  int curlerr = CURLE_SSL_CONNECT_ERROR;
+
+  /* FIXME. NSS doesn't support multiple databases open at the same time. */
+  if(!initialized) {
+    if(!data->set.ssl.CAfile) {
+      if(data->set.ssl.verifypeer) {
+        failf(data, "No NSS cacert database specified.");
+        return CURLE_SSL_CACERT_BADFILE;
+      }
+      else {
+        rv = NSS_NoDB_Init(NULL);
+        noverify = 1;
+      }
+    }
+    else {
+      rv = NSS_Initialize(data->set.ssl.CAfile, NULL, NULL, "secmod.db",
+                          NSS_INIT_READONLY);
+    }
+    if(rv != SECSuccess) {
+      curlerr = CURLE_SSL_CACERT_BADFILE;
+      goto error;
+    }
+  }
+
+  NSS_SetDomesticPolicy();
+
+  model = PR_NewTCPSocket();
+  if(!model)
+    goto error;
+  model = SSL_ImportFD(NULL, model);
+
+  if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess)
+    goto error;
+  if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess)
+    goto error;
+  if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess)
+    goto error;
+
+  ssl2 = ssl3 = tlsv1 = PR_FALSE;
+
+  switch (data->set.ssl.version) {
+  default:
+  case CURL_SSLVERSION_DEFAULT:
+    ssl2 = ssl3 = tlsv1 = PR_TRUE;
+    break;
+  case CURL_SSLVERSION_TLSv1:
+    tlsv1 = PR_TRUE;
+    break;
+  case CURL_SSLVERSION_SSLv2:
+    ssl2 = PR_TRUE;
+    break;
+  case CURL_SSLVERSION_SSLv3:
+    ssl3 = PR_TRUE;
+    break;
+  }
+
+  if(SSL_OptionSet(model, SSL_ENABLE_SSL2, ssl2) != SECSuccess)
+    goto error;
+  if(SSL_OptionSet(model, SSL_ENABLE_SSL3, ssl3) != SECSuccess)
+    goto error;
+  if(SSL_OptionSet(model, SSL_ENABLE_TLS, tlsv1) != SECSuccess)
+    goto error;
+
+  if(data->set.ssl.cipher_list) {
+    if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess)
+      goto error;
+  }
+
+  if(SSL_BadCertHook(model, (SSLBadCertHandler) BadCertHandler, NULL)
+     != SECSuccess)
+    goto error;
+  if(SSL_HandshakeCallback(model, (SSLHandshakeCallback) HandshakeCallback,
+                           NULL) != SECSuccess)
+    goto error;
+
+  if(data->set.cert) {
+    if(SSL_GetClientAuthDataHook(model,
+                                 (SSLGetClientAuthData) SelectClientCert,
+                                 (void *)data->set.cert) != SECSuccess) {
+      curlerr = CURLE_SSL_CERTPROBLEM;
+      goto error;
+    }
+    if(nss_Init_Tokens(conn) != SECSuccess)
+      goto error;
+  }
+
+  /* Import our model socket  onto the existing file descriptor */
+  connssl->handle = PR_ImportTCPSocket(sockfd);
+  connssl->handle = SSL_ImportFD(model, connssl->handle);
+  if(!connssl->handle)
+    goto error;
+
+  /* Force handshake on next I/O */
+  SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE);
+
+  SSL_SetURL(connssl->handle, conn->host.name);
+
+  return CURLE_OK;
+
+error:
+  err = PR_GetError();
+  failf(data, "NSS error %d", err);
+  if(model)
+    PR_Close(model);
+  return curlerr;
+}
+
+/* return number of sent (non-SSL) bytes */
+int Curl_nss_send(struct connectdata *conn,  /* connection data */
+                  int sockindex,             /* socketindex */
+                  void *mem,                 /* send this data */
+                  size_t len)	             /* amount to write */
+{
+  PRInt32 err;
+  struct SessionHandle *data = conn->data;
+  PRInt32 timeout;
+
+  if(data->set.timeout)
+    timeout = PR_SecondsToInterval(data->set.timeout);
+  else
+    timeout = PR_MillisecondsToInterval(DEFAULT_CONNECT_TIMEOUT);
+
+  int rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0, timeout);
+
+  if(rc < 0) {
+    err = PR_GetError();
+
+    if(err == PR_IO_TIMEOUT_ERROR) {
+      failf(data, "SSL connection timeout");
+      return CURLE_OPERATION_TIMEOUTED;
+    }
+
+    failf(conn->data, "SSL write: error %d\n", err);
+    return -1;
+  }
+  return rc; /* number of bytes */
+}
+
+/*
+ * If the read would block we return -1 and set 'wouldblock' to TRUE.
+ * Otherwise we return the amount of data read. Other errors should return -1
+ * and set 'wouldblock' to FALSE.
+ */
+ssize_t Curl_nss_recv(struct connectdata * conn, /* connection data */
+                      int num,                   /* socketindex */
+                      char *buf,                 /* store read data here */
+                      size_t buffersize,         /* max amount to read */
+                      bool * wouldblock)
+{
+  ssize_t nread;
+  struct SessionHandle *data = conn->data;
+  PRInt32 timeout;
+
+  if(data->set.timeout)
+    timeout = PR_SecondsToInterval(data->set.timeout);
+  else
+    timeout = PR_MillisecondsToInterval(DEFAULT_CONNECT_TIMEOUT);
+
+  nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0, timeout);
+  *wouldblock = FALSE;
+  if(nread < 0) {
+    /* failed SSL read */
+    PRInt32 err = PR_GetError();
+
+    if(err == PR_WOULD_BLOCK_ERROR) {
+      *wouldblock = TRUE;
+      return -1; /* basically EWOULDBLOCK */
+    }
+    if(err == PR_IO_TIMEOUT_ERROR) {
+      failf(data, "SSL connection timeout");
+      return CURLE_OPERATION_TIMEOUTED;
+    }
+    failf(conn->data, "SSL read: errno %d", err);
+    return -1;
+  }
+  return nread;
+}
+
+size_t Curl_nss_version(char *buffer, size_t size)
+{
+  return snprintf(buffer, size, " NSS/%s", NSS_VERSION);
+}
+#endif /* USE_NSS */
Index: lib/nssg.h
===================================================================
RCS file: lib/nssg.h
diff -N lib/nssg.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/nssg.h	12 Feb 2007 15:01:21 -0000
@@ -0,0 +1,57 @@
+#ifndef __NSS_H
+#define __NSS_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * $Id: $
+ ***************************************************************************/
+
+/*
+ * This header should only be needed to get included by sslgen.c and nss.c
+ */
+
+#include "urldata.h"
+CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex);
+CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn, 
+                                      int sockindex, 
+                                      bool *done);
+void Curl_nss_close(struct connectdata *conn); /* close a SSL connection */
+/* tell NSS to close down all open information regarding connections (and
+   thus session ID caching etc) */
+int Curl_nss_close_all(struct SessionHandle *data);
+
+int Curl_nss_init(void);
+void Curl_nss_cleanup(void);
+
+int Curl_nss_send(struct connectdata *conn,
+                  int sockindex,
+                  void *mem,
+                  size_t len);
+ssize_t Curl_nss_recv(struct connectdata *conn, /* connection data */
+                      int num,                  /* socketindex */
+                      char *buf,                /* store read data here */
+                      size_t buffersize,        /* max amount to read */
+                      bool *wouldblock);
+
+size_t Curl_nss_version(char *buffer, size_t size);
+int Curl_nss_check_cxn(struct connectdata *cxn);
+int Curl_nss_seed(struct SessionHandle *data);
+
+#endif
Index: lib/setup.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/setup.h,v
retrieving revision 1.123
diff -u -r1.123 setup.h
--- lib/setup.h	18 Oct 2006 15:57:49 -0000	1.123
+++ lib/setup.h	12 Feb 2007 15:01:21 -0000
@@ -348,8 +348,8 @@
 #define HAVE_INET_NTOA_R_2_ARGS 1
 #endif
 
-#if defined(USE_GNUTLS) || defined(USE_SSLEAY)
-#define USE_SSL    /* Either OpenSSL || GnuTLS */
+#if defined(USE_GNUTLS) || defined(USE_SSLEAY) || defined(USE_NSS)
+#define USE_SSL    /* Either OpenSSL || GnuTLS || NSS */
 #endif
 
 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_NTLM)
Index: lib/sslgen.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/sslgen.c,v
retrieving revision 1.11
diff -u -r1.11 sslgen.c
--- lib/sslgen.c	12 Sep 2006 23:51:01 -0000	1.11
+++ lib/sslgen.c	12 Feb 2007 15:01:21 -0000
@@ -31,6 +31,7 @@
    Curl_ssl_ - prefix for generic ones
    Curl_ossl_ - prefix for OpenSSL ones
    Curl_gtls_ - prefix for GnuTLS ones
+   Curl_nss_ - prefix for NSS ones
 
    "SSL/TLS Strong Encryption: An Introduction"
    http://httpd.apache.org/docs-2.0/ssl/ssl_intro.html
@@ -52,6 +53,7 @@
 #include "sslgen.h" /* generic SSL protos etc */
 #include "ssluse.h" /* OpenSSL versions */
 #include "gtls.h"   /* GnuTLS versions */
+#include "nssg.h"   /* NSS versions */
 #include "sendf.h"
 #include "strequal.h"
 #include "url.h"
@@ -169,8 +171,12 @@
 #ifdef USE_GNUTLS
   return Curl_gtls_init();
 #else
+#ifdef USE_NSS
+  return Curl_nss_init();
+#else
   /* no SSL support */
   return 1;
+#endif /* USE_NSS */
 #endif /* USE_GNUTLS */
 #endif /* USE_SSLEAY */
 }
@@ -186,6 +192,9 @@
 #else
 #ifdef USE_GNUTLS
     Curl_gtls_cleanup();
+#ifdef USE_NSS
+    Curl_nss_cleanup();
+#endif /* USE_NSS */
 #endif /* USE_GNUTLS */
 #endif /* USE_SSLEAY */
     init_ssl = FALSE;
@@ -204,6 +213,10 @@
 #else
 #ifdef USE_GNUTLS
   return Curl_gtls_connect(conn, sockindex);
+#else
+#ifdef USE_NSS
+  return Curl_nss_connect(conn, sockindex);
+#endif /* USE_NSS */
 #endif /* USE_GNUTLS */
 #endif /* USE_SSLEAY */
 
@@ -225,11 +238,15 @@
   return Curl_ossl_connect_nonblocking(conn, sockindex, done);
 
 #else
+#ifdef USE_NSS
+  return Curl_nss_connect(conn, sockindex);
+#else
   /* not implemented!
      fallback to BLOCKING call. */
   *done = TRUE;
   return Curl_ssl_connect(conn, sockindex);
-#endif
+#endif /* USE_NSS */
+#endif /* USE_SSLEAY */
 }
 
 #ifdef USE_SSL
@@ -283,8 +300,14 @@
 #ifdef USE_SSLEAY
     Curl_ossl_session_free(session->sessionid);
 #else
+#ifdef USE_GNUTLS
     Curl_gtls_session_free(session->sessionid);
-#endif
+#else
+#ifdef USE_NSS
+    /* NSS has its own session ID cache */
+#endif /* USE_NSS */
+#endif /* USE_GNUTLS */
+#endif /* USE_SSLEAY */
     session->sessionid=NULL;
     session->age = 0; /* fresh */
 
@@ -375,6 +398,10 @@
 #else
 #ifdef USE_GNUTLS
   Curl_gtls_close_all(data);
+#else
+#ifdef USE_NSS
+  Curl_nss_close_all(data);
+#endif /* USE_NSS */
 #endif /* USE_GNUTLS */
 #endif /* USE_SSLEAY */
 #else /* USE_SSL */
@@ -391,7 +418,11 @@
 #ifdef USE_GNUTLS
     Curl_gtls_close(conn);
 #else
+#ifdef USE_GNUTLS
+    Curl_nss_close(conn);
+#else
   (void)conn;
+#endif /* USE_NSS */
 #endif /* USE_GNUTLS */
 #endif /* USE_SSLEAY */
   }
@@ -410,10 +441,17 @@
   (void)engine;
   return CURLE_FAILED_INIT;
 #else
+#ifdef USE_NSS
+  /* NSS doesn't set an engine this way */
+  (void)data;
+  (void)engine;
+  return CURLE_FAILED_INIT;
+#else
   /* no SSL layer */
   (void)data;
   (void)engine;
   return CURLE_FAILED_INIT;
+#endif /* USE_NSS */
 #endif /* USE_GNUTLS */
 #endif /* USE_SSLEAY */
 }
@@ -430,9 +468,15 @@
   (void)data;
   return CURLE_FAILED_INIT;
 #else
+#ifdef USE_NSS
+  /* A no-op for NSS */
+  (void)data;
+  return CURLE_FAILED_INIT;
+#else
   /* No SSL layer */
   (void)data;
   return CURLE_FAILED_INIT;
+#endif /* USE_NSS */
 #endif /* USE_GNUTLS */
 #endif /* USE_SSLEAY */
 }
@@ -448,8 +492,14 @@
   (void)data;
   return NULL;
 #else
+#ifdef USE_NSS
+  /* In theory we could return the PKCS#11 modules loaded but that
+   * would just confuse things */
   (void)data;
   return NULL;
+  (void)data;
+  return NULL;
+#endif /* USE_NSS */
 #endif /* USE_GNUTLS */
 #endif /* USE_SSLEAY */
 }
@@ -466,11 +516,15 @@
 #ifdef USE_GNUTLS
   return Curl_gtls_send(conn, sockindex, mem, len);
 #else
+#ifdef USE_NSS
+  return Curl_nss_send(conn, sockindex, mem, len);
+#else
   (void)conn;
   (void)sockindex;
   (void)mem;
   (void)len;
   return 0;
+#endif /* USE_NSS */
 #endif /* USE_GNUTLS */
 #endif /* USE_SSLEAY */
 }
@@ -495,6 +549,10 @@
 #else
 #ifdef USE_GNUTLS
   nread = Curl_gtls_recv(conn, sockindex, mem, len, &block);
+#else
+#ifdef USE_NSS
+  nread = Curl_nss_recv(conn, sockindex, mem, len, &block);
+#endif /* USE_NSS */
 #endif /* USE_GNUTLS */
 #endif /* USE_SSLEAY */
   if(nread == -1) {
@@ -555,9 +613,13 @@
 #ifdef USE_GNUTLS
   return Curl_gtls_version(buffer, size);
 #else
+#ifdef USE_NSS
+  return Curl_nss_version(buffer, size);
+#else
   (void)buffer;
   (void)size;
   return 0; /* no SSL support */
+#endif /* USE_NSS */
 #endif /* USE_GNUTLS */
 #endif /* USE_SSLEAY */
 }
@@ -576,8 +638,12 @@
 #ifdef USE_SSLEAY
   return Curl_ossl_check_cxn(conn);
 #else
+#ifdef USE_NSS
+  return Curl_nss_check_cxn(conn);
+#else
   (void)conn;
   /* TODO: we lack implementation of this for GnuTLS */
   return -1; /* connection status unknown */
+#endif /* USE_NSS */
 #endif /* USE_SSLEAY */
 }
Index: lib/urldata.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/urldata.h,v
retrieving revision 1.308
diff -u -r1.308 urldata.h
--- lib/urldata.h	3 Nov 2006 12:43:56 -0000	1.308
+++ lib/urldata.h	12 Feb 2007 15:01:22 -0000
@@ -78,6 +78,10 @@
 #include <gnutls/gnutls.h>
 #endif
 
+#ifdef USE_NSS
+#include <nspr.h>
+#endif
+
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
@@ -169,6 +173,9 @@
   gnutls_session session;
   gnutls_certificate_credentials cred;
 #endif /* USE_GNUTLS */
+#ifdef USE_NSS
+  PRFileDesc *handle;
+#endif /* USE_NSS */
 };
 
 struct ssl_config_data {
Index: tests/runtests.pl
===================================================================
RCS file: /cvsroot/curl/curl/tests/runtests.pl,v
retrieving revision 1.212
diff -u -r1.212 runtests.pl
--- tests/runtests.pl	9 Nov 2006 13:20:42 -0000	1.212
+++ tests/runtests.pl	12 Feb 2007 15:01:23 -0000
@@ -143,6 +143,7 @@
 my $has_ntlm;    # set if libcurl is built with NTLM support
 my $has_openssl; # set if libcurl is built with OpenSSL
 my $has_gnutls;  # set if libcurl is built with GnuTLS
+my $has_nss;     # set if libcurl is built with NSS
 my $has_textaware; # set if running on a system that has a text mode concept
   # on files. Windows for example
 
@@ -955,6 +956,10 @@
                # GnuTLS in use
                $has_gnutls=1;
            }
+           elsif ($libcurl =~ /nss/i) {
+               # NSS in use
+               $has_nss=1;
+           }
         }
         elsif($_ =~ /^Protocols: (.*)/i) {
             # these are the supported protocols, we don't use this knowledge
@@ -1083,7 +1088,7 @@
 
     if($ssl_version) {
         logmsg sprintf("* SSL library:    %s\n",
-               $has_gnutls?"GnuTLS":($has_openssl?"OpenSSL":"<unknown>"));
+               $has_gnutls?"GnuTLS":($has_openssl?"OpenSSL":($has_nss?"NSS":"<unknown>")));
     }
 
     $has_textaware = ($^O eq 'MSWin32') || ($^O eq 'msys');
@@ -1178,6 +1183,11 @@
                 next;
             }
         }
+        elsif($f eq "NSS") {
+            if($has_nss) {
+                next;
+            }
+        }
         elsif($f eq "netrc_debug") {
             if($curl_debug) {
                 next;

