Asterisk - The Open Source Telephony Project GIT-master-f36a736
Macros | Functions | Variables
verification.c File Reference
#include <curl/curl.h>
#include <sys/stat.h>
#include <jwt.h>
#include <regex.h>
#include "asterisk.h"
#include "asterisk/channel.h"
#include "asterisk/cli.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/sorcery.h"
#include "asterisk/astdb.h"
#include "asterisk/conversions.h"
#include "asterisk/utils.h"
#include "asterisk/paths.h"
#include "asterisk/logger.h"
#include "asterisk/acl.h"
#include "asterisk/time.h"
#include "asterisk/localtime.h"
#include "asterisk/crypto.h"
#include "asterisk/json.h"
#include "stir_shaken.h"
Include dependency graph for verification.c:

Go to the source code of this file.

Macros

#define _TRACE_PREFIX_   "v",__LINE__, ""
 
#define ASN1_TAG_TNAUTH_SPC   0
 
#define ASN1_TAG_TNAUTH_TN   2
 
#define ASN1_TAG_TNAUTH_TN_RANGE   1
 
#define AST_DB_FAMILY   "STIR_SHAKEN"
 
#define BEGIN_CERTIFICATE_STR   "-----BEGIN CERTIFICATE-----"
 
#define DUMP_X5U_MATCH()
 
#define FULL_URL_REGEX   "^([a-zA-Z]+)://(([^@]+@[^:]+):)?(([^:/?]+)|([0-9.]+)|([[][0-9a-fA-F:]+[]]))(:([0-9]+))?(/([^#\\?]+))?(\\?([^#]+))?(#(.*))?"
 
#define FULL_URL_REGEX_GROUPS   15
 
#define get_match_string(__x5u, __pmatch, __i)
 
#define IS_GET_OBJ_ERR(ret)   (ret & 0x80)
 
#define URL_MATCH_FRAGMENT   15
 
#define URL_MATCH_HOST   4
 
#define URL_MATCH_PATH   11
 
#define URL_MATCH_PORT   9
 
#define URL_MATCH_QUERY   13
 
#define URL_MATCH_SCHEME   1
 
#define URL_MATCH_USERPASS   3
 

Functions

static int add_cert_expiration_to_astdb (struct ast_stir_shaken_vs_ctx *cert, const char *cache_control_header, const char *expires_header)
 
static int add_cert_key_to_astdb (struct ast_stir_shaken_vs_ctx *cert, const char *cache_control_hdr, const char *expires_hdr)
 
enum ast_stir_shaken_vs_response_code ast_stir_shaken_vs_ctx_add_date_hdr (struct ast_stir_shaken_vs_ctx *ctx, const char *date_hdr)
 Add the received Date header value to the VS context. More...
 
enum ast_stir_shaken_vs_response_code ast_stir_shaken_vs_ctx_add_identity_hdr (struct ast_stir_shaken_vs_ctx *ctx, const char *identity_hdr)
 Add the received Identity header value to the VS context. More...
 
enum ast_stir_shaken_vs_response_code ast_stir_shaken_vs_ctx_create (const char *caller_id, struct ast_channel *chan, const char *profile_name, const char *tag, struct ast_stir_shaken_vs_ctx **ctxout)
 Create Verification Service context. More...
 
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)
 Sets response code on VS context. More...
 
enum stir_shaken_failure_action_enum ast_stir_shaken_vs_get_failure_action (struct ast_stir_shaken_vs_ctx *ctx)
 Get failure_action from context. More...
 
int ast_stir_shaken_vs_get_use_rfc9410_responses (struct ast_stir_shaken_vs_ctx *ctx)
 Get use_rfc9410_responses from context. More...
 
enum ast_stir_shaken_vs_response_code ast_stir_shaken_vs_verify (struct ast_stir_shaken_vs_ctx *ctx)
 Perform incoming call verification. More...
 
static enum ast_stir_shaken_vs_response_code check_cert (struct ast_stir_shaken_vs_ctx *ctx)
 
static enum ast_stir_shaken_vs_response_code check_date_header (struct ast_stir_shaken_vs_ctx *ctx)
 
static enum ast_stir_shaken_vs_response_code check_tn_auth_list (struct ast_stir_shaken_vs_ctx *ctx)
 
static int check_x5u_url (struct ast_stir_shaken_vs_ctx *ctx, const char *x5u)
 
static void cleanup_cert_from_astdb_and_fs (struct ast_stir_shaken_vs_ctx *ctx)
 
static void ctx_destructor (void *obj)
 
static enum ast_stir_shaken_vs_response_code ctx_populate (struct ast_stir_shaken_vs_ctx *ctx)
 
static int is_cert_cache_entry_expired (char *expiration)
 
static enum ast_stir_shaken_vs_response_code retrieve_cert_from_cache (struct ast_stir_shaken_vs_ctx *ctx)
 
static enum ast_stir_shaken_vs_response_code retrieve_cert_from_url (struct ast_stir_shaken_vs_ctx *ctx)
 
static enum ast_stir_shaken_vs_response_code retrieve_verification_cert (struct ast_stir_shaken_vs_ctx *ctx)
 
int vs_load ()
 Load the stir/shaken verification service. More...
 
int vs_reload ()
 Reload the stir/shaken verification service. More...
 
const char * vs_response_code_to_str (enum ast_stir_shaken_vs_response_code vs_rc)
 Return string version of VS response code. More...
 
int vs_unload ()
 Unload the stir/shaken verification service. More...
 

Variables

static regex_t url_match_regex
 
static const char * vs_rc_map []
 

Macro Definition Documentation

◆ _TRACE_PREFIX_

#define _TRACE_PREFIX_   "v",__LINE__, ""

Definition at line 26 of file verification.c.

◆ ASN1_TAG_TNAUTH_SPC

#define ASN1_TAG_TNAUTH_SPC   0

Definition at line 246 of file verification.c.

◆ ASN1_TAG_TNAUTH_TN

#define ASN1_TAG_TNAUTH_TN   2

Definition at line 248 of file verification.c.

◆ ASN1_TAG_TNAUTH_TN_RANGE

#define ASN1_TAG_TNAUTH_TN_RANGE   1

Definition at line 247 of file verification.c.

◆ AST_DB_FAMILY

#define AST_DB_FAMILY   "STIR_SHAKEN"

Definition at line 46 of file verification.c.

◆ BEGIN_CERTIFICATE_STR

#define BEGIN_CERTIFICATE_STR   "-----BEGIN CERTIFICATE-----"

Definition at line 51 of file verification.c.

◆ DUMP_X5U_MATCH

#define DUMP_X5U_MATCH ( )

Definition at line 810 of file verification.c.

◆ FULL_URL_REGEX

#define FULL_URL_REGEX   "^([a-zA-Z]+)://(([^@]+@[^:]+):)?(([^:/?]+)|([0-9.]+)|([[][0-9a-fA-F:]+[]]))(:([0-9]+))?(/([^#\\?]+))?(\\?([^#]+))?(#(.*))?"

Definition at line 771 of file verification.c.

◆ FULL_URL_REGEX_GROUPS

#define FULL_URL_REGEX_GROUPS   15

Definition at line 772 of file verification.c.

◆ get_match_string

#define get_match_string (   __x5u,
  __pmatch,
  __i 
)

Definition at line 798 of file verification.c.

◆ IS_GET_OBJ_ERR

#define IS_GET_OBJ_ERR (   ret)    (ret & 0x80)

Definition at line 250 of file verification.c.

◆ URL_MATCH_FRAGMENT

#define URL_MATCH_FRAGMENT   15

Definition at line 796 of file verification.c.

◆ URL_MATCH_HOST

#define URL_MATCH_HOST   4

Definition at line 792 of file verification.c.

◆ URL_MATCH_PATH

#define URL_MATCH_PATH   11

Definition at line 794 of file verification.c.

◆ URL_MATCH_PORT

#define URL_MATCH_PORT   9

Definition at line 793 of file verification.c.

◆ URL_MATCH_QUERY

#define URL_MATCH_QUERY   13

Definition at line 795 of file verification.c.

◆ URL_MATCH_SCHEME

#define URL_MATCH_SCHEME   1

Definition at line 790 of file verification.c.

◆ URL_MATCH_USERPASS

#define URL_MATCH_USERPASS   3

Definition at line 791 of file verification.c.

Function Documentation

◆ add_cert_expiration_to_astdb()

static int add_cert_expiration_to_astdb ( struct ast_stir_shaken_vs_ctx cert,
const char *  cache_control_header,
const char *  expires_header 
)
static

Definition at line 111 of file verification.c.

