pjproject: sync patches with asterisk 18.5.1
authorSebastian Kemper <sebastian_ml@gmx.net>
Sat, 31 Jul 2021 09:24:10 +0000 (11:24 +0200)
committerSebastian Kemper <sebastian_ml@gmx.net>
Sat, 31 Jul 2021 09:24:10 +0000 (11:24 +0200)
Signed-off-by: Sebastian Kemper <sebastian_ml@gmx.net>
libs/pjproject/Makefile
libs/pjproject/patches/0090-Skip-unsupported-digest-algorithm-2408.patch [new file with mode: 0644]
libs/pjproject/patches/0100-fix-double-stun-free.patch [new file with mode: 0644]
libs/pjproject/patches/0110-tls-parent-listener-destroyed.patch [new file with mode: 0644]

index 28cc7345db23fecd16a9e74791d9d8630572c4b2..7d441cbee93f8b044738191530660b91b86f66fa 100644 (file)
@@ -11,7 +11,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=pjproject
 PKG_VERSION:=2.10
-PKG_RELEASE:=3
+PKG_RELEASE:=4
 
 # download "vX.Y.tar.gz" as "pjproject-vX.Y.tar.gz"
 PKG_SOURCE_URL_FILE:=$(PKG_VERSION).tar.gz
diff --git a/libs/pjproject/patches/0090-Skip-unsupported-digest-algorithm-2408.patch b/libs/pjproject/patches/0090-Skip-unsupported-digest-algorithm-2408.patch
new file mode 100644 (file)
index 0000000..c779f67
--- /dev/null
@@ -0,0 +1,201 @@
+From bdbeb7c4b2b11efc2e59f5dee7aa4360a2bc9fff Mon Sep 17 00:00:00 2001
+From: sauwming <ming@teluu.com>
+Date: Thu, 22 Apr 2021 14:03:28 +0800
+Subject: [PATCH 90/90] Skip unsupported digest algorithm (#2408)
+
+Co-authored-by: Nanang Izzuddin <nanang@teluu.com>
+---
+ pjsip/src/pjsip/sip_auth_client.c             | 32 +++++--
+ tests/pjsua/scripts-sipp/uas-auth-two-algo.py |  7 ++
+ .../pjsua/scripts-sipp/uas-auth-two-algo.xml  | 83 +++++++++++++++++++
+ 3 files changed, 117 insertions(+), 5 deletions(-)
+ create mode 100644 tests/pjsua/scripts-sipp/uas-auth-two-algo.py
+ create mode 100644 tests/pjsua/scripts-sipp/uas-auth-two-algo.xml
+
+--- a/pjsip/src/pjsip/sip_auth_client.c
++++ b/pjsip/src/pjsip/sip_auth_client.c
+@@ -1042,7 +1042,7 @@ static pj_status_t process_auth( pj_pool
+     pjsip_hdr *hdr;
+     pj_status_t status;
+-    /* See if we have sent authorization header for this realm */
++    /* See if we have sent authorization header for this realm (and scheme) */
+     hdr = tdata->msg->hdr.next;
+     while (hdr != &tdata->msg->hdr) {
+       if ((hchal->type == PJSIP_H_WWW_AUTHENTICATE &&
+@@ -1052,7 +1052,8 @@ static pj_status_t process_auth( pj_pool
+       {
+           sent_auth = (pjsip_authorization_hdr*) hdr;
+           if (pj_stricmp(&hchal->challenge.common.realm,
+-                         &sent_auth->credential.common.realm )==0)
++                         &sent_auth->credential.common.realm)==0 &&
++              pj_stricmp(&hchal->scheme, &sent_auth->scheme)==0)
+           {
+               /* If this authorization has empty response, remove it. */
+               if (pj_stricmp(&sent_auth->scheme, &pjsip_DIGEST_STR)==0 &&
+@@ -1062,6 +1063,14 @@ static pj_status_t process_auth( pj_pool
+                   hdr = hdr->next;
+                   pj_list_erase(sent_auth);
+                   continue;
++              } else
++              if (pj_stricmp(&sent_auth->scheme, &pjsip_DIGEST_STR)==0 &&
++                  pj_stricmp(&sent_auth->credential.digest.algorithm,
++                             &hchal->challenge.digest.algorithm)!=0)
++              {
++                  /* Same 'digest' scheme but different algo */
++                  hdr = hdr->next;
++                  continue;
+               } else {
+                   /* Found previous authorization attempt */
+                   break;
+@@ -1155,9 +1164,10 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_reini
+ {
+     pjsip_tx_data *tdata;
+     const pjsip_hdr *hdr;
+-    unsigned chal_cnt;
++    unsigned chal_cnt, auth_cnt;
+     pjsip_via_hdr *via;
+     pj_status_t status;
++    pj_status_t last_auth_err;
+     PJ_ASSERT_RETURN(sess && rdata && old_request && new_request,
+                    PJ_EINVAL);
+@@ -1178,6 +1188,8 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_reini
+      */
+     hdr = rdata->msg_info.msg->hdr.next;
+     chal_cnt = 0;
++    auth_cnt = 0;
++    last_auth_err = PJSIP_EAUTHNOAUTH;
+     while (hdr != &rdata->msg_info.msg->hdr) {
+       pjsip_cached_auth *cached_auth;
+       const pjsip_www_authenticate_hdr *hchal;
+@@ -1222,8 +1234,13 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_reini
+        */
+       status = process_auth(tdata->pool, hchal, tdata->msg->line.req.uri,
+                             tdata, sess, cached_auth, &hauth);
+-      if (status != PJ_SUCCESS)
+-          return status;
++      if (status != PJ_SUCCESS) {
++          last_auth_err = status;
++
++          /* Process next header. */
++          hdr = hdr->next;
++          continue;
++      }
+       if (pj_pool_get_used_size(cached_auth->pool) >
+           PJSIP_AUTH_CACHED_POOL_MAX_SIZE) 
+@@ -1236,12 +1253,17 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_reini
+       /* Process next header. */
+       hdr = hdr->next;
++      auth_cnt++;
+     }
+     /* Check if challenge is present */
+     if (chal_cnt == 0)
+       return PJSIP_EAUTHNOCHAL;
++    /* Check if any authorization header has been created */
++    if (auth_cnt == 0)
++      return last_auth_err;
++
+     /* Remove branch param in Via header. */
+     via = (pjsip_via_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
+     via->branch_param.slen = 0;
+--- /dev/null
++++ b/tests/pjsua/scripts-sipp/uas-auth-two-algo.py
+@@ -0,0 +1,7 @@
++# $Id$
++#
++import inc_const as const
++
++PJSUA = ["--null-audio --max-calls=1 --id=sip:a@localhost --username=a --realm=* --registrar=$SIPP_URI"]
++
++PJSUA_EXPECTS = [[0, "registration success", ""]]
+--- /dev/null
++++ b/tests/pjsua/scripts-sipp/uas-auth-two-algo.xml
+@@ -0,0 +1,83 @@
++<?xml version="1.0" encoding="ISO-8859-1" ?>
++<!DOCTYPE scenario SYSTEM "sipp.dtd">
++
++<scenario name="Basic UAS responder">
++  <recv request="REGISTER" crlf="true">
++  </recv>
++
++  <send>
++    <![CDATA[
++      SIP/2.0 100 Trying
++      [last_Via:];received=1.1.1.1;rport=1111
++      [last_From:]
++      [last_To:];tag=[call_number]
++      [last_Call-ID:]
++      [last_CSeq:]
++      Content-Length: 0
++    ]]>
++  </send>
++
++  <send>
++    <![CDATA[
++      SIP/2.0 401 Unauthorized
++      [last_Via:];received=1.1.1.1;rport=1111
++      [last_From:]
++      [last_To:];tag=[call_number]
++      [last_Call-ID:]
++      [last_CSeq:]
++      WWW-Authenticate: Digest realm="sip.linphone.org", nonce="PARV4gAAAADgw3asAADW8zsi5BEAAAAA", opaque="+GNywA==", algorithm=SHA-256, qop="auth"
++      WWW-Authenticate: Digest realm="sip.linphone.org", nonce="PARV4gAAAADgw3asAADW8zsi5BEAAAAA", opaque="+GNywA==", algorithm=MD5, qop="auth"
++      WWW-Authenticate: Digest realm="sip.linphone.org", nonce="PARV4gAAAADgw3asAADW8zsi5BEAAAAA", opaque="+GNywA==", algorithm=MD2, qop="auth"
++      Content-Length: 0
++    ]]>
++  </send>
++
++  <recv request="REGISTER" crlf="true">
++    <action>
++      <ereg regexp=".*"
++            search_in="hdr"
++          header="Authorization:"
++          assign_to="have_auth" />
++    </action>
++  </recv>
++
++  <nop next="resp_okay" test="have_auth" />
++  
++  <send next="end">
++    <![CDATA[
++      SIP/2.0 403 no auth
++      [last_Via:];received=1.1.1.1;rport=1111
++      [last_From:]
++      [last_To:];tag=[call_number]
++      [last_Call-ID:]
++      [last_CSeq:]
++      [last_Contact:]
++      Content-Length: 0
++    ]]>
++  </send>
++
++  <label id="resp_okay" />
++  
++  <send>
++    <![CDATA[
++      SIP/2.0 200 OK
++      [last_Via:];received=1.1.1.1;rport=1111
++      [last_From:]
++      [last_To:];tag=[call_number]
++      [last_Call-ID:]
++      [last_CSeq:]
++      [last_Contact:]
++      Content-Length: 0
++    ]]>
++  </send>
++
++  <label id="end" />
++
++  <!-- definition of the response time repartition table (unit is ms)   -->
++  <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
++
++  <!-- definition of the call length repartition table (unit is ms)     -->
++  <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
++
++</scenario>
++
diff --git a/libs/pjproject/patches/0100-fix-double-stun-free.patch b/libs/pjproject/patches/0100-fix-double-stun-free.patch
new file mode 100644 (file)
index 0000000..f1691b9
--- /dev/null
@@ -0,0 +1,78 @@
+commit f0ff5817d0647bdecd1ec99488db9378e304cf83
+Author: sauwming <ming@teluu.com>
+Date:   Mon May 17 09:56:27 2021 +0800
+
+    Fix double free of stun session (#2709)
+
+--- a/pjnath/include/pjnath/stun_session.h
++++ b/pjnath/include/pjnath/stun_session.h
+@@ -341,6 +341,7 @@ struct pj_stun_tx_data
+     pj_pool_t         *pool;          /**< Pool.                          */
+     pj_stun_session   *sess;          /**< The STUN session.              */
+     pj_stun_msg               *msg;           /**< The STUN message.              */
++    pj_bool_t          is_destroying; /**< Is destroying?                 */
+     void              *token;         /**< The token.                     */
+--- a/pjnath/src/pjnath/stun_session.c
++++ b/pjnath/src/pjnath/stun_session.c
+@@ -167,16 +167,27 @@ static void tdata_on_destroy(void *arg)
+ {
+     pj_stun_tx_data *tdata = (pj_stun_tx_data*)arg;
++    if (tdata->grp_lock) {
++      pj_grp_lock_dec_ref(tdata->sess->grp_lock);
++    }
++
+     pj_pool_safe_release(&tdata->pool);
+ }
+ static void destroy_tdata(pj_stun_tx_data *tdata, pj_bool_t force)
+ {
+-    TRACE_((THIS_FILE, "tdata %p destroy request, force=%d, tsx=%p", tdata,
+-          force, tdata->client_tsx));
++    TRACE_((THIS_FILE,
++          "tdata %p destroy request, force=%d, tsx=%p, destroying=%d",
++          tdata, force, tdata->client_tsx, tdata->is_destroying));
++
++    /* Just return if destroy has been requested before */
++    if (tdata->is_destroying)
++      return;
+     /* STUN session may have been destroyed, except when tdata is cached. */
++    tdata->is_destroying = PJ_TRUE;
++
+     if (tdata->res_timer.id != PJ_FALSE) {
+       pj_timer_heap_cancel_if_active(tdata->sess->cfg->timer_heap,
+                                      &tdata->res_timer, PJ_FALSE);
+@@ -189,7 +200,6 @@ static void destroy_tdata(pj_stun_tx_dat
+           pj_stun_client_tsx_set_data(tdata->client_tsx, NULL);
+       }
+       if (tdata->grp_lock) {
+-          pj_grp_lock_dec_ref(tdata->sess->grp_lock);
+           pj_grp_lock_dec_ref(tdata->grp_lock);
+       } else {
+           tdata_on_destroy(tdata);
+@@ -200,11 +210,11 @@ static void destroy_tdata(pj_stun_tx_dat
+           /* "Probably" this is to absorb retransmission */
+           pj_time_val delay = {0, 300};
+           pj_stun_client_tsx_schedule_destroy(tdata->client_tsx, &delay);
++          tdata->is_destroying = PJ_FALSE;
+       } else {
+           pj_list_erase(tdata);
+           if (tdata->grp_lock) {
+-              pj_grp_lock_dec_ref(tdata->sess->grp_lock);
+               pj_grp_lock_dec_ref(tdata->grp_lock);
+           } else {
+               tdata_on_destroy(tdata);
+@@ -238,7 +248,7 @@ static void on_cache_timeout(pj_timer_he
+     sess = tdata->sess;
+     pj_grp_lock_acquire(sess->grp_lock);
+-    if (sess->is_destroying) {
++    if (sess->is_destroying || tdata->is_destroying) {
+       pj_grp_lock_release(sess->grp_lock);
+       return;
+     }
diff --git a/libs/pjproject/patches/0110-tls-parent-listener-destroyed.patch b/libs/pjproject/patches/0110-tls-parent-listener-destroyed.patch
new file mode 100644 (file)
index 0000000..e496fe4
--- /dev/null
@@ -0,0 +1,162 @@
+From bb92c97ea512aa0ef316c9b2335c7d57b84dfc9a Mon Sep 17 00:00:00 2001
+From: Nanang Izzuddin <nanang@teluu.com>
+Date: Wed, 16 Jun 2021 12:12:35 +0700
+Subject: [PATCH 1/2] - Avoid SSL socket parent/listener getting destroyed
+ during handshake by increasing parent's reference count. - Add missing SSL
+ socket close when the newly accepted SSL socket is discarded in SIP TLS
+ transport.
+
+---
+ pjlib/src/pj/ssl_sock_imp_common.c  | 44 +++++++++++++++++++++--------
+ pjsip/src/pjsip/sip_transport_tls.c | 23 ++++++++++++++-
+ 2 files changed, 55 insertions(+), 12 deletions(-)
+
+--- a/pjlib/src/pj/ssl_sock_imp_common.c
++++ b/pjlib/src/pj/ssl_sock_imp_common.c
+@@ -224,6 +224,8 @@ static pj_bool_t on_handshake_complete(p
+     /* Accepting */
+     if (ssock->is_server) {
++      pj_bool_t ret = PJ_TRUE;
++
+       if (status != PJ_SUCCESS) {
+           /* Handshake failed in accepting, destroy our self silently. */
+@@ -241,6 +243,12 @@ static pj_bool_t on_handshake_complete(p
+                     status);
+           }
++          /* Decrement ref count of parent */
++          if (ssock->parent->param.grp_lock) {
++              pj_grp_lock_dec_ref(ssock->parent->param.grp_lock);
++              ssock->parent = NULL;
++          }
++
+           /* Originally, this is a workaround for ticket #985. However,
+            * a race condition may occur in multiple worker threads
+            * environment when we are destroying SSL objects while other
+@@ -284,23 +292,29 @@ static pj_bool_t on_handshake_complete(p
+           return PJ_FALSE;
+       }
++
+       /* Notify application the newly accepted SSL socket */
+       if (ssock->param.cb.on_accept_complete2) {
+-          pj_bool_t ret;
+           ret = (*ssock->param.cb.on_accept_complete2) 
+                   (ssock->parent, ssock, (pj_sockaddr_t*)&ssock->rem_addr, 
+                   pj_sockaddr_get_len((pj_sockaddr_t*)&ssock->rem_addr), 
+                   status);
+-          if (ret == PJ_FALSE)
+-              return PJ_FALSE;        
+       } else if (ssock->param.cb.on_accept_complete) {
+-          pj_bool_t ret;
+           ret = (*ssock->param.cb.on_accept_complete)
+                     (ssock->parent, ssock, (pj_sockaddr_t*)&ssock->rem_addr,
+                      pj_sockaddr_get_len((pj_sockaddr_t*)&ssock->rem_addr));
+-          if (ret == PJ_FALSE)
+-              return PJ_FALSE;
+       }
++
++      /* Decrement ref count of parent and reset parent (we don't need it
++       * anymore, right?).
++       */
++      if (ssock->parent->param.grp_lock) {
++          pj_grp_lock_dec_ref(ssock->parent->param.grp_lock);
++          ssock->parent = NULL;
++      }
++
++      if (ret == PJ_FALSE)
++          return PJ_FALSE;
+     }
+     /* Connecting */
+@@ -864,9 +878,13 @@ static pj_bool_t asock_on_accept_complet
+     if (status != PJ_SUCCESS)
+       goto on_return;
++    /* Set parent and add ref count (avoid parent destroy during handshake) */
++    ssock->parent = ssock_parent;
++    if (ssock->parent->param.grp_lock)
++      pj_grp_lock_add_ref(ssock->parent->param.grp_lock);
++
+     /* Update new SSL socket attributes */
+     ssock->sock = newsock;
+-    ssock->parent = ssock_parent;
+     ssock->is_server = PJ_TRUE;
+     if (ssock_parent->cert) {
+       status = pj_ssl_sock_set_certificate(ssock, ssock->pool, 
+@@ -913,16 +931,20 @@ static pj_bool_t asock_on_accept_complet
+     ssock->asock_rbuf = (void**)pj_pool_calloc(ssock->pool, 
+                                              ssock->param.async_cnt,
+                                              sizeof(void*));
+-    if (!ssock->asock_rbuf)
+-        return PJ_ENOMEM;
++    if (!ssock->asock_rbuf) {
++              status = PJ_ENOMEM;
++              goto on_return;
++      }
+     for (i = 0; i<ssock->param.async_cnt; ++i) {
+-      ssock->asock_rbuf[i] = (void*) pj_pool_alloc(
++              ssock->asock_rbuf[i] = (void*) pj_pool_alloc(
+                                           ssock->pool, 
+                                           ssock->param.read_buffer_size + 
+                                           sizeof(read_data_t*));
+-        if (!ssock->asock_rbuf[i])
+-            return PJ_ENOMEM;
++              if (!ssock->asock_rbuf[i]) {
++                      status = PJ_ENOMEM;
++                      goto on_return;
++              }
+     }
+     /* Create active socket */
+--- a/pjsip/src/pjsip/sip_transport_tls.c
++++ b/pjsip/src/pjsip/sip_transport_tls.c
+@@ -1325,9 +1325,26 @@ static pj_bool_t on_accept_complete2(pj_
+     PJ_UNUSED_ARG(src_addr_len);
+     listener = (struct tls_listener*) pj_ssl_sock_get_user_data(ssock);
++    if (!listener) {
++      /* Listener already destroyed, e.g: after TCP accept but before SSL
++       * handshake is completed.
++       */
++      if (new_ssock && accept_status == PJ_SUCCESS) {
++          /* Close the SSL socket if the accept op is successful */
++          PJ_LOG(4,(THIS_FILE,
++                    "Incoming TLS connection from %s (sock=%d) is discarded "
++                    "because listener is already destroyed",
++                    pj_sockaddr_print(src_addr, addr, sizeof(addr), 3),
++                    new_ssock));
++
++          pj_ssl_sock_close(new_ssock);
++      }
++
++      return PJ_FALSE;
++    }
+     if (accept_status != PJ_SUCCESS) {
+-      if (listener && listener->tls_setting.on_accept_fail_cb) {
++      if (listener->tls_setting.on_accept_fail_cb) {
+           pjsip_tls_on_accept_fail_param param;
+           pj_ssl_sock_info ssi;
+@@ -1350,6 +1367,8 @@ static pj_bool_t on_accept_complete2(pj_
+     PJ_ASSERT_RETURN(new_ssock, PJ_TRUE);
+     if (!listener->is_registered) {
++      pj_ssl_sock_close(new_ssock);
++
+       if (listener->tls_setting.on_accept_fail_cb) {
+           pjsip_tls_on_accept_fail_param param;
+           pj_bzero(&param, sizeof(param));
+@@ -1401,6 +1420,8 @@ static pj_bool_t on_accept_complete2(pj_
+                        ssl_info.grp_lock, &tls);
+     
+     if (status != PJ_SUCCESS) {
++      pj_ssl_sock_close(new_ssock);
++
+       if (listener->tls_setting.on_accept_fail_cb) {
+           pjsip_tls_on_accept_fail_param param;
+           pj_bzero(&param, sizeof(param));