From d558818ec1cc97e557a0790ef7ed399a72932992 Mon Sep 17 00:00:00 2001 From: George Joseph Date: Wed, 5 Feb 2025 10:33:10 -0700 Subject: [PATCH] res_stir_shaken: Allow missing or anonymous CID to continue to the dialplan. The verification check for missing or anonymous callerid was happening before the endpoint's profile was retrieved which meant that the failure_action parameter wasn't available. Therefore, if verification was enabled and there was no callerid or it was "anonymous", the call was immediately terminated instead of giving the dialplan the ability to decide what to do with the call. * The callerid check now happens after the verification context is created and the endpoint's stir_shaken_profile is available. * The check now processes the callerid failure just as it does for other verification failures and respects the failure_action parameter. If set to "continue" or "continue_return_reason", `STIR_SHAKEN(0,verify_result)` in the dialplan will return "invalid_or_no_callerid". * If the endpoint's failure_action is "reject_request", the call will be rejected with `433 "Anonymity Disallowed"`. * If the endpoint's failure_action is "continue_return_reason", the call will continue but a `Reason: STIR; cause=433; text="Anonymity Disallowed"` header will be added to the next provisional or final response. Resolves: #1112 --- include/asterisk/res_stir_shaken.h | 11 +++++++++++ res/res_pjsip_stir_shaken.c | 25 ++++++++++++++++++------- res/res_stir_shaken/verification.c | 12 +++++++----- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/include/asterisk/res_stir_shaken.h b/include/asterisk/res_stir_shaken.h index 81e330c41d..7db676fc56 100644 --- a/include/asterisk/res_stir_shaken.h +++ b/include/asterisk/res_stir_shaken.h @@ -55,6 +55,7 @@ enum ast_stir_shaken_vs_response_code { AST_STIR_SHAKEN_VS_NO_DEST_TN, AST_STIR_SHAKEN_VS_INVALID_HEADER, AST_STIR_SHAKEN_VS_INVALID_GRANT, + AST_STIR_SHAKEN_VS_INVALID_OR_NO_CID, AST_STIR_SHAKEN_VS_RESPONSE_CODE_MAX }; @@ -233,6 +234,16 @@ enum stir_shaken_failure_action_enum int ast_stir_shaken_vs_get_use_rfc9410_responses( struct ast_stir_shaken_vs_ctx *ctx); +/*! + * \brief Get caller_id from context + * + * \param ctx VS context + * + * \retval Caller ID or NULL + */ +const char *ast_stir_shaken_vs_get_caller_id( + struct ast_stir_shaken_vs_ctx *ctx); + /*! * \brief Add a STIR/SHAKEN verification result to a channel * diff --git a/res/res_pjsip_stir_shaken.c b/res/res_pjsip_stir_shaken.c index f64152f3a2..ea498942eb 100644 --- a/res/res_pjsip_stir_shaken.c +++ b/res/res_pjsip_stir_shaken.c @@ -44,10 +44,10 @@ enum sip_response_code { SIP_RESPONSE_CODE_OK = 200, SIP_RESPONSE_CODE_STALE_DATE = 403, SIP_RESPONSE_CODE_USE_IDENTITY_HEADER = 428, + SIP_RESPONSE_CODE_ANONYMITY_DISALLOWED = 433, SIP_RESPONSE_CODE_BAD_IDENTITY_INFO = 436, SIP_RESPONSE_CODE_UNSUPPORTED_CREDENTIAL = 437, SIP_RESPONSE_CODE_INVALID_IDENTITY_HEADER = 438, - SIP_RESPONSE_CODE_USE_SUPPORTED_PASSPORT_FORMAT = 428, SIP_RESPONSE_CODE_INTERNAL_ERROR = 500, }; @@ -55,7 +55,7 @@ enum sip_response_code { /* Response strings from RFC8224 */ #define SIP_RESPONSE_CODE_STALE_DATE_STR "Stale Date" #define SIP_RESPONSE_CODE_USE_IDENTITY_HEADER_STR "Use Identity Header" -#define SIP_RESPONSE_CODE_USE_SUPPORTED_PASSPORT_FORMAT_STR "Use Supported PASSporT Format" +#define SIP_RESPONSE_CODE_ANONYMITY_DISALLOWED_STR "Anonymity Disallowed" #define SIP_RESPONSE_CODE_BAD_IDENTITY_INFO_STR "Bad Identity Info" #define SIP_RESPONSE_CODE_UNSUPPORTED_CREDENTIAL_STR "Unsupported Credential" #define SIP_RESPONSE_CODE_INVALID_IDENTITY_HEADER_STR "Invalid Identity Header" @@ -71,6 +71,7 @@ static const char *sip_response_code_to_str(enum sip_response_code code) response_to_str(SIP_RESPONSE_CODE_OK) response_to_str(SIP_RESPONSE_CODE_STALE_DATE) response_to_str(SIP_RESPONSE_CODE_USE_IDENTITY_HEADER) + response_to_str(SIP_RESPONSE_CODE_ANONYMITY_DISALLOWED) response_to_str(SIP_RESPONSE_CODE_BAD_IDENTITY_INFO) response_to_str(SIP_RESPONSE_CODE_UNSUPPORTED_CREDENTIAL) response_to_str(SIP_RESPONSE_CODE_INVALID_IDENTITY_HEADER) @@ -127,6 +128,7 @@ static enum sip_response_code vs_code_to_sip_code( translate_code(INVALID_GRANT, INVALID_IDENTITY_HEADER) translate_code(INVALID_OR_NO_GRANTS, INVALID_IDENTITY_HEADER) translate_code(CID_ORIG_TN_MISMATCH, INVALID_IDENTITY_HEADER) + translate_code(INVALID_OR_NO_CID, ANONYMITY_DISALLOWED) translate_code(RESPONSE_CODE_MAX, INVALID_IDENTITY_HEADER) } @@ -227,12 +229,10 @@ static int stir_shaken_incoming_request(struct ast_sip_session *session, pjsip_r } /* - * Shortcut: If there's no callerid or profile name, - * just bail now. + * Shortcut: If there's no profile name just bail now. */ - if (ast_strlen_zero(caller_id) - || ast_strlen_zero(session->endpoint->stir_shaken_profile)) { - SCOPE_EXIT_RTN_VALUE(0, "%s: No callerid or profile name. No action needed\n", session_name); + if (ast_strlen_zero(session->endpoint->stir_shaken_profile)) { + SCOPE_EXIT_RTN_VALUE(0, "%s: No profile name on endpoint. No action needed\n", session_name); } vs_rc = ast_stir_shaken_vs_ctx_create(caller_id, chan, @@ -246,6 +246,17 @@ static int stir_shaken_incoming_request(struct ast_sip_session *session, pjsip_r session_name); } + if (ast_strlen_zero(ast_stir_shaken_vs_get_caller_id(ctx))) { + p_rc = process_failure(ctx, caller_id, session, rdata, + AST_STIR_SHAKEN_VS_INVALID_OR_NO_CID); + if (p_rc == PROCESS_FAILURE_CONTINUE) { + SCOPE_EXIT_RTN_VALUE(0, "%s: Invalid or no callerid found. Call continuing\n", + session_name); + } + SCOPE_EXIT_LOG_RTN_VALUE(1, LOG_ERROR, "%s: Invalid or no callerid found. Call terminated\n", + session_name); + } + identity_hdr_val = ast_sip_rdata_get_header_value(rdata, identity_hdr_str); if (ast_strlen_zero(identity_hdr_val)) { p_rc = process_failure(ctx, caller_id, session, rdata, diff --git a/res/res_stir_shaken/verification.c b/res/res_stir_shaken/verification.c index 6e8366585c..f6609e6236 100644 --- a/res/res_stir_shaken/verification.c +++ b/res/res_stir_shaken/verification.c @@ -84,6 +84,7 @@ static const char *vs_rc_map[] = { [AST_STIR_SHAKEN_VS_NO_DEST_TN] = "missing_dest_tn", [AST_STIR_SHAKEN_VS_INVALID_HEADER] = "invalid_header", [AST_STIR_SHAKEN_VS_INVALID_GRANT] = "invalid_grant", + [AST_STIR_SHAKEN_VS_INVALID_OR_NO_CID] = "invalid_or_no_callerid", }; const char *vs_response_code_to_str( @@ -629,6 +630,12 @@ int ast_stir_shaken_vs_get_use_rfc9410_responses( return ctx->eprofile->vcfg_common.use_rfc9410_responses; } +const char *ast_stir_shaken_vs_get_caller_id( + struct ast_stir_shaken_vs_ctx *ctx) +{ + return ctx->caller_id; +} + void ast_stir_shaken_vs_ctx_set_response_code( struct ast_stir_shaken_vs_ctx *ctx, enum ast_stir_shaken_vs_response_code vs_rc) @@ -687,11 +694,6 @@ enum ast_stir_shaken_vs_response_code LOG_ERROR, "%s: Must provide tag\n", t); } - if (ast_strlen_zero(canon_caller_id)) { - SCOPE_EXIT_LOG_RTN_VALUE(AST_STIR_SHAKEN_VS_INVALID_ARGUMENTS, - LOG_ERROR, "%s: Must provide caller_id\n", t); - } - ctx = ao2_alloc_options(sizeof(*ctx), ctx_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK); if (!ctx) {