113{
115
116 char time_buf[32];
117 time_t current_time = time(NULL);
118 time_t max_age_hdr = 0;
119 time_t expires_hdr = 0;
120 ASN1_TIME *notAfter = NULL;
121 time_t cert_expires = 0;
122 time_t config_expires = 0;
123 time_t expires = 0;
124 int rc = 0;
125
126 config_expires = current_time + cfg->vcfg_common.max_cache_entry_age;
127
128 if (!ast_strlen_zero(cache_control_header)) {
129 char *str_max_age;
130
131 str_max_age = strstr(cache_control_header, "s-maxage");
132 if (!str_max_age) {
133 str_max_age = strstr(cache_control_header, "max-age");
134 }
135
136 if (str_max_age) {
137 unsigned int m;
138 char *equal = strchr(str_max_age, '=');
139 if (equal && !ast_str_to_uint(equal + 1, &m)) {
140 max_age_hdr = current_time + m;
141 }
142 }
143 }
144
145 if (!ast_strlen_zero(expires_header)) {
146 struct ast_tm expires_time;
147
148 ast_strptime(expires_header, "%a, %d %b %Y %T %z", &expires_time);
149 expires_time.tm_isdst = -1;
150 expires_hdr = ast_mktime(&expires_time, "GMT").tv_sec;
151 }
152
153 notAfter = X509_get_notAfter(cert->xcert);
154 cert_expires = crypto_asn_time_as_time_t(notAfter);
155
156 /*
157 * ATIS-1000074 says:
158 * The STI-VS shall implement the cache behavior described in
159 * [Ref 10]. If the HTTP response does not include any recognized
160 * caching directives or indicates caching for less than 24 hours,
161 * then the STI-VS should cache the HTTP response for 24 hours.
162 *
163 * Basically, they're saying "cache for 24 hours unless the HTTP
164 * response says to cache for longer." Instead of the fixed 24
165 * hour minumum, however, we'll use max_cache_entry_age instead.
166 *
167 * We got all the possible values of expires so let's find the
168 * highest value greater than the configured max_cache_entry_age.
169 */
170
171 /* The default */
172 expires = config_expires;
173
174 if (max_age_hdr > expires) {
175 expires = max_age_hdr;
176 }
177
178 if (expires_hdr > expires) {
179 expires = expires_hdr;
180 }
181
182 /*
183 * However... Don't cache for longer than the
184 * certificate is actually valid.
185 */
186 if (cert_expires && cert_expires < expires) {
187 expires = cert_expires;
188 }
189
190 snprintf(time_buf, sizeof(time_buf), "%ld", expires);
191
192 rc = ast_db_put(cert->hash_family, "expiration", time_buf);
193 if (rc == 0) {
194 strcpy(cert->expiration, time_buf); /* safe */
195 }
196
197 return rc;
198}
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:341
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
struct verification_cfg * vs_get_cfg(void)
int ast_str_to_uint(const char *str, unsigned int *res)
Convert the given string to an unsigned integer.
Definition: conversions.c:56
time_t crypto_asn_time_as_time_t(ASN1_TIME *at)
Return a time_t for an ASN1_TIME.
Definition: crypto_utils.c:770
struct timeval ast_mktime(struct ast_tm *const tmp, const char *zone)
Timezone-independent version of mktime(3).
Definition: localtime.c:2357
char * ast_strptime(const char *s, const char *format, struct ast_tm *tm)
Special version of strptime(3) which places the answer in the common structure ast_tm....
Definition: localtime.c:2550
#define NULL
Definition: resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
const ast_string_field hash_family
Definition: verification.h:39
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References ao2_cleanup, ast_db_put(), ast_mktime(), ast_str_to_uint(), ast_strlen_zero(), ast_strptime(), crypto_asn_time_as_time_t(), ast_stir_shaken_vs_ctx::expiration, ast_stir_shaken_vs_ctx::hash_family, NULL, RAII_VAR, ast_tm::tm_isdst, vs_get_cfg(), and ast_stir_shaken_vs_ctx::xcert.

Referenced by add_cert_key_to_astdb().

◆ add_cert_key_to_astdb()

static int add_cert_key_to_astdb ( struct ast_stir_shaken_vs_ctx cert,
const char *  cache_control_hdr,
const char *  expires_hdr 
)
static

Definition at line 200 of file verification.c.

202{
203 int rc = 0;
204
205 rc = ast_db_put(cert->url_family, cert->public_url, cert->hash);
206 if (rc) {
207 return rc;
208 }
209 rc = ast_db_put(cert->hash_family, "path", cert->filename);
210 if (rc) {
211 ast_db_del(cert->url_family, cert->public_url);
212 return rc;
213 }
214
215 rc = add_cert_expiration_to_astdb(cert, cache_control_hdr, expires_hdr);
216 if (rc) {
217 ast_db_del(cert->url_family, cert->public_url);
218 ast_db_del(cert->hash_family, "path");
219 }
220
221 return rc;
222}
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:478
const ast_string_field public_url
Definition: verification.h:39
const ast_string_field hash
Definition: verification.h:39
const ast_string_field filename
Definition: verification.h:39
const ast_string_field url_family
Definition: verification.h:39
static int add_cert_expiration_to_astdb(struct ast_stir_shaken_vs_ctx *cert, const char *cache_control_header, const char *expires_header)
Definition: verification.c:111

References add_cert_expiration_to_astdb(), ast_db_del(), ast_db_put(), ast_stir_shaken_vs_ctx::filename, ast_stir_shaken_vs_ctx::hash, ast_stir_shaken_vs_ctx::hash_family, ast_stir_shaken_vs_ctx::public_url, and ast_stir_shaken_vs_ctx::url_family.

Referenced by retrieve_cert_from_url().

◆ ast_stir_shaken_vs_ctx_add_date_hdr()

enum ast_stir_shaken_vs_response_code ast_stir_shaken_vs_ctx_add_date_hdr ( struct ast_stir_shaken_vs_ctx ctx,
const char *  date_hdr 
)

Add the received Date header value to the VS context.

Parameters
ctxVS context
date_hdrDate header value
Return values
AST_STIR_SHAKEN_VS_SUCCESSif successful
OtherAST_STIR_SHAKEN_VS errors.

Definition at line 612 of file verification.c.

614{
615 return ast_string_field_set(ctx, date_hdr, date_hdr) == 0 ?
617}
@ AST_STIR_SHAKEN_VS_SUCCESS
@ AST_STIR_SHAKEN_VS_INTERNAL_ERROR
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521

References AST_STIR_SHAKEN_VS_INTERNAL_ERROR, AST_STIR_SHAKEN_VS_SUCCESS, and ast_string_field_set.

Referenced by stir_shaken_incoming_request().

◆ ast_stir_shaken_vs_ctx_add_identity_hdr()

enum ast_stir_shaken_vs_response_code ast_stir_shaken_vs_ctx_add_identity_hdr ( struct ast_stir_shaken_vs_ctx ctx,
const char *  identity_hdr 
)

Add the received Identity header value to the VS context.

Parameters
ctxVS context
identity_hdrIdentity header value
Return values
AST_STIR_SHAKEN_VS_SUCCESSif successful
OtherAST_STIR_SHAKEN_VS errors.

Definition at line 604 of file verification.c.

606{
607 return ast_string_field_set(ctx, identity_hdr, identity_hdr) == 0 ?
609}

References AST_STIR_SHAKEN_VS_INTERNAL_ERROR, AST_STIR_SHAKEN_VS_SUCCESS, and ast_string_field_set.

Referenced by stir_shaken_incoming_request().

◆ ast_stir_shaken_vs_ctx_create()

enum ast_stir_shaken_vs_response_code ast_stir_shaken_vs_ctx_create ( const char *  caller_id,
struct ast_channel chan,
const char *  profile_name,
const char *  tag,
struct ast_stir_shaken_vs_ctx **  ctxout 
)

Create Verification Service context.

Parameters
caller_idIncoming caller id
chanIncoming channel
profile_nameThe profile name on the endpoint May be NULL.
endpoint_behaviorBehavior associated to the specific endpoint
tagIdentifying string to output in log and trace messages.
ctxoutReceives a pointer to the newly created context The caller must release with ao2_ref or ao2_cleanup.
Return values
AST_STIR_SHAKEN_VS_SUCCESSif successful.
AST_STIR_SHAKEN_VS_DISABLEDif verification is disabled by the endpoint itself, the profile or globally.
OtherAST_STIR_SHAKEN_VS errors.

Definition at line 650 of file verification.c.

