]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_stir_shaken: Add "ignore_sip_date_header" config option.
authorGeorge Joseph <gjoseph@sangoma.com>
Sun, 15 Jun 2025 20:43:13 +0000 (14:43 -0600)
committergithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Wed, 18 Jun 2025 15:26:47 +0000 (15:26 +0000)
UserNote: A new STIR/SHAKEN verification option "ignore_sip_date_header" has
been added that when set to true, will cause the verification process to
not consider a missing or invalid SIP "Date" header to be a failure.  This
will make the IAT the sole "truth" for Date in the verification process.
The option can be set in the "verification" and "profile" sections of
stir_shaken.conf.

Also fixed a bug in the port match logic.

Resolves: #1251
Resolves: #1271

configs/samples/stir_shaken.conf.sample
res/res_pjsip_stir_shaken.c
res/res_stir_shaken/common_config.c
res/res_stir_shaken/common_config.h
res/res_stir_shaken/profile_config.c
res/res_stir_shaken/stir_shaken_doc.xml
res/res_stir_shaken/verification.c
res/res_stir_shaken/verification_config.c

index 3fe9d7e955792759901df7642f73cb432c554d94..afe4bc024f54b6ad88013fd2725d894fc69e1400 100644 (file)
@@ -330,6 +330,13 @@ considered "failed".
 
 Default: 15
 
+-- ignore_sip_date_header ---------------------------------------------
+When set to true, will cause the verification process to not consider a
+missing or invalid SIP "Date" header to be a failure.  This will make
+the IAT the sole "truth" for Date in the verification process.
+
+Default: no
+
 -- max_date_header_age ------------------------------------------------
 The sender MUST also send a SIP Date header in their request.  If we
 receive one that is older than the current time by the number of seconds
index ea498942ebbef48e7e8777b71e7d9fa52bbc3029..bd4e030c63a737967c1c4d8caae2bcc1c6a67b2f 100644 (file)
@@ -277,22 +277,13 @@ static int stir_shaken_incoming_request(struct ast_sip_session *session, pjsip_r
        }
 
        date_hdr_val = ast_sip_rdata_get_header_value(rdata, date_hdr_str);
