From 736ad5cc3b4ba4a25ac81d3b98af6e83b4129404 Mon Sep 17 00:00:00 2001 From: Vlad Patrascu Date: Thu, 12 Aug 2021 21:03:45 +0300 Subject: [PATCH] stir_shaken: add ability to skip Date header checks when verifying Add a new "require_date_hdr" modparam that controls whether the Date header is mandatory when verifying. --- modules/stir_shaken/doc/stir_shaken_admin.xml | 41 +++++++++- modules/stir_shaken/stir_shaken.c | 78 ++++++++++++------- 2 files changed, 89 insertions(+), 30 deletions(-) diff --git a/modules/stir_shaken/doc/stir_shaken_admin.xml b/modules/stir_shaken/doc/stir_shaken_admin.xml index dcf0be277d1..5fb8a8b26e4 100644 --- a/modules/stir_shaken/doc/stir_shaken_admin.xml +++ b/modules/stir_shaken/doc/stir_shaken_admin.xml @@ -66,13 +66,18 @@ modparam("stir_shaken", "auth_date_freshness", 300)
<varname>verify_date_freshness</varname> (integer) - The maximum number of seconds that the value in the Date header field - can be older than the current time. Also, if the iat - value in the PASSporT is different than the Date value, but remains within - this interval, it will be used in the verification process (for the + The maximum number of seconds that the value in the Date header field can be + older than the current time. Also, if the iat value in + the PASSporT is different than the Date value, but remains within the + permitted interval, it will be used in the verification process (for the reconstructed PASSporT) instead of the Date value. + If the parameter is set to not + required and the Date header is missing, the iat value + will be used for this check instead. + + This parameter is only relevant for the function. @@ -172,6 +177,34 @@ modparam("stir_shaken", "crl_dir", "/stir_certs/crls") ... modparam("stir_shaken", "e164_strict_mode", 1) ... + + +
+ +
+ <varname>require_date_hdr</varname> (integer) + + Specifies whether the Date header is mandatory when doing verification + with the function. + + + A value of 1 means required and 0 + not required. + + + If the parameter is set to not required but the header is present in the + message, the Date value will be used as normally to check the freshness (as + configured in the + parameter). If the Date header is indeed missing, the value of the + iat claim in the PASSporT will be used instead. + + The default value is 1 (required). + + Set <varname>require_date_hdr</varname> parameter + +... +modparam("stir_shaken", "require_date_hdr", 0) +...
diff --git a/modules/stir_shaken/stir_shaken.c b/modules/stir_shaken/stir_shaken.c index 9c3d58e76c7..0772a1ed191 100644 --- a/modules/stir_shaken/stir_shaken.c +++ b/modules/stir_shaken/stir_shaken.c @@ -105,6 +105,8 @@ static char *crl_dir; static int e164_strict_mode; +static int require_date_hdr = 1; + static int tn_authlist_nid; static int parsed_ctx_idx =-1; @@ -119,6 +121,7 @@ static param_export_t params[] = { {"crl_list", STR_PARAM, &crl_list}, {"crl_dir", STR_PARAM, &crl_dir}, {"e164_strict_mode", INT_PARAM, &e164_strict_mode}, + {"require_date_hdr", INT_PARAM, &require_date_hdr}, {0, 0, 0} }; @@ -1756,19 +1759,6 @@ static int w_stir_verify(struct sip_msg *msg, str *cert_buf, } date_hf = get_header_by_static_name(msg, "Date"); - if (!date_hf) { - LM_NOTICE("No Date header found\n"); - SET_VERIFY_ERR_VARS(BADREQ_CODE, BADREQ_NODATE_REASON); - rc = -2; - goto error; - } - - if (get_date_ts(date_hf, &date_ts) < 0) { - LM_ERR("Failed to get UNIX time from Date header\n"); - SET_VERIFY_ERR_VARS(IERROR_CODE, IERROR_REASON); - rc = -1; - goto error; - } if ((now = time(0)) == -1) { LM_ERR("Failed to get current time\n"); @@ -1776,12 +1766,39 @@ static int w_stir_verify(struct sip_msg *msg, str *cert_buf, rc = -1; goto error; } - if (now - date_ts > verify_date_freshness) { - LM_NOTICE("Date header value is older than local policy (%lds > %ds)\n", - now - date_ts, verify_date_freshness); - SET_VERIFY_ERR_VARS(STALE_DATE_CODE, STALE_DATE_REASON); - rc = -6; - goto error; + + iat_ts = (time_t)parsed->iat->valuedouble; + + if (require_date_hdr || date_hf) { + if (!date_hf) { + LM_NOTICE("No Date header found\n"); + SET_VERIFY_ERR_VARS(BADREQ_CODE, BADREQ_NODATE_REASON); + rc = -2; + goto error; + } + + if (get_date_ts(date_hf, &date_ts) < 0) { + LM_ERR("Failed to get UNIX time from Date header\n"); + SET_VERIFY_ERR_VARS(IERROR_CODE, IERROR_REASON); + rc = -1; + goto error; + } + + if (now - date_ts > verify_date_freshness) { + LM_NOTICE("Date header value is older than local policy (%lds > %ds)\n", + now - date_ts, verify_date_freshness); + SET_VERIFY_ERR_VARS(STALE_DATE_CODE, STALE_DATE_REASON); + rc = -6; + goto error; + } + } else { + if (now - iat_ts > verify_date_freshness) { + LM_NOTICE("'iat' value is older than local policy (%lds > %ds)\n", + now - iat_ts, verify_date_freshness); + SET_VERIFY_ERR_VARS(STALE_DATE_CODE, STALE_DATE_REASON); + rc = -6; + goto error; + } } /* if the identities in the PASSporT and SIP message are different @@ -1815,11 +1832,20 @@ static int w_stir_verify(struct sip_msg *msg, str *cert_buf, goto error; } - if (!check_cert_validity(&date_ts, cert)) { - LM_INFO("The Date header does not fall within the certificate validity\n"); - SET_VERIFY_ERR_VARS(STALE_DATE_CODE, STALE_DATE_REASON); - rc = -7; - goto error; + if (require_date_hdr || date_hf) { + if (!check_cert_validity(&date_ts, cert)) { + LM_INFO("The Date header does not fall within the certificate validity\n"); + SET_VERIFY_ERR_VARS(STALE_DATE_CODE, STALE_DATE_REASON); + rc = -7; + goto error; + } + } else { + if (!check_cert_validity(&iat_ts, cert)) { + LM_INFO("The 'iat' value does not fall within the certificate validity\n"); + SET_VERIFY_ERR_VARS(STALE_DATE_CODE, STALE_DATE_REASON); + rc = -7; + goto error; + } } if ((rc = validate_certificate(cert, certchain)) < 0) { @@ -1834,8 +1860,8 @@ static int w_stir_verify(struct sip_msg *msg, str *cert_buf, } } - iat_ts = (time_t)parsed->iat->valuedouble; - if (iat_ts != date_ts && (now - iat_ts > verify_date_freshness)) + if (date_hf && iat_ts != date_ts && + (now - iat_ts > verify_date_freshness)) iat_ts = date_ts; if ((rc = verify_signature(cert, parsed, iat_ts, orig_tn_p, dest_tn_p)) <= 0) {