aboutsummaryrefslogtreecommitdiff
path: root/lib/ssluse.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2007-12-03 11:39:27 +0000
committerDaniel Stenberg <daniel@haxx.se>2007-12-03 11:39:27 +0000
commit2be50baf975ffaad77e7356d217af209431916f8 (patch)
tree351e4a73bf494abaa8ce2a16fe97fd1a7991a537 /lib/ssluse.c
parenta1772ca406e97c3c3c77a62b550dab66d53fa8f8 (diff)
Now libcurl (built with OpenSSL) doesn't return error anymore if the remote
SSL-based server doesn't present a certificate when the request is told to ignore certificate verification anyway.
Diffstat (limited to 'lib/ssluse.c')
-rw-r--r--lib/ssluse.c137
1 files changed, 84 insertions, 53 deletions
diff --git a/lib/ssluse.c b/lib/ssluse.c
index 8aa78f367..6b1835e5b 100644
--- a/lib/ssluse.c
+++ b/lib/ssluse.c
@@ -1569,61 +1569,27 @@ Curl_ossl_connect_step2(struct connectdata *conn,
}
}
-static CURLcode
-Curl_ossl_connect_step3(struct connectdata *conn,
- int sockindex)
+/*
+ * Get the server cert, verify it and show it etc, only call failf() if the
+ * 'strict' argument is TRUE as otherwise all this is for informational
+ * purposes only!
+ *
+ * We check certificates to authenticate the server; otherwise we risk
+ * man-in-the-middle attack.
+ */
+static CURLcode servercert(struct connectdata *conn,
+ struct ssl_connect_data *connssl,
+ bool strict)
{
- CURLcode retcode = CURLE_OK;
- char * str;
+ CURLcode retcode;
+ char *str;
long lerr;
ASN1_TIME *certdate;
- void *ssl_sessionid=NULL;
struct SessionHandle *data = conn->data;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-
- DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
-
- if(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
- /* Since this is not a cached session ID, then we want to stach this one
- in the cache! */
- SSL_SESSION *our_ssl_sessionid;
-#ifdef HAVE_SSL_GET1_SESSION
- our_ssl_sessionid = SSL_get1_session(connssl->handle);
-
- /* SSL_get1_session() will increment the reference
- count and the session will stay in memory until explicitly freed with
- SSL_SESSION_free(3), regardless of its state.
- This function was introduced in openssl 0.9.5a. */
-#else
- our_ssl_sessionid = SSL_get_session(connssl->handle);
-
- /* if SSL_get1_session() is unavailable, use SSL_get_session().
- This is an inferior option because the session can be flushed
- at any time by openssl. It is included only so curl compiles
- under versions of openssl < 0.9.5a.
-
- WARNING: How curl behaves if it's session is flushed is
- untested.
- */
-#endif
- retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
- 0 /* unknown size */);
- if(retcode) {
- failf(data, "failed to store ssl session");
- return retcode;
- }
- }
-
-
- /* Get server's certificate (note: beware of dynamic allocation) - opt */
- /* major serious hack alert -- we should check certificates
- * to authenticate the server; otherwise we risk man-in-the-middle
- * attack
- */
-
connssl->server_cert = SSL_get_peer_certificate(connssl->handle);
if(!connssl->server_cert) {
- failf(data, "SSL: couldn't get peer certificate!");
+ if(strict)
+ failf(data, "SSL: couldn't get peer certificate!");
return CURLE_PEER_FAILED_VERIFICATION;
}
infof (data, "Server certificate:\n");
@@ -1631,7 +1597,8 @@ Curl_ossl_connect_step3(struct connectdata *conn,
str = X509_NAME_oneline(X509_get_subject_name(connssl->server_cert),
NULL, 0);
if(!str) {
- failf(data, "SSL: couldn't get X509-subject!");
+ if(strict)
+ failf(data, "SSL: couldn't get X509-subject!");
X509_free(connssl->server_cert);
connssl->server_cert = NULL;
return CURLE_SSL_CONNECT_ERROR;
@@ -1657,7 +1624,8 @@ Curl_ossl_connect_step3(struct connectdata *conn,
str = X509_NAME_oneline(X509_get_issuer_name(connssl->server_cert),
NULL, 0);
if(!str) {
- failf(data, "SSL: couldn't get X509-issuer name!");
+ if(strict)
+ failf(data, "SSL: couldn't get X509-issuer name!");
retcode = CURLE_SSL_CONNECT_ERROR;
}
else {
@@ -1673,8 +1641,9 @@ Curl_ossl_connect_step3(struct connectdata *conn,
if(data->set.ssl.verifypeer) {
/* We probably never reach this, because SSL_connect() will fail
and we return earlyer if verifypeer is set? */
- failf(data, "SSL certificate verify result: %s (%ld)",
- X509_verify_cert_error_string(lerr), lerr);
+ if(strict)
+ failf(data, "SSL certificate verify result: %s (%ld)",
+ X509_verify_cert_error_string(lerr), lerr);
retcode = CURLE_PEER_FAILED_VERIFICATION;
}
else
@@ -1689,6 +1658,68 @@ Curl_ossl_connect_step3(struct connectdata *conn,
X509_free(connssl->server_cert);
connssl->server_cert = NULL;
connssl->connecting_state = ssl_connect_done;
+
+ return retcode;
+}
+
+
+static CURLcode
+Curl_ossl_connect_step3(struct connectdata *conn,
+ int sockindex)
+{
+ CURLcode retcode = CURLE_OK;
+ void *ssl_sessionid=NULL;
+ struct SessionHandle *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
+
+ if(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
+ /* Since this is not a cached session ID, then we want to stach this one
+ in the cache! */
+ SSL_SESSION *our_ssl_sessionid;
+#ifdef HAVE_SSL_GET1_SESSION
+ our_ssl_sessionid = SSL_get1_session(connssl->handle);
+
+ /* SSL_get1_session() will increment the reference
+ count and the session will stay in memory until explicitly freed with
+ SSL_SESSION_free(3), regardless of its state.
+ This function was introduced in openssl 0.9.5a. */
+#else
+ our_ssl_sessionid = SSL_get_session(connssl->handle);
+
+ /* if SSL_get1_session() is unavailable, use SSL_get_session().
+ This is an inferior option because the session can be flushed
+ at any time by openssl. It is included only so curl compiles
+ under versions of openssl < 0.9.5a.
+
+ WARNING: How curl behaves if it's session is flushed is
+ untested.
+ */
+#endif
+ retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
+ 0 /* unknown size */);
+ if(retcode) {
+ failf(data, "failed to store ssl session");
+ return retcode;
+ }
+ }
+
+
+ /*
+ * We check certificates to authenticate the server; otherwise we risk
+ * man-in-the-middle attack; NEVERTHELESS, if we're told explicitly not to
+ * verify the peer ignore faults and failures from the server cert
+ * operations.
+ */
+
+ if(!data->set.ssl.verifypeer)
+ (void)servercert(conn, connssl, FALSE);
+ else
+ retcode = servercert(conn, connssl, TRUE);
+
+ if(CURLE_OK == retcode)
+ connssl->connecting_state = ssl_connect_done;
return retcode;
}