From df39ccc590abcfa275907ce8ed259fb11da33623 Mon Sep 17 00:00:00 2001 From: Kamil Dudka 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 --- 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