2010-03-19 15:08:16 +00:00
|
|
|
diff --git a/lib/nss.c b/lib/nss.c
|
2010-03-23 18:47:25 +00:00
|
|
|
index 2366c57..2c029c4 100644
|
2010-03-19 15:08:16 +00:00
|
|
|
--- a/lib/nss.c
|
|
|
|
+++ b/lib/nss.c
|
2010-03-23 18:47:25 +00:00
|
|
|
@@ -1337,6 +1337,29 @@ error:
|
2010-03-19 15:08:16 +00:00
|
|
|
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 */
|
2010-03-23 18:47:25 +00:00
|
|
|
@@ -1348,7 +1371,9 @@ int Curl_nss_send(struct connectdata *conn, /* connection data */
|
2010-03-19 15:08:16 +00:00
|
|
|
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 */
|
2010-03-23 18:47:25 +00:00
|
|
|
@@ -1377,7 +1402,8 @@ ssize_t Curl_nss_recv(struct connectdata * conn, /* connection data */
|
2010-03-19 15:08:16 +00:00
|
|
|
*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;
|