<p>Kevin Harwell <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/18572">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Joshua Colp: Looks good to me, but someone else must approve
  Kevin Harwell: Looks good to me, approved; Approved for Submit
  Benjamin Keith Ford: Looks good to me, but someone else must approve
  Michael Bradeen: Looks good to me, but someone else must approve

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_pjsip: allow TLS verification of wildcard cert-bearing servers<br><br>Rightly the use of wildcards in certificates is disallowed in accordance<br>with RFC5922. However, RFC2818 does make some allowances with regards to<br>their use when using subject alt names with DNS name types.<br><br>As such this patch creates a new setting for TLS transports called<br>'allow_wildcard_certs', which when it and 'verify_server' are both enabled<br>allows DNS name types, as well as the common name that start with '*.'<br>to match as a wildcard.<br><br>For instance: *.example.com<br>will match for: foo.example.com<br><br>Partial matching is not allowed, e.g. f*.example.com, foo.*.com, etc...<br>And the starting wildcard only matches for a single level.<br><br>For instance: *.example.com<br>will NOT match for: foo.bar.example.com<br><br>The new setting is disabled by default.<br><br>ASTERISK-30072 #close<br><br>Change-Id: If0be3fdab2e09c2a66bb54824fca406ebaac3da4<br>---<br>M configs/samples/pjsip.conf.sample<br>A contrib/ast-db-manage/config/versions/58e440314c2a_allow_wildcard_certs.py<br>A doc/CHANGES-staging/allow_wildcard_certs.txt<br>M include/asterisk/res_pjsip.h<br>M res/res_pjsip/config_transport.c<br>M res/res_pjsip/pjsip_config.xml<br>M res/res_pjsip/pjsip_transport_events.c<br>7 files changed, 218 insertions(+), 2 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample</span><br><span>index 0e8f265..1ce14db 100644</span><br><span>--- a/configs/samples/pjsip.conf.sample</span><br><span>+++ b/configs/samples/pjsip.conf.sample</span><br><span>@@ -1037,6 +1037,15 @@</span><br><span>                         ; URI is not a hostname, the saved transport will be</span><br><span>                         ; used and the 'x-ast-txp' parameter stripped from the</span><br><span>                         ; outgoing packet.</span><br><span style="color: hsl(120, 100%, 40%);">+;allow_wildcard_certs=no ; In conjunction with verify_server, if 'yes' allow use</span><br><span style="color: hsl(120, 100%, 40%);">+                         ; of wildcards, i.e. '*.' in certs for common, and</span><br><span style="color: hsl(120, 100%, 40%);">+                         ; subject alt names of type DNS for TLS transport</span><br><span style="color: hsl(120, 100%, 40%);">+                         ; types. Note, names must start with the wildcard.</span><br><span style="color: hsl(120, 100%, 40%);">+                         ; Partial wildcards, e.g. 'f*.example.com' and</span><br><span style="color: hsl(120, 100%, 40%);">+                         ; 'foo.*.com' are disallowed. As well, names only</span><br><span style="color: hsl(120, 100%, 40%);">+                         ; match against a single level meaning '*.example.com'</span><br><span style="color: hsl(120, 100%, 40%);">+                         ; matches 'foo.example.com', but not</span><br><span style="color: hsl(120, 100%, 40%);">+                         ; 'foo.bar.example.com'. Defaults to 'no'.</span><br><span> </span><br><span> ;==========================AOR SECTION OPTIONS=========================</span><br><span> ;[aor]</span><br><span>diff --git a/contrib/ast-db-manage/config/versions/58e440314c2a_allow_wildcard_certs.py b/contrib/ast-db-manage/config/versions/58e440314c2a_allow_wildcard_certs.py</span><br><span>new file mode 100644</span><br><span>index 0000000..2e56f73</span><br><span>--- /dev/null</span><br><span>+++ b/contrib/ast-db-manage/config/versions/58e440314c2a_allow_wildcard_certs.py</span><br><span>@@ -0,0 +1,29 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""allow_wildcard_certs</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Revision ID: 58e440314c2a</span><br><span style="color: hsl(120, 100%, 40%);">+Revises: 18e0805d367f</span><br><span style="color: hsl(120, 100%, 40%);">+Create Date: 2022-05-12 12:15:55.343743</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# revision identifiers, used by Alembic.</span><br><span style="color: hsl(120, 100%, 40%);">+revision = '58e440314c2a'</span><br><span style="color: hsl(120, 100%, 40%);">+down_revision = '18e0805d367f'</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from alembic import op</span><br><span style="color: hsl(120, 100%, 40%);">+import sqlalchemy as sa</span><br><span style="color: hsl(120, 100%, 40%);">+from sqlalchemy.dialects.postgresql import ENUM</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+YESNO_NAME = 'yesno_values'</span><br><span style="color: hsl(120, 100%, 40%);">+YESNO_VALUES = ['yes', 'no']</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def upgrade():</span><br><span style="color: hsl(120, 100%, 40%);">+    yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    op.add_column('ps_transports', sa.Column('allow_wildcard_certs', type_=yesno_values))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def downgrade():</span><br><span style="color: hsl(120, 100%, 40%);">+    if op.get_context().bind.dialect.name == 'mssql':</span><br><span style="color: hsl(120, 100%, 40%);">+        op.drop_constraint('ck_ps_transports_allow_wildcard_certs_yesno_values', 'ps_transports')</span><br><span style="color: hsl(120, 100%, 40%);">+    op.drop_column('ps_transports', 'allow_wildcard_certs')</span><br><span>diff --git a/doc/CHANGES-staging/allow_wildcard_certs.txt b/doc/CHANGES-staging/allow_wildcard_certs.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..29a53dd</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/allow_wildcard_certs.txt</span><br><span>@@ -0,0 +1,9 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: res_pjsip</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+A new transport option 'allow_wildcard_certs' has been added that when it</span><br><span style="color: hsl(120, 100%, 40%);">+and 'verify_server' are both set to 'yes', enables verification against</span><br><span style="color: hsl(120, 100%, 40%);">+wildcards, i.e. '*.' in certs for common, and subject alt names of type DNS</span><br><span style="color: hsl(120, 100%, 40%);">+for TLS transport types. Names must start with the wildcard. Partial wildcards,</span><br><span style="color: hsl(120, 100%, 40%);">+e.g. 'f*.example.com' and 'foo.*.com' are not allowed. As well, names only</span><br><span style="color: hsl(120, 100%, 40%);">+match against a single level meaning '*.example.com' matches 'foo.example.com',</span><br><span style="color: hsl(120, 100%, 40%);">+but not 'foo.bar.example.com'.</span><br><span>diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h</span><br><span>index f0105f3..d517c35 100644</span><br><span>--- a/include/asterisk/res_pjsip.h</span><br><span>+++ b/include/asterisk/res_pjsip.h</span><br><span>@@ -155,6 +155,14 @@</span><br><span>      * \since 13.18.0</span><br><span>     */</span><br><span>  struct ast_sockaddr external_media_address;</span><br><span style="color: hsl(120, 100%, 40%);">+   /*!</span><br><span style="color: hsl(120, 100%, 40%);">+    * Disregard RFC5922 7.2, and allow wildcard certs (TLS only)</span><br><span style="color: hsl(120, 100%, 40%);">+  */</span><br><span style="color: hsl(120, 100%, 40%);">+   int allow_wildcard_certs;</span><br><span style="color: hsl(120, 100%, 40%);">+     /*!</span><br><span style="color: hsl(120, 100%, 40%);">+    * If true, fail if server certificate cannot verify (TLS only)</span><br><span style="color: hsl(120, 100%, 40%);">+        */</span><br><span style="color: hsl(120, 100%, 40%);">+   int verify_server;</span><br><span> };</span><br><span> </span><br><span> #define ast_sip_transport_is_nonlocal(transport_state, addr) \</span><br><span>diff --git a/res/res_pjsip/config_transport.c b/res/res_pjsip/config_transport.c</span><br><span>index 4bc6f6e..522a89d 100644</span><br><span>--- a/res/res_pjsip/config_transport.c</span><br><span>+++ b/res/res_pjsip/config_transport.c</span><br><span>@@ -658,6 +658,16 @@</span><br><span>                           &temp_state->state->host, NULL, transport->async_operations,</span><br><span>                            &temp_state->state->factory);</span><br><span>              }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (res == PJ_SUCCESS) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      temp_state->state->factory->info = pj_pool_alloc(</span><br><span style="color: hsl(120, 100%, 40%);">+                            temp_state->state->factory->pool, (strlen(transport_id) + 1));</span><br><span style="color: hsl(120, 100%, 40%);">+                       /*</span><br><span style="color: hsl(120, 100%, 40%);">+                     * Store transport id on the factory instance so it can be used</span><br><span style="color: hsl(120, 100%, 40%);">+                        * later to look up the transport state.</span><br><span style="color: hsl(120, 100%, 40%);">+                       */</span><br><span style="color: hsl(120, 100%, 40%);">+                   sprintf(temp_state->state->factory->info, "%s", transport_id);</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span> #else</span><br><span>           ast_log(LOG_ERROR, "Transport: %s: PJSIP has not been compiled with TLS transport support, ensure OpenSSL development packages are installed\n",</span><br><span>                   ast_sorcery_object_get_id(obj));</span><br><span>@@ -875,11 +885,13 @@</span><br><span>     }</span><br><span> </span><br><span>        if (!strcasecmp(var->name, "verify_server")) {</span><br><span style="color: hsl(0, 100%, 40%);">-             state->tls.verify_server = ast_true(var->value) ? PJ_TRUE : PJ_FALSE;</span><br><span style="color: hsl(120, 100%, 40%);">+           state->verify_server = ast_true(var->value);</span><br><span>   } else if (!strcasecmp(var->name, "verify_client")) {</span><br><span>           state->tls.verify_client = ast_true(var->value) ? PJ_TRUE : PJ_FALSE;</span><br><span>  } else if (!strcasecmp(var->name, "require_client_cert")) {</span><br><span>             state->tls.require_client_cert = ast_true(var->value) ? PJ_TRUE : PJ_FALSE;</span><br><span style="color: hsl(120, 100%, 40%);">+     } else if (!strcasecmp(var->name, "allow_wildcard_certs")) {</span><br><span style="color: hsl(120, 100%, 40%);">+             state->allow_wildcard_certs = ast_true(var->value);</span><br><span>    } else {</span><br><span>             return -1;</span><br><span>   }</span><br><span>@@ -896,7 +908,7 @@</span><br><span>              return -1;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   *buf = ast_strdup(AST_YESNO(state->tls.verify_server));</span><br><span style="color: hsl(120, 100%, 40%);">+    *buf = ast_strdup(AST_YESNO(state->verify_server));</span><br><span> </span><br><span>   return 0;</span><br><span> }</span><br><span>@@ -929,6 +941,20 @@</span><br><span>        return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int allow_wildcard_certs_to_str(const void *obj, const intptr_t *args, char **buf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_sip_transport_state *state = find_state_by_transport(obj);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!state) {</span><br><span style="color: hsl(120, 100%, 40%);">+         return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   *buf = ast_strdup(AST_YESNO(state->allow_wildcard_certs));</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(state, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! \brief Custom handler for TLS method setting */</span><br><span> static int transport_tls_method_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)</span><br><span> {</span><br><span>@@ -1461,6 +1487,7 @@</span><br><span>     ast_sorcery_object_field_register_custom(sorcery, "transport", "verify_server", "", transport_tls_bool_handler, verify_server_to_str, NULL, 0, 0);</span><br><span>     ast_sorcery_object_field_register_custom(sorcery, "transport", "verify_client", "", transport_tls_bool_handler, verify_client_to_str, NULL, 0, 0);</span><br><span>     ast_sorcery_object_field_register_custom(sorcery, "transport", "require_client_cert", "", transport_tls_bool_handler, require_client_cert_to_str, NULL, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_sorcery_object_field_register_custom(sorcery, "transport", "allow_wildcard_certs", "", transport_tls_bool_handler, allow_wildcard_certs_to_str, NULL, 0, 0);</span><br><span>       ast_sorcery_object_field_register_custom(sorcery, "transport", "method", "", transport_tls_method_handler, tls_method_to_str, NULL, 0, 0);</span><br><span> #if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0</span><br><span>     ast_sorcery_object_field_register_custom(sorcery, "transport", "cipher", "", transport_tls_cipher_handler, transport_tls_cipher_to_str, NULL, 0, 0);</span><br><span>diff --git a/res/res_pjsip/pjsip_config.xml b/res/res_pjsip/pjsip_config.xml</span><br><span>index 0a85c7e..c4cb44b 100644</span><br><span>--- a/res/res_pjsip/pjsip_config.xml</span><br><span>+++ b/res/res_pjsip/pjsip_config.xml</span><br><span>@@ -1445,6 +1445,18 @@</span><br><span>                                             in-progress calls.</para></span><br><span>                                      </description></span><br><span>                                 </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+                         <configOption name="allow_wildcard_certs" default="false"></span><br><span style="color: hsl(120, 100%, 40%);">+                                  <synopsis>Allow use of wildcards in certificates (TLS ONLY)</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                                    <description></span><br><span style="color: hsl(120, 100%, 40%);">+                                     <para>In combination with verify_server, when enabled allow use of wildcards,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   i.e. '*.' in certs for common,and subject alt names of type DNS for TLS</span><br><span style="color: hsl(120, 100%, 40%);">+                                       transport types. Names must start with the wildcard. Partial wildcards, e.g.</span><br><span style="color: hsl(120, 100%, 40%);">+                                          'f*.example.com' and 'foo.*.com' are not allowed. As well, names only match</span><br><span style="color: hsl(120, 100%, 40%);">+                                   against a single level meaning '*.example.com' matches 'foo.example.com',</span><br><span style="color: hsl(120, 100%, 40%);">+                                     but not 'foo.bar.example.com'.</span><br><span style="color: hsl(120, 100%, 40%);">+                                        </para></span><br><span style="color: hsl(120, 100%, 40%);">+                                       </description></span><br><span style="color: hsl(120, 100%, 40%);">+                          </configOption></span><br><span>                                <configOption name="symmetric_transport" default="no"></span><br><span>                                     <synopsis>Use the same transport for outgoing requests as incoming ones.</synopsis></span><br><span>                                      <description></span><br><span>diff --git a/res/res_pjsip/pjsip_transport_events.c b/res/res_pjsip/pjsip_transport_events.c</span><br><span>index 4df1d5e..a816f46 100644</span><br><span>--- a/res/res_pjsip/pjsip_transport_events.c</span><br><span>+++ b/res/res_pjsip/pjsip_transport_events.c</span><br><span>@@ -142,6 +142,122 @@</span><br><span>     }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void verify_log_result(int log_level, const pjsip_transport *transport,</span><br><span style="color: hsl(120, 100%, 40%);">+    pj_uint32_t verify_status)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *status[32];</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned int count;</span><br><span style="color: hsl(120, 100%, 40%);">+   unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     count = ARRAY_LEN(status);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (pj_ssl_cert_get_verify_status_strings(verify_status, status, &count) != PJ_SUCCESS) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_log(LOG_ERROR, "Error retrieving certificate verification result(s)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < count; ++i) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_log(log_level, _A_, "Transport '%s' to remote '%.*s' - %s\n", transport->factory->info,</span><br><span style="color: hsl(120, 100%, 40%);">+                   (int)pj_strlen(&transport->remote_name.host), pj_strbuf(&transport->remote_name.host),</span><br><span style="color: hsl(120, 100%, 40%);">+                  status[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int verify_cert_name(const pj_str_t *local, const pj_str_t *remote)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *p;</span><br><span style="color: hsl(120, 100%, 40%);">+        pj_ssize_t size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_debug(3, "Verify certificate name: local = %.*s, remote = %.*s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+              (unsigned int)pj_strlen(local), pj_strbuf(local),</span><br><span style="color: hsl(120, 100%, 40%);">+             (unsigned int)pj_strlen(remote), pj_strbuf(remote));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!pj_stricmp(remote, local)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (pj_strnicmp2(remote, "*.", 2)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   p = pj_strchr(local, '.');</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!p) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   size = pj_strbuf(local) + pj_strlen(local) - ++p;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return size == pj_strlen(remote) - 2 ?</span><br><span style="color: hsl(120, 100%, 40%);">+                !pj_memcmp(pj_strbuf(remote) + 2,  p, size) : 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int verify_cert_names(const pj_str_t *host, const pj_ssl_cert_info *remote)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 0; i < remote->subj_alt_name.cnt; ++i) {</span><br><span style="color: hsl(120, 100%, 40%);">+               /*</span><br><span style="color: hsl(120, 100%, 40%);">+             * DNS is the only type we're matching wildcards against,</span><br><span style="color: hsl(120, 100%, 40%);">+          * so only recheck those.</span><br><span style="color: hsl(120, 100%, 40%);">+              */</span><br><span style="color: hsl(120, 100%, 40%);">+           if (remote->subj_alt_name.entry[i].type == PJ_SSL_CERT_NAME_DNS</span><br><span style="color: hsl(120, 100%, 40%);">+                    && verify_cert_name(host, &remote->subj_alt_name.entry[i].name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return verify_cert_name(host, &remote->subject.cn);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int transport_tls_verify(const pjsip_transport *transport,</span><br><span style="color: hsl(120, 100%, 40%);">+    const pjsip_tls_state_info *state_info)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    pj_uint32_t verify_status;</span><br><span style="color: hsl(120, 100%, 40%);">+    const struct ast_sip_transport_state *state;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (transport->dir == PJSIP_TP_DIR_INCOMING) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* transport_id should always be in factory info (see config_transport) */</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_assert(!ast_strlen_zero(transport->factory->info));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       state = ast_sip_get_transport_state(transport->factory->info);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!state) {</span><br><span style="color: hsl(120, 100%, 40%);">+         /*</span><br><span style="color: hsl(120, 100%, 40%);">+             * There should always be an associated state, but if for some</span><br><span style="color: hsl(120, 100%, 40%);">+                 * reason there is not then fail verification</span><br><span style="color: hsl(120, 100%, 40%);">+          */</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_log(LOG_ERROR, "Transport state not found for '%s'\n", transport->factory->info);</span><br><span style="color: hsl(120, 100%, 40%);">+         return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   verify_status = state_info->ssl_sock_info->verify_status;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * By this point pjsip has already completed its verification process. If</span><br><span style="color: hsl(120, 100%, 40%);">+      * there was a name matching error it could be because they disallow wildcards.</span><br><span style="color: hsl(120, 100%, 40%);">+        * If this transport has been configured to allow wildcards then we'll need</span><br><span style="color: hsl(120, 100%, 40%);">+        * to re-check the name(s) for such.</span><br><span style="color: hsl(120, 100%, 40%);">+   */</span><br><span style="color: hsl(120, 100%, 40%);">+   if (state->allow_wildcard_certs &&</span><br><span style="color: hsl(120, 100%, 40%);">+                 (verify_status & PJ_SSL_CERT_EIDENTITY_NOT_MATCH)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (verify_cert_names(&transport->remote_name.host,</span><br><span style="color: hsl(120, 100%, 40%);">+                    state_info->ssl_sock_info->remote_cert_info)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 /* A name matched a wildcard, so clear the error */</span><br><span style="color: hsl(120, 100%, 40%);">+                   verify_status &= ~PJ_SSL_CERT_EIDENTITY_NOT_MATCH;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (state->verify_server && verify_status != PJ_SSL_CERT_ESUCCESS) {</span><br><span style="color: hsl(120, 100%, 40%);">+               verify_log_result(__LOG_ERROR, transport, verify_status);</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   verify_log_result(__LOG_NOTICE, transport, verify_status);</span><br><span style="color: hsl(120, 100%, 40%);">+    return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! \brief Callback invoked when transport state changes occur */</span><br><span> static void transport_state_callback(pjsip_transport *transport,</span><br><span>      pjsip_transport_state state, const pjsip_transport_state_info *info)</span><br><span>@@ -157,6 +273,12 @@</span><br><span>                  transport->obj_name, transport_state2str(state));</span><br><span>                 switch (state) {</span><br><span>             case PJSIP_TP_STATE_CONNECTED:</span><br><span style="color: hsl(120, 100%, 40%);">+                        if (PJSIP_TRANSPORT_IS_SECURE(transport) &&</span><br><span style="color: hsl(120, 100%, 40%);">+                           !transport_tls_verify(transport, info->ext_info)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                pjsip_transport_shutdown(transport);</span><br><span style="color: hsl(120, 100%, 40%);">+                          return;</span><br><span style="color: hsl(120, 100%, 40%);">+                       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>                  monitored = ao2_alloc_options(sizeof(*monitored),</span><br><span>                            transport_monitor_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK);</span><br><span>                  if (!monitored) {</span><br><span></span><br></pre><div style="white-space:pre-wrap"></div><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/18572">change 18572</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/18572"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 16 </div>
<div style="display:none"> Gerrit-Change-Id: If0be3fdab2e09c2a66bb54824fca406ebaac3da4 </div>
<div style="display:none"> Gerrit-Change-Number: 18572 </div>
<div style="display:none"> Gerrit-PatchSet: 5 </div>
<div style="display:none"> Gerrit-Owner: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Benjamin Keith Ford <bford@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@sangoma.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Michael Bradeen <mbradeen@sangoma.com> </div>
<div style="display:none"> Gerrit-CC: N A <mail@interlinked.x10host.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>