diff --git a/lib/nss.c b/lib/nss.c index 2366c57..2c029c4 100644 --- a/lib/nss.c +++ b/lib/nss.c @@ -1337,6 +1337,29 @@ error: 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 */ @@ -1348,7 +1371,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 */ @@ -1377,7 +1402,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;