aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.inc4
-rw-r--r--lib/curl_config.h.cmake3
-rw-r--r--lib/http.c12
-rw-r--r--lib/polarssl.c391
-rw-r--r--lib/polarssl.h67
-rw-r--r--lib/setup.h2
-rw-r--r--lib/sslgen.c2
-rw-r--r--lib/urldata.h17
8 files changed, 495 insertions, 3 deletions
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index f90e4dce0..e35e8bb57 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -12,7 +12,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
strdup.c socks.c ssh.c nss.c qssl.c rawstr.c curl_addrinfo.c \
socks_gssapi.c socks_sspi.c curl_sspi.c slist.c nonblock.c \
curl_memrchr.c imap.c pop3.c smtp.c pingpong.c rtsp.c curl_threads.c \
- warnless.c hmac.c
+ warnless.c hmac.c polarssl.c
HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
@@ -25,4 +25,4 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h nssg.h \
curl_base64.h rawstr.h curl_addrinfo.h curl_sspi.h slist.h nonblock.h \
curl_memrchr.h imap.h pop3.h smtp.h pingpong.h rtsp.h curl_threads.h \
- warnless.h curl_hmac.h
+ warnless.h curl_hmac.h polarssl.h
diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake
index fd6b32aa8..14d2719d3 100644
--- a/lib/curl_config.h.cmake
+++ b/lib/curl_config.h.cmake
@@ -889,6 +889,9 @@
/* if GnuTLS is enabled */
#cmakedefine USE_GNUTLS ${USE_GNUTLS}
+/* if PolarSSL is enabled */
+#cmakedefine USE_POLARSSL ${USE_POLARSSL}
+
/* if libSSH2 is in use */
#cmakedefine USE_LIBSSH2 ${USE_LIBSSH2}
diff --git a/lib/http.c b/lib/http.c
index cfc09cd5e..fc01ee889 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -1865,6 +1865,18 @@ static int https_getsock(struct connectdata *conn,
(void)numsocks;
return GETSOCK_BLANK;
}
+#else
+#ifdef USE_POLARSSL
+static int https_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+ (void)conn;
+ (void)socks;
+ (void)numsocks;
+ return GETSOCK_BLANK;
+}
+#endif
#endif
#endif
#endif
diff --git a/lib/polarssl.c b/lib/polarssl.c
new file mode 100644
index 000000000..95baa1320
--- /dev/null
+++ b/lib/polarssl.c
@@ -0,0 +1,391 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ *
+ * 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.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all PolarSSL-specific code for the TLS/SSL layer. No code
+ * but sslgen.c should ever call or use these functions.
+ *
+ */
+
+#include "setup.h"
+#ifdef USE_POLARSSL
+
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#include <polarssl/net.h>
+#include <polarssl/ssl.h>
+#include <polarssl/havege.h>
+#include <polarssl/certs.h>
+#include <polarssl/x509.h>
+
+#include "urldata.h"
+#include "sendf.h"
+#include "inet_pton.h"
+#include "polarssl.h"
+#include "sslgen.h"
+#include "parsedate.h"
+#include "connect.h" /* for the connect timeout */
+#include "select.h"
+#include "rawstr.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/* Define this to enable lots of debugging for PolarSSL */
+#undef POLARSSL_DEBUG
+
+#ifdef POLARSSL_DEBUG
+static void polarssl_debug(void *context, int level, char *line)
+{
+ struct SessionHandle *data = NULL;
+
+ if(!context)
+ return;
+
+ data = (struct SessionHandle *)context;
+
+ infof(data, "%s", line);
+}
+#else
+#endif
+
+/*
+ * This function loads all the client/CA certificates and CRLs. Setup the TLS
+ * layer and do all necessary magic.
+ */
+CURLcode
+Curl_polarssl_connect(struct connectdata *conn,
+ int sockindex)
+{
+ struct SessionHandle *data = conn->data;
+ bool sni = TRUE; /* default is SNI enabled */
+ int ret = -1;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif
+ void *old_session = NULL;
+ size_t old_session_size = 0;
+#if defined(HAVE_POLARSSL_GPL)
+ char buffer[1024];
+#endif
+
+ if(conn->ssl[sockindex].state == ssl_connection_complete)
+ return CURLE_OK;
+
+ /* PolarSSL only supports SSLv3 and TLSv1 */
+ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
+ failf(data, "PolarSSL does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ } else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) {
+ sni = FALSE; /* SSLv3 has no SNI */
+ }
+
+ havege_init(&conn->ssl[sockindex].hs);
+
+ /* Load the trusted CA */
+ memset(&conn->ssl[sockindex].cacert, 0, sizeof(x509_cert));
+
+ if(data->set.str[STRING_SSL_CAFILE]) {
+ ret = x509parse_crtfile(&conn->ssl[sockindex].cacert,
+ data->set.str[STRING_SSL_CAFILE]);
+
+ if(ret) {
+ failf(data, "Error reading ca cert file %s: -0x%04X",
+ data->set.str[STRING_SSL_CAFILE], -ret);
+
+ if(data->set.ssl.verifypeer)
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+
+ /* Load the client certificate */
+ memset(&conn->ssl[sockindex].clicert, 0, sizeof(x509_cert));
+
+ if(data->set.str[STRING_CERT]) {
+#if !defined(HAVE_POLARSSL_GPL)
+ /* FIXME: PolarSSL has a bug where we need to import it twice */
+ ret = x509parse_crtfile(&conn->ssl[sockindex].clicert,
+ data->set.str[STRING_CERT]);
+#endif
+ ret = x509parse_crtfile(&conn->ssl[sockindex].clicert,
+ data->set.str[STRING_CERT]);
+
+ if(ret) {
+ failf(data, "Error reading client cert file %s: -0x%04X",
+ data->set.str[STRING_CERT], -ret);
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ }
+
+ /* Load the client private key */
+ if(data->set.str[STRING_KEY]) {
+ ret = x509parse_keyfile(&conn->ssl[sockindex].rsa,
+ data->set.str[STRING_KEY],
+ data->set.str[STRING_KEY_PASSWD]);
+
+ if(ret) {
+ failf(data, "Error reading private key %s: -0x%04X",
+ data->set.str[STRING_KEY], -ret);
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ }
+
+#if defined(HAVE_POLARSSL_GPL)
+ /* Load the CRL */
+ memset(&conn->ssl[sockindex].crl, 0, sizeof(x509_crl));
+
+ if(data->set.str[STRING_SSL_CRLFILE]) {
+ ret = x509parse_crlfile(&conn->ssl[sockindex].crl,
+ data->set.str[STRING_SSL_CRLFILE]);
+
+ if(ret) {
+ failf(data, "Error reading CRL file %s: -0x%04X",
+ data->set.str[STRING_SSL_CRLFILE], -ret);
+ return CURLE_SSL_CRL_BADFILE;
+ }
+ }
+
+#endif
+ infof(data, "PolarSSL: Connected to %s:%d\n",
+ conn->host.name, conn->remote_port);
+
+ havege_init(&conn->ssl[sockindex].hs);
+
+ if(ssl_init(&conn->ssl[sockindex].ssl)) {
+ failf(data, "PolarSSL: ssl_init failed");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ ssl_set_endpoint(&conn->ssl[sockindex].ssl, SSL_IS_CLIENT);
+ ssl_set_authmode(&conn->ssl[sockindex].ssl, SSL_VERIFY_OPTIONAL);
+
+ ssl_set_rng(&conn->ssl[sockindex].ssl, havege_rand,
+ &conn->ssl[sockindex].hs);
+ ssl_set_bio(&conn->ssl[sockindex].ssl,
+ net_recv, &conn->sock[sockindex],
+ net_send, &conn->sock[sockindex]);
+
+ ssl_set_ciphers(&conn->ssl[sockindex].ssl, ssl_default_ciphers);
+
+ if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) {
+ memcpy(&conn->ssl[sockindex].ssn, old_session, old_session_size);
+ infof(data, "PolarSSL re-using session\n");
+ }
+
+ ssl_set_session(&conn->ssl[sockindex].ssl, 1, 600,
+ &conn->ssl[sockindex].ssn);
+
+ ssl_set_ca_chain(&conn->ssl[sockindex].ssl,
+#if defined(HAVE_POLARSSL_GPL)
+ &conn->ssl[sockindex].cacert,
+ &conn->ssl[sockindex].crl,
+ conn->host.name);
+#else
+ &conn->ssl[sockindex].cacert, conn->host.name);
+#endif
+
+ ssl_set_own_cert(&conn->ssl[sockindex].ssl,
+ &conn->ssl[sockindex].clicert, &conn->ssl[sockindex].rsa);
+
+ if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) &&
+#ifdef ENABLE_IPV6
+ !Curl_inet_pton(AF_INET6, conn->host.name, &addr) &&
+#endif
+ sni && ssl_set_hostname(&conn->ssl[sockindex].ssl, conn->host.name)) {
+ infof(data, "WARNING: failed to configure "
+ "server name indication (SNI) TLS extension\n");
+ }
+
+ infof(data, "PolarSSL: performing SSL/TLS handshake...\n");
+
+#ifdef POLARSSL_DEBUG
+ ssl_set_dbg(&conn->ssl[sockindex].ssl, polarssl_debug, data);
+#endif
+
+ do {
+ if (!(ret = ssl_handshake(&conn->ssl[sockindex].ssl))) {
+ break;
+ } else if(ret != POLARSSL_ERR_NET_TRY_AGAIN) {
+ failf(data, "ssl_handshake returned -0x%04X", -ret);
+ return CURLE_SSL_CONNECT_ERROR;
+ } else {
+ /* wait for data from server... */
+ long timeout_ms = Curl_timeleft(conn, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ switch(Curl_socket_ready(conn->sock[sockindex],
+ CURL_SOCKET_BAD, timeout_ms)) {
+ case 0:
+ failf(data, "SSL handshake timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ break;
+ case CURL_CSELECT_IN:
+ continue;
+ break;
+ default:
+ return CURLE_SSL_CONNECT_ERROR;
+ break;
+ }
+ }
+ } while (1);
+
+ infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
+ ssl_get_cipher(&conn->ssl[sockindex].ssl));
+
+ ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl);
+
+ if(ret && data->set.ssl.verifypeer) {
+ if(ret & BADCERT_EXPIRED)
+ failf(data, "Cert verify failed: BADCERT_EXPIRED\n");
+
+ if(ret & BADCERT_REVOKED)
+ failf(data, "Cert verify failed: BADCERT_REVOKED");
+
+ if(ret & BADCERT_CN_MISMATCH)
+ failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");
+
+ if(ret & BADCERT_NOT_TRUSTED)
+ failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");
+
+ return CURLE_SSL_CACERT;
+ }
+
+ if(conn->ssl[sockindex].ssl.peer_cert) {
+ /* If the session was resumed, there will be no peer certs */
+#if !defined(HAVE_POLARSSL_GPL)
+ char *buffer = x509parse_cert_info("* ", conn->ssl[sockindex].ssl.peer_cert);
+
+ if(buffer)
+#else
+ memset(buffer, 0, sizeof(buffer));
+
+ if(x509parse_cert_info(buffer, sizeof(buffer), (char *)"* ",
+ conn->ssl[sockindex].ssl.peer_cert) != -1)
+#endif
+ infof(data, "Dumping cert info:\n%s\n", buffer);
+ }
+
+ conn->ssl[sockindex].state = ssl_connection_complete;
+
+ /* Save the current session data for possible re-use */
+ {
+ void *new_session = malloc(sizeof(conn->ssl[sockindex].ssn));
+
+ if(new_session) {
+ memcpy(new_session, &conn->ssl[sockindex].ssn,
+ sizeof(conn->ssl[sockindex].ssn));
+
+ if(old_session)
+ Curl_ssl_delsessionid(conn, old_session);
+
+ return Curl_ssl_addsessionid(conn, new_session,
+ sizeof(conn->ssl[sockindex].ssn));
+ }
+ }
+
+ return CURLE_OK;
+}
+
+/* for documentation see Curl_ssl_send() in sslgen.h */
+ssize_t Curl_polarssl_send(struct connectdata *conn,
+ int sockindex,
+ const void *mem,
+ size_t len,
+ int *curlcode)
+{
+ int ret = -1;
+
+ ret = ssl_write(&conn->ssl[sockindex].ssl,
+ (unsigned char *)mem, len);
+
+ if(ret < 0) {
+ *curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ? -1 : CURLE_SEND_ERROR;
+ ret = -1;
+ }
+
+ return ret;
+}
+
+void Curl_polarssl_close_all(struct SessionHandle *data)
+{
+ (void)data;
+}
+
+void Curl_polarssl_close(struct connectdata *conn, int sockindex)
+{
+ rsa_free(&conn->ssl[sockindex].rsa);
+ x509_free(&conn->ssl[sockindex].clicert);
+ x509_free(&conn->ssl[sockindex].cacert);
+#if defined(HAVE_POLARSSL_GPL)
+ x509_crl_free(&conn->ssl[sockindex].crl);
+#endif
+ ssl_free(&conn->ssl[sockindex].ssl);
+}
+
+/* for documentation see Curl_ssl_recv() in sslgen.h */
+ssize_t Curl_polarssl_recv(struct connectdata *conn,
+ int num,
+ char *buf,
+ size_t buffersize,
+ int *curlcode)
+{
+ int ret = -1;
+ ssize_t len = -1;
+
+ memset(buf, 0, buffersize);
+ ret = ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf, buffersize);
+
+ if(ret <= 0) {
+ *curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ? -1 : CURLE_RECV_ERROR;
+ return -1;
+ }
+
+ len = ret;
+
+ return len;
+}
+
+void Curl_polarssl_session_free(void *ptr)
+{
+ free(ptr);
+}
+
+size_t Curl_polarssl_version(char *buffer, size_t size)
+{
+ return snprintf(buffer, size, "PolarSSL");
+}
+
+#endif
diff --git a/lib/polarssl.h b/lib/polarssl.h
new file mode 100644
index 000000000..7d406ef70
--- /dev/null
+++ b/lib/polarssl.h
@@ -0,0 +1,67 @@
+#ifndef __POLARSSL_H
+#define __POLARSSL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ *
+ * 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: polarssl.h,v 1.10 2009-02-12 20:48:43 danf Exp $
+ ***************************************************************************/
+
+#ifdef USE_POLARSSL
+
+CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex);
+
+/* tell PolarSSL to close down all open information regarding connections (and
+ thus session ID caching etc) */
+void Curl_polarssl_close_all(struct SessionHandle *data);
+
+ /* close a SSL connection */
+void Curl_polarssl_close(struct connectdata *conn, int sockindex);
+
+/* return number of sent (non-SSL) bytes */
+ssize_t Curl_polarssl_send(struct connectdata *conn, int sockindex,
+ const void *mem, size_t len, int *curlcode);
+ssize_t Curl_polarssl_recv(struct connectdata *conn, /* connection data */
+ int num, /* socketindex */
+ char *buf, /* store read data here */
+ size_t buffersize, /* max amount to read */
+ int *curlcode);
+void Curl_polarssl_session_free(void *ptr);
+size_t Curl_polarssl_version(char *buffer, size_t size);
+int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex);
+
+/* API setup for PolarSSL */
+#define curlssl_init() (1)
+#define curlssl_cleanup()
+#define curlssl_connect Curl_polarssl_connect
+#define curlssl_session_free(x) Curl_polarssl_session_free(x)
+#define curlssl_close_all Curl_polarssl_close_all
+#define curlssl_close Curl_polarssl_close
+#define curlssl_shutdown(x,y) 0
+#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_FAILED_INIT)
+#define curlssl_set_engine_default(x) (x=x, CURLE_FAILED_INIT)
+#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL)
+#define curlssl_send Curl_polarssl_send
+#define curlssl_recv Curl_polarssl_recv
+#define curlssl_version Curl_polarssl_version
+#define curlssl_check_cxn(x) (x=x, -1)
+#define curlssl_data_pending(x,y) (x=x, y=y, 0)
+
+#endif /* USE_POLARSSL */
+#endif
diff --git a/lib/setup.h b/lib/setup.h
index ca98ad7e0..5fae0926b 100644
--- a/lib/setup.h
+++ b/lib/setup.h
@@ -525,7 +525,7 @@ int netware_init(void);
#define LIBIDN_REQUIRED_VERSION "0.4.1"
-#if defined(USE_GNUTLS) || defined(USE_SSLEAY) || defined(USE_NSS) || defined(USE_QSOSSL)
+#if defined(USE_GNUTLS) || defined(USE_SSLEAY) || defined(USE_NSS) || defined(USE_QSOSSL) || defined(USE_POLARSSL)
#define USE_SSL /* SSL support has been enabled */
#endif
diff --git a/lib/sslgen.c b/lib/sslgen.c
index df2a4075a..24b6dcbd6 100644
--- a/lib/sslgen.c
+++ b/lib/sslgen.c
@@ -31,6 +31,7 @@
Curl_ossl_ - prefix for OpenSSL ones
Curl_gtls_ - prefix for GnuTLS ones
Curl_nss_ - prefix for NSS ones
+ Curl_polarssl_ - prefix for PolarSSL ones
Note that this source code uses curlssl_* functions, and they are all
defines/macros #defined by the lib-specific header files.
@@ -55,6 +56,7 @@
#include "gtls.h" /* GnuTLS versions */
#include "nssg.h" /* NSS versions */
#include "qssl.h" /* QSOSSL versions */
+#include "polarssl.h" /* PolarSSL versions */
#include "sendf.h"
#include "rawstr.h"
#include "url.h"
diff --git a/lib/urldata.h b/lib/urldata.h
index 42065d184..7e3afee7c 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -102,6 +102,11 @@
#include <gnutls/gnutls.h>
#endif
+#ifdef USE_POLARSSL
+#include <polarssl/havege.h>
+#include <polarssl/ssl.h>
+#endif
+
#ifdef USE_NSS
#include <nspr.h>
#include <pk11pub.h>
@@ -233,6 +238,18 @@ struct ssl_connect_data {
gnutls_certificate_credentials cred;
ssl_connect_state connecting_state;
#endif /* USE_GNUTLS */
+#ifdef USE_POLARSSL
+ havege_state hs;
+ ssl_context ssl;
+ ssl_session ssn;
+ int server_fd;
+ x509_cert cacert;
+ x509_cert clicert;
+#if defined(HAVE_POLARSSL_GPL)
+ x509_crl crl;
+#endif
+ rsa_context rsa;
+#endif /* USE_POLARSSL */
#ifdef USE_NSS
PRFileDesc *handle;
char *client_nickname;