Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Rob Crittenden added support for NSS (Network Security Service) for the

  • Loading branch information...
commit 7f70dbcad58eb7183d129860192d6968dd7063a1 1 parent 28b932f
Daniel Stenberg authored
5 CHANGES
@@ -7,6 +7,11 @@
7 7 Changelog
8 8
9 9 Daniel (12 February 2007)
  10 +- Rob Crittenden added support for NSS (Network Security Service) for the
  11 + SSL/TLS layer. http://www.mozilla.org/projects/security/pki/nss/
  12 +
  13 + This is the fourth supported library for TLS/SSL that libcurl supports!
  14 +
10 15 - Shmulik Regev fixed so that the final CRLF of HTTP response headers are sent
11 16 to the debug callback.
12 17
4 RELEASE-NOTES
@@ -14,6 +14,7 @@ This release includes the following changes:
14 14 o Added CURLOPT_TIMEOUT_MS and CURLOPT_CONNECTTIMEOUT_MS
15 15 o Added CURLOPT_HTTP_CONTENT_DECODING, CURLOPT_HTTP_TRANSFER_DECODING and
16 16 --raw
  17 + o Added support for using the NSS library for TLS/SSL
17 18
18 19 This release includes the following bugfixes:
19 20
@@ -36,6 +37,7 @@ New curl mirrors:
36 37 This release would not have looked like this without help, code, reports and
37 38 advice from friends like these:
38 39
39   - Yang Tse, Manfred Schwarb, Michael Wallner, Jeff Pohlmeyer, Shmulik Regev
  40 + Yang Tse, Manfred Schwarb, Michael Wallner, Jeff Pohlmeyer, Shmulik Regev,
  41 + Rob Crittenden
40 42
41 43 Thanks! (and sorry if I forgot to mention someone)
83 configure.ac
@@ -1183,6 +1183,7 @@ if test "$OPENSSL_ENABLED" != "1"; then
1183 1183 [
1184 1184 AC_DEFINE(USE_GNUTLS, 1, [if GnuTLS is enabled])
1185 1185 AC_SUBST(USE_GNUTLS, [1])
  1186 + GNUTLS_ENABLED = 1
1186 1187 USE_GNUTLS="yes"
1187 1188 curl_ssl_msg="enabled (GnuTLS)"
1188 1189 ],
@@ -1208,13 +1209,85 @@ if test "$OPENSSL_ENABLED" != "1"; then
1208 1209
1209 1210 fi dnl GNUTLS not disabled
1210 1211
1211   - if test X"$USE_GNUTLS" != "Xyes"; then
1212   - AC_MSG_WARN([SSL disabled, you will not be able to use HTTPS, FTPS, NTLM and more.])
1213   - AC_MSG_WARN([Use --with-ssl or --with-gnutls to address this.])
1214   - fi
1215   -
1216 1212 fi dnl OPENSSL != 1
1217 1213
  1214 +dnl ----------------------------------------------------
  1215 +dnl NSS. Only check if GnuTLS and OpenSSL are not enabled
  1216 +dnl ----------------------------------------------------
  1217 +
  1218 +dnl Default to compiler & linker defaults for NSS files & libraries.
  1219 +OPT_NSS=no
  1220 +
  1221 +AC_ARG_WITH(nss,dnl
  1222 +AC_HELP_STRING([--with-nss=PATH],[where to look for NSS, PATH points to the installation root (default: /usr/local/)])
  1223 +AC_HELP_STRING([--without-nss], [disable NSS detection]),
  1224 + OPT_NSS=$withval)
  1225 +
  1226 +if test "$OPENSSL_ENABLED" != "1" -a "$GNUTLS_ENABLED" != "1"; then
  1227 +
  1228 + if test X"$OPT_NSS" != Xno; then
  1229 + if test "x$OPT_NSS" = "xyes"; then
  1230 + check=`pkg-config --version 2>/dev/null`
  1231 + if test -n "$check"; then
  1232 + addlib=`pkg-config --libs nss`
  1233 + addcflags=`pkg-config --cflags nss`
  1234 + version=`pkg-config --modversion nss`
  1235 + nssprefix=`pkg-config --variable=prefix nss`
  1236 + fi
  1237 + else
  1238 + # Without pkg-config, we'll kludge in some defaults
  1239 + addlib="-lssl3 -lsmime3 -lnss3 -lplds4 -lplc4 -lnspr4 -lpthread -ldl"
  1240 + addcflags="-I$OPT_NSS/include"
  1241 + version="unknown"
  1242 + gtlsprefix=$OPT_GNUTLS
  1243 + fi
  1244 + if test -n "$addlib"; then
  1245 +
  1246 + CLEANLIBS="$LIBS"
  1247 + CLEANCPPFLAGS="$CPPFLAGS"
  1248 +
  1249 + LIBS="$LIBS $addlib"
  1250 + if test "$addcflags" != "-I/usr/include"; then
  1251 + CPPFLAGS="$CPPFLAGS $addcflags"
  1252 + fi
  1253 +
  1254 + AC_CHECK_LIB(nss3, NSS_Initialize,
  1255 + [
  1256 + AC_DEFINE(USE_NSS, 1, [if NSS is enabled])
  1257 + AC_SUBST(USE_NSS, [1])
  1258 + USE_NSS="yes"
  1259 + NSS_ENABLED=1
  1260 + curl_ssl_msg="enabled (NSS)"
  1261 + ],
  1262 + [
  1263 + LIBS="$CLEANLIBS"
  1264 + CPPFLAGS="$CLEANCPPFLAGS"
  1265 + ])
  1266 +
  1267 + if test "x$USE_NSS" = "xyes"; then
  1268 + AC_MSG_NOTICE([detected NSS version $version])
  1269 +
  1270 + dnl when shared libs were found in a path that the run-time
  1271 + dnl linker doesn't search through, we need to add it to
  1272 + dnl LD_LIBRARY_PATH to prevent further configure tests to fail
  1273 + dnl due to this
  1274 +
  1275 + LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$nssprefix/lib$libsuff"
  1276 + export LD_LIBRARY_PATH
  1277 + AC_MSG_NOTICE([Added $nssprefix/lib$libsuff to LD_LIBRARY_PATH])
  1278 + fi
  1279 +
  1280 + fi
  1281 +
  1282 + fi dnl NSS not disabled
  1283 +
  1284 +fi dnl OPENSSL != 1 -a GNUTLS_ENABLED != 1
  1285 +
  1286 +if test "x$OPENSSL_ENABLED$GNUTLS_ENABLED$NSS_ENABLED" = "x"; then
  1287 + AC_MSG_WARN([SSL disabled, you will not be able to use HTTPS, FTPS, NTLM and more.])
  1288 + AC_MSG_WARN([Use --with-ssl, --with-gnutls or --with-nss to address this.])
  1289 +fi
  1290 +