653{
655 RAII_VAR(struct profile_cfg *, profile, NULL, ao2_cleanup);
657 RAII_VAR(char *, canon_caller_id , canonicalize_tn_alloc(caller_id), ast_free);
658
659 const char *t = S_OR(tag, S_COR(chan, ast_channel_name(chan), ""));
660 SCOPE_ENTER(3, "%s: Enter\n", t);
661
662 vs = vs_get_cfg();
663 if (vs->global_disable) {
665 "%s: Globally disabled\n", t);
666 }
667
668 if (ast_strlen_zero(profile_name)) {
670 "%s: Disabled due to missing profile name\n", t);
671 }
672
673 profile = eprofile_get_cfg(profile_name);
674 if (!profile) {
676 LOG_ERROR, "%s: No profile for profile name '%s'. Call will continue\n", tag,
677 profile_name);
678 }
679
680 if (!PROFILE_ALLOW_VERIFY(profile)) {
682 "%s: Disabled by profile '%s'\n", t, profile_name);
683 }
684
685 if (ast_strlen_zero(tag)) {
687 LOG_ERROR, "%s: Must provide tag\n", t);
688 }
689
690 if (ast_strlen_zero(canon_caller_id)) {
692 LOG_ERROR, "%s: Must provide caller_id\n", t);
693 }
694
695 ctx = ao2_alloc_options(sizeof(*ctx), ctx_destructor,
697 if (!ctx) {
699 }
700 if (ast_string_field_init(ctx, 1024) != 0) {
702 }
703
704 if (ast_string_field_set(ctx, tag, tag) != 0) {
706 }
707
708 ctx->chan = chan;
709 if (ast_string_field_set(ctx, caller_id, canon_caller_id) != 0) {
711 }
712
713 /* Transfer references to ctx */
714 ctx->eprofile = profile;
715 profile = NULL;
716
717 ao2_ref(ctx, +1);
718 *ctxout = ctx;
720}
#define ast_free(a)
Definition: astmm.h:180
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
const char * ast_channel_name(const struct ast_channel *chan)
char * canonicalize_tn_alloc(const char *tn)
Canonicalize a TN into nre buffer.
struct profile_cfg * eprofile_get_cfg(const char *id)
#define PROFILE_ALLOW_VERIFY(__profile)
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
#define SCOPE_EXIT_LOG_RTN_VALUE(__value, __log_level,...)
#define SCOPE_ENTER(level,...)
#define LOG_ERROR
@ AST_STIR_SHAKEN_VS_INVALID_ARGUMENTS
@ AST_STIR_SHAKEN_VS_DISABLED
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:87
Profile configuration for stir/shaken.
static void ctx_destructor(void *obj)
Definition: verification.c:639

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_cleanup, ao2_ref, ast_channel_name(), ast_free, AST_STIR_SHAKEN_VS_DISABLED, AST_STIR_SHAKEN_VS_INTERNAL_ERROR, AST_STIR_SHAKEN_VS_INVALID_ARGUMENTS, AST_STIR_SHAKEN_VS_SUCCESS, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_stir_shaken_vs_ctx::caller_id, canonicalize_tn_alloc(), ast_stir_shaken_vs_ctx::chan, ctx_destructor(), eprofile_get_cfg(), LOG_ERROR, NULL, PROFILE_ALLOW_VERIFY, RAII_VAR, S_COR, S_OR, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, ast_stir_shaken_vs_ctx::tag, and vs_get_cfg().

Referenced by stir_shaken_incoming_request().

◆ ast_stir_shaken_vs_ctx_set_response_code()

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 
)

Sets response code on VS context.

Parameters
ctxVS context
vs_rcast_stir_shaken_vs_response_code to set

Definition at line 632 of file verification.c.

635{
636 ctx->failure_reason = vs_rc;
637}
enum ast_stir_shaken_vs_response_code failure_reason
Definition: verification.h:48

References ast_stir_shaken_vs_ctx::failure_reason.

Referenced by process_failure().

◆ ast_stir_shaken_vs_get_failure_action()

enum stir_shaken_failure_action_enum ast_stir_shaken_vs_get_failure_action ( struct ast_stir_shaken_vs_ctx ctx)

Get failure_action from context.

Parameters
ctxVS context
Return values
ast_stir_shaken_failure_action

Definition at line 620 of file verification.c.

622{
624}
struct profile_cfg * eprofile
Definition: verification.h:40
struct verification_cfg_common vcfg_common
enum stir_shaken_failure_action_enum stir_shaken_failure_action

References ast_stir_shaken_vs_ctx::eprofile, verification_cfg_common::stir_shaken_failure_action, and profile_cfg::vcfg_common.

Referenced by process_failure().

◆ ast_stir_shaken_vs_get_use_rfc9410_responses()

int ast_stir_shaken_vs_get_use_rfc9410_responses ( struct ast_stir_shaken_vs_ctx ctx)

Get use_rfc9410_responses from context.

Parameters
ctxVS context
Return values
1if true
0if false

Definition at line 626 of file verification.c.

628{
630}
enum use_rfc9410_responses_enum use_rfc9410_responses

References ast_stir_shaken_vs_ctx::eprofile, verification_cfg_common::use_rfc9410_responses, and profile_cfg::vcfg_common.

Referenced by process_failure().

◆ ast_stir_shaken_vs_verify()

enum ast_stir_shaken_vs_response_code ast_stir_shaken_vs_verify ( struct ast_stir_shaken_vs_ctx ctx)

Perform incoming call verification.

Parameters
ctxVS context
Return values
AST_STIR_SHAKEN_AS_SUCCESSif successful
OtherAST_STIR_SHAKEN_AS errors.

Definition at line 882 of file verification.c.