-       if (ast_strlen_zero(date_hdr_val)) {
-               p_rc = process_failure(ctx, caller_id, session, rdata,
-                       AST_STIR_SHAKEN_VS_NO_DATE_HDR);
-               if (p_rc == PROCESS_FAILURE_CONTINUE) {
-                       SCOPE_EXIT_RTN_VALUE(0, "%s: No Date header found.  Call continuing\n",
+       if (!ast_strlen_zero(date_hdr_val)) {
+               vs_rc = ast_stir_shaken_vs_ctx_add_date_hdr(ctx, date_hdr_val);
+               if (vs_rc != AST_STIR_SHAKEN_VS_SUCCESS) {
+                       reject_incoming_call(session, 500);
+                       SCOPE_EXIT_LOG_RTN_VALUE(1, LOG_ERROR, "%s: Unable to add Date header.  Call terminated.\n",
                                session_name);
                }
-               SCOPE_EXIT_LOG_RTN_VALUE(1, LOG_ERROR, "%s: No Date header found.  Call terminated\n",
-                       session_name);
-       }
-
-       ast_stir_shaken_vs_ctx_add_date_hdr(ctx, date_hdr_val);
-       if (vs_rc != AST_STIR_SHAKEN_VS_SUCCESS) {
-               reject_incoming_call(session, 500);
-               SCOPE_EXIT_LOG_RTN_VALUE(1, LOG_ERROR, "%s: Unable to add Date header.  Call terminated.\n",
-                       session_name);
        }
 
        vs_rc = ast_stir_shaken_vs_verify(ctx);
index b669762ec3c7b4ef66448ec8fd3f1e4cbf60283c..0cbd9b50358e4d8cfc884a567f77e8c8d577a724 100644 (file)
@@ -62,6 +62,7 @@ const char *param_name ## _to_str(enum param_name ## _enum value) \
 }
 
 generate_bool_handler_functions(use_rfc9410_responses);
+generate_bool_handler_functions(ignore_sip_date_header);
 generate_bool_handler_functions(send_mky);
 generate_bool_handler_functions(check_tn_cert_public_url);
 generate_bool_handler_functions(relax_x5u_port_scheme_restrictions);
index e390b548b6be793b04762333bb509319df7efb6e..4eb9e5e02fb57a0ae0e5e465a8a1aadbf0c605ec 100644 (file)
@@ -79,6 +79,8 @@ generate_bool_string_prototypes(relax_x5u_path_restrictions);
 
 generate_bool_string_prototypes(load_system_certs);
 
+generate_bool_string_prototypes(ignore_sip_date_header);
+
 generate_bool_string_prototypes(check_tn_cert_public_url);
 
 generate_bool_string_prototypes(send_mky);
@@ -365,7 +367,7 @@ struct verification_cfg_common {
        enum relax_x5u_path_restrictions_enum
                relax_x5u_path_restrictions;
        enum load_system_certs_enum load_system_certs;
-
+       enum ignore_sip_date_header_enum ignore_sip_date_header;
        struct ast_acl_list *acl;
        struct crypto_cert_store *tcs;
 };
@@ -381,6 +383,8 @@ struct verification_cfg_common {
        generate_sorcery_enum_to_str(object, vcfg_common.,relax_x5u_path_restrictions); \
        generate_sorcery_enum_from_str(object, vcfg_common.,load_system_certs, UNKNOWN); \
        generate_sorcery_enum_to_str(object, vcfg_common.,load_system_certs); \
+       generate_sorcery_enum_from_str(object, vcfg_common.,ignore_sip_date_header, UNKNOWN); \
+       generate_sorcery_enum_to_str(object, vcfg_common.,ignore_sip_date_header); \
        generate_sorcery_acl_from_str(object, acl, NULL); \
        generate_sorcery_acl_to_str(object, acl);
 
@@ -533,6 +537,7 @@ int tn_config_unload(void);
                relax_x5u_path_restrictions, nodoc); \
                enum_option_register(sorcery, CONFIG_TYPE, \
                        load_system_certs, nodoc); \
+       enum_option_register(sorcery, CONFIG_TYPE, ignore_sip_date_header, nodoc); \
 \
        ast_sorcery_object_field_register_custom ## nodoc(sorcery, CONFIG_TYPE, "x5u_deny", "", sorcery_acl_from_str, NULL, NULL, 0, 0); \
        ast_sorcery_object_field_register_custom ## nodoc(sorcery, CONFIG_TYPE, "x5u_permit", "", sorcery_acl_from_str, NULL, NULL, 0, 0); \
index e3379ebe3bbf6b7bdc96d6c184f1ffdb17b9c98c..1a6a76cf964abfb8d3ffd0f2d4c3fa1aed0670ff 100644 (file)
@@ -49,6 +49,7 @@
 #define DEFAULT_relax_x5u_port_scheme_restrictions relax_x5u_port_scheme_restrictions_NOT_SET
 #define DEFAULT_relax_x5u_path_restrictions relax_x5u_path_restrictions_NOT_SET
 #define DEFAULT_load_system_certs load_system_certs_NOT_SET
+#define DEFAULT_ignore_sip_date_header ignore_sip_date_header_NOT_SET
 
 #define DEFAULT_check_tn_cert_public_url check_tn_cert_public_url_NOT_SET
 #define DEFAULT_private_key_file NULL
index 18af72a5ed658d211e38baac324a7c6e74152e02..2f648e6f1698ab86c6d460a239ab01aaf567bc42 100644 (file)
                                        <synopsis>RFC9410 uses the STIR protocol on Reason headers
                                        instead of the SIP protocol</synopsis>
                                </configOption>
+                               <configOption name="ignore_sip_date_header" default="no">
+                                       <since>
+                                               <version>20.15.0</version>
+                                               <version>21.10.0</version>
+                                               <version>22.5.0</version>
+                                       </since>
+                                       <synopsis>When set to true, will cause the verification process to not consider a
+                                               missing or invalid SIP "Date" header to be a failure.  This will make the
+                                               IAT the sole "truth" for Date in the verification process.</synopsis>
+                               </configOption>
                                <configOption name="relax_x5u_port_scheme_restrictions" default="no">
                                        <since>
                                                <version>18.22.0</version>
                                <xi:include xpointer="xpointer(/docs/configInfo[@name='res_stir_shaken']/configFile[@name='stir_shaken.conf']/configObject[@name='verification']/configOption[@name='curl_timeout'])" />
                                <xi:include xpointer="xpointer(/docs/configInfo[@name='res_stir_shaken']/configFile[@name='stir_shaken.conf']/configObject[@name='verification']/configOption[@name='max_iat_age'])" />
                                <xi:include xpointer="xpointer(/docs/configInfo[@name='res_stir_shaken']/configFile[@name='stir_shaken.conf']/configObject[@name='verification']/configOption[@name='max_date_header_age'])" />
+                               <xi:include xpointer="xpointer(/docs/configInfo[@name='res_stir_shaken']/configFile[@name='stir_shaken.conf']/configObject[@name='verification']/configOption[@name='ignore_sip_date_header'])" />
                                <xi:include xpointer="xpointer(/docs/configInfo[@name='res_stir_shaken']/configFile[@name='stir_shaken.conf']/configObject[@name='verification']/configOption[@name='max_cache_entry_age'])" />
                                <xi:include xpointer="xpointer(/docs/configInfo[@name='res_stir_shaken']/configFile[@name='stir_shaken.conf']/configObject[@name='verification']/configOption[@name='max_cache_size'])" />
                                <xi:include xpointer="xpointer(/docs/configInfo[@name='res_stir_shaken']/configFile[@name='stir_shaken.conf']/configObject[@name='verification']/configOption[@name='failure_action'])" />
index f6609e6236cc6e16a74b64e1c02c8f74ab12a020..04f003504e92b43d8f526675f58492f957b792ed 100644 (file)
@@ -733,6 +733,15 @@ static enum ast_stir_shaken_vs_response_code check_date_header(
        SCOPE_ENTER(3, "%s: Checking date header: '%s'\n",
                ctx->tag, ctx->date_hdr);
 
+       if (ast_strlen_zero(ctx->date_hdr)) {
+               if (ctx->eprofile->vcfg_common.ignore_sip_date_header) {
+                       SCOPE_EXIT_RTN_VALUE(AST_STIR_SHAKEN_VS_SUCCESS,
+                               "%s: ignore_sip_date_header set\n", ctx->tag);
+               }
+               SCOPE_EXIT_LOG_RTN_VALUE(AST_STIR_SHAKEN_VS_NO_DATE_HDR,
+                       LOG_ERROR, "%s: No date header provided\n", ctx->tag);
+       }
+
        if (!(remainder = ast_strptime(ctx->date_hdr, "%a, %d %b %Y %T", &date_hdr_tm))) {
                SCOPE_EXIT_LOG_RTN_VALUE(AST_STIR_SHAKEN_VS_DATE_HDR_PARSE_FAILURE,
                        LOG_ERROR, "%s: Failed to parse: '%s'\n",
@@ -853,7 +862,7 @@ static int check_x5u_url(struct ast_stir_shaken_vs_ctx * ctx,
                }
                if (!ast_strlen_zero(port)) {
                        if (!ast_strings_equal(port, "443")
-                               || !ast_strings_equal(port, "8443")) {
+                               && !ast_strings_equal(port, "8443")) {
                                DUMP_X5U_MATCH();
                                SCOPE_EXIT_LOG_RTN_VALUE(AST_STIR_SHAKEN_VS_INVALID_OR_NO_X5U, LOG_ERROR,
                                        "%s: x5u '%s': port '%s' not port 443 or 8443\n",
@@ -940,8 +949,8 @@ enum ast_stir_shaken_vs_response_code
                        "%s: No x5u in Identity header\n", ctx->tag);
        }
 
-       rc = check_x5u_url(ctx, x5u);
-       if (rc != AST_STIR_SHAKEN_VS_SUCCESS) {
+       vs_rc = check_x5u_url(ctx, x5u);
+       if (vs_rc != AST_STIR_SHAKEN_VS_SUCCESS) {
                SCOPE_EXIT_RTN_VALUE(vs_rc,
                        "%s: x5u URL verification failed\n", ctx->tag);
        }
@@ -957,8 +966,9 @@ enum ast_stir_shaken_vs_response_code
                SCOPE_EXIT_LOG_RTN_VALUE(AST_STIR_SHAKEN_VS_NO_IAT, LOG_ERROR,
                        "%s: No 'iat' in Identity header\n", ctx->tag);
        }
-       ast_trace(1, "date_hdr: %zu  iat: %zu  diff: %zu\n",
-               ctx->date_hdr_time, iat, ctx->date_hdr_time - iat);
+       ast_trace(1, "date_hdr: %zu  iat: %zu\n",
+               ctx->date_hdr_time, iat);
+
        if (iat + ctx->eprofile->vcfg_common.max_iat_age < now_s) {
                SCOPE_EXIT_RTN_VALUE(AST_STIR_SHAKEN_VS_IAT_EXPIRED,
                        "%s: iat %ld older than %u seconds\n", ctx->tag,
index 81199747c38a115de7b34a5ec9ced369f842df75..b0ed7d4f32b68dabf33289a0d590f2ae94554797 100644 (file)
@@ -46,6 +46,7 @@ static char DEFAULT_cert_cache_dir[PATH_MAX];
 #define DEFAULT_relax_x5u_port_scheme_restrictions relax_x5u_port_scheme_restrictions_NO
 #define DEFAULT_relax_x5u_path_restrictions relax_x5u_path_restrictions_NO
 #define DEFAULT_load_system_certs load_system_certs_NO
+#define DEFAULT_ignore_sip_date_header ignore_sip_date_header_NO
 
 static struct verification_cfg *empty_cfg = NULL;
 
@@ -153,6 +154,7 @@ int vs_copy_cfg_common(const char *id, struct verification_cfg_common *cfg_dst,
        cfg_enum_copy(cfg_dst, cfg_src, relax_x5u_port_scheme_restrictions);
        cfg_enum_copy(cfg_dst, cfg_src, relax_x5u_path_restrictions);
        cfg_enum_copy(cfg_dst, cfg_src, load_system_certs);
+       cfg_enum_copy(cfg_dst, cfg_src, ignore_sip_date_header);
 
        if (cfg_src->acl) {
                ast_free_acl_list(cfg_dst->acl);