summaryrefslogtreecommitdiff
path: root/third-party
diff options
context:
space:
mode:
Diffstat (limited to 'third-party')
-rw-r--r--third-party/pjproject/patches/0075-Fixed-2030-Improve-error-handling-in-OpenSSL-socket.patch247
1 files changed, 247 insertions, 0 deletions
diff --git a/third-party/pjproject/patches/0075-Fixed-2030-Improve-error-handling-in-OpenSSL-socket.patch b/third-party/pjproject/patches/0075-Fixed-2030-Improve-error-handling-in-OpenSSL-socket.patch
new file mode 100644
index 000000000..1e7035d93
--- /dev/null
+++ b/third-party/pjproject/patches/0075-Fixed-2030-Improve-error-handling-in-OpenSSL-socket.patch
@@ -0,0 +1,247 @@
+From 96c06899d95eaf01d05561554b21e8c63baa7129 Mon Sep 17 00:00:00 2001
+From: ming <ming@localhost>
+Date: Thu, 27 Jul 2017 06:07:54 +0000
+Subject: [PATCH 75/76] Fixed #2030: Improve error handling in OpenSSL socket
+
+---
+ pjlib/src/pj/ssl_sock_ossl.c | 173 ++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 156 insertions(+), 17 deletions(-)
+
+diff --git a/pjlib/src/pj/ssl_sock_ossl.c b/pjlib/src/pj/ssl_sock_ossl.c
+index c466b3c..b8175e1 100644
+--- a/pjlib/src/pj/ssl_sock_ossl.c
++++ b/pjlib/src/pj/ssl_sock_ossl.c
+@@ -298,14 +298,104 @@ static pj_status_t flush_delayed_send(pj_ssl_sock_t *ssock);
+ /* Expected maximum value of reason component in OpenSSL error code */
+ #define MAX_OSSL_ERR_REASON 1200
+
+-static pj_status_t STATUS_FROM_SSL_ERR(pj_ssl_sock_t *ssock,
+- unsigned long err)
++
++static char *SSLErrorString (int err)
+ {
+- pj_status_t status;
++ switch (err) {
++ case SSL_ERROR_NONE:
++ return "SSL_ERROR_NONE";
++ case SSL_ERROR_ZERO_RETURN:
++ return "SSL_ERROR_ZERO_RETURN";
++ case SSL_ERROR_WANT_READ:
++ return "SSL_ERROR_WANT_READ";
++ case SSL_ERROR_WANT_WRITE:
++ return "SSL_ERROR_WANT_WRITE";
++ case SSL_ERROR_WANT_CONNECT:
++ return "SSL_ERROR_WANT_CONNECT";
++ case SSL_ERROR_WANT_ACCEPT:
++ return "SSL_ERROR_WANT_ACCEPT";
++ case SSL_ERROR_WANT_X509_LOOKUP:
++ return "SSL_ERROR_WANT_X509_LOOKUP";
++ case SSL_ERROR_SYSCALL:
++ return "SSL_ERROR_SYSCALL";
++ case SSL_ERROR_SSL:
++ return "SSL_ERROR_SSL";
++ default:
++ return "SSL_ERROR_UNKNOWN";
++ }
++}
+
+- /* General SSL error, dig more from OpenSSL error queue */
+- if (err == SSL_ERROR_SSL)
+- err = ERR_get_error();
++#define ERROR_LOG(msg, err) \
++ PJ_LOG(2,("SSL", "%s (%s): Level: %d err: <%lu> <%s-%s-%s> len: %d", \
++ msg, action, level, err, \
++ (ERR_lib_error_string(err)? ERR_lib_error_string(err): "???"), \
++ (ERR_func_error_string(err)? ERR_func_error_string(err):"???"),\
++ (ERR_reason_error_string(err)? \
++ ERR_reason_error_string(err): "???"), len));
++
++static void SSLLogErrors(char * action, int ret, int ssl_err, int len)
++{
++ char *ssl_err_str = SSLErrorString(ssl_err);
++
++ if (!action) {
++ action = "UNKNOWN";
++ }
++
++ switch (ssl_err) {
++ case SSL_ERROR_SYSCALL:
++ {
++ unsigned long err2 = ERR_get_error();
++ if (err2) {
++ int level = 0;
++ while (err2) {
++ ERROR_LOG("SSL_ERROR_SYSCALL", err2);
++ level++;
++ err2 = ERR_get_error();
++ }
++ } else if (ret == 0) {
++ /* An EOF was observed that violates the protocol */
++
++ /* The TLS/SSL handshake was not successful but was shut down
++ * controlled and by the specifications of the TLS/SSL protocol.
++ */
++ } else if (ret == -1) {
++ /* BIO error - look for more info in errno... */
++ char errStr[250] = "";
++ strerror_r(errno, errStr, sizeof(errStr));
++ /* for now - continue logging these if they occur.... */
++ PJ_LOG(4,("SSL", "BIO error, SSL_ERROR_SYSCALL (%s): "
++ "errno: <%d> <%s> len: %d",
++ action, errno, errStr, len));
++ } else {
++ /* ret!=0 & ret!=-1 & nothing on error stack - is this valid??? */
++ PJ_LOG(2,("SSL", "SSL_ERROR_SYSCALL (%s) ret: %d len: %d",
++ action, ret, len));
++ }
++ break;
++ }
++ case SSL_ERROR_SSL:
++ {
++ unsigned long err2 = ERR_get_error();
++ int level = 0;
++
++ while (err2) {
++ ERROR_LOG("SSL_ERROR_SSL", err2);
++ level++;
++ err2 = ERR_get_error();
++ }
++ break;
++ }
++ default:
++ PJ_LOG(2,("SSL", "%lu [%s] (%s) ret: %d len: %d",
++ ssl_err, ssl_err_str, action, ret, len));
++ break;
++ }
++}
++
++
++static pj_status_t GET_STATUS_FROM_SSL_ERR(unsigned long err)
++{
++ pj_status_t status;
+
+ /* OpenSSL error range is much wider than PJLIB errno space, so
+ * if it exceeds the space, only the error reason will be kept.
+@@ -317,13 +407,49 @@ static pj_status_t STATUS_FROM_SSL_ERR(pj_ssl_sock_t *ssock,
+ status = ERR_GET_REASON(err);
+
+ status += PJ_SSL_ERRNO_START;
+- ssock->last_err = err;
+ return status;
+ }
+
++/* err contains ERR_get_error() status */
++static pj_status_t STATUS_FROM_SSL_ERR(char *action, pj_ssl_sock_t *ssock,
++ unsigned long err)
++{
++ int level = 0;
++ int len = 0; //dummy
++
++ ERROR_LOG("STATUS_FROM_SSL_ERR", err);
++ level++;
++
++ /* General SSL error, dig more from OpenSSL error queue */
++ if (err == SSL_ERROR_SSL) {
++ err = ERR_get_error();
++ ERROR_LOG("STATUS_FROM_SSL_ERR", err);
++ }
++
++ ssock->last_err = err;
++ return GET_STATUS_FROM_SSL_ERR(err);
++}
++
++/* err contains SSL_get_error() status */
++static pj_status_t STATUS_FROM_SSL_ERR2(char *action, pj_ssl_sock_t *ssock,
++ int ret, int err, int len)
++{
++ unsigned long ssl_err = err;
++
++ if (err == SSL_ERROR_SSL) {
++ ssl_err = ERR_peek_error();
++ }
++
++ /* Dig for more from OpenSSL error queue */
++ SSLLogErrors(action, ret, err, len);
++
++ ssock->last_err = ssl_err;
++ return GET_STATUS_FROM_SSL_ERR(ssl_err);
++}
++
+ static pj_status_t GET_SSL_STATUS(pj_ssl_sock_t *ssock)
+ {
+- return STATUS_FROM_SSL_ERR(ssock, ERR_get_error());
++ return STATUS_FROM_SSL_ERR("status", ssock, ERR_get_error());
+ }
+
+
+@@ -1514,7 +1640,7 @@ static pj_bool_t on_handshake_complete(pj_ssl_sock_t *ssock,
+ unsigned long err;
+ err = ERR_get_error();
+ if (err != SSL_ERROR_NONE)
+- status = STATUS_FROM_SSL_ERR(ssock, err);
++ status = STATUS_FROM_SSL_ERR("connecting", ssock, err);
+ }
+ reset_ssl_sock_state(ssock);
+ }
+@@ -1833,11 +1959,11 @@ static pj_status_t do_handshake(pj_ssl_sock_t *ssock)
+ }
+
+ if (err < 0) {
+- err = SSL_get_error(ssock->ossl_ssl, err);
+- if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ)
++ int err2 = SSL_get_error(ssock->ossl_ssl, err);
++ if (err2 != SSL_ERROR_NONE && err2 != SSL_ERROR_WANT_READ)
+ {
+ /* Handshake fails */
+- status = STATUS_FROM_SSL_ERR(ssock, err);
++ status = STATUS_FROM_SSL_ERR2("Handshake", ssock, err, err2, 0);
+ return status;
+ }
+ }
+@@ -1913,6 +2039,7 @@ static pj_bool_t asock_on_data_read (pj_activesock_t *asock,
+ read_data_t *buf = *(OFFSET_OF_READ_DATA_PTR(ssock, data));
+ void *data_ = (pj_int8_t*)buf->data + buf->len;
+ int size_ = (int)(ssock->read_size - buf->len);
++ int len = size_;
+
+ /* SSL_read() may write some data to BIO write when re-negotiation
+ * is on progress, so let's protect it with write mutex.
+@@ -1965,10 +2092,22 @@ static pj_bool_t asock_on_data_read (pj_activesock_t *asock,
+ */
+ if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ)
+ {
+- /* Reset SSL socket state, then return PJ_FALSE */
+- status = STATUS_FROM_SSL_ERR(ssock, err);
+- reset_ssl_sock_state(ssock);
+- goto on_error;
++ if (err == SSL_ERROR_SYSCALL && size_ == -1 &&
++ ERR_peek_error() == 0 && errno == 0)
++ {
++ status = STATUS_FROM_SSL_ERR2("Read", ssock, size_,
++ err, len);
++ PJ_LOG(4,("SSL", "SSL_read() = -1, with "
++ "SSL_ERROR_SYSCALL, no SSL error, "
++ "and errno = 0 - skip BIO error"));
++ /* Ignore these errors */
++ } else {
++ /* Reset SSL socket state, then return PJ_FALSE */
++ status = STATUS_FROM_SSL_ERR2("Read", ssock, size_,
++ err, len);
++ reset_ssl_sock_state(ssock);
++ goto on_error;
++ }
+ }
+
+ status = do_handshake(ssock);
+@@ -2856,7 +2995,7 @@ static pj_status_t ssl_write(pj_ssl_sock_t *ssock,
+ status = PJ_EBUSY;
+ } else {
+ /* Some problem occured */
+- status = STATUS_FROM_SSL_ERR(ssock, err);
++ status = STATUS_FROM_SSL_ERR2("Write", ssock, nwritten, err, size);
+ }
+ } else {
+ /* nwritten < *size, shouldn't happen, unless write BIO cannot hold
+--
+2.9.4
+