883{
884 RAII_VAR(char *, jwt_encoded, NULL, ast_free);
885 RAII_VAR(jwt_t *, jwt, NULL, jwt_free);
886 RAII_VAR(struct ast_json *, grants, NULL, ast_json_unref);
887 char *p = NULL;
888 char *grants_str = NULL;
889 const char *x5u;
890 const char *ppt_header = NULL;
891 const char *grant = NULL;
892 time_t now_s = time(NULL);
893 time_t iat;
894 struct ast_json *grant_obj = NULL;
895 int len;
896 int rc;
898 SCOPE_ENTER(3, "%s: Verifying\n", ctx ? ctx->tag : "NULL");
899
900 if (!ctx) {
902 "%s: No context object!\n", "NULL");
903 }
904
905 if (ast_strlen_zero(ctx->identity_hdr)) {
907 "%s: No identity header in ctx\n", ctx->tag);
908 }
909
910 p = strchr(ctx->identity_hdr, ';');
911 len = p - ctx->identity_hdr + 1;
912 jwt_encoded = ast_malloc(len);
913 if (!jwt_encoded) {
915 "%s: Failed to allocate memory for encoded jwt\n", ctx->tag);
916 }
917
918 memcpy(jwt_encoded, ctx->identity_hdr, len);
919 jwt_encoded[len - 1] = '\0';
920
921 jwt_decode(&jwt, jwt_encoded, NULL, 0);
922
923 ppt_header = jwt_get_header(jwt, "ppt");
924 if (!ppt_header || strcmp(ppt_header, STIR_SHAKEN_PPT)) {
927 }
928
929 vs_rc = check_date_header(ctx);
930 if (vs_rc != AST_STIR_SHAKEN_VS_SUCCESS) {
932 "%s: Date header verification failed\n", ctx->tag);
933 }
934
935 x5u = jwt_get_header(jwt, "x5u");
936 if (ast_strlen_zero(x5u)) {
938 "%s: No x5u in Identity header\n", ctx->tag);
939 }
940
941 rc = check_x5u_url(ctx, x5u);
942 if (rc != AST_STIR_SHAKEN_VS_SUCCESS) {
944 "%s: x5u URL verification failed\n", ctx->tag);
945 }
946
947 ast_trace(3, "%s: Decoded enough to get x5u: '%s'\n", ctx->tag, x5u);
948 if (ast_string_field_set(ctx, public_url, x5u) != 0) {
950 "%s: Failed to set public_url '%s'\n", ctx->tag, x5u);
951 }
952
953 iat = jwt_get_grant_int(jwt, "iat");
954 if (iat == 0) {
956 "%s: No 'iat' in Identity header\n", ctx->tag);
957 }
958 ast_trace(1, "date_hdr: %zu iat: %zu diff: %zu\n",
959 ctx->date_hdr_time, iat, ctx->date_hdr_time - iat);
960 if (iat + ctx->eprofile->vcfg_common.max_iat_age < now_s) {
962 "%s: iat %ld older than %u seconds\n", ctx->tag,
963 iat, ctx->eprofile->vcfg_common.max_iat_age);
964 }
965 ctx->validity_check_time = iat;
966
967 vs_rc = ctx_populate(ctx);
968 if (vs_rc != AST_STIR_SHAKEN_VS_SUCCESS) {
970 "%s: Unable to populate ctx\n", ctx->tag);
971 }
972
973 vs_rc = retrieve_verification_cert(ctx);
974 if (vs_rc != AST_STIR_SHAKEN_VS_SUCCESS) {
976 "%s: Could not get valid cert from '%s'\n", ctx->tag, ctx->public_url);
977 }
978
979 jwt_free(jwt);
980 jwt = NULL;
981
982 rc = jwt_decode(&jwt, jwt_encoded, ctx->raw_key, ctx->raw_key_len);
983 if (rc != 0) {
985 LOG_ERROR, "%s: Signature validation failed for '%s'\n",
986 ctx->tag, ctx->public_url);
987 }
988
989 ast_trace(1, "%s: Decoding succeeded\n", ctx->tag);
990
991 ppt_header = jwt_get_header(jwt, "alg");
992 if (!ppt_header || strcmp(ppt_header, STIR_SHAKEN_ENCRYPTION_ALGORITHM)) {
994 "%s: %s\n", ctx->tag,
996 }
997
998 ppt_header = jwt_get_header(jwt, "ppt");
999 if (!ppt_header || strcmp(ppt_header, STIR_SHAKEN_PPT)) {
1001 "%s: %s\n", ctx->tag,
1003 }
1004
1005 ppt_header = jwt_get_header(jwt, "typ");
1006 if (!ppt_header || strcmp(ppt_header, STIR_SHAKEN_TYPE)) {
1008 "%s: %s\n", ctx->tag,
1010 }
1011
1012 grants_str = jwt_get_grants_json(jwt, NULL);
1013 if (ast_strlen_zero(grants_str)) {
1015 "%s: %s\n", ctx->tag,
1017 }
1018 ast_trace(1, "grants: %s\n", grants_str);
1019 grants = ast_json_load_string(grants_str, NULL);
1020 ast_std_free(grants_str);
1021 if (!grants) {
1023 "%s: %s\n", ctx->tag,
1025 }
1026
1027 grant = ast_json_object_string_get(grants, "attest");
1028 if (ast_strlen_zero(grant)) {
1030 "%s: No 'attest' in Identity header\n", ctx->tag);
1031 }
1032 if (grant[0] < 'A' || grant[0] > 'C') {
1034 "%s: Invalid attest value '%s'\n", ctx->tag, grant);
1035 }
1036 ast_string_field_set(ctx, attestation, grant);
1037 ast_trace(1, "got attest: %s\n", grant);
1038
1039 grant_obj = ast_json_object_get(grants, "dest");
1040 if (!grant_obj) {
1042 "%s: No 'dest' in Identity header\n", ctx->tag);
1043 }
1044 if (TRACE_ATLEAST(3)) {
1045 char *otn = ast_json_dump_string(grant_obj);
1046 ast_trace(1, "got dest: %s\n", otn);
1047 ast_json_free(otn);
1048 }
1049
1050 grant_obj = ast_json_object_get(grants, "orig");
1051 if (!grant_obj) {
1053 "%s: No 'orig' in Identity header\n", ctx->tag);
1054 }
1055 if (TRACE_ATLEAST(3)) {
1056 char *otn = ast_json_dump_string(grant_obj);
1057 ast_trace(1, "got orig: %s\n", otn);
1058 ast_json_free(otn);
1059 }
1060 grant = ast_json_object_string_get(grant_obj, "tn");
1061 if (!grant) {
1063 "%s: No 'orig.tn' in Indentity header\n", ctx->tag);
1064 }
1065 ast_string_field_set(ctx, orig_tn, grant);
1066 if (strcmp(ctx->caller_id, ctx->orig_tn) != 0) {
1068 "%s: Mismatched cid '%s' and orig_tn '%s'\n", ctx->tag,
1069 ctx->caller_id, grant);
1070 }
1071
1072 grant = ast_json_object_string_get(grants, "origid");
1073 if (ast_strlen_zero(grant)) {
1075 "%s: No 'origid' in Identity header\n", ctx->tag);
1076 }
1077
1079 "%s: verification succeeded\n", ctx->tag);
1080}
void ast_std_free(void *ptr)
Definition: astmm.c:1734
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define TRACE_ATLEAST(level)
#define ast_trace(level,...)
#define ast_json_object_string_get(object, key)
Get a string field from a JSON object.
Definition: json.h:600
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
void ast_json_free(void *p)
Asterisk's custom JSON allocator. Exposed for use by unit tests.
Definition: json.c:52
#define ast_json_dump_string(root)
Encode a JSON value to a compact string.
Definition: json.h:810
struct ast_json * ast_json_load_string(const char *input, struct ast_json_error *error)
Parse null terminated string into a JSON object or array.
Definition: json.c:567
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
ast_stir_shaken_vs_response_code
@ AST_STIR_SHAKEN_VS_INVALID_OR_NO_ATTEST
@ AST_STIR_SHAKEN_VS_INVALID_OR_NO_TYP
@ AST_STIR_SHAKEN_VS_CID_ORIG_TN_MISMATCH
@ AST_STIR_SHAKEN_VS_NO_DEST_TN
@ AST_STIR_SHAKEN_VS_IAT_EXPIRED
@ AST_STIR_SHAKEN_VS_SIGNATURE_VALIDATION
@ AST_STIR_SHAKEN_VS_INVALID_OR_NO_ALG
@ AST_STIR_SHAKEN_VS_NO_ORIGID
@ AST_STIR_SHAKEN_VS_NO_IAT
@ AST_STIR_SHAKEN_VS_NO_ORIG_TN
@ AST_STIR_SHAKEN_VS_INVALID_OR_NO_PPT
@ AST_STIR_SHAKEN_VS_INVALID_OR_NO_GRANTS
@ AST_STIR_SHAKEN_VS_INVALID_OR_NO_X5U
#define STIR_SHAKEN_ENCRYPTION_ALGORITHM
Definition: stir_shaken.h:28
#define STIR_SHAKEN_PPT
Definition: stir_shaken.h:29
#define STIR_SHAKEN_TYPE
Definition: stir_shaken.h:30
Abstract JSON element (object, array, string, int, ...).
const ast_string_field orig_tn
Definition: verification.h:39
unsigned char * raw_key
Definition: verification.h:45
const ast_string_field tag
Definition: verification.h:39
const ast_string_field identity_hdr
Definition: verification.h:39
const ast_string_field caller_id
Definition: verification.h:39
static int check_x5u_url(struct ast_stir_shaken_vs_ctx *ctx, const char *x5u)
Definition: verification.c:824
const char * vs_response_code_to_str(enum ast_stir_shaken_vs_response_code vs_rc)
Return string version of VS response code.
Definition: verification.c:89
static enum ast_stir_shaken_vs_response_code retrieve_verification_cert(struct ast_stir_shaken_vs_ctx *ctx)
Definition: verification.c:575
static enum ast_stir_shaken_vs_response_code check_date_header(struct ast_stir_shaken_vs_ctx *ctx)
Definition: verification.c:722
static enum ast_stir_shaken_vs_response_code ctx_populate(struct ast_stir_shaken_vs_ctx *ctx)
Definition: verification.c:547

References ast_free, ast_json_dump_string, ast_json_free(), ast_json_load_string(), ast_json_object_get(), ast_json_object_string_get, ast_json_unref(), ast_malloc, ast_std_free(), AST_STIR_SHAKEN_VS_CID_ORIG_TN_MISMATCH, AST_STIR_SHAKEN_VS_IAT_EXPIRED, AST_STIR_SHAKEN_VS_INTERNAL_ERROR, AST_STIR_SHAKEN_VS_INVALID_OR_NO_ALG, AST_STIR_SHAKEN_VS_INVALID_OR_NO_ATTEST, AST_STIR_SHAKEN_VS_INVALID_OR_NO_GRANTS, AST_STIR_SHAKEN_VS_INVALID_OR_NO_PPT, AST_STIR_SHAKEN_VS_INVALID_OR_NO_TYP, AST_STIR_SHAKEN_VS_INVALID_OR_NO_X5U, AST_STIR_SHAKEN_VS_NO_DEST_TN, AST_STIR_SHAKEN_VS_NO_IAT, AST_STIR_SHAKEN_VS_NO_ORIG_TN, AST_STIR_SHAKEN_VS_NO_ORIGID, AST_STIR_SHAKEN_VS_SIGNATURE_VALIDATION, AST_STIR_SHAKEN_VS_SUCCESS, ast_string_field_set, ast_strlen_zero(), ast_trace, ast_stir_shaken_vs_ctx::caller_id, check_date_header(), check_x5u_url(), ctx_populate(), ast_stir_shaken_vs_ctx::date_hdr_time, ast_stir_shaken_vs_ctx::eprofile, ast_stir_shaken_vs_ctx::identity_hdr, len(), LOG_ERROR, verification_cfg_common::max_iat_age, NULL, ast_stir_shaken_vs_ctx::orig_tn, ast_stir_shaken_vs_ctx::public_url, RAII_VAR, ast_stir_shaken_vs_ctx::raw_key, ast_stir_shaken_vs_ctx::raw_key_len, retrieve_verification_cert(), SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, STIR_SHAKEN_ENCRYPTION_ALGORITHM, STIR_SHAKEN_PPT, STIR_SHAKEN_TYPE, ast_stir_shaken_vs_ctx::tag, TRACE_ATLEAST, ast_stir_shaken_vs_ctx::validity_check_time, profile_cfg::vcfg_common, and vs_response_code_to_str().

Referenced by stir_shaken_incoming_request().

◆ check_cert()

static enum ast_stir_shaken_vs_response_code check_cert ( struct ast_stir_shaken_vs_ctx ctx)
static

Definition at line 325 of file verification.c.

327{
328 RAII_VAR(char *, CN, NULL, ast_free);
329 int res = 0;
330 const char *err_msg;
331 SCOPE_ENTER(3, "%s: Validating cert '%s'\n", ctx->tag, ctx->public_url);
332
333 CN = crypto_get_cert_subject(ctx->xcert, "CN");
334 if (!CN) {
337 LOG_ERROR, "%s: Cert '%s' has no commonName(CN) in Subject '%s'\n",
338 ctx->tag, ctx->public_url, CN);
339 }
340
341 res = ast_string_field_set(ctx, cert_cn, CN);
342 if (res != 0) {
344 }
345
346 ast_trace(3,"%s: Checking ctx against CA ctx\n", ctx->tag);
347 res = crypto_is_cert_trusted(ctx->eprofile->vcfg_common.tcs, ctx->xcert, &err_msg);
348 if (!res) {
350 LOG_ERROR, "%s: Cert '%s' not trusted: %s\n",
351 ctx->tag, ctx->public_url, err_msg);
352 }
353
354 ast_trace(3,"%s: Attempting to get the raw pubkey\n", ctx->tag);
356 &ctx->raw_key);
357 if (ctx->raw_key_len <= 0) {
359 LOG_ERROR, "%s: Unable to extract raw public key from '%s'\n",
360 ctx->tag, ctx->public_url);
361 }
362
363 ast_trace(3,"%s: Checking cert '%s' validity dates\n",
364 ctx->tag, ctx->public_url);
367 LOG_ERROR, "%s: Cert '%s' dates not valid\n",
368 ctx->tag, ctx->public_url);
369 }
370
372 "%s: Cert '%s' with SPC: %s CN: %s is valid\n",
373 ctx->tag, ctx->public_url, ctx->cert_spc, ctx->cert_cn);
374}
int crypto_is_cert_trusted(struct crypto_cert_store *store, X509 *cert, const char **err_msg)
Check if the cert is trusted.
Definition: crypto_utils.c:740
int crypto_get_raw_pubkey_from_cert(X509 *cert, unsigned char **buffer)
Retrieve RAW public key from cert.
Definition: crypto_utils.c:307
char * crypto_get_cert_subject(X509 *cert, const char *short_name)
Returns the Subject (or component of Subject) from a certificate.
Definition: crypto_utils.c:787
int crypto_is_cert_time_valid(X509 *cert, time_t reftime)
Check if the reftime is within the cert's valid dates.
Definition: crypto_utils.c:721
@ AST_STIR_SHAKEN_VS_CERT_DATE_INVALID
@ AST_STIR_SHAKEN_VS_NO_RAW_KEY
@ AST_STIR_SHAKEN_VS_CERT_CONTENTS_INVALID
@ AST_STIR_SHAKEN_VS_CERT_NOT_TRUSTED
const ast_string_field cert_cn
Definition: verification.h:39
const ast_string_field cert_spc
Definition: verification.h:39
struct crypto_cert_store * tcs
static enum ast_stir_shaken_vs_response_code check_tn_auth_list(struct ast_stir_shaken_vs_ctx *ctx)
Definition: verification.c:253

References ast_free, AST_STIR_SHAKEN_VS_CERT_CONTENTS_INVALID, AST_STIR_SHAKEN_VS_CERT_DATE_INVALID, AST_STIR_SHAKEN_VS_CERT_NOT_TRUSTED, AST_STIR_SHAKEN_VS_INTERNAL_ERROR, AST_STIR_SHAKEN_VS_NO_RAW_KEY, ast_string_field_set, ast_trace, ast_stir_shaken_vs_ctx::cert_cn, ast_stir_shaken_vs_ctx::cert_spc, check_tn_auth_list(), crypto_get_cert_subject(), crypto_get_raw_pubkey_from_cert(), crypto_is_cert_time_valid(), crypto_is_cert_trusted(), ast_stir_shaken_vs_ctx::eprofile, LOG_ERROR, NULL, ast_stir_shaken_vs_ctx::public_url, RAII_VAR, ast_stir_shaken_vs_ctx::raw_key, ast_stir_shaken_vs_ctx::raw_key_len, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, ast_stir_shaken_vs_ctx::tag, verification_cfg_common::tcs, ast_stir_shaken_vs_ctx::validity_check_time, profile_cfg::vcfg_common, and ast_stir_shaken_vs_ctx::xcert.

Referenced by retrieve_cert_from_cache(), and retrieve_cert_from_url().

◆ check_date_header()

static enum ast_stir_shaken_vs_response_code check_date_header ( struct ast_stir_shaken_vs_ctx ctx)
static

Definition at line 722 of file verification.c.

724{
725 struct ast_tm date_hdr_tm;
726 struct timeval date_hdr_timeval;
727 struct timeval current_timeval;
728 char *remainder;
729 char timezone[80] = { 0 };
730 int64_t time_diff;
731 SCOPE_ENTER(3, "%s: Checking date header: '%s'\n",
732 ctx->tag, ctx->date_hdr);
733
734 if (!(remainder = ast_strptime(ctx->date_hdr, "%a, %d %b %Y %T", &date_hdr_tm))) {
736 LOG_ERROR, "%s: Failed to parse: '%s'\n",
737 ctx->tag, ctx->date_hdr);
738 }
739
740 sscanf(remainder, "%79s", timezone);
741
742 if (ast_strlen_zero(timezone)) {
744 LOG_ERROR, "%s: A timezone is required: '%s'\n",
745 ctx->tag, ctx->date_hdr);
746 }
747
748 date_hdr_timeval = ast_mktime(&date_hdr_tm, timezone);
749 ctx->date_hdr_time = date_hdr_timeval.tv_sec;
750 current_timeval = ast_tvnow();
751
752 time_diff = ast_tvdiff_ms(current_timeval, date_hdr_timeval);
753 ast_trace(3, "%zu %zu %zu %d\n", current_timeval.tv_sec,
754 date_hdr_timeval.tv_sec,
755 (current_timeval.tv_sec - date_hdr_timeval.tv_sec), (int)time_diff);
756 if (time_diff < 0) {
757 /* An INVITE from the future! */
759 LOG_ERROR, "%s: Future date: '%s'\n",
760 ctx->tag, ctx->date_hdr);
761 } else if (time_diff > (ctx->eprofile->vcfg_common.max_date_header_age * 1000)) {
763 LOG_ERROR, "%s: More than %u seconds old: '%s'\n",
765 }
766
768 "%s: Success: '%s'\n", ctx->tag, ctx->date_hdr);
769}
@ AST_STIR_SHAKEN_VS_DATE_HDR_EXPIRED
@ AST_STIR_SHAKEN_VS_DATE_HDR_PARSE_FAILURE
const ast_string_field date_hdr
Definition: verification.h:39
unsigned int max_date_header_age
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

References ast_mktime(), AST_STIR_SHAKEN_VS_DATE_HDR_EXPIRED, AST_STIR_SHAKEN_VS_DATE_HDR_PARSE_FAILURE, AST_STIR_SHAKEN_VS_SUCCESS, ast_strlen_zero(), ast_strptime(), ast_trace, ast_tvdiff_ms(), ast_tvnow(), ast_stir_shaken_vs_ctx::date_hdr, ast_stir_shaken_vs_ctx::date_hdr_time, ast_stir_shaken_vs_ctx::eprofile, LOG_ERROR, verification_cfg_common::max_date_header_age, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, ast_stir_shaken_vs_ctx::tag, and profile_cfg::vcfg_common.

Referenced by ast_stir_shaken_vs_verify().

◆ check_tn_auth_list()

static enum ast_stir_shaken_vs_response_code check_tn_auth_list ( struct ast_stir_shaken_vs_ctx ctx)
static

Definition at line 253 of file verification.c.

254{
255 ASN1_OCTET_STRING *tn_exten;
256 const unsigned char* octet_str_data = NULL;
257 long xlen;
258 int tag, xclass;
259 int ret;
260 SCOPE_ENTER(3, "%s: Checking TNAuthList in cert '%s'\n", ctx->tag, ctx->public_url);
261
263 if (!tn_exten) {
265 LOG_ERROR, "%s: Cert '%s' doesn't have a TNAuthList extension\n",
266 ctx->tag, ctx->public_url);
267 }
268 octet_str_data = tn_exten->data;
269
270 /* The first call to ASN1_get_object should return a SEQUENCE */
271 ret = ASN1_get_object(&octet_str_data, &xlen, &tag, &xclass, tn_exten->length);
272 if (IS_GET_OBJ_ERR(ret)) {
273 crypto_log_openssl(LOG_ERROR, "%s: Cert '%s' has malformed TNAuthList extension\n",
274 ctx->tag, ctx->public_url);
276 }
277
278 if (ret != V_ASN1_CONSTRUCTED || tag != V_ASN1_SEQUENCE) {
280 LOG_ERROR, "%s: Cert '%s' has malformed TNAuthList extension (tag %d != V_ASN1_SEQUENCE)\n",
281 ctx->tag, ctx->public_url, tag);
282 }
283
284 /*
285 * The second call to ASN1_get_object should return one of
286 * the following tags defined in RFC8226 section 9:
287 *
288 * ASN1_TAG_TNAUTH_SPC 0
289 * ASN1_TAG_TNAUTH_TN_RANGE 1
290 * ASN1_TAG_TNAUTH_TN 2
291 *
292 * ATIS-1000080 however limits this to only ASN1_TAG_TNAUTH_SPC
293 *
294 */
295 ret = ASN1_get_object(&octet_str_data, &xlen, &tag, &xclass, tn_exten->length);
296 if (IS_GET_OBJ_ERR(ret)) {
297 crypto_log_openssl(LOG_ERROR, "%s: Cert '%s' has malformed TNAuthList extension\n",
298 ctx->tag, ctx->public_url);
300 }
301
302 if (ret != V_ASN1_CONSTRUCTED || tag != ASN1_TAG_TNAUTH_SPC) {
304 LOG_ERROR, "%s: Cert '%s' has malformed TNAuthList extension (tag %d != ASN1_TAG_TNAUTH_SPC(0))\n",
305 ctx->tag, ctx->public_url, tag);
306 }
307
308 /* The third call to ASN1_get_object should contain the SPC */
309 ret = ASN1_get_object(&octet_str_data, &xlen, &tag, &xclass, tn_exten->length);
310 if (ret != 0) {
312 LOG_ERROR, "%s: Cert '%s' has malformed TNAuthList extension (no SPC)\n",
313 ctx->tag, ctx->public_url);
314 }
315
316 if (ast_string_field_set(ctx, cert_spc, (char *)octet_str_data) != 0) {
318 }
319
320 SCOPE_EXIT_RTN_VALUE(AST_STIR_SHAKEN_VS_SUCCESS, "%s: Cert '%s' with SPC: %s CN: %s has valid TNAuthList\n",
321 ctx->tag, ctx->public_url, ctx->cert_spc, ctx->cert_cn);
322}
void crypto_log_openssl(int level, char *file, int line, const char *function, const char *fmt,...)
Print a log message with any OpenSSL errors appended.
Definition: crypto_utils.c:45
ASN1_OCTET_STRING * crypto_get_cert_extension_data(X509 *cert, int nid, const char *short_name)
Return the data from a specific extension in a cert.
Definition: crypto_utils.c:107
int get_tn_auth_nid(void)
Retrieves the OpenSSL NID for the TN Auth list extension.
@ AST_STIR_SHAKEN_VS_CERT_NO_SPC_IN_TN_AUTH_EXT
@ AST_STIR_SHAKEN_VS_CERT_NO_TN_AUTH_EXT
#define IS_GET_OBJ_ERR(ret)
Definition: verification.c:250
#define ASN1_TAG_TNAUTH_SPC
Definition: verification.c:246

References ASN1_TAG_TNAUTH_SPC, AST_STIR_SHAKEN_VS_CERT_NO_SPC_IN_TN_AUTH_EXT, AST_STIR_SHAKEN_VS_CERT_NO_TN_AUTH_EXT, AST_STIR_SHAKEN_VS_INTERNAL_ERROR, AST_STIR_SHAKEN_VS_SUCCESS, ast_string_field_set, ast_stir_shaken_vs_ctx::cert_cn, ast_stir_shaken_vs_ctx::cert_spc, crypto_get_cert_extension_data(), crypto_log_openssl(), get_tn_auth_nid(), IS_GET_OBJ_ERR, LOG_ERROR, NULL, ast_stir_shaken_vs_ctx::public_url, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, ast_stir_shaken_vs_ctx::tag, and ast_stir_shaken_vs_ctx::xcert.

Referenced by check_cert().

◆ check_x5u_url()

static int check_x5u_url ( struct ast_stir_shaken_vs_ctx ctx,
const char *  x5u 
)
static

Definition at line 824 of file verification.c.

826{
827 int max_groups = url_match_regex.re_nsub + 1;
828 regmatch_t pmatch[max_groups];
829 int rc;
830 SCOPE_ENTER(3, "%s: Checking x5u '%s'\n", ctx->tag, x5u);
831
832 rc = regexec(&url_match_regex, x5u, max_groups, pmatch, 0);
833 if (rc) {
834 char regex_error[512];
835 regerror(rc, &url_match_regex, regex_error, sizeof(regex_error));
837 "%s: x5u '%s' in Identity header failed basic URL validation: %s\n",
838 ctx->tag, x5u, regex_error);
839 }
840
842 != relax_x5u_port_scheme_restrictions_YES) {
843 const char *scheme = get_match_string(x5u, pmatch, URL_MATCH_SCHEME);
844 const char *port = get_match_string(x5u, pmatch, URL_MATCH_PORT);
845
846 if (!ast_strings_equal(scheme, "https")) {
849 "%s: x5u '%s': scheme '%s' not https\n",
850 ctx->tag, x5u, scheme);
851 }
852 if (!ast_strlen_zero(port)) {
853 if (!ast_strings_equal(port, "443")
854 || !ast_strings_equal(port, "8443")) {
857 "%s: x5u '%s': port '%s' not port 443 or 8443\n",
858 ctx->tag, x5u, port);
859 }
860 }
861 }
862
864 != relax_x5u_path_restrictions_YES) {
865 const char *userpass = get_match_string(x5u, pmatch, URL_MATCH_USERPASS);
866 const char *qs = get_match_string(x5u, pmatch, URL_MATCH_QUERY);
867 const char *frag = get_match_string(x5u, pmatch, URL_MATCH_FRAGMENT);
868
869 if (!ast_strlen_zero(userpass) || !ast_strlen_zero(qs)
870 || !ast_strlen_zero(frag)) {
873 "%s: x5u '%s' contains user:password, query parameters or fragment\n",
874 ctx->tag, x5u);
875 }
876 }
877
878 return 0;
879}
int ast_strings_equal(const char *str1, const char *str2)
Compare strings for equality checking for NULL.
Definition: strings.c:238
enum relax_x5u_path_restrictions_enum relax_x5u_path_restrictions
enum relax_x5u_port_scheme_restrictions_enum relax_x5u_port_scheme_restrictions
static regex_t url_match_regex
Definition: verification.c:48
#define URL_MATCH_USERPASS
Definition: verification.c:791
#define URL_MATCH_SCHEME
Definition: verification.c:790
#define URL_MATCH_PORT
Definition: verification.c:793
#define get_match_string(__x5u, __pmatch, __i)
Definition: verification.c:798
#define URL_MATCH_FRAGMENT
Definition: verification.c:796
#define DUMP_X5U_MATCH()
Definition: verification.c:810
#define URL_MATCH_QUERY
Definition: verification.c:795

References AST_STIR_SHAKEN_VS_INVALID_OR_NO_X5U, ast_strings_equal(), ast_strlen_zero(), DUMP_X5U_MATCH, ast_stir_shaken_vs_ctx::eprofile, get_match_string, LOG_ERROR, verification_cfg_common::relax_x5u_path_restrictions, verification_cfg_common::relax_x5u_port_scheme_restrictions, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, ast_stir_shaken_vs_ctx::tag, URL_MATCH_FRAGMENT, URL_MATCH_PORT, URL_MATCH_QUERY, url_match_regex, URL_MATCH_SCHEME, URL_MATCH_USERPASS, and profile_cfg::vcfg_common.

Referenced by ast_stir_shaken_vs_verify().

◆ cleanup_cert_from_astdb_and_fs()

static void cleanup_cert_from_astdb_and_fs ( struct ast_stir_shaken_vs_ctx ctx)
static

Definition at line 96 of file verification.c.

98{
99 if (ast_db_exists(ctx->hash_family, "path") || ast_db_exists(ctx->hash_family, "expiration")) {
101 }
102
103 if (ast_db_exists(ctx->url_family, ctx->public_url)) {
104 ast_db_del(ctx->url_family, ctx->public_url);
105 }
106
107 /* Remove the actual file from the system */
108 remove(ctx->filename);
109}
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb.
Definition: main/db.c:565
int ast_db_exists(const char *family, const char *key)
Check if family/key exitsts.
Definition: main/db.c:444
#define remove

References ast_db_del(), ast_db_deltree(), ast_db_exists(), ast_stir_shaken_vs_ctx::filename, ast_stir_shaken_vs_ctx::hash_family, NULL, ast_stir_shaken_vs_ctx::public_url, remove, and ast_stir_shaken_vs_ctx::url_family.

Referenced by retrieve_cert_from_cache().

◆ ctx_destructor()

static void ctx_destructor ( void *  obj)
static

Definition at line 639 of file verification.c.

640{
641 struct ast_stir_shaken_vs_ctx *ctx = obj;
642
643 ao2_cleanup(ctx->eprofile);
644 ast_free(ctx->raw_key);
646 X509_free(ctx->xcert);
647}
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374

References ao2_cleanup, ast_free, ast_string_field_free_memory, ast_stir_shaken_vs_ctx::eprofile, ast_stir_shaken_vs_ctx::raw_key, and ast_stir_shaken_vs_ctx::xcert.

Referenced by ast_stir_shaken_vs_ctx_create().

◆ ctx_populate()

static enum ast_stir_shaken_vs_response_code ctx_populate ( struct ast_stir_shaken_vs_ctx ctx)
static

Definition at line 547 of file verification.c.

549{
550 char hash[41];
551
552 ast_sha1_hash(hash, ctx->public_url);
553 if (ast_string_field_set(ctx, hash, hash) != 0) {
555 }
556
557 if (ast_string_field_build(ctx, filename, "%s/%s.pem",
558 ctx->eprofile->vcfg_common.cert_cache_dir, hash) != 0) {
560 }
561
562 if (ast_string_field_build(ctx, hash_family, "%s/hash/%s",
563 AST_DB_FAMILY, hash) != 0) {
565 }
566
567 if (ast_string_field_build(ctx, url_family, "%s/url", AST_DB_FAMILY) != 0) {
569 }
570
572}
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Definition: stringfields.h:555
const ast_string_field cert_cache_dir
void ast_sha1_hash(char *output, const char *input)
Produces SHA1 hash based on input string.
Definition: utils.c:266
#define AST_DB_FAMILY
Definition: verification.c:46

References AST_DB_FAMILY, ast_sha1_hash(), AST_STIR_SHAKEN_VS_INTERNAL_ERROR, AST_STIR_SHAKEN_VS_SUCCESS, ast_string_field_build, ast_string_field_set, verification_cfg_common::cert_cache_dir, ast_stir_shaken_vs_ctx::eprofile, ast_stir_shaken_vs_ctx::public_url, and profile_cfg::vcfg_common.

Referenced by ast_stir_shaken_vs_verify().

◆ is_cert_cache_entry_expired()

static int is_cert_cache_entry_expired ( char *  expiration)
static

Definition at line 224 of file verification.c.

225{
226 struct timeval current_time = ast_tvnow();
227 struct timeval expires = { .tv_sec = 0, .tv_usec = 0 };
228 int res = 0;
229 SCOPE_ENTER(3, "Checking for cache expiration: %s\n", expiration);
230
231 if (ast_strlen_zero(expiration)) {
232 SCOPE_EXIT_RTN_VALUE(1, "No expiration date provided\n");
233 }
234
235 if (ast_str_to_ulong(expiration, (unsigned long *)&expires.tv_sec)) {
236 SCOPE_EXIT_RTN_VALUE(1, "Couldn't convert expiration string '%s' to ulong",
237 expiration);
238 }
239 ast_trace(2, "Expiration comparison: exp: %" PRIu64 " curr: %" PRIu64 " Diff: %" PRIu64 ".\n",
240 expires.tv_sec, current_time.tv_sec, expires.tv_sec - current_time.tv_sec);
241
242 res = (ast_tvcmp(current_time, expires) == -1 ? 0 : 1);
243 SCOPE_EXIT_RTN_VALUE(res , "entry was %sexpired\n", res ? "" : "not ");
244}
int ast_str_to_ulong(const char *str, unsigned long *res)
Convert the given string to an unsigned long.
Definition: conversions.c:80
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compress two struct timeval instances returning -1, 0, 1 if the first arg is smaller,...
Definition: time.h:137

References ast_str_to_ulong(), ast_strlen_zero(), ast_trace, ast_tvcmp(), ast_tvnow(), SCOPE_ENTER, and SCOPE_EXIT_RTN_VALUE.

Referenced by retrieve_cert_from_cache().

◆ retrieve_cert_from_cache()

static enum ast_stir_shaken_vs_response_code retrieve_cert_from_cache ( struct ast_stir_shaken_vs_ctx ctx)
static

Definition at line 489 of file verification.c.

490{
491 int rc = 0;
493
494 SCOPE_ENTER(2, "%s: Attempting to retrieve cert '%s' from cache\n",
495 ctx->tag, ctx->public_url);
496
497 if (!ast_db_exists(ctx->hash_family, "path")) {
500 "%s: No cert found in astdb for '%s'\n",
501 ctx->tag, ctx->public_url);
502 }
503
504 rc = ast_db_get(ctx->hash_family, "expiration", ctx->expiration, sizeof(ctx->expiration));
505 if (rc) {
508 "%s: No cert found in astdb for '%s'\n",
509 ctx->tag, ctx->public_url);
510 }
511
512 if (!ast_file_is_readable(ctx->filename)) {
515 "%s: Cert file '%s' was not found or was not readable for '%s'\n",
516 ctx->tag, ctx->filename, ctx->public_url);
517 }
518
522 "%s: Cert file '%s' cache entry was expired for '%s'\n",
523 ctx->tag, ctx->filename, ctx->public_url);
524 }
525
527 if (!ctx->xcert) {
530 "%s: Cert file '%s' was not parseable as an X509 certificate for '%s'\n",
531 ctx->tag, ctx->filename, ctx->public_url);
532 }
533
534 vs_rc = check_cert(ctx);
535 if (vs_rc != AST_STIR_SHAKEN_VS_SUCCESS) {
536 X509_free(ctx->xcert);
537 ctx->xcert = NULL;
538 SCOPE_EXIT_RTN_VALUE(vs_rc, "%s: Cert '%s' failed validity checks\n",
539 ctx->tag, ctx->public_url);
540 }
541
543 "%s: Cert '%s' successfully retrieved from cache\n",
544 ctx->tag, ctx->public_url);
545}
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition: main/db.c:427
X509 * crypto_load_cert_from_file(const char *filename)
Load an X509 Cert from a file.
Definition: crypto_utils.c:189
@ AST_STIR_SHAKEN_VS_CERT_CACHE_MISS
@ AST_STIR_SHAKEN_VS_CERT_CACHE_EXPIRED
int ast_file_is_readable(const char *filename)
Test that a file exists and is readable by the effective user.
Definition: utils.c:3107
static int is_cert_cache_entry_expired(char *expiration)
Definition: verification.c:224
static enum ast_stir_shaken_vs_response_code check_cert(struct ast_stir_shaken_vs_ctx *ctx)
Definition: verification.c:325
static void cleanup_cert_from_astdb_and_fs(struct ast_stir_shaken_vs_ctx *ctx)
Definition: verification.c:96

References ast_db_exists(), ast_db_get(), ast_file_is_readable(), AST_STIR_SHAKEN_VS_CERT_CACHE_EXPIRED, AST_STIR_SHAKEN_VS_CERT_CACHE_MISS, AST_STIR_SHAKEN_VS_CERT_CONTENTS_INVALID, AST_STIR_SHAKEN_VS_SUCCESS, check_cert(), cleanup_cert_from_astdb_and_fs(), crypto_load_cert_from_file(), ast_stir_shaken_vs_ctx::expiration, ast_stir_shaken_vs_ctx::filename, ast_stir_shaken_vs_ctx::hash_family, is_cert_cache_entry_expired(), NULL, ast_stir_shaken_vs_ctx::public_url, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, ast_stir_shaken_vs_ctx::tag, and ast_stir_shaken_vs_ctx::xcert.

Referenced by retrieve_verification_cert().

◆ retrieve_cert_from_url()

static enum ast_stir_shaken_vs_response_code retrieve_cert_from_url ( struct ast_stir_shaken_vs_ctx ctx)
static

Definition at line 376 of file verification.c.

378{
379 FILE *cert_file;
380 long http_code;
381 int rc = 0;
385 RAII_VAR(struct curl_write_data *, write_data,
386 ast_calloc(1, sizeof(*write_data)), curl_write_data_free);
387 RAII_VAR(struct curl_open_socket_data *, open_socket_data,
388 ast_calloc(1, sizeof(*open_socket_data)), curl_open_socket_data_free);
389
390 const char *cache_control;
391 const char *expires;
392 SCOPE_ENTER(2, "%s: Attempting to retrieve '%s' from net\n",
393 ctx->tag, ctx->public_url);
394
395 if (!header_data || !write_data || !open_socket_data) {
397 LOG_ERROR, "%s: Unable to allocate memory for curl '%s' transaction\n",
398 ctx->tag, ctx->public_url);
399 }
400
401 header_data->debug_info = ast_strdup(ctx->public_url);
402 write_data->debug_info = ast_strdup(ctx->public_url);
403 write_data->max_download_bytes = 8192;
404 write_data->stream_buffer = NULL;
405 open_socket_data->debug_info = ast_strdup(ctx->public_url);
406 open_socket_data->acl = ctx->eprofile->vcfg_common.acl;
407
408 if (!header_data->debug_info || !write_data->debug_info ||
409 !open_socket_data->debug_info) {
411 LOG_ERROR, "%s: Unable to allocate memory for curl '%s' transaction\n",
412 ctx->tag, ctx->public_url);
413 }
414
415 http_code = curler(ctx->public_url,
417 write_data, header_data, open_socket_data);
418
419 if (http_code / 100 != 2) {
421 LOG_ERROR, "%s: Failed to retrieve cert %s: code %ld\n",
422 ctx->tag, ctx->public_url, http_code);
423 }
424
425 if (!ast_begins_with(write_data->stream_buffer, BEGIN_CERTIFICATE_STR)) {
427 LOG_ERROR, "%s: Cert '%s' contains invalid data\n",
428 ctx->tag, ctx->public_url);
429 }
430
431 ctx->xcert = crypto_load_cert_from_memory(write_data->stream_buffer,
432 write_data->stream_bytes_downloaded);
433 if (!ctx->xcert) {
435 LOG_ERROR, "%s: Cert '%s' was not parseable as an X509 certificate\n",
436 ctx->tag, ctx->public_url);
437 }
438
439 vs_rc = check_cert(ctx);
440 if (vs_rc != AST_STIR_SHAKEN_VS_SUCCESS) {
441 X509_free(ctx->xcert);
442 ctx->xcert = NULL;
443 SCOPE_EXIT_RTN_VALUE(vs_rc, "%s: Cert '%s' failed validity checks\n",
444 ctx->tag, ctx->public_url);
445 }
446
447 cert_file = fopen(ctx->filename, "w");
448 if (!cert_file) {
449 X509_free(ctx->xcert);
450 ctx->xcert = NULL;
452 LOG_ERROR, "%s: Failed to write cert %s: file '%s' %s (%d)\n",
453 ctx->tag, ctx->public_url, ctx->filename, strerror(errno), errno);
454 }
455
456 rc = fputs(write_data->stream_buffer, cert_file);
457 fclose(cert_file);
458 if (rc == EOF) {
459 X509_free(ctx->xcert);
460 ctx->xcert = NULL;
462 LOG_ERROR, "%s: Failed to write cert %s: file '%s' %s (%d)\n",
463 ctx->tag, ctx->public_url, ctx->filename, strerror(errno), errno);
464 }
465
466 ast_trace(2, "%s: Cert '%s' written to file '%s'\n",
467 ctx->tag, ctx->public_url, ctx->filename);
468
469 ast_trace(2, "%s: Adding cert '%s' to astdb",
470 ctx->tag, ctx->public_url);
471 cache_control = ast_variable_find_in_list(header_data->headers, "cache-control");
472 expires = ast_variable_find_in_list(header_data->headers, "expires");
473
474 rc = add_cert_key_to_astdb(ctx, cache_control, expires);
475 if (rc) {
476 X509_free(ctx->xcert);
477 ctx->xcert = NULL;
479 LOG_ERROR, "%s: Unable to add cert '%s' to ASTDB\n",
480 ctx->tag, ctx->public_url);
481 }
482
484 "%s: Cert '%s' successfully retrieved from internet and cached\n",
485 ctx->tag, ctx->public_url);
486}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
X509 * crypto_load_cert_from_memory(const char *buffer, size_t size)
Load an X509 Cert from a NULL terminated buffer.
Definition: crypto_utils.c:213
void curl_write_data_free(void *obj)
Definition: curl_utils.c:134
void curl_header_data_free(void *obj)
Definition: curl_utils.c:26
void curl_open_socket_data_free(void *obj)
Definition: curl_utils.c:193
long curler(const char *url, int request_timeout, struct curl_write_data *write_data, struct curl_header_data *header_data, struct curl_open_socket_data *open_socket_data)
Perform a curl request.
Definition: curl_utils.c:232
const char * ast_variable_find_in_list(const struct ast_variable *list, const char *variable)
Gets the value of a variable from a variable list by name.
Definition: main/config.c:928
int errno
@ AST_STIR_SHAKEN_VS_CERT_RETRIEVAL_FAILURE
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
Definition: strings.h:97
Context structure passed to ast_curl_header_default_cb.
Definition: curl_utils.h:163
Context structure passed to ast_curl_open_socket_default_cb.
Definition: curl_utils.h:341
Context structure passed to ast_curl_write_default_cb.
Definition: curl_utils.h:245
Data structure used for ast_sip_push_task_wait_serializer
struct ast_acl_list * acl
static int add_cert_key_to_astdb(struct ast_stir_shaken_vs_ctx *cert, const char *cache_control_hdr, const char *expires_hdr)
Definition: verification.c:200
#define BEGIN_CERTIFICATE_STR
Definition: verification.c:51

References verification_cfg_common::acl, add_cert_key_to_astdb(), ast_begins_with(), ast_calloc, AST_STIR_SHAKEN_VS_CERT_CONTENTS_INVALID, AST_STIR_SHAKEN_VS_CERT_RETRIEVAL_FAILURE, AST_STIR_SHAKEN_VS_INTERNAL_ERROR, AST_STIR_SHAKEN_VS_SUCCESS, ast_strdup, ast_trace, ast_variable_find_in_list(), BEGIN_CERTIFICATE_STR, check_cert(), crypto_load_cert_from_memory(), curl_header_data_free(), curl_open_socket_data_free(), verification_cfg_common::curl_timeout, curl_write_data_free(), curler(), ast_stir_shaken_vs_ctx::eprofile, errno, ast_stir_shaken_vs_ctx::filename, LOG_ERROR, NULL, ast_stir_shaken_vs_ctx::public_url, RAII_VAR, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, ast_stir_shaken_vs_ctx::tag, profile_cfg::vcfg_common, and ast_stir_shaken_vs_ctx::xcert.

Referenced by retrieve_verification_cert().

◆ retrieve_verification_cert()

static enum ast_stir_shaken_vs_response_code retrieve_verification_cert ( struct ast_stir_shaken_vs_ctx ctx)
static

Definition at line 575 of file verification.c.

576{
578 SCOPE_ENTER(3, "%s: Retrieving cert '%s'\n", ctx->tag, ctx->public_url);
579
580 ast_trace(1, "%s: Checking cache for cert '%s'\n", ctx->tag, ctx->public_url);
581 rc = retrieve_cert_from_cache(ctx);
582 if (rc == AST_STIR_SHAKEN_VS_SUCCESS) {
583 SCOPE_EXIT_RTN_VALUE(rc, "%s: Using cert '%s' from cache\n",
584 ctx->tag, ctx->public_url);;
585 }
586
587 ast_trace(1, "%s: No valid cert for '%s' available in cache\n",
588 ctx->tag, ctx->public_url);
589 ast_trace(1, "%s: Retrieving cert directly from url '%s'\n",
590 ctx->tag, ctx->public_url);
591
592 rc = retrieve_cert_from_url(ctx);
593 if (rc == AST_STIR_SHAKEN_VS_SUCCESS) {
594 SCOPE_EXIT_RTN_VALUE(rc, "%s: Using cert '%s' from internet\n",
595 ctx->tag, ctx->public_url);
596 }
597
599 "%s: Unable to retrieve cert '%s' from cache or internet\n",
600 ctx->tag, ctx->public_url);
601}
static enum ast_stir_shaken_vs_response_code retrieve_cert_from_url(struct ast_stir_shaken_vs_ctx *ctx)
Definition: verification.c:376
static enum ast_stir_shaken_vs_response_code retrieve_cert_from_cache(struct ast_stir_shaken_vs_ctx *ctx)
Definition: verification.c:489

References AST_STIR_SHAKEN_VS_SUCCESS, ast_trace, LOG_ERROR, ast_stir_shaken_vs_ctx::public_url, retrieve_cert_from_cache(), retrieve_cert_from_url(), SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, and ast_stir_shaken_vs_ctx::tag.

Referenced by ast_stir_shaken_vs_verify().

◆ vs_load()

int vs_load ( void  )

Load the stir/shaken verification service.

Return values
0on success
-1on error

Definition at line 1099 of file verification.c.

1100{
1101 int rc = 0;
1102
1103 if (vs_config_load()) {
1105 }
1106
1107 rc = regcomp(&url_match_regex, FULL_URL_REGEX, REG_EXTENDED);
1108 if (rc) {
1109 char regex_error[512];
1110 regerror(rc, &url_match_regex, regex_error, sizeof(regex_error));
1111 ast_log(LOG_ERROR, "Verification service URL regex failed to compile: %s\n", regex_error);
1112 vs_unload();
1114 }
1115 if (url_match_regex.re_nsub != FULL_URL_REGEX_GROUPS) {
1116 ast_log(LOG_ERROR, "The verification service URL regex was updated without updating FULL_URL_REGEX_GROUPS\n");
1117 vs_unload();
1119 }
1120
1122}
#define ast_log
Definition: astobj2.c:42
int vs_config_load(void)
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define FULL_URL_REGEX_GROUPS
Definition: verification.c:772
#define FULL_URL_REGEX
Definition: verification.c:771
int vs_unload()
Unload the stir/shaken verification service.

References ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, FULL_URL_REGEX, FULL_URL_REGEX_GROUPS, LOG_ERROR, url_match_regex, vs_config_load(), and vs_unload().

Referenced by common_config_load().

◆ vs_reload()

int vs_reload ( void  )

Reload the stir/shaken verification service.

Return values
0on success
-1on error

Definition at line 1082 of file verification.c.

1083{
1085
1086 return 0;
1087}
int vs_config_reload(void)

References vs_config_reload().

Referenced by common_config_reload().

◆ vs_response_code_to_str()

const char * vs_response_code_to_str ( enum ast_stir_shaken_vs_response_code  vs_rc)

Return string version of VS response code.

Parameters
vs_rc
Returns
Response string

Definition at line 89 of file verification.c.

91{
92 return ARRAY_IN_BOUNDS(vs_rc, vs_rc_map) ?
93 vs_rc_map[vs_rc] : NULL;
94}
#define ARRAY_IN_BOUNDS(v, a)
Checks to see if value is within the bounds of the given array.
Definition: utils.h:687
static const char * vs_rc_map[]
Definition: verification.c:53

References ARRAY_IN_BOUNDS, NULL, and vs_rc_map.

Referenced by ast_stir_shaken_vs_verify(), and func_read().

◆ vs_unload()

int vs_unload ( void  )

Unload the stir/shaken verification service.

Return values
0on success
-1on error

Definition at line 1089 of file verification.c.

1090{
1092 if (url_match_regex.re_nsub > 0) {
1093 regfree(&url_match_regex);
1094 }
1095
1096 return 0;
1097}
int vs_config_unload(void)

References url_match_regex, and vs_config_unload().

Referenced by common_config_unload(), and vs_load().

Variable Documentation

◆ url_match_regex

regex_t url_match_regex
static

Definition at line 48 of file verification.c.

Referenced by check_x5u_url(), vs_load(), and vs_unload().

◆ vs_rc_map

const char* vs_rc_map[]
static

Definition at line 53 of file verification.c.

Referenced by vs_response_code_to_str().