1218 1291 dnl **********************************************************************
1219 1292 dnl Check for the CA bundle
1220 1293 dnl **********************************************************************
10 docs/FAQ
@@ -358,10 +358,10 @@ FAQ
358 358
359 359 2.2 Does curl work/build with other SSL libraries?
360 360
361   - Curl has been written to use OpenSSL, GnuTLS or yassl, although there should
362   - not be many problems using a different library. If anyone does "port" curl
363   - to use a different SSL library, we are of course very interested in getting
364   - the patch!
  361 + Curl has been written to use OpenSSL, GnuTLS, yassl or NSS, although there
  362 + should not be many problems using a different library. If anyone does "port"
  363 + curl to use a different SSL library, we are of course very interested in
  364 + getting the patch!
365 365
366 366 2.3 Where can I find a copy of LIBEAY32.DLL?
367 367
@@ -844,6 +844,8 @@ FAQ
844 844
845 845 http://www.gnu.org/software/gnutls/manual/html_node/Multi_002dthreaded-applications.html
846 846
  847 + No special locking is needed with a NSS-powered libcurl. NSS is thread-safe.
  848 +
847 849 5.2 How can I receive all data into a large memory chunk?
848 850
849 851 [ See also the examples/getinmemory.c source ]
4 docs/FEATURES
@@ -116,10 +116,10 @@ FILE
116 116 FOOTNOTES
117 117 =========
118 118
119   - *1 = requires OpenSSL or GnuTLS
  119 + *1 = requires OpenSSL, GnuTLS or NSS
120 120 *2 = requires OpenLDAP
121 121 *3 = requires a GSSAPI-compliant library, such as Heimdal or similar.
122 122 *4 = requires FBopenssl
123 123 *5 = requires a krb4 library, such as the MIT one or similar.
124 124 *6 = requires c-ares
125   - *7 = requires OpenSSL specificly, as GnuTLS only supports SSLv3 and TLSv1
  125 + *7 = requires OpenSSL or NSS, as GnuTLS only supports SSLv3 and TLSv1
3  docs/INSTALL
@@ -140,6 +140,9 @@ UNIX
140 140 yassl with its OpenSSL emulation enabled and point to that directory root
141 141 with configure --with-ssl.
142 142
  143 + To build with NSS support instead of OpenSSL for SSL/TLS, note that
  144 + you need to use both --without-ssl and --with-nss.
  145 +
143 146
144 147 Win32
145 148 =====
10 docs/LICENSE-MIXING
@@ -47,6 +47,14 @@ yassl http://www.yassl.com/
47 47 (May be used for SSL/TLS support) Uses the GPL[1] license. If this is
48 48 a problem for you, consider using OpenSSL or GnuTLS instead.
49 49
  50 +NSS http://www.mozilla.org/projects/security/pki/nss/
  51 +
  52 + (May be used for SSL/TLS support) Is covered by the MPL[4] license,
  53 + the GPL[1] license and the LGPL[3] license. You may choose to license
  54 + the code under MPL terms, GPL terms, or LGPL terms. These licenses
  55 + grant you different permissions and impose different obligations. You
  56 + should select the license that best meets your needs.
  57 +
50 58 c-ares http://daniel.haxx.se/projects/c-ares/license.html
51 59
52 60 (Used for asynchronous name resolves) Uses an MIT license that is very
@@ -110,3 +118,5 @@ OpenLDAP http://www.openldap.org/software/release/license.html
110 118 how to write such an exception to the GPL
111 119 [3] = LGPL - GNU Lesser General Public License:
112 120 http://www.gnu.org/licenses/lgpl.html
  121 +[4] = MPL - Mozilla Public License:
  122 + http://www.mozilla.org/MPL/
