From: George Joseph Date: Sun, 15 Jun 2025 20:43:13 +0000 (-0600) Subject: res_stir_shaken: Add "ignore_sip_date_header" config option. X-Git-Tag: 21.10.0-rc1~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6c1417b228970cd810fb71e59a0803a8202fb159;p=thirdparty%2Fasterisk.git res_stir_shaken: Add "ignore_sip_date_header" config option. 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 (cherry picked from commit 6e9c33caad26e8f129cb5a60e6c0b794d0cb2ade) --- diff --git a/configs/samples/stir_shaken.conf.sample b/configs/samples/stir_shaken.conf.sample index 3fe9d7e955..afe4bc024f 100644 --- a/configs/samples/stir_shaken.conf.sample +++ b/configs/samples/stir_shaken.conf.sample @@ -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 diff --git a/res/res_pjsip_stir_shaken.c b/res/res_pjsip_stir_shaken.c index ea498942eb..bd4e030c63 100644 --- a/res/res_pjsip_stir_shaken.c +++ b/res/res_pjsip_stir_shaken.c @@ -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); diff --git a/res/res_stir_shaken/common_config.c b/res/res_stir_shaken/common_config.c index b669762ec3..0cbd9b5035 100644 --- a/res/res_stir_shaken/common_config.c +++ b/res/res_stir_shaken/common_config.c @@ -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); diff --git a/res/res_stir_shaken/common_config.h b/res/res_stir_shaken/common_config.h index e390b548b6..4eb9e5e02f 100644 --- a/res/res_stir_shaken/common_config.h +++ b/res/res_stir_shaken/common_config.h @@ -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); \ diff --git a/res/res_stir_shaken/profile_config.c b/res/res_stir_shaken/profile_config.c index e3379ebe3b..1a6a76cf96 100644 --- a/res/res_stir_shaken/profile_config.c +++ b/res/res_stir_shaken/profile_config.c @@ -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 diff --git a/res/res_stir_shaken/stir_shaken_doc.xml b/res/res_stir_shaken/stir_shaken_doc.xml index 18af72a5ed..2f648e6f16 100644 --- a/res/res_stir_shaken/stir_shaken_doc.xml +++ b/res/res_stir_shaken/stir_shaken_doc.xml @@ -350,6 +350,16 @@ RFC9410 uses the STIR protocol on Reason headers instead of the SIP protocol + + + 20.15.0 + 21.10.0 + 22.5.0 + + 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. + 18.22.0 @@ -422,6 +432,7 @@ + diff --git a/res/res_stir_shaken/verification.c b/res/res_stir_shaken/verification.c index f6609e6236..04f003504e 100644 --- a/res/res_stir_shaken/verification.c +++ b/res/res_stir_shaken/verification.c @@ -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, diff --git a/res/res_stir_shaken/verification_config.c b/res/res_stir_shaken/verification_config.c index 81199747c3..b0ed7d4f32 100644 --- a/res/res_stir_shaken/verification_config.c +++ b/res/res_stir_shaken/verification_config.c @@ -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);