mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
Rob Crittenden added support for NSS (Network Security Service) for the
SSL/TLS layer. http://www.mozilla.org/projects/security/pki/nss/
This commit is contained in:
parent
28b932fb4e
commit
7f70dbcad5
5
CHANGES
5
CHANGES
@ -7,6 +7,11 @@
|
||||
Changelog
|
||||
|
||||
Daniel (12 February 2007)
|
||||
- Rob Crittenden added support for NSS (Network Security Service) for the
|
||||
SSL/TLS layer. http://www.mozilla.org/projects/security/pki/nss/
|
||||
|
||||
This is the fourth supported library for TLS/SSL that libcurl supports!
|
||||
|
||||
- Shmulik Regev fixed so that the final CRLF of HTTP response headers are sent
|
||||
to the debug callback.
|
||||
|
||||
|
@ -14,6 +14,7 @@ This release includes the following changes:
|
||||
o Added CURLOPT_TIMEOUT_MS and CURLOPT_CONNECTTIMEOUT_MS
|
||||
o Added CURLOPT_HTTP_CONTENT_DECODING, CURLOPT_HTTP_TRANSFER_DECODING and
|
||||
--raw
|
||||
o Added support for using the NSS library for TLS/SSL
|
||||
|
||||
This release includes the following bugfixes:
|
||||
|
||||
@ -36,6 +37,7 @@ New curl mirrors:
|
||||
This release would not have looked like this without help, code, reports and
|
||||
advice from friends like these:
|
||||
|
||||
Yang Tse, Manfred Schwarb, Michael Wallner, Jeff Pohlmeyer, Shmulik Regev
|
||||
Yang Tse, Manfred Schwarb, Michael Wallner, Jeff Pohlmeyer, Shmulik Regev,
|
||||
Rob Crittenden
|
||||
|
||||
Thanks! (and sorry if I forgot to mention someone)
|
||||
|
83
configure.ac
83
configure.ac
@ -1183,6 +1183,7 @@ if test "$OPENSSL_ENABLED" != "1"; then
|
||||
[
|
||||
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)"
|
||||
],
|
||||
@ -1208,13 +1209,85 @@ if test "$OPENSSL_ENABLED" != "1"; then
|
||||
|
||||
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"
|
||||
NSS_ENABLED=1
|
||||
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$GNUTLS_ENABLED$NSS_ENABLED" = "x"; 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 **********************************************************************
|
||||
|
10
docs/FAQ
10
docs/FAQ
@ -358,10 +358,10 @@ FAQ
|
||||
|
||||
2.2 Does curl work/build with other SSL libraries?
|
||||
|
||||
Curl has been written to use OpenSSL, GnuTLS or yassl, 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, yassl 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?
|
||||
|
||||
@ -844,6 +844,8 @@ FAQ
|
||||
|
||||
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 ]
|
||||
|
@ -116,10 +116,10 @@ FILE
|
||||
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
|
||||
|
@ -140,6 +140,9 @@ UNIX
|
||||
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
|
||||
=====
|
||||
|
@ -47,6 +47,14 @@ yassl http://www.yassl.com/
|
||||
(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 @@ OpenLDAP http://www.openldap.org/software/release/license.html
|
||||
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/
|
||||
|
@ -157,16 +157,14 @@ TODO
|
||||
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/) or MatrixSSL
|
||||
(http://www.matrixssl.org/).
|
||||
MatrixSSL (http://www.matrixssl.org/).
|
||||
|
||||
* 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.
|
||||
* make the configure --with-ssl option first check for OpenSSL, then GnuTLS,
|
||||
then NSS...
|
||||
|
||||
GnuTLS
|
||||
|
||||
|
11
docs/curl.1
11
docs/curl.1
@ -167,6 +167,10 @@ difference.
|
||||
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 @@ this option assumes a \&"certificate" file that is the private key and the
|
||||
private certificate concatenated! See \fI--cert\fP 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 @@ The windows version of curl will automatically look for a CA certs file named
|
||||
\'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
|
||||
|
@ -1178,6 +1178,9 @@ transfers. (Added in 7.15.2)
|
||||
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
|
||||
@ -1222,8 +1225,8 @@ Pass a long as parameter to control what version of SSL/TLS to attempt to use.
|
||||
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
|
||||
@ -1266,6 +1269,9 @@ even indicate an accessible file.
|
||||
|
||||
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 directory must be
|
||||
@ -1315,12 +1321,23 @@ Pass a char *, pointing to a zero terminated string holding the list of
|
||||
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
|
||||
|
@ -8,7 +8,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
|
||||
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,5 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \
|
||||
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
|
||||
|
12
lib/http.c
12
lib/http.c
@ -1502,6 +1502,18 @@ int Curl_https_getsock(struct connectdata *conn,
|
||||
(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
|
||||
|
||||
|
605
lib/nss.c
Normal file
605
lib/nss.c
Normal file
@ -0,0 +1,605 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2007, 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 "nssg.h"
|
||||
#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
|
||||
};
|
||||
|
||||
static 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;
|
||||
(void)slot; /* unused */
|
||||
(void)retry; /* unused */
|
||||
if(parg->data->set.key_passwd)
|
||||
return (char *)PORT_Strdup((char *)parg->data->set.key_passwd);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static 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;
|
||||
(void)arg;
|
||||
(void)socket;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform the application that the handshake is complete.
|
||||
*/
|
||||
static SECStatus HandshakeCallback(PRFileDesc * socket, void *arg)
|
||||
{
|
||||
(void)socket;
|
||||
(void)arg;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Callback to pick the SSL client certificate.
|
||||
*/
|
||||
static 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;
|
||||
(void)caNames;
|
||||
|
||||
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;
|
||||
int rc;
|
||||
|
||||
if(data->set.timeout)
|
||||
timeout = PR_MillisecondsToInterval(data->set.timeout);
|
||||
else
|
||||
timeout = PR_MillisecondsToInterval(DEFAULT_CONNECT_TIMEOUT);
|
||||
|
||||
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 */
|
57
lib/nssg.h
Normal file
57
lib/nssg.h
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef __NSSG_H
|
||||
#define __NSSG_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2007, 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
|
@ -348,8 +348,8 @@ int fileno( FILE *stream);
|
||||
#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)
|
||||
|
71
lib/sslgen.c
71
lib/sslgen.c
@ -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"
|
||||
@ -168,9 +170,13 @@ int Curl_ssl_init(void)
|
||||
#else
|
||||
#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 @@ void Curl_ssl_cleanup(void)
|
||||
#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 @@ Curl_ssl_connect(struct connectdata *conn, int sockindex)
|
||||
#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 */
|
||||
|
||||
@ -224,12 +237,17 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
|
||||
conn->ssl[sockindex].use = TRUE;
|
||||
return Curl_ossl_connect_nonblocking(conn, sockindex, done);
|
||||
|
||||
#else
|
||||
#ifdef USE_NSS
|
||||
*done = TRUE; /* fallback to BLOCKING */
|
||||
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 +301,14 @@ static int kill_session(struct curl_ssl_session *session)
|
||||
#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 +399,10 @@ void Curl_ssl_close_all(struct SessionHandle *data)
|
||||
#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 */
|
||||
@ -390,8 +418,12 @@ void Curl_ssl_close(struct connectdata *conn)
|
||||
#else
|
||||
#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 */
|
||||
}
|
||||
@ -428,11 +460,18 @@ CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine)
|
||||
(void)data;
|
||||
(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 */
|
||||
}
|
||||
@ -448,10 +487,16 @@ CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data)
|
||||
/* FIX: add code here */
|
||||
(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 */
|
||||
}
|
||||
@ -467,8 +512,14 @@ struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data)
|
||||
(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 */
|
||||
}
|
||||
@ -484,12 +535,16 @@ ssize_t Curl_ssl_send(struct connectdata *conn,
|
||||
#else
|
||||
#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 */
|
||||
}
|
||||
@ -514,6 +569,10 @@ ssize_t Curl_ssl_recv(struct connectdata *conn, /* connection data */
|
||||
#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) {
|
||||
@ -573,10 +632,14 @@ size_t Curl_ssl_version(char *buffer, size_t size)
|
||||
#else
|
||||
#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 */
|
||||
}
|
||||
@ -594,10 +657,14 @@ int Curl_ssl_check_cxn(struct connectdata *conn)
|
||||
{
|
||||
#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 */
|
||||
}
|
||||
|
||||
|
@ -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 @@ struct ssl_connect_data {
|
||||
gnutls_session session;
|
||||
gnutls_certificate_credentials cred;
|
||||
#endif /* USE_GNUTLS */
|
||||
#ifdef USE_NSS
|
||||
PRFileDesc *handle;
|
||||
#endif /* USE_NSS */
|
||||
};
|
||||
|
||||
struct ssl_config_data {
|
||||
|
@ -143,6 +143,7 @@ my $has_getrlimit; # set if system has getrlimit()
|
||||
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 @@ sub checksystem {
|
||||
# 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 @@ sub checksystem {
|
||||
|
||||
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');
|
||||
@ -1179,6 +1184,11 @@ sub singletest {
|
||||
next;
|
||||
}
|
||||
}
|
||||
elsif($f eq "NSS") {
|
||||
if($has_nss) {
|
||||
next;
|
||||
}
|
||||
}
|
||||
elsif($f eq "netrc_debug") {
|
||||
if($curl_debug) {
|
||||
next;
|
||||
|
Loading…
Reference in New Issue
Block a user