8 docs/TODO
@@ -157,16 +157,14 @@ TODO
157 157 Clark)
158 158
159 159 * Make curl's SSL layer capable of using other free SSL libraries. Such as
160   - Mozilla Security Services
161   - (http://www.mozilla.org/projects/security/pki/nss/) or MatrixSSL
162   - (http://www.matrixssl.org/).
  160 + MatrixSSL (http://www.matrixssl.org/).
163 161
164 162 * Peter Sylvester's patch for SRP on the TLS layer.
165 163 Awaits OpenSSL support for this, no need to support this in libcurl before
166 164 there's an OpenSSL release that does it.
167 165
168   - * make the configure --with-ssl option first check for OpenSSL and then for
169   - GnuTLS if OpenSSL wasn't detected.
  166 + * make the configure --with-ssl option first check for OpenSSL, then GnuTLS,
  167 + then NSS...
170 168
171 169 GnuTLS
172 170
11 docs/curl.1
@@ -167,6 +167,10 @@ difference.
167 167 must be using valid ciphers. Read up on SSL cipher list details on this URL:
168 168 \fIhttp://www.openssl.org/docs/apps/ciphers.html\fP
169 169
  170 +NSS ciphers are done differently than OpenSSL and GnuTLS. The full list of
  171 +NSS ciphers is in the NSSCipherSuite entry at this URL:
  172 +\fIhttp://directory.fedora.redhat.com/docs/mod_nss.html#Directives\fP
  173 +
170 174 If this option is used several times, the last one will override the others.
171 175 .IP "--compressed"
172 176 (HTTP) Request a compressed response using one of the algorithms libcurl
@@ -323,6 +327,10 @@ this option assumes a \&"certificate" file that is the private key and the
323 327 private certificate concatenated! See \fI--cert\fP and \fI--key\fP to specify
324 328 them independently.
325 329
  330 +If curl is built against the NSS SSL library then this option tells
  331 +curl the nickname of the certificate to use within the NSS database defined
  332 +by --cacert.
  333 +
326 334 If this option is used several times, the last one will be used.
327 335 .IP "--cert-type <type>"
328 336 (SSL) Tells curl what certificate type the provided certificate is in. PEM,
@@ -342,6 +350,9 @@ The windows version of curl will automatically look for a CA certs file named
342 350 \'curl-ca-bundle.crt\', either in the same directory as curl.exe, or in the
343 351 Current Working Directory, or in any folder along your PATH.
344 352
  353 +If curl is built against the NSS SSL library then this option tells
  354 +curl the directory that the NSS certificate database resides in.
  355 +
345 356 If this option is used several times, the last one will be used.
346 357 .IP "--capath <CA certificate directory>"
347 358 (SSL) Tells curl to use the specified certificate directory to verify the
23 docs/libcurl/curl_easy_setopt.3
@@ -1178,6 +1178,9 @@ transfers. (Added in 7.15.2)
1178 1178 Pass a pointer to a zero terminated string as parameter. The string should be
1179 1179 the file name of your certificate. The default format is "PEM" and can be
1180 1180 changed with \fICURLOPT_SSLCERTTYPE\fP.
  1181 +
  1182 +With NSS this is the nickname of the certificate you wish to authenticate
  1183 +with.
1181 1184 .IP CURLOPT_SSLCERTTYPE
1182 1185 Pass a pointer to a zero terminated string as parameter. The string should be
1183 1186 the format of your certificate. Supported formats are "PEM" and "DER". (Added
@@ -1222,8 +1225,8 @@ Pass a long as parameter to control what version of SSL/TLS to attempt to use.
1222 1225 The available options are:
1223 1226 .RS
1224 1227 .IP CURL_SSLVERSION_DEFAULT
1225   -The default action. When libcurl built with OpenSSL, this will attempt to
1226   -figure out the remote SSL protocol version. Unfortunately there are a lot of
  1228 +The default action. When libcurl built with OpenSSL or NSS, this will attempt
  1229 +to figure out the remote SSL protocol version. Unfortunately there are a lot of
1227 1230 ancient and broken servers in use which cannot handle this technique and will
1228 1231 fail to connect. When libcurl is built with GnuTLS, this will mean SSLv3.
1229 1232 .IP CURL_SSLVERSION_TLSv1
@@ -1266,6 +1269,9 @@ even indicate an accessible file.
1266 1269
1267 1270 Note that option is by default set to the system path where libcurl's cacert
1268 1271 bundle is assumed to be stored, as established at build time.
  1272 +
  1273 +When built against NSS this is the directory that the NSS certificate
  1274 +database resides in.
1269 1275 .IP CURLOPT_CAPATH
1270 1276 Pass a char * to a zero terminated string naming a directory holding multiple
1271 1277 CA certificates to verify the peer with. The certificate directory must be
@@ -1315,12 +1321,23 @@ Pass a char *, pointing to a zero terminated string holding the list of
1315 1321 ciphers to use for the SSL connection. The list must be syntactically correct,
1316 1322 it consists of one or more cipher strings separated by colons. Commas or spaces
1317 1323 are also acceptable separators but colons are normally used, \!, \- and \+ can
1318   -be used as operators. Valid examples of cipher lists include 'RC4-SHA',
  1324 +be used as operators.
  1325 +
  1326 +For OpenSSL and GnuTLS valid examples of cipher lists include 'RC4-SHA',
1319 1327 \'SHA1+DES\', 'TLSv1' and 'DEFAULT'. The default list is normally set when you
1320 1328 compile OpenSSL.
1321 1329
1322 1330 You'll find more details about cipher lists on this URL:
1323 1331 \fIhttp://www.openssl.org/docs/apps/ciphers.html\fP
  1332 +
  1333 +For NSS valid examples of cipher lists include 'rsa_rc4_128_md5',
  1334 +\'rsa_aes_128_sha\', etc. With NSS you don't add/remove ciphers. If one uses
  1335 +this option then all known ciphers are disabled and only those passed in
  1336 +are enabled.
  1337 +
  1338 +You'll find more details about the NSS cipher lists on this URL:
  1339 +\fIhttp://directory.fedora.redhat.com/docs/mod_nss.html#Directives\fP
  1340 +
1324 1341 .IP CURLOPT_SSL_SESSIONID_CACHE
1325 1342 Pass a long set to 0 to disable libcurl's use of SSL session-ID caching. Set
1326 1343 this to 1 to enable it. By default all transfers are done using the
7 lib/Makefile.inc
@@ -8,7 +8,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
8 8 content_encoding.c share.c http_digest.c md5.c http_negotiate.c \
9 9 http_ntlm.c inet_pton.c strtoofft.c strerror.c hostares.c hostasyn.c \
10 10 hostip4.c hostip6.c hostsyn.c hostthre.c inet_ntop.c parsedate.c \
11   - select.c gtls.c sslgen.c tftp.c splay.c strdup.c socks.c ssh.c
  11 + select.c gtls.c sslgen.c tftp.c splay.c strdup.c socks.c ssh.c nss.c
12 12
13 13 HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \
14 14 progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
@@ -18,6 +18,5 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \
18 18 share.h md5.h http_digest.h http_negotiate.h http_ntlm.h ca-bundle.h \
19 19 inet_pton.h strtoofft.h strerror.h inet_ntop.h curlx.h memory.h \
20 20 setup.h transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h \
21   - gtls.h tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h
22   -
23   -
  21 + gtls.h tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h \
  22 + nssg.h
12 lib/http.c
@@ -1502,6 +1502,18 @@ int Curl_https_getsock(struct connectdata *conn,
1502 1502 (void)numsocks;
1503 1503 return GETSOCK_BLANK;
1504 1504 }
  1505 +#else
  1506 +#ifdef USE_NSS
  1507 +int Curl_https_getsock(struct connectdata *conn,
  1508 + curl_socket_t *socks,
  1509 + int numsocks)
  1510 +{
  1511 + (void)conn;
  1512 + (void)socks;
  1513 + (void)numsocks;
  1514 + return GETSOCK_BLANK;
  1515 +}
  1516 +#endif
1505 1517 #endif
1506 1518 #endif
1507 1519
605 lib/nss.c
... ... @@ -0,0 +1,605 @@
  1 +/***************************************************************************
  2 + * _ _ ____ _
  3 + * Project ___| | | | _ \| |
  4 + * / __| | | | |_) | |
  5 + * | (__| |_| | _ <| |___
  6 + * \___|\___/|_| \_\_____|
  7 + *
  8 + * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
  9 + *
  10 + * This software is licensed as described in the file COPYING, which
  11 + * you should have received as part of this distribution. The terms
  12 + * are also available at http://curl.haxx.se/docs/copyright.html.
  13 + *
  14 + * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15 + * copies of the Software, and permit persons to whom the Software is
  16 + * furnished to do so, under the terms of the COPYING file.
  17 + *
  18 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19 + * KIND, either express or implied.
  20 + *
  21 + * $Id$
  22 + ***************************************************************************/
  23 +
  24 +/*
  25 + * Source file for all NSS-specific code for the TLS/SSL layer. No code
  26 + * but sslgen.c should ever call or use these functions.
  27 + */
  28 +
  29 +#include "setup.h"
  30 +
  31 +#include <string.h>
  32 +#include <stdlib.h>
  33 +#include <ctype.h>
  34 +#ifdef HAVE_SYS_TYPES_H
  35 +#include <sys/types.h>
  36 +#endif
  37 +#ifdef HAVE_SYS_SOCKET_H
  38 +#include <sys/socket.h>
  39 +#endif
  40 +
  41 +#include "urldata.h"
  42 +#include "sendf.h"
  43 +#include "formdata.h" /* for the boundary function */
  44 +#include "url.h" /* for the ssl config check function */
  45 +#include "connect.h" /* Curl_sockerrno() proto */
  46 +#include "strequal.h"
  47 +#include "select.h"
  48 +#include "sslgen.h"
  49 +
  50 +#define _MPRINTF_REPLACE /* use the internal *printf() functions */
  51 +#include <curl/mprintf.h>
  52 +
  53 +#ifdef USE_NSS
  54 +
  55 +#include "nssg.h"
  56 +#include <nspr.h>
  57 +#include <nss.h>
  58 +#include <ssl.h>
  59 +#include <sslerr.h>
  60 +#include <secerr.h>
  61 +#include <sslproto.h>
  62 +#include <prtypes.h>
  63 +#include <pk11pub.h>
  64 +
  65 +#include "memory.h"
  66 +#include "easyif.h" /* for Curl_convert_from_utf8 prototype */
  67 +
  68 +/* The last #include file should be: */
  69 +#include "memdebug.h"
  70 +
  71 +#ifndef min
  72 +#define min(a, b) ((a) < (b) ? (a) : (b))
  73 +#endif
  74 +
  75 +PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
  76 +
  77 +static int initialized = 0;
  78 +static int noverify = 0;
  79 +
  80 +typedef struct {
  81 + PRInt32 retryCount;
  82 + struct SessionHandle *data;
  83 +} pphrase_arg_t;
  84 +
  85 +typedef struct {
  86 + const char *name;
  87 + int num;
  88 + PRInt32 version; /* protocol version valid for this cipher */
  89 +} cipher_s;
  90 +
  91 +/* the table itself is defined in nss_engine_init.c */
  92 +#ifdef NSS_ENABLE_ECC
  93 +#define ciphernum 48
  94 +#else
  95 +#define ciphernum 23
  96 +#endif
  97 +
  98 +enum sslversion { SSL2 = 1, SSL3 = 2, TLS = 4 };
  99 +
  100 +cipher_s cipherlist[ciphernum] = {
  101 + /* SSL2 cipher suites */
  102 + {"rc4", SSL_EN_RC4_128_WITH_MD5, SSL2},
  103 + {"rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5, SSL2},
  104 + {"rc2", SSL_EN_RC2_128_CBC_WITH_MD5, SSL2},
  105 + {"rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, SSL2},
  106 + {"des", SSL_EN_DES_64_CBC_WITH_MD5, SSL2},
  107 + {"desede3", SSL_EN_DES_192_EDE3_CBC_WITH_MD5, SSL2},
  108 + /* SSL3/TLS cipher suites */
  109 + {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5, SSL3 | TLS},
  110 + {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA, SSL3 | TLS},
  111 + {"rsa_3des_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL3 | TLS},
  112 + {"rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA, SSL3 | TLS},
  113 + {"rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL3 | TLS},
  114 + {"rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL3 | TLS},
  115 + {"rsa_null_md5", SSL_RSA_WITH_NULL_MD5, SSL3 | TLS},
  116 + {"rsa_null_sha", SSL_RSA_WITH_NULL_SHA, SSL3 | TLS},
  117 + {"fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL3 | TLS},
  118 + {"fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA, SSL3 | TLS},
  119 + {"fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, SSL3 | TLS},
  120 + {"fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, SSL3 | TLS},
  121 + {"fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA, SSL3 | TLS},
  122 + /* TLS 1.0: Exportable 56-bit Cipher Suites. */
  123 + {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL3 | TLS},
  124 + {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL3 | TLS},
  125 + /* AES ciphers. */
  126 + {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA, SSL3 | TLS},
  127 + {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA, SSL3 | TLS},
  128 +#ifdef NSS_ENABLE_ECC
  129 + /* ECC ciphers. */
  130 + {"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA, TLS},
  131 + {"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS},
  132 + {"ecdh_ecdsa_3des_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS},
  133 + {"ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS},
  134 + {"ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS},
  135 + {"ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLS},
  136 + {"ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS},
  137 + {"ecdhe_ecdsa_3des_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS},
  138 + {"ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS},
  139 + {"ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS},
  140 + {"ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA, TLS},
  141 + {"ecdh_rsa_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA, TLS},
  142 + {"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, TLS},
  143 + {"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS},
  144 + {"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS},
  145 + {"echde_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA, TLS},
  146 + {"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS},
  147 + {"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS},
  148 + {"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS},
  149 + {"ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS},
  150 + {"ecdh_anon_null_sha", TLS_ECDH_anon_WITH_NULL_SHA, TLS},
  151 + {"ecdh_anon_rc4_128sha", TLS_ECDH_anon_WITH_RC4_128_SHA, TLS},
  152 + {"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, TLS},
  153 + {"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA, TLS},
  154 + {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA, TLS},
  155 +#endif
  156 +};
  157 +
  158 +static SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model,
  159 + char *cipher_list)
  160 +{
  161 + int i;
  162 + PRBool cipher_state[ciphernum];
  163 + PRBool found;
  164 + char *cipher;
  165 + SECStatus rv;
  166 +
  167 + /* First disable all ciphers. This uses a different max value in case
  168 + * NSS adds more ciphers later we don't want them available by
  169 + * accident
  170 + */
  171 + for(i=0; i<SSL_NumImplementedCiphers; i++) {
  172 + SSL_CipherPrefSet(model, SSL_ImplementedCiphers[i], SSL_NOT_ALLOWED);
  173 + }
  174 +
  175 + /* Set every entry in our list to false */
  176 + for(i=0; i<ciphernum; i++) {
  177 + cipher_state[i] = PR_FALSE;
  178 + }
  179 +
  180 + cipher = cipher_list;
  181 +
  182 + while(cipher_list && (cipher_list[0])) {
  183 + while((*cipher) && (isspace(*cipher)))
  184 + ++cipher;
  185 +
  186 + if((cipher_list = strchr(cipher, ','))) {
  187 + *cipher_list++ = '\0';
  188 + }
  189 +
  190 + found = PR_FALSE;
  191 +
  192 + for(i=0; i<ciphernum; i++) {
  193 + if(!strcasecmp(cipher, cipherlist[i].name)) {
  194 + cipher_state[i] = PR_TRUE;
  195 + found = PR_TRUE;
  196 + break;
  197 + }
  198 + }
  199 +
  200 + if(found == PR_FALSE) {
  201 + char buf[1024];
  202 + snprintf(buf, 1024, "Unknown cipher in list: %s", cipher);
  203 + failf(data, buf);
  204 + return SECFailure;
  205 + }
  206 +
  207 + if(cipher_list) {
  208 + cipher = cipher_list;
  209 + }
  210 + }
  211 +
  212 + /* Finally actually enable the selected ciphers */
  213 + for(i=0; i<ciphernum; i++) {
  214 + rv = SSL_CipherPrefSet(model, cipherlist[i].num, cipher_state[i]);
  215 + if(rv != SECSuccess) {
  216 + failf(data, "Unknown cipher in cipher list");
  217 + return SECFailure;
  218 + }
  219 + }
  220 +
  221 + return SECSuccess;
  222 +}
  223 +
  224 +static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg)
  225 +{
  226 + pphrase_arg_t *parg = (pphrase_arg_t *) arg;
  227 + (void)slot; /* unused */
  228 + (void)retry; /* unused */
  229 + if(parg->data->set.key_passwd)
  230 + return (char *)PORT_Strdup((char *)parg->data->set.key_passwd);
  231 + else
  232 + return NULL;
  233 +}
  234 +
  235 +static SECStatus nss_Init_Tokens(struct connectdata * conn)
  236 +{
  237 + PK11SlotList *slotList;
  238 + PK11SlotListElement *listEntry;
  239 + SECStatus ret, status = SECSuccess;
  240 + pphrase_arg_t *parg;
  241 +
  242 + parg = (pphrase_arg_t *) malloc(sizeof(*parg));
  243 + parg->retryCount = 0;
  244 + parg->data = conn->data;
  245 +
  246 + PK11_SetPasswordFunc(nss_get_password);
  247 +
  248 + slotList =
  249 + PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_TRUE, NULL);
  250 +
  251 + for(listEntry = PK11_GetFirstSafe(slotList);
  252 + listEntry; listEntry = listEntry->next) {
  253 + PK11SlotInfo *slot = listEntry->slot;
  254 +
  255 + if(PK11_NeedLogin(slot) && PK11_NeedUserInit(slot)) {
  256 + if(slot == PK11_GetInternalKeySlot()) {
  257 + failf(conn->data, "The NSS database has not been initialized.\n");
  258 + }
  259 + else {
  260 + failf(conn->data, "The token %s has not been initialized.",
  261 + PK11_GetTokenName(slot));
  262 + }
  263 + PK11_FreeSlot(slot);
  264 + continue;
  265 + }
  266 +
  267 + ret = PK11_Authenticate(slot, PR_TRUE, parg);
  268 + if(SECSuccess != ret) {
  269 + status = SECFailure;
  270 + break;
  271 + }
  272 + parg->retryCount = 0; /* reset counter to 0 for the next token */
  273 + PK11_FreeSlot(slot);
  274 + }
  275 +
  276 + free(parg);
  277 + return status;
  278 +}
  279 +
  280 +static SECStatus BadCertHandler(void *arg, PRFileDesc * socket)
  281 +{
  282 + SECStatus success = SECSuccess;
  283 + (void)arg;
  284 + (void)socket;
  285 +
  286 + return success;
  287 +}
  288 +
  289 +/**
  290 + * Inform the application that the handshake is complete.
  291 + */
  292 +static SECStatus HandshakeCallback(PRFileDesc * socket, void *arg)
  293 +{
  294 + (void)socket;
  295 + (void)arg;
  296 + return SECSuccess;
  297 +}
  298 +
  299 +/**
  300 + *
  301 + * Callback to pick the SSL client certificate.
  302 + */
  303 +static SECStatus SelectClientCert(void *arg, PRFileDesc * socket,
  304 + struct CERTDistNamesStr * caNames,
  305 + struct CERTCertificateStr ** pRetCert,
  306 + struct SECKEYPrivateKeyStr ** pRetKey)
  307 +{
  308 + CERTCertificate *cert;
  309 + SECKEYPrivateKey *privKey;
  310 + char *nickname = (char *)arg;
  311 + void *proto_win = NULL;
  312 + SECStatus secStatus = SECFailure;
  313 + (void)caNames;
  314 +
  315 + proto_win = SSL_RevealPinArg(socket);
  316 +
  317 + cert = PK11_FindCertFromNickname(nickname, proto_win);
  318 + if(cert) {
  319 + privKey = PK11_FindKeyByAnyCert(cert, proto_win);
  320 + if(privKey) {
  321 + secStatus = SECSuccess;
  322 + }
  323 + else {
  324 + CERT_DestroyCertificate(cert);
  325 + }
  326 + }
  327 +
  328 + if(secStatus == SECSuccess) {
  329 + *pRetCert = cert;
  330 + *pRetKey = privKey;
  331 + }
  332 +
  333 + return secStatus;
  334 +}
  335 +
  336 +/**
  337 + * Global SSL init
  338 + *
  339 + * @retval 0 error initializing SSL
  340 + * @retval 1 SSL initialized successfully
  341 + */
  342 +int Curl_nss_init(void)
  343 +{
  344 + if(!initialized)
  345 + PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
  346 +
  347 + /* We will actually initialize NSS later */
  348 +
  349 + return 1;
  350 +}
  351 +
  352 +/* Global cleanup */
  353 +void Curl_nss_cleanup(void)
  354 +{
  355 + NSS_Shutdown();
  356 + initialized = 0;
  357 +}
  358 +
  359 +/*
  360 + * This function uses SSL_peek to determine connection status.
  361 + *
  362 + * Return codes:
  363 + * 1 means the connection is still in place
  364 + * 0 means the connection has been closed
  365 + * -1 means the connection status is unknown
  366 + */
  367 +int
  368 +Curl_nss_check_cxn(struct connectdata *conn)
  369 +{
  370 + int rc;
  371 + char buf;
  372 +
  373 + rc =
  374 + PR_Recv(conn->ssl[FIRSTSOCKET].handle, (void *)&buf, 1, PR_MSG_PEEK,
  375 + PR_SecondsToInterval(1));
  376 + if(rc > 0)
  377 + return 1; /* connection still in place */
  378 +
  379 + if(rc == 0)
  380 + return 0; /* connection has been closed */
  381 +
  382 + return -1; /* connection status unknown */
  383 +}
  384 +
  385 +/*
  386 + * This function is called when an SSL connection is closed.
  387 + */
  388 +void Curl_nss_close(struct connectdata *conn)
  389 +{
  390 + int i;
  391 +
  392 + for(i=0; i<2; i++) {
  393 + struct ssl_connect_data *connssl = &conn->ssl[i];
  394 +
  395 + if(connssl->handle) {
  396 + PR_Close(connssl->handle);
  397 + connssl->handle = NULL;
  398 + }
  399 + connssl->use = FALSE; /* get back to ordinary socket usage */
  400 + }
  401 +}
  402 +
  403 +/*
  404 + * This function is called when the 'data' struct is going away. Close
  405 + * down everything and free all resources!
  406 + */
  407 +int Curl_nss_close_all(struct SessionHandle *data)
  408 +{
  409 + (void)data;
  410 + return 0;
  411 +}
  412 +
  413 +CURLcode Curl_nss_connect(struct connectdata * conn, int sockindex)
  414 +{
  415 + PRInt32 err;
  416 + PRFileDesc *model = NULL;
  417 + PRBool ssl2, ssl3, tlsv1;
  418 + struct SessionHandle *data = conn->data;
  419 + curl_socket_t sockfd = conn->sock[sockindex];
  420 + struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  421 + SECStatus rv;
  422 + int curlerr = CURLE_SSL_CONNECT_ERROR;
  423 +
  424 + /* FIXME. NSS doesn't support multiple databases open at the same time. */
  425 + if(!initialized) {
  426 + if(!data->set.ssl.CAfile) {
  427 + if(data->set.ssl.verifypeer) {
  428 + failf(data, "No NSS cacert database specified.");
  429 + return CURLE_SSL_CACERT_BADFILE;
  430 + }
  431 + else {
  432 + rv = NSS_NoDB_Init(NULL);
  433 + noverify = 1;
  434 + }
  435 + }
  436 + else {
  437 + rv = NSS_Initialize(data->set.ssl.CAfile, NULL, NULL, "secmod.db",
  438 + NSS_INIT_READONLY);
  439 + }
  440 + if(rv != SECSuccess) {
  441 + curlerr = CURLE_SSL_CACERT_BADFILE;
  442 + goto error;
  443 + }
  444 + }
  445 +
  446 + NSS_SetDomesticPolicy();
  447 +
  448 + model = PR_NewTCPSocket();
  449 + if(!model)
  450 + goto error;
  451 + model = SSL_ImportFD(NULL, model);
  452 +
  453 + if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess)
  454 + goto error;
  455 + if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess)
  456 + goto error;
  457 + if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess)
  458 + goto error;
  459 +
  460 + ssl2 = ssl3 = tlsv1 = PR_FALSE;
  461 +
  462 + switch (data->set.ssl.version) {
  463 + default:
  464 + case CURL_SSLVERSION_DEFAULT:
  465 + ssl2 = ssl3 = tlsv1 = PR_TRUE;
  466 + break;
  467 + case CURL_SSLVERSION_TLSv1:
  468 + tlsv1 = PR_TRUE;
  469 + break;
  470 + case CURL_SSLVERSION_SSLv2:
  471 + ssl2 = PR_TRUE;
  472 + break;
  473 + case CURL_SSLVERSION_SSLv3:
  474 + ssl3 = PR_TRUE;
  475 + break;
  476 + }
  477 +
  478 + if(SSL_OptionSet(model, SSL_ENABLE_SSL2, ssl2) != SECSuccess)
  479 + goto error;
  480 + if(SSL_OptionSet(model, SSL_ENABLE_SSL3, ssl3) != SECSuccess)
  481 + goto error;
  482 + if(SSL_OptionSet(model, SSL_ENABLE_TLS, tlsv1) != SECSuccess)
  483 + goto error;
  484 +
  485 + if(data->set.ssl.cipher_list) {
  486 + if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess)
  487 + goto error;
  488 + }
  489 +
  490 + if(SSL_BadCertHook(model, (SSLBadCertHandler) BadCertHandler, NULL)
  491 + != SECSuccess)
  492 + goto error;
  493 + if(SSL_HandshakeCallback(model, (SSLHandshakeCallback) HandshakeCallback,
  494 + NULL) != SECSuccess)
  495 + goto error;
  496 +
  497 + if(data->set.cert) {
  498 + if(SSL_GetClientAuthDataHook(model,
  499 + (SSLGetClientAuthData) SelectClientCert,
  500 + (void *)data->set.cert) != SECSuccess) {
  501 + curlerr = CURLE_SSL_CERTPROBLEM;
  502 + goto error;
  503 + }
  504 + if(nss_Init_Tokens(conn) != SECSuccess)
  505 + goto error;
  506 + }
  507 +
  508 + /* Import our model socket onto the existing file descriptor */
  509 + connssl->handle = PR_ImportTCPSocket(sockfd);
  510 + connssl->handle = SSL_ImportFD(model, connssl->handle);
  511 + if(!connssl->handle)
  512 + goto error;
  513 +
  514 + /* Force handshake on next I/O */
  515 + SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE);
  516 +
  517 + SSL_SetURL(connssl->handle, conn->host.name);
  518 +
  519 + return CURLE_OK;
  520 +
  521 +error:
  522 + err = PR_GetError();
  523 + failf(data, "NSS error %d", err);
  524 + if(model)
  525 + PR_Close(model);
  526 + return curlerr;
  527 +}
  528 +
  529 +/* return number of sent (non-SSL) bytes */
  530 +int Curl_nss_send(struct connectdata *conn, /* connection data */
  531 + int sockindex, /* socketindex */
  532 + void *mem, /* send this data */
  533 + size_t len) /* amount to write */
  534 +{
  535 + PRInt32 err;
  536 + struct SessionHandle *data = conn->data;
  537 + PRInt32 timeout;
  538 + int rc;
  539 +
  540 + if(data->set.timeout)
  541 + timeout = PR_MillisecondsToInterval(data->set.timeout);
  542 + else
  543 + timeout = PR_MillisecondsToInterval(DEFAULT_CONNECT_TIMEOUT);
  544 +
  545 + rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0, timeout);
  546 +
  547 + if(rc < 0) {
  548 + err = PR_GetError();
  549 +
  550 + if(err == PR_IO_TIMEOUT_ERROR) {
  551 + failf(data, "SSL connection timeout");
  552 + return CURLE_OPERATION_TIMEOUTED;
  553 + }
  554 +
  555 + failf(conn->data, "SSL write: error %d\n", err);
  556 + return -1;
  557 + }
  558 + return rc; /* number of bytes */
  559 +}
  560 +
  561 +/*
  562 + * If the read would block we return -1 and set 'wouldblock' to TRUE.
  563 + * Otherwise we return the amount of data read. Other errors should return -1
  564 + * and set 'wouldblock' to FALSE.
  565 + */
  566 +ssize_t Curl_nss_recv(struct connectdata * conn, /* connection data */
  567 + int num, /* socketindex */
  568 + char *buf, /* store read data here */
  569 + size_t buffersize, /* max amount to read */
  570 + bool * wouldblock)
  571 +{
  572 + ssize_t nread;
  573 + struct SessionHandle *data = conn->data;
  574 + PRInt32 timeout;
  575 +
  576 + if(data->set.timeout)
  577 + timeout = PR_SecondsToInterval(data->set.timeout);
  578 + else
  579 + timeout = PR_MillisecondsToInterval(DEFAULT_CONNECT_TIMEOUT);
  580 +
  581 + nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0, timeout);
  582 + *wouldblock = FALSE;
  583 + if(nread < 0) {
  584 + /* failed SSL read */
  585 + PRInt32 err = PR_GetError();
  586 +
  587 + if(err == PR_WOULD_BLOCK_ERROR) {
  588 + *wouldblock = TRUE;
  589 + return -1; /* basically EWOULDBLOCK */
  590 + }
  591 + if(err == PR_IO_TIMEOUT_ERROR) {
  592 + failf(data, "SSL connection timeout");
  593 + return CURLE_OPERATION_TIMEOUTED;
  594 + }
  595 + failf(conn->data, "SSL read: errno %d", err);
  596 + return -1;
  597 + }
  598 + return nread;
  599 +}
  600 +
  601 +size_t Curl_nss_version(char *buffer, size_t size)
  602 +{
  603 + return snprintf(buffer, size, " NSS/%s", NSS_VERSION);
  604 +}
  605 +#endif /* USE_NSS */
57 lib/nssg.h
... ... @@ -0,0 +1,57 @@
  1 +#ifndef __NSSG_H
  2 +#define __NSSG_H
  3 +/***************************************************************************
  4 + * _ _ ____ _
  5 + * Project ___| | | | _ \| |
  6 + * / __| | | | |_) | |
  7 + * | (__| |_| | _ <| |___
  8 + * \___|\___/|_| \_\_____|
  9 + *
  10 + * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
  11 + *
  12 + * This software is licensed as described in the file COPYING, which
  13 + * you should have received as part of this distribution. The terms
  14 + * are also available at http://curl.haxx.se/docs/copyright.html.
  15 + *
  16 + * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  17 + * copies of the Software, and permit persons to whom the Software is
  18 + * furnished to do so, under the terms of the COPYING file.
  19 + *
  20 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  21 + * KIND, either express or implied.
  22 + *
  23 + * $Id$
  24 + ***************************************************************************/
  25 +
  26 +/*
  27 + * This header should only be needed to get included by sslgen.c and nss.c
  28 + */
  29 +
  30 +#include "urldata.h"
  31 +CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex);
  32 +CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
  33 + int sockindex,
  34 + bool *done);
  35 +void Curl_nss_close(struct connectdata *conn); /* close a SSL connection */
  36 +/* tell NSS to close down all open information regarding connections (and
  37 + thus session ID caching etc) */
  38 +int Curl_nss_close_all(struct SessionHandle *data);
  39 +
  40 +int Curl_nss_init(void);
  41 +void Curl_nss_cleanup(void);
  42 +
  43 +int Curl_nss_send(struct connectdata *conn,
  44 + int sockindex,
  45 + void *mem,
  46 + size_t len);
  47 +ssize_t Curl_nss_recv(struct connectdata *conn, /* connection data */
  48 + int num, /* socketindex */
  49 + char *buf, /* store read data here */
  50 + size_t buffersize, /* max amount to read */
  51 + bool *wouldblock);
  52 +
  53 +size_t Curl_nss_version(char *buffer, size_t size);
  54 +int Curl_nss_check_cxn(struct connectdata *cxn);
  55 +int Curl_nss_seed(struct SessionHandle *data);
  56 +
  57 +#endif
4 lib/setup.h
@@ -348,8 +348,8 @@ int fileno( FILE *stream);
348 348 #define HAVE_INET_NTOA_R_2_ARGS 1
349 349 #endif
350 350
351   -#if defined(USE_GNUTLS) || defined(USE_SSLEAY)
352   -#define USE_SSL /* Either OpenSSL || GnuTLS */
  351 +#if defined(USE_GNUTLS) || defined(USE_SSLEAY) || defined(USE_NSS)
  352 +#define USE_SSL /* Either OpenSSL || GnuTLS || NSS */
353 353 #endif
354 354
355 355 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_NTLM)
71 lib/sslgen.c
@@ -31,6 +31,7 @@
31 31 Curl_ssl_ - prefix for generic ones
32 32 Curl_ossl_ - prefix for OpenSSL ones
33 33 Curl_gtls_ - prefix for GnuTLS ones
  34 + Curl_nss_ - prefix for NSS ones
34 35
35 36 "SSL/TLS Strong Encryption: An Introduction"
36 37 http://httpd.apache.org/docs-2.0/ssl/ssl_intro.html
@@ -52,6 +53,7 @@
52 53 #include "sslgen.h" /* generic SSL protos etc */
53 54 #include "ssluse.h" /* OpenSSL versions */
54 55 #include "gtls.h" /* GnuTLS versions */
  56 +#include "nssg.h" /* NSS versions */
55 57 #include "sendf.h"
56 58 #include "strequal.h"
57 59 #include "url.h"
@@ -169,8 +171,12 @@ int Curl_ssl_init(void)
169 171 #ifdef USE_GNUTLS
170 172 return Curl_gtls_init();
171 173 #else
  174 +#ifdef USE_NSS
  175 + return Curl_nss_init();
  176 +#else
172 177 /* no SSL support */
173 178 return 1;
  179 +#endif /* USE_NSS */
174 180 #endif /* USE_GNUTLS */
175 181 #endif /* USE_SSLEAY */
176 182 }
@@ -186,6 +192,9 @@ void Curl_ssl_cleanup(void)
186 192 #else
187 193 #ifdef USE_GNUTLS
188 194 Curl_gtls_cleanup();
  195 +#ifdef USE_NSS
  196 + Curl_nss_cleanup();
  197 +#endif /* USE_NSS */
189 198 #endif /* USE_GNUTLS */
190 199 #endif /* USE_SSLEAY */
191 200 init_ssl = FALSE;
@@ -204,6 +213,10 @@ Curl_ssl_connect(struct connectdata *conn, int sockindex)
204 213 #else
205 214 #ifdef USE_GNUTLS
206 215 return Curl_gtls_connect(conn, sockindex);
  216 +#else
  217 +#ifdef USE_NSS
  218 + return Curl_nss_connect(conn, sockindex);
  219 +#endif /* USE_NSS */
207 220 #endif /* USE_GNUTLS */
208 221 #endif /* USE_SSLEAY */
209 222
@@ -225,11 +238,16 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
225 238 return Curl_ossl_connect_nonblocking(conn, sockindex, done);
226 239
227 240 #else
  241 +#ifdef USE_NSS
  242 + *done = TRUE; /* fallback to BLOCKING */
  243 + return Curl_nss_connect(conn, sockindex);
  244 +#else
228 245 /* not implemented!
229 246 fallback to BLOCKING call. */
230 247 *done = TRUE;
231 248 return Curl_ssl_connect(conn, sockindex);
232   -#endif
  249 +#endif /* USE_NSS */
  250 +#endif /* USE_SSLEAY */
233 251 }
234 252
235 253 #ifdef USE_SSL
@@ -283,8 +301,14 @@ static int kill_session(struct curl_ssl_session *session)
283 301 #ifdef USE_SSLEAY
284 302 Curl_ossl_session_free(session->sessionid);
285 303 #else
  304 +#ifdef USE_GNUTLS
286 305 Curl_gtls_session_free(session->sessionid);
287   -#endif
  306 +#else
  307 +#ifdef USE_NSS
  308 + /* NSS has its own session ID cache */
  309 +#endif /* USE_NSS */
  310 +#endif /* USE_GNUTLS */
  311 +#endif /* USE_SSLEAY */
288 312 session->sessionid=NULL;
289 313 session->age = 0; /* fresh */
290 314
@@ -375,6 +399,10 @@ void Curl_ssl_close_all(struct SessionHandle *data)
375 399 #else
376 400 #ifdef USE_GNUTLS
377 401 Curl_gtls_close_all(data);
  402 +#else
  403 +#ifdef USE_NSS
  404 + Curl_nss_close_all(data);
  405 +#endif /* USE_NSS */
378 406 #endif /* USE_GNUTLS */
379 407 #endif /* USE_SSLEAY */
380 408 #else /* USE_SSL */
@@ -391,7 +419,11 @@ void Curl_ssl_close(struct connectdata *conn)
391 419 #ifdef USE_GNUTLS
392 420 Curl_gtls_close(conn);
393 421 #else
  422 +#ifdef USE_GNUTLS
  423 + Curl_nss_close(conn);
  424 +#else
394 425 (void)conn;
  426 +#endif /* USE_NSS */
395 427 #endif /* USE_GNUTLS */
396 428 #endif /* USE_SSLEAY */
397 429 }
@@ -429,10 +461,17 @@ CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine)
429 461 (void)engine;
430 462 return CURLE_FAILED_INIT;
431 463 #else
  464 +#ifdef USE_NSS
  465 + /* NSS doesn't set an engine this way */
  466 + (void)data;
  467 + (void)engine;
  468 + return CURLE_FAILED_INIT;
  469 +#else
432 470 /* no SSL layer */
433 471 (void)data;
434 472 (void)engine;
435 473 return CURLE_FAILED_INIT;
  474 +#endif /* USE_NSS */
436 475 #endif /* USE_GNUTLS */
437 476 #endif /* USE_SSLEAY */
438 477 }
@@ -449,9 +488,15 @@ CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data)
449 488 (void)data;
450 489 return CURLE_FAILED_INIT;
451 490 #else
  491 +#ifdef USE_NSS
  492 + /* A no-op for NSS */
  493 + (void)data;
  494 + return CURLE_FAILED_INIT;
  495 +#else
452 496 /* No SSL layer */
453 497 (void)data;
454 498 return CURLE_FAILED_INIT;
  499 +#endif /* USE_NSS */
455 500 #endif /* USE_GNUTLS */
456 501 #endif /* USE_SSLEAY */
457 502 }
@@ -467,8 +512,14 @@ struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data)
467 512 (void)data;
468 513 return NULL;
469 514 #else
  515 +#ifdef USE_NSS
  516 + /* In theory we could return the PKCS#11 modules loaded but that
  517 + * would just confuse things */
470 518 (void)data;
471 519 return NULL;
  520 + (void)data;
  521 + return NULL;
  522 +#endif /* USE_NSS */
472 523 #endif /* USE_GNUTLS */
473 524 #endif /* USE_SSLEAY */
474 525 }
@@ -485,11 +536,15 @@ ssize_t Curl_ssl_send(struct connectdata *conn,
485 536 #ifdef USE_GNUTLS
486 537 return Curl_gtls_send(conn, sockindex, mem, len);
487 538 #else
  539 +#ifdef USE_NSS
  540 + return Curl_nss_send(conn, sockindex, mem, len);
  541 +#else
488 542 (void)conn;
489 543 (void)sockindex;
490 544 (void)mem;
491 545 (void)len;
492 546 return 0;
  547 +#endif /* USE_NSS */
493 548 #endif /* USE_GNUTLS */
494 549 #endif /* USE_SSLEAY */
495 550 }
@@ -514,6 +569,10 @@ ssize_t Curl_ssl_recv(struct connectdata *conn, /* connection data */
514 569 #else
515 570 #ifdef USE_GNUTLS
516 571 nread = Curl_gtls_recv(conn, sockindex, mem, len, &block);
  572 +#else
  573 +#ifdef USE_NSS
  574 + nread = Curl_nss_recv(conn, sockindex, mem, len, &block);
  575 +#endif /* USE_NSS */
517 576 #endif /* USE_GNUTLS */
518 577 #endif /* USE_SSLEAY */
519 578 if(nread == -1) {
@@ -574,9 +633,13 @@ size_t Curl_ssl_version(char *buffer, size_t size)
574 633 #ifdef USE_GNUTLS
575 634 return Curl_gtls_version(buffer, size);
576 635 #else
  636 +#ifdef USE_NSS
  637 + return Curl_nss_version(buffer, size);
  638 +#else
577 639 (void)buffer;
578 640 (void)size;
579 641 return 0; /* no SSL support */
  642 +#endif /* USE_NSS */
580 643 #endif /* USE_GNUTLS */
581 644 #endif /* USE_SSLEAY */
582 645 }
@@ -595,9 +658,13 @@ int Curl_ssl_check_cxn(struct connectdata *conn)
595 658 #ifdef USE_SSLEAY
596 659 return Curl_ossl_check_cxn(conn);
597 660 #else
  661 +#ifdef USE_NSS
  662 + return Curl_nss_check_cxn(conn);
  663 +#else
598 664 (void)conn;
599 665 /* TODO: we lack implementation of this for GnuTLS */
600 666 return -1; /* connection status unknown */
  667 +#endif /* USE_NSS */
601