135 lines
4.4 KiB
Diff
135 lines
4.4 KiB
Diff
|
From df39ccc590abcfa275907ce8ed259fb11da33623 Mon Sep 17 00:00:00 2001
|
||
|
From: Kamil Dudka <kdudka@redhat.com>
|
||
|
Date: Thu, 18 Mar 2010 22:07:21 +0100
|
||
|
Subject: [PATCH 2/2] throw CURLE_SSL_CERTPROBLEM in case peer rejects a cert
|
||
|
|
||
|
... supported only by NSS for now. It may be extended for OpenSSL at
|
||
|
some point if anybody helps with deciphering of its error codes.
|
||
|
|
||
|
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
||
|
---
|
||
|
lib/nss.c | 30 ++++++++++++++++++++++++++++--
|
||
|
lib/sendf.c | 18 ++++++++++++------
|
||
|
lib/urldata.h | 3 +++
|
||
|
3 files changed, 43 insertions(+), 8 deletions(-)
|
||
|
|
||
|
diff --git a/lib/nss.c b/lib/nss.c
|
||
|
index 9dd84a2..a5523dc 100644
|
||
|
--- a/lib/nss.c
|
||
|
+++ b/lib/nss.c
|
||
|
@@ -1341,6 +1341,29 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
|
||
|
return curlerr;
|
||
|
}
|
||
|
|
||
|
+/* handle certificate related errors during send/recv, return false otherwise */
|
||
|
+static bool handle_cert_error(PRInt32 err, struct connectdata *conn, int num)
|
||
|
+{
|
||
|
+ switch(err) {
|
||
|
+ case SSL_ERROR_BAD_CERT_ALERT:
|
||
|
+ failf(conn->data, "SSL error: SSL_ERROR_BAD_CERT_ALERT");
|
||
|
+ break;
|
||
|
+ case SSL_ERROR_REVOKED_CERT_ALERT:
|
||
|
+ failf(conn->data, "SSL error: SSL_ERROR_REVOKED_CERT_ALERT");
|
||
|
+ break;
|
||
|
+ case SSL_ERROR_EXPIRED_CERT_ALERT:
|
||
|
+ failf(conn->data, "SSL error: SSL_ERROR_EXPIRED_CERT_ALERT");
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ /* handle it as a ususal error during send/recv */
|
||
|
+ conn->ssl[num].err = CURLE_OK;
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+ conn->ssl[num].err = CURLE_SSL_CERTPROBLEM;
|
||
|
+ return true;
|
||
|
+}
|
||
|
+
|
||
|
/* return number of sent (non-SSL) bytes */
|
||
|
int Curl_nss_send(struct connectdata *conn, /* connection data */
|
||
|
int sockindex, /* socketindex */
|
||
|
@@ -1352,7 +1375,9 @@ int Curl_nss_send(struct connectdata *conn, /* connection data */
|
||
|
rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0, -1);
|
||
|
|
||
|
if(rc < 0) {
|
||
|
- failf(conn->data, "SSL write: error %d", PR_GetError());
|
||
|
+ PRInt32 err = PR_GetError();
|
||
|
+ if(!handle_cert_error(err, conn, sockindex))
|
||
|
+ failf(conn->data, "SSL write: error %d", err);
|
||
|
return -1;
|
||
|
}
|
||
|
return rc; /* number of bytes */
|
||
|
@@ -1381,7 +1406,8 @@ ssize_t Curl_nss_recv(struct connectdata * conn, /* connection data */
|
||
|
*wouldblock = TRUE;
|
||
|
return -1; /* basically EWOULDBLOCK */
|
||
|
}
|
||
|
- failf(conn->data, "SSL read: errno %d", err);
|
||
|
+ if(!handle_cert_error(err, conn, num))
|
||
|
+ failf(conn->data, "SSL read: errno %d", err);
|
||
|
return -1;
|
||
|
}
|
||
|
return nread;
|
||
|
diff --git a/lib/sendf.c b/lib/sendf.c
|
||
|
index a366fd1..223fac2 100644
|
||
|
--- a/lib/sendf.c
|
||
|
+++ b/lib/sendf.c
|
||
|
@@ -277,10 +277,10 @@ CURLcode Curl_write(struct connectdata *conn,
|
||
|
ssize_t *written)
|
||
|
{
|
||
|
ssize_t bytes_written;
|
||
|
- CURLcode retcode;
|
||
|
int num = (sockfd == conn->sock[SECONDARYSOCKET]);
|
||
|
+ const bool do_ssl = (conn->ssl[num].state == ssl_connection_complete);
|
||
|
|
||
|
- if(conn->ssl[num].state == ssl_connection_complete)
|
||
|
+ if(do_ssl)
|
||
|
bytes_written = Curl_ssl_send(conn, num, mem, len);
|
||
|
else if(Curl_ssh_enabled(conn, PROT_SCP))
|
||
|
bytes_written = Curl_scp_send(conn, num, mem, len);
|
||
|
@@ -292,9 +292,13 @@ CURLcode Curl_write(struct connectdata *conn,
|
||
|
bytes_written = send_plain(conn, num, mem, len);
|
||
|
|
||
|
*written = bytes_written;
|
||
|
- retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
|
||
|
+ if(-1 == bytes_written)
|
||
|
+ /* send error */
|
||
|
+ return (do_ssl && conn->ssl[num].err)
|
||
|
+ ? (conn->ssl[num].err)
|
||
|
+ : CURLE_SEND_ERROR;
|
||
|
|
||
|
- return retcode;
|
||
|
+ return CURLE_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
@@ -540,9 +544,11 @@ int Curl_read(struct connectdata *conn, /* connection data */
|
||
|
|
||
|
if(nread == -1)
|
||
|
return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */
|
||
|
- else if(nread == -2)
|
||
|
+ else if(nread == -2) {
|
||
|
/* -2 from Curl_ssl_recv() means a true error, not EWOULDBLOCK */
|
||
|
- return CURLE_RECV_ERROR;
|
||
|
+ CURLcode ssl_err = conn->ssl[num].err;
|
||
|
+ return ssl_err?ssl_err:CURLE_RECV_ERROR;
|
||
|
+ }
|
||
|
}
|
||
|
else if(Curl_ssh_enabled(conn, (PROT_SCP|PROT_SFTP))) {
|
||
|
if(conn->protocol & PROT_SCP)
|
||
|
diff --git a/lib/urldata.h b/lib/urldata.h
|
||
|
index d03146a..c24a450 100644
|
||
|
--- a/lib/urldata.h
|
||
|
+++ b/lib/urldata.h
|
||
|
@@ -222,6 +222,9 @@ struct ssl_connect_data {
|
||
|
current state of the connection. */
|
||
|
bool use;
|
||
|
ssl_connection_state state;
|
||
|
+ /* If an error occurs in curlssl_recv() or Curl_ssl_send() and ERR is
|
||
|
+ non-zero, it contains the error code. */
|
||
|
+ CURLcode err;
|
||
|
#ifdef USE_SSLEAY
|
||
|
/* these ones requires specific SSL-types */
|
||
|
SSL_CTX* ctx;
|
||
|
--
|
||
|
1.7.0.2
|
||
|
|