Asterisk - The Open Source Telephony Project GIT-master-8f1982c
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
Enumerations | Functions
res_stir_shaken.h File Reference
#include "asterisk/sorcery.h"
Include dependency graph for res_stir_shaken.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Enumerations

enum  ast_stir_shaken_as_response_code {
  AST_STIR_SHAKEN_AS_SUCCESS = 0 , AST_STIR_SHAKEN_AS_DISABLED , AST_STIR_SHAKEN_AS_INVALID_ARGUMENTS , AST_STIR_SHAKEN_AS_MISSING_PARAMETERS ,
  AST_STIR_SHAKEN_AS_INTERNAL_ERROR , AST_STIR_SHAKEN_AS_NO_TN_FOR_CALLERID , AST_STIR_SHAKEN_AS_NO_PRIVATE_KEY_AVAIL , AST_STIR_SHAKEN_AS_NO_PUBLIC_CERT_URL_AVAIL ,
  AST_STIR_SHAKEN_AS_NO_ATTEST_LEVEL , AST_STIR_SHAKEN_AS_IDENTITY_HDR_EXISTS , AST_STIR_SHAKEN_AS_NO_TO_HDR , AST_STIR_SHAKEN_AS_TO_HDR_BAD_URI ,
  AST_STIR_SHAKEN_AS_SIGN_ENCODE_FAILURE , AST_STIR_SHAKEN_AS_RESPONSE_CODE_MAX
}
 
enum  ast_stir_shaken_vs_response_code {
  AST_STIR_SHAKEN_VS_SUCCESS = 0 , AST_STIR_SHAKEN_VS_DISABLED , AST_STIR_SHAKEN_VS_INVALID_ARGUMENTS , AST_STIR_SHAKEN_VS_INTERNAL_ERROR ,
  AST_STIR_SHAKEN_VS_NO_IDENTITY_HDR , AST_STIR_SHAKEN_VS_NO_DATE_HDR , AST_STIR_SHAKEN_VS_DATE_HDR_PARSE_FAILURE , AST_STIR_SHAKEN_VS_DATE_HDR_EXPIRED ,
  AST_STIR_SHAKEN_VS_NO_JWT_HDR , AST_STIR_SHAKEN_VS_INVALID_OR_NO_X5U , AST_STIR_SHAKEN_VS_CERT_CACHE_MISS , AST_STIR_SHAKEN_VS_CERT_CACHE_INVALID ,
  AST_STIR_SHAKEN_VS_CERT_CACHE_EXPIRED , AST_STIR_SHAKEN_VS_CERT_RETRIEVAL_FAILURE , AST_STIR_SHAKEN_VS_CERT_CONTENTS_INVALID , AST_STIR_SHAKEN_VS_CERT_NOT_TRUSTED ,
  AST_STIR_SHAKEN_VS_CERT_DATE_INVALID , AST_STIR_SHAKEN_VS_CERT_NO_TN_AUTH_EXT , AST_STIR_SHAKEN_VS_CERT_NO_SPC_IN_TN_AUTH_EXT , AST_STIR_SHAKEN_VS_NO_RAW_KEY ,
  AST_STIR_SHAKEN_VS_SIGNATURE_VALIDATION , AST_STIR_SHAKEN_VS_NO_IAT , AST_STIR_SHAKEN_VS_IAT_EXPIRED , AST_STIR_SHAKEN_VS_INVALID_OR_NO_PPT ,
  AST_STIR_SHAKEN_VS_INVALID_OR_NO_ALG , AST_STIR_SHAKEN_VS_INVALID_OR_NO_TYP , AST_STIR_SHAKEN_VS_INVALID_OR_NO_GRANTS , AST_STIR_SHAKEN_VS_INVALID_OR_NO_ATTEST ,
  AST_STIR_SHAKEN_VS_NO_ORIGID , AST_STIR_SHAKEN_VS_NO_ORIG_TN , AST_STIR_SHAKEN_VS_CID_ORIG_TN_MISMATCH , 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
}
 
enum  stir_shaken_failure_action_enum {
  stir_shaken_failure_action_UNKNOWN = -1 , stir_shaken_failure_action_CONTINUE = 0 , stir_shaken_failure_action_REJECT_REQUEST , stir_shaken_failure_action_CONTINUE_RETURN_REASON ,
  stir_shaken_failure_action_NOT_SET
}
 

Functions

int ast_stir_shaken_add_result_to_channel (struct ast_stir_shaken_vs_ctx *ctx)
 Add a STIR/SHAKEN verification result to a channel. More...
 
enum ast_stir_shaken_as_response_code ast_stir_shaken_as_ctx_add_fingerprint (struct ast_stir_shaken_as_ctx *ctx, const char *alg, const char *fingerprint)
 Add DTLS fingerprints to AS context. More...
 
enum ast_stir_shaken_as_response_code ast_stir_shaken_as_ctx_create (const char *caller_id, const char *dest_tn, struct ast_channel *chan, const char *profile_name, const char *tag, struct ast_stir_shaken_as_ctx **ctxout)
 Create Attestation Service Context. More...
 
int ast_stir_shaken_as_ctx_wants_fingerprints (struct ast_stir_shaken_as_ctx *ctx)
 Indicates if the AS context needs DTLS fingerprints. More...
 
enum ast_stir_shaken_as_response_code ast_stir_shaken_attest (struct ast_stir_shaken_as_ctx *ctx, char **header)
 Attest and return Identity header value. More...
 
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...
 
const char * ast_stir_shaken_vs_get_caller_id (struct ast_stir_shaken_vs_ctx *ctx)
 Get caller_id from 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...
 

Enumeration Type Documentation

◆ ast_stir_shaken_as_response_code

Enumerator
AST_STIR_SHAKEN_AS_SUCCESS 
AST_STIR_SHAKEN_AS_DISABLED 
AST_STIR_SHAKEN_AS_INVALID_ARGUMENTS 
AST_STIR_SHAKEN_AS_MISSING_PARAMETERS 
AST_STIR_SHAKEN_AS_INTERNAL_ERROR 
AST_STIR_SHAKEN_AS_NO_TN_FOR_CALLERID 
AST_STIR_SHAKEN_AS_NO_PRIVATE_KEY_AVAIL 
AST_STIR_SHAKEN_AS_NO_PUBLIC_CERT_URL_AVAIL 
AST_STIR_SHAKEN_AS_NO_ATTEST_LEVEL 
AST_STIR_SHAKEN_AS_IDENTITY_HDR_EXISTS 
AST_STIR_SHAKEN_AS_NO_TO_HDR 
AST_STIR_SHAKEN_AS_TO_HDR_BAD_URI 
AST_STIR_SHAKEN_AS_SIGN_ENCODE_FAILURE 
AST_STIR_SHAKEN_AS_RESPONSE_CODE_MAX 

Definition at line 62 of file res_stir_shaken.h.

62 {
77};
@ AST_STIR_SHAKEN_AS_NO_TN_FOR_CALLERID
@ AST_STIR_SHAKEN_AS_INVALID_ARGUMENTS
@ AST_STIR_SHAKEN_AS_TO_HDR_BAD_URI
@ AST_STIR_SHAKEN_AS_MISSING_PARAMETERS
@ AST_STIR_SHAKEN_AS_NO_PRIVATE_KEY_AVAIL
@ AST_STIR_SHAKEN_AS_DISABLED
@ AST_STIR_SHAKEN_AS_SIGN_ENCODE_FAILURE
@ AST_STIR_SHAKEN_AS_NO_TO_HDR
@ AST_STIR_SHAKEN_AS_NO_PUBLIC_CERT_URL_AVAIL
@ AST_STIR_SHAKEN_AS_SUCCESS
@ AST_STIR_SHAKEN_AS_RESPONSE_CODE_MAX
@ AST_STIR_SHAKEN_AS_INTERNAL_ERROR
@ AST_STIR_SHAKEN_AS_IDENTITY_HDR_EXISTS
@ AST_STIR_SHAKEN_AS_NO_ATTEST_LEVEL

◆ ast_stir_shaken_vs_response_code

Enumerator
AST_STIR_SHAKEN_VS_SUCCESS 
AST_STIR_SHAKEN_VS_DISABLED 
AST_STIR_SHAKEN_VS_INVALID_ARGUMENTS 
AST_STIR_SHAKEN_VS_INTERNAL_ERROR 
AST_STIR_SHAKEN_VS_NO_IDENTITY_HDR 
AST_STIR_SHAKEN_VS_NO_DATE_HDR 
AST_STIR_SHAKEN_VS_DATE_HDR_PARSE_FAILURE 
AST_STIR_SHAKEN_VS_DATE_HDR_EXPIRED 
AST_STIR_SHAKEN_VS_NO_JWT_HDR 
AST_STIR_SHAKEN_VS_INVALID_OR_NO_X5U 
AST_STIR_SHAKEN_VS_CERT_CACHE_MISS 
AST_STIR_SHAKEN_VS_CERT_CACHE_INVALID 
AST_STIR_SHAKEN_VS_CERT_CACHE_EXPIRED 
AST_STIR_SHAKEN_VS_CERT_RETRIEVAL_FAILURE 
AST_STIR_SHAKEN_VS_CERT_CONTENTS_INVALID 
AST_STIR_SHAKEN_VS_CERT_NOT_TRUSTED 
AST_STIR_SHAKEN_VS_CERT_DATE_INVALID 
AST_STIR_SHAKEN_VS_CERT_NO_TN_AUTH_EXT 
AST_STIR_SHAKEN_VS_CERT_NO_SPC_IN_TN_AUTH_EXT 
AST_STIR_SHAKEN_VS_NO_RAW_KEY 
AST_STIR_SHAKEN_VS_SIGNATURE_VALIDATION 
AST_STIR_SHAKEN_VS_NO_IAT 
AST_STIR_SHAKEN_VS_IAT_EXPIRED 
AST_STIR_SHAKEN_VS_INVALID_OR_NO_PPT 
AST_STIR_SHAKEN_VS_INVALID_OR_NO_ALG 
AST_STIR_SHAKEN_VS_INVALID_OR_NO_TYP 
AST_STIR_SHAKEN_VS_INVALID_OR_NO_GRANTS 
AST_STIR_SHAKEN_VS_INVALID_OR_NO_ATTEST 
AST_STIR_SHAKEN_VS_NO_ORIGID 
AST_STIR_SHAKEN_VS_NO_ORIG_TN 
AST_STIR_SHAKEN_VS_CID_ORIG_TN_MISMATCH 
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 

Definition at line 23 of file res_stir_shaken.h.

23 {
60};
@ AST_STIR_SHAKEN_VS_CERT_DATE_INVALID
@ AST_STIR_SHAKEN_VS_NO_DATE_HDR
@ AST_STIR_SHAKEN_VS_SUCCESS
@ 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_JWT_HDR
@ AST_STIR_SHAKEN_VS_NO_DEST_TN
@ AST_STIR_SHAKEN_VS_IAT_EXPIRED
@ AST_STIR_SHAKEN_VS_NO_IDENTITY_HDR
@ AST_STIR_SHAKEN_VS_NO_RAW_KEY
@ AST_STIR_SHAKEN_VS_DATE_HDR_EXPIRED
@ AST_STIR_SHAKEN_VS_INVALID_ARGUMENTS
@ AST_STIR_SHAKEN_VS_SIGNATURE_VALIDATION
@ AST_STIR_SHAKEN_VS_INVALID_OR_NO_ALG
@ AST_STIR_SHAKEN_VS_CERT_CONTENTS_INVALID
@ AST_STIR_SHAKEN_VS_NO_ORIGID
@ AST_STIR_SHAKEN_VS_INVALID_HEADER
@ AST_STIR_SHAKEN_VS_CERT_CACHE_INVALID
@ AST_STIR_SHAKEN_VS_INVALID_GRANT
@ AST_STIR_SHAKEN_VS_DISABLED
@ AST_STIR_SHAKEN_VS_CERT_CACHE_MISS
@ AST_STIR_SHAKEN_VS_CERT_CACHE_EXPIRED
@ 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_CERT_NOT_TRUSTED
@ AST_STIR_SHAKEN_VS_DATE_HDR_PARSE_FAILURE
@ AST_STIR_SHAKEN_VS_INTERNAL_ERROR
@ AST_STIR_SHAKEN_VS_INVALID_OR_NO_CID
@ AST_STIR_SHAKEN_VS_CERT_NO_SPC_IN_TN_AUTH_EXT
@ AST_STIR_SHAKEN_VS_RESPONSE_CODE_MAX
@ AST_STIR_SHAKEN_VS_INVALID_OR_NO_GRANTS
@ AST_STIR_SHAKEN_VS_INVALID_OR_NO_X5U
@ AST_STIR_SHAKEN_VS_CERT_RETRIEVAL_FAILURE
@ AST_STIR_SHAKEN_VS_CERT_NO_TN_AUTH_EXT

◆ stir_shaken_failure_action_enum

Enumerator
stir_shaken_failure_action_UNKNOWN 

Unknown value

stir_shaken_failure_action_CONTINUE 

Continue and let dialplan decide action

stir_shaken_failure_action_REJECT_REQUEST 

Reject request with respone codes defined in RFC8224

stir_shaken_failure_action_CONTINUE_RETURN_REASON 

Continue but return a Reason header in next provisional response

stir_shaken_failure_action_NOT_SET 

Not set in config

Definition at line 79 of file res_stir_shaken.h.

79 {
80 /*! Unknown value */
82 /*! Continue and let dialplan decide action */
84 /*! Reject request with respone codes defined in RFC8224 */
86 /*! Continue but return a Reason header in next provisional response */
88 /*! Not set in config */
90};
@ stir_shaken_failure_action_CONTINUE
@ stir_shaken_failure_action_CONTINUE_RETURN_REASON
@ stir_shaken_failure_action_UNKNOWN
@ stir_shaken_failure_action_NOT_SET
@ stir_shaken_failure_action_REJECT_REQUEST

Function Documentation

◆ ast_stir_shaken_add_result_to_channel()

int ast_stir_shaken_add_result_to_channel ( struct ast_stir_shaken_vs_ctx ctx)

Add a STIR/SHAKEN verification result to a channel.

Parameters
ctxVS context
Return values
-1on failure
0on success

Definition at line 89 of file res_stir_shaken.c.

91{
93 struct ast_datastore *chan_datastore;
94 const char *chan_name;
95
96 if (!ctx->chan) {
97 ast_log(LOG_ERROR, "Channel is required to add STIR/SHAKEN verification\n");
98 return -1;
99 }
100
101 chan_name = ast_channel_name(ctx->chan);
102
103 if (!ctx->identity_hdr) {
104 ast_log(LOG_ERROR, "No identity to add STIR/SHAKEN verification to channel "
105 "%s\n", chan_name);
106 return -1;
107 }
108
109 if (!ctx->attestation) {
110 ast_log(LOG_ERROR, "Attestation cannot be NULL to add STIR/SHAKEN verification to "
111 "channel %s\n", chan_name);
112 return -1;
113 }
114
116 if (!stir_datastore) {
117 ast_log(LOG_ERROR, "Failed to allocate space for STIR/SHAKEN datastore for "
118 "channel %s\n", chan_name);
119 return -1;
120 }
121
123 if (!stir_datastore->identity) {
124 ast_log(LOG_ERROR, "Failed to allocate space for STIR/SHAKEN datastore "
125 "identity for channel %s\n", chan_name);
127 return -1;
128 }
129
132 ast_log(LOG_ERROR, "Failed to allocate space for STIR/SHAKEN datastore "
133 "attestation for channel %s\n", chan_name);
135 return -1;
136 }
137
139
141 if (!chan_datastore) {
142 ast_log(LOG_ERROR, "Failed to allocate space for datastore for channel "
143 "%s\n", chan_name);
145 return -1;
146 }
147
148 chan_datastore->data = stir_datastore;
149
151 ast_channel_datastore_add(ctx->chan, chan_datastore);
153
154 return 0;
155}
#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
#define ast_log
Definition: astobj2.c:42
const char * ast_channel_name(const struct ast_channel *chan)
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2354
#define ast_channel_lock(chan)
Definition: channel.h:2972
#define ast_channel_unlock(chan)
Definition: channel.h:2973
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
#define LOG_ERROR
static const struct ast_datastore_info stir_shaken_datastore_info
static void stir_datastore_free(struct stir_datastore *datastore)
Frees a stir_shaken_datastore structure.
#define NULL
Definition: resample.c:96
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
const ast_string_field attestation
Definition: verification.h:39
const ast_string_field identity_hdr
Definition: verification.h:39
struct ast_channel * chan
Definition: verification.h:41
enum ast_stir_shaken_vs_response_code failure_reason
Definition: verification.h:48
enum ast_stir_shaken_vs_response_code verify_result

References ast_calloc, ast_channel_datastore_add(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_datastore_alloc, ast_log, ast_strdup, stir_datastore::attestation, ast_stir_shaken_vs_ctx::attestation, ast_stir_shaken_vs_ctx::chan, ast_datastore::data, ast_stir_shaken_vs_ctx::failure_reason, stir_datastore::identity, ast_stir_shaken_vs_ctx::identity_hdr, LOG_ERROR, NULL, stir_datastore_free(), stir_shaken_datastore_info, and stir_datastore::verify_result.

Referenced by process_failure(), and stir_shaken_incoming_request().

◆ ast_stir_shaken_as_ctx_add_fingerprint()

enum ast_stir_shaken_as_response_code ast_stir_shaken_as_ctx_add_fingerprint ( struct ast_stir_shaken_as_ctx ctx,
const char *  alg,
const char *  fingerprint 
)

Add DTLS fingerprints to AS context.

Parameters
ctxAS context
algFingerprint algorithm ("sha-1" or "sha-256")
fingerprintFingerprint
Return values
AST_STIR_SHAKEN_AS_SUCCESSif successful
OtherAST_STIR_SHAKEN_AS errors.

Definition at line 206 of file attestation.c.

208{
209 char *compacted_fp = ast_alloca(strlen(fingerprint) + 1);
210 const char *f = fingerprint;
211 char *fp = compacted_fp;
212 char *combined;
213 int rc;
214 SCOPE_ENTER(4, "%s: Add fingerprint %s:%s\n", ctx ? ctx->tag : "",
215 alg, fingerprint);
216
217 if (!ctx || ast_strlen_zero(alg) || ast_strlen_zero(fingerprint)) {
219 "%s: Missing arguments\n", ctx->tag);
220 }
221
222 if (!ENUM_BOOL(ctx->etn->acfg_common.send_mky, send_mky)) {
224 "%s: Not needed\n", ctx->tag);
225 }
226
227 /* De-colonize */
228 while (*f != '\0') {
229 if (*f != ':') {
230 *fp++ = *f;
231 }
232 f++;
233 }
234 *fp = '\0';
235 rc = ast_asprintf(&combined, "%s:%s", alg, compacted_fp);
236 if (rc < 0) {
238 "%s: Can't allocate memory for comobined string\n", ctx->tag);
239 }
240
241 rc = AST_VECTOR_ADD_SORTED(&ctx->fingerprints, combined, strcasecmp);
242 if (rc < 0) {
244 "%s: Can't add entry to vector\n", ctx->tag);
245 }
246
248 "%s: Done\n", ctx->tag);
249}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ENUM_BOOL(__enum1, __field)
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
#define SCOPE_ENTER(level,...)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
struct tn_cfg * etn
Definition: attestation.h:32
const ast_string_field tag
Definition: attestation.h:29
struct ast_vector_string fingerprints
Definition: attestation.h:31
enum send_mky_enum send_mky
struct attestation_cfg_common acfg_common
#define AST_VECTOR_ADD_SORTED(vec, elem, cmp)
Add an element into a sorted vector.
Definition: vector.h:371

References tn_cfg::acfg_common, ast_alloca, ast_asprintf, AST_STIR_SHAKEN_AS_DISABLED, AST_STIR_SHAKEN_AS_INTERNAL_ERROR, AST_STIR_SHAKEN_AS_INVALID_ARGUMENTS, AST_STIR_SHAKEN_AS_SUCCESS, ast_strlen_zero(), AST_VECTOR_ADD_SORTED, ENUM_BOOL, ast_stir_shaken_as_ctx::etn, ast_stir_shaken_as_ctx::fingerprints, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, attestation_cfg_common::send_mky, and ast_stir_shaken_as_ctx::tag.

Referenced by add_fingerprints_if_present().

◆ ast_stir_shaken_as_ctx_create()

enum ast_stir_shaken_as_response_code ast_stir_shaken_as_ctx_create ( const char *  caller_id,
const char *  dest_tn,
struct ast_channel chan,
const char *  profile_name,
const char *  tag,
struct ast_stir_shaken_as_ctx **  ctxout 
)

Create Attestation Service Context.

Parameters
caller_idThe caller_id for the outgoing call
dest_tnCanonicalized destination tn
chanThe outgoing channel
profile_nameThe profile name on the endpoint May be NULL.
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_AS_SUCCESSif successful.
AST_STIR_SHAKEN_AS_DISABLEDif attestation is disabled by the endpoint itself, the profile or globally.
OtherAST_STIR_SHAKEN_AS errors.

Definition at line 66 of file attestation.c.

70{
72 RAII_VAR(struct profile_cfg *, eprofile, NULL, ao2_cleanup);
73 RAII_VAR(struct attestation_cfg *, as_cfg, NULL, ao2_cleanup);
74 RAII_VAR(struct tn_cfg *, etn, NULL, ao2_cleanup);
75 RAII_VAR(char *, canon_dest_tn , canonicalize_tn_alloc(dest_tn), ast_free);
76 RAII_VAR(char *, canon_orig_tn , canonicalize_tn_alloc(orig_tn), ast_free);
77
78 const char *t = S_OR(tag, S_COR(chan, ast_channel_name(chan), ""));
79 SCOPE_ENTER(3, "%s: Enter\n", t);
80
81 as_cfg = as_get_cfg();
82 if (as_cfg->global_disable) {
84 "%s: Globally disabled\n", t);
85 }
86
87 if (ast_strlen_zero(profile_name)) {
89 "%s: Disabled due to missing profile name\n", t);
90 }
91
92 eprofile = eprofile_get_cfg(profile_name);
93 if (!eprofile) {
95 LOG_ERROR, "%s: No profile for profile name '%s'. Call will continue\n", tag,
96 profile_name);
97 }
98
99 if (!PROFILE_ALLOW_ATTEST(eprofile)) {
101 "%s: Disabled by profile '%s'\n", t, profile_name);
102 }
103
104 if (ast_strlen_zero(tag)) {
106 LOG_ERROR, "%s: Must provide tag\n", t);
107 }
108
109 if (!canon_orig_tn) {
111 LOG_ERROR, "%s: Must provide caller_id/orig_tn\n", tag);
112 }
113
114 if (!canon_dest_tn) {
116 LOG_ERROR, "%s: Must provide dest_tn\n", tag);
117 }
118
119 if (!ctxout) {
121 LOG_ERROR, "%s: Must provide ctxout\n", tag);
122 }
123
124 etn = tn_get_etn(canon_orig_tn, eprofile);
125 if (!etn) {
127 "%s: No tn for orig_tn '%s'\n", tag, canon_orig_tn);
128 }
129
130 /* We don't need eprofile or as_cfg anymore so let's clean em up */
131 ao2_cleanup(as_cfg);
132 as_cfg = NULL;
133 ao2_cleanup(eprofile);
134 eprofile = NULL;
135
136
137 if (etn->acfg_common.attest_level == attest_level_NOT_SET) {
139 LOG_ERROR,
140 "'%s': No attest_level specified in tn, profile or attestation objects\n",
141 tag);
142 }
143
144 if (ast_strlen_zero(etn->acfg_common.public_cert_url)) {
146 LOG_ERROR, "%s: No public cert url in tn %s, profile or attestation objects\n",
147 tag, canon_orig_tn);
148 }
149
150 if (etn->acfg_common.raw_key_length == 0) {
152 LOG_ERROR, "%s: No private key in tn %s, profile or attestation objects\n",
153 canon_orig_tn, tag);
154 }
155
156 ctx = ao2_alloc_options(sizeof(*ctx), ctx_destructor,
158 if (!ctx) {
160 LOG_ERROR, "%s: Unable to allocate memory for ctx\n", tag);
161 }
162
163 if (ast_string_field_init(ctx, 1024) != 0) {
165 LOG_ERROR, "%s: Unable to allocate memory for ctx\n", tag);
166 }
167
168 if (ast_string_field_set(ctx, tag, tag) != 0) {
170 LOG_ERROR, "%s: Unable to allocate memory for ctx\n", tag);
171 }
172
173 if (ast_string_field_set(ctx, orig_tn, canon_orig_tn) != 0) {
175 LOG_ERROR, "%s: Unable to allocate memory for ctx\n", tag);
176 }
177
178 if (ast_string_field_set(ctx, dest_tn, canon_dest_tn)) {
180 LOG_ERROR, "%s: Unable to allocate memory for ctx\n", tag);
181 }
182
183 ctx->chan = chan;
184 ast_channel_ref(ctx->chan);
185
186 if (AST_VECTOR_INIT(&ctx->fingerprints, 1) != 0) {
188 LOG_ERROR, "%s: Unable to allocate memory for ctx\n", tag);
189 }
190
191 /* Transfer the references */
192 ctx->etn = etn;
193 etn = NULL;
194 *ctxout = ctx;
195 ctx = NULL;
196
198}
#define ast_free(a)
Definition: astmm.h:180
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
static void ctx_destructor(void *obj)
Definition: attestation.c:54
struct attestation_cfg * as_get_cfg(void)
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2997
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_ATTEST(__profile)
struct tn_cfg * tn_get_etn(const char *tn, struct profile_cfg *eprofile)
Definition: tn_config.c:111
#define SCOPE_EXIT_LOG_RTN_VALUE(__value, __log_level,...)
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#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.
TN configuration for stir/shaken.
#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
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113

References tn_cfg::acfg_common, AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_cleanup, as_get_cfg(), ast_channel_name(), ast_channel_ref, ast_free, AST_STIR_SHAKEN_AS_DISABLED, AST_STIR_SHAKEN_AS_INTERNAL_ERROR, AST_STIR_SHAKEN_AS_INVALID_ARGUMENTS, AST_STIR_SHAKEN_AS_MISSING_PARAMETERS, AST_STIR_SHAKEN_AS_NO_PRIVATE_KEY_AVAIL, AST_STIR_SHAKEN_AS_NO_PUBLIC_CERT_URL_AVAIL, AST_STIR_SHAKEN_AS_SUCCESS, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), AST_VECTOR_INIT, attestation_cfg_common::attest_level, canonicalize_tn_alloc(), ast_stir_shaken_as_ctx::chan, ctx_destructor(), ast_stir_shaken_as_ctx::dest_tn, eprofile_get_cfg(), ast_stir_shaken_as_ctx::etn, LOG_ERROR, NULL, ast_stir_shaken_as_ctx::orig_tn, PROFILE_ALLOW_ATTEST, attestation_cfg_common::public_cert_url, RAII_VAR, attestation_cfg_common::raw_key_length, S_COR, S_OR, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, ast_stir_shaken_as_ctx::tag, and tn_get_etn().

Referenced by stir_shaken_outgoing_request().

◆ ast_stir_shaken_as_ctx_wants_fingerprints()

int ast_stir_shaken_as_ctx_wants_fingerprints ( struct ast_stir_shaken_as_ctx ctx)

Indicates if the AS context needs DTLS fingerprints.

Parameters
ctxAS Context
Return values
0Not needed
1Needed

Definition at line 200 of file attestation.c.

201{
202 return ENUM_BOOL(ctx->etn->acfg_common.send_mky, send_mky);
203}

References tn_cfg::acfg_common, ENUM_BOOL, ast_stir_shaken_as_ctx::etn, and attestation_cfg_common::send_mky.

Referenced by add_fingerprints_if_present().

◆ ast_stir_shaken_attest()

enum ast_stir_shaken_as_response_code ast_stir_shaken_attest ( struct ast_stir_shaken_as_ctx ctx,
char **  header 
)

Attest and return Identity header value.

Parameters
ctxAS Context
headerPointer to buffer to receive the header value Must be freed with ast_free when done
Return values
AST_STIR_SHAKEN_AS_SUCCESSif successful
OtherAST_STIR_SHAKEN_AS errors.

Definition at line 364 of file attestation.c.

366{
367 RAII_VAR(jwt_t *, jwt, NULL, jwt_free);
368 jwt_alg_t alg;
369 char *encoded = NULL;
371 int rc = 0;
372 SCOPE_ENTER(3, "%s: Attestation: orig: %s dest: %s\n",
373 ctx ? ctx->tag : "NULL", ctx ? ctx->orig_tn : "NULL",
374 ctx ? ctx->dest_tn : "NULL");
375
376 if (!ctx) {
378 "%s: No context object!\n", "NULL");
379 }
380
381 if (header == NULL) {
383 LOG_ERROR, "%s: Header buffer was NULL\n", ctx->tag);
384 }
385
386 rc = jwt_new(&jwt);
387 if (rc != 0) {
389 LOG_ERROR, "%s: Cannot create JWT\n", ctx->tag);
390 }
391
392 /*
393 * All headers added need to be in alphabetical order!
394 */
395 alg = jwt_str_alg(STIR_SHAKEN_ENCRYPTION_ALGORITHM);
396 jwt_set_alg(jwt, alg, (const unsigned char *)ctx->etn->acfg_common.raw_key,
398 jwt_add_header(jwt, "ppt", STIR_SHAKEN_PPT);
399 jwt_add_header(jwt, "typ", STIR_SHAKEN_TYPE);
400 jwt_add_header(jwt, "x5u", ctx->etn->acfg_common.public_cert_url);
401
402 as_rc = pack_payload(ctx, jwt);
403 if (as_rc != AST_STIR_SHAKEN_AS_SUCCESS) {
405 LOG_ERROR, "%s: Cannot pack payload\n", ctx->tag);
406 }
407
408 encoded = jwt_encode_str(jwt);
409 if (!encoded) {
411 LOG_ERROR, "%s: Unable to sign/encode JWT\n", ctx->tag);
412 }
413
414 rc = ast_asprintf(header, "%s;info=<%s>;alg=%s;ppt=%s",
415 encoded, ctx->etn->acfg_common.public_cert_url, jwt_alg_str(alg),
417 ast_std_free(encoded);
418 if (rc < 0) {
420 LOG_ERROR, "%s: Unable to allocate memory for identity header\n",
421 ctx->tag);
422 }
423
425}
void ast_std_free(void *ptr)
Definition: astmm.c:1734
static enum ast_stir_shaken_as_response_code pack_payload(struct ast_stir_shaken_as_ctx *ctx, jwt_t *jwt)
Definition: attestation.c:290
ast_stir_shaken_as_response_code
#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
const ast_string_field dest_tn
Definition: attestation.h:29
const ast_string_field orig_tn
Definition: attestation.h:29
unsigned char * raw_key
const ast_string_field public_cert_url

References tn_cfg::acfg_common, ast_asprintf, ast_std_free(), AST_STIR_SHAKEN_AS_INTERNAL_ERROR, AST_STIR_SHAKEN_AS_INVALID_ARGUMENTS, AST_STIR_SHAKEN_AS_SIGN_ENCODE_FAILURE, AST_STIR_SHAKEN_AS_SUCCESS, AST_STIR_SHAKEN_VS_INTERNAL_ERROR, ast_stir_shaken_as_ctx::dest_tn, ast_stir_shaken_as_ctx::etn, LOG_ERROR, NULL, ast_stir_shaken_as_ctx::orig_tn, pack_payload(), attestation_cfg_common::public_cert_url, RAII_VAR, attestation_cfg_common::raw_key, attestation_cfg_common::raw_key_length, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, STIR_SHAKEN_ENCRYPTION_ALGORITHM, STIR_SHAKEN_PPT, STIR_SHAKEN_TYPE, and ast_stir_shaken_as_ctx::tag.

Referenced by stir_shaken_outgoing_request().

◆ 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 613 of file verification.c.

615{
616 return ast_string_field_set(ctx, date_hdr, date_hdr) == 0 ?
618}

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 605 of file verification.c.

607{
608 return ast_string_field_set(ctx, identity_hdr, identity_hdr) == 0 ?
610}

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 657 of file verification.c.

660{
662 RAII_VAR(struct profile_cfg *, profile, NULL, ao2_cleanup);
664 RAII_VAR(char *, canon_caller_id , canonicalize_tn_alloc(caller_id), ast_free);
665
666 const char *t = S_OR(tag, S_COR(chan, ast_channel_name(chan), ""));
667 SCOPE_ENTER(3, "%s: Enter\n", t);
668
669 vs = vs_get_cfg();
670 if (vs->global_disable) {
672 "%s: Globally disabled\n", t);
673 }
674
675 if (ast_strlen_zero(profile_name)) {
677 "%s: Disabled due to missing profile name\n", t);
678 }
679
680 profile = eprofile_get_cfg(profile_name);
681 if (!profile) {
683 LOG_ERROR, "%s: No profile for profile name '%s'. Call will continue\n", tag,
684 profile_name);
685 }
686
687 if (!PROFILE_ALLOW_VERIFY(profile)) {
689 "%s: Disabled by profile '%s'\n", t, profile_name);
690 }
691
692 if (ast_strlen_zero(tag)) {
694 LOG_ERROR, "%s: Must provide tag\n", t);
695 }
696
697 ctx = ao2_alloc_options(sizeof(*ctx), ctx_destructor,
699 if (!ctx) {
701 }
702 if (ast_string_field_init(ctx, 1024) != 0) {
704 }
705
706 if (ast_string_field_set(ctx, tag, tag) != 0) {
708 }
709
710 ctx->chan = chan;
711 if (ast_string_field_set(ctx, caller_id, canon_caller_id) != 0) {
713 }
714
715 /* Transfer references to ctx */
716 ctx->eprofile = profile;
717 profile = NULL;
718
719 ao2_ref(ctx, +1);
720 *ctxout = ctx;
722}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
struct verification_cfg * vs_get_cfg(void)
#define PROFILE_ALLOW_VERIFY(__profile)
static void ctx_destructor(void *obj)
Definition: verification.c:646

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 639 of file verification.c.

642{
643 ctx->failure_reason = vs_rc;
644}

References ast_stir_shaken_vs_ctx::failure_reason.

Referenced by process_failure().

◆ ast_stir_shaken_vs_get_caller_id()

const char * ast_stir_shaken_vs_get_caller_id ( struct ast_stir_shaken_vs_ctx ctx)

Get caller_id from context.

Parameters
ctxVS context
Return values
CallerID or NULL

Definition at line 633 of file verification.c.

635{
636 return ctx->caller_id;
637}
const ast_string_field caller_id
Definition: verification.h:39

References ast_stir_shaken_vs_ctx::caller_id.

Referenced by stir_shaken_incoming_request().

◆ 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 621 of file verification.c.

623{
625}
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 627 of file verification.c.

629{
631}
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 884 of file verification.c.

885{
886 RAII_VAR(char *, jwt_encoded, NULL, ast_free);
887 RAII_VAR(jwt_t *, jwt, NULL, jwt_free);
888 RAII_VAR(struct ast_json *, grants, NULL, ast_json_unref);
889 char *p = NULL;
890 char *grants_str = NULL;
891 const char *x5u;
892 const char *ppt_header = NULL;
893 const char *grant = NULL;
894 time_t now_s = time(NULL);
895 time_t iat;
896 struct ast_json *grant_obj = NULL;
897 int len;
898 int rc;
900 SCOPE_ENTER(3, "%s: Verifying\n", ctx ? ctx->tag : "NULL");
901
902 if (!ctx) {
904 "%s: No context object!\n", "NULL");
905 }
906
907 if (ast_strlen_zero(ctx->identity_hdr)) {
909 "%s: No identity header in ctx\n", ctx->tag);
910 }
911
912 p = strchr(ctx->identity_hdr, ';');
913 len = p - ctx->identity_hdr + 1;
914 jwt_encoded = ast_malloc(len);
915 if (!jwt_encoded) {
917 "%s: Failed to allocate memory for encoded jwt\n", ctx->tag);
918 }
919
920 memcpy(jwt_encoded, ctx->identity_hdr, len);
921 jwt_encoded[len - 1] = '\0';
922
923 jwt_decode(&jwt, jwt_encoded, NULL, 0);
924
925 ppt_header = jwt_get_header(jwt, "ppt");
926 if (!ppt_header || strcmp(ppt_header, STIR_SHAKEN_PPT)) {
929 }
930
931 vs_rc = check_date_header(ctx);
932 if (vs_rc != AST_STIR_SHAKEN_VS_SUCCESS) {
934 "%s: Date header verification failed\n", ctx->tag);
935 }
936
937 x5u = jwt_get_header(jwt, "x5u");
938 if (ast_strlen_zero(x5u)) {
940 "%s: No x5u in Identity header\n", ctx->tag);
941 }
942
943 rc = check_x5u_url(ctx, x5u);
944 if (rc != AST_STIR_SHAKEN_VS_SUCCESS) {
946 "%s: x5u URL verification failed\n", ctx->tag);
947 }
948
949 ast_trace(3, "%s: Decoded enough to get x5u: '%s'\n", ctx->tag, x5u);
950 if (ast_string_field_set(ctx, public_url, x5u) != 0) {
952 "%s: Failed to set public_url '%s'\n", ctx->tag, x5u);
953 }
954
955 iat = jwt_get_grant_int(jwt, "iat");
956 if (iat == 0) {
958 "%s: No 'iat' in Identity header\n", ctx->tag);
959 }
960 ast_trace(1, "date_hdr: %zu iat: %zu diff: %zu\n",
961 ctx->date_hdr_time, iat, ctx->date_hdr_time - iat);
962 if (iat + ctx->eprofile->vcfg_common.max_iat_age < now_s) {
964 "%s: iat %ld older than %u seconds\n", ctx->tag,
965 iat, ctx->eprofile->vcfg_common.max_iat_age);
966 }
967 ctx->validity_check_time = iat;
968
969 vs_rc = ctx_populate(ctx);
970 if (vs_rc != AST_STIR_SHAKEN_VS_SUCCESS) {
972 "%s: Unable to populate ctx\n", ctx->tag);
973 }
974
975 vs_rc = retrieve_verification_cert(ctx);
976 if (vs_rc != AST_STIR_SHAKEN_VS_SUCCESS) {
978 "%s: Could not get valid cert from '%s'\n", ctx->tag, ctx->public_url);
979 }
980
981 jwt_free(jwt);
982 jwt = NULL;
983
984 rc = jwt_decode(&jwt, jwt_encoded, ctx->raw_key, ctx->raw_key_len);
985 if (rc != 0) {
987 LOG_ERROR, "%s: Signature validation failed for '%s'\n",
988 ctx->tag, ctx->public_url);
989 }
990
991 ast_trace(1, "%s: Decoding succeeded\n", ctx->tag);
992
993 ppt_header = jwt_get_header(jwt, "alg");
994 if (!ppt_header || strcmp(ppt_header, STIR_SHAKEN_ENCRYPTION_ALGORITHM)) {
996 "%s: %s\n", ctx->tag,
998 }
999
1000 ppt_header = jwt_get_header(jwt, "ppt");
1001 if (!ppt_header || strcmp(ppt_header, STIR_SHAKEN_PPT)) {
1003 "%s: %s\n", ctx->tag,
1005 }
1006
1007 ppt_header = jwt_get_header(jwt, "typ");
1008 if (!ppt_header || strcmp(ppt_header, STIR_SHAKEN_TYPE)) {
1010 "%s: %s\n", ctx->tag,
1012 }
1013
1014 grants_str = jwt_get_grants_json(jwt, NULL);
1015 if (ast_strlen_zero(grants_str)) {
1017 "%s: %s\n", ctx->tag,
1019 }
1020 ast_trace(1, "grants: %s\n", grants_str);
1021 grants = ast_json_load_string(grants_str, NULL);
1022 ast_std_free(grants_str);
1023 if (!grants) {
1025 "%s: %s\n", ctx->tag,
1027 }
1028
1029 grant = ast_json_object_string_get(grants, "attest");
1030 if (ast_strlen_zero(grant)) {
1032 "%s: No 'attest' in Identity header\n", ctx->tag);
1033 }
1034 if (grant[0] < 'A' || grant[0] > 'C') {
1036 "%s: Invalid attest value '%s'\n", ctx->tag, grant);
1037 }
1038 ast_string_field_set(ctx, attestation, grant);
1039 ast_trace(1, "got attest: %s\n", grant);
1040
1041 grant_obj = ast_json_object_get(grants, "dest");
1042 if (!grant_obj) {
1044 "%s: No 'dest' in Identity header\n", ctx->tag);
1045 }
1046 if (TRACE_ATLEAST(3)) {
1047 char *otn = ast_json_dump_string(grant_obj);
1048 ast_trace(1, "got dest: %s\n", otn);
1049 ast_json_free(otn);
1050 }
1051
1052 grant_obj = ast_json_object_get(grants, "orig");
1053 if (!grant_obj) {
1055 "%s: No 'orig' in Identity header\n", ctx->tag);
1056 }
1057 if (TRACE_ATLEAST(3)) {
1058 char *otn = ast_json_dump_string(grant_obj);
1059 ast_trace(1, "got orig: %s\n", otn);
1060 ast_json_free(otn);
1061 }
1062 grant = ast_json_object_string_get(grant_obj, "tn");
1063 if (!grant) {
1065 "%s: No 'orig.tn' in Indentity header\n", ctx->tag);
1066 }
1067 ast_string_field_set(ctx, orig_tn, grant);
1068 if (strcmp(ctx->caller_id, ctx->orig_tn) != 0) {
1070 "%s: Mismatched cid '%s' and orig_tn '%s'\n", ctx->tag,
1071 ctx->caller_id, grant);
1072 }
1073
1074 grant = ast_json_object_string_get(grants, "origid");
1075 if (ast_strlen_zero(grant)) {
1077 "%s: No 'origid' in Identity header\n", ctx->tag);
1078 }
1079
1081 "%s: verification succeeded\n", ctx->tag);
1082}
#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
Abstract JSON element (object, array, string, int, ...).
const ast_string_field public_url
Definition: verification.h:39
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
static int check_x5u_url(struct ast_stir_shaken_vs_ctx *ctx, const char *x5u)
Definition: verification.c:826
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:90
static enum ast_stir_shaken_vs_response_code retrieve_verification_cert(struct ast_stir_shaken_vs_ctx *ctx)
Definition: verification.c:576
static enum ast_stir_shaken_vs_response_code check_date_header(struct ast_stir_shaken_vs_ctx *ctx)
Definition: verification.c:724
static enum ast_stir_shaken_vs_response_code ctx_populate(struct ast_stir_shaken_vs_ctx *ctx)
Definition: verification.c:548

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().