Asterisk - The Open Source Telephony Project GIT-master-f36a736
Macros | Enumerations | Functions | Variables
res_pjsip_stir_shaken.c File Reference
#include "asterisk.h"
#include "asterisk/callerid.h"
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_session.h"
#include "asterisk/module.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/res_stir_shaken.h"
Include dependency graph for res_pjsip_stir_shaken.c:

Go to the source code of this file.

Macros

#define _TRACE_PREFIX_   "pjss",__LINE__, ""
 
#define AST_BUILDOPT_SUM   ""
 
#define response_to_str(_code)
 
#define SIP_RESPONSE_CODE_BAD_IDENTITY_INFO_STR   "Bad Identity Info"
 
#define SIP_RESPONSE_CODE_INTERNAL_ERROR_STR   "Internal Error"
 
#define SIP_RESPONSE_CODE_INVALID_IDENTITY_HEADER_STR   "Invalid Identity Header"
 
#define SIP_RESPONSE_CODE_OK_STR   "OK"
 
#define SIP_RESPONSE_CODE_STALE_DATE_STR   "Stale Date"
 
#define SIP_RESPONSE_CODE_UNSUPPORTED_CREDENTIAL_STR   "Unsupported Credential"
 
#define SIP_RESPONSE_CODE_USE_IDENTITY_HEADER_STR   "Use Identity Header"
 
#define SIP_RESPONSE_CODE_USE_SUPPORTED_PASSPORT_FORMAT_STR   "Use Supported PASSporT Format"
 
#define translate_code(_vs_rc, _sip_rc)
 

Enumerations

enum  process_failure_rc { PROCESS_FAILURE_CONTINUE = 0 , PROCESS_FAILURE_REJECT , PROCESS_FAILURE_SYSTEM_FAILURE }
 
enum  sip_response_code {
  SIP_RESPONSE_CODE_OK = 200 , SIP_RESPONSE_CODE_STALE_DATE = 403 , SIP_RESPONSE_CODE_USE_IDENTITY_HEADER = 428 , SIP_RESPONSE_CODE_BAD_IDENTITY_INFO = 436 ,
  SIP_RESPONSE_CODE_UNSUPPORTED_CREDENTIAL = 437 , SIP_RESPONSE_CODE_INVALID_IDENTITY_HEADER = 438 , SIP_RESPONSE_CODE_USE_SUPPORTED_PASSPORT_FORMAT = 428 , SIP_RESPONSE_CODE_INTERNAL_ERROR = 500
}
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static void add_date_header (const struct ast_sip_session *session, pjsip_tx_data *tdata)
 
static void add_fingerprints_if_present (struct ast_sip_session *session, struct ast_stir_shaken_as_ctx *ctx)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static char * get_dest_tn (pjsip_tx_data *tdata, const char *tag)
 
static int load_module (void)
 
static enum process_failure_rc process_failure (struct ast_stir_shaken_vs_ctx *ctx, const char *caller_id, struct ast_sip_session *session, pjsip_rx_data *rdata, enum ast_stir_shaken_vs_response_code vs_rc)
 
static void reject_incoming_call (struct ast_sip_session *session, enum sip_response_code response_code)
 
static const char * sip_response_code_to_str (enum sip_response_code code)
 
static int stir_shaken_incoming_request (struct ast_sip_session *session, pjsip_rx_data *rdata)
 
static void stir_shaken_outgoing_request (struct ast_sip_session *session, pjsip_tx_data *tdata)
 
static int unload_module (void)
 
static enum sip_response_code vs_code_to_sip_code (enum ast_stir_shaken_vs_response_code vs_rc)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "PJSIP STIR/SHAKEN Module for Asterisk" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .requires = "res_pjsip,res_pjsip_session,res_stir_shaken", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const pj_str_t date_hdr_str = { "Date", 4 }
 
static const pj_str_t identity_hdr_str = { "Identity", 8 }
 
static struct ast_sip_session_supplement stir_shaken_supplement
 

Macro Definition Documentation

◆ _TRACE_PREFIX_

#define _TRACE_PREFIX_   "pjss",__LINE__, ""

Definition at line 29 of file res_pjsip_stir_shaken.c.

◆ AST_BUILDOPT_SUM

#define AST_BUILDOPT_SUM   ""

Definition at line 492 of file res_pjsip_stir_shaken.c.

◆ response_to_str

#define response_to_str (   _code)
Value:
case _code: \
return _code ## _STR;

Definition at line 64 of file res_pjsip_stir_shaken.c.

◆ SIP_RESPONSE_CODE_BAD_IDENTITY_INFO_STR

#define SIP_RESPONSE_CODE_BAD_IDENTITY_INFO_STR   "Bad Identity Info"

Definition at line 59 of file res_pjsip_stir_shaken.c.

◆ SIP_RESPONSE_CODE_INTERNAL_ERROR_STR

#define SIP_RESPONSE_CODE_INTERNAL_ERROR_STR   "Internal Error"

Definition at line 62 of file res_pjsip_stir_shaken.c.

◆ SIP_RESPONSE_CODE_INVALID_IDENTITY_HEADER_STR

#define SIP_RESPONSE_CODE_INVALID_IDENTITY_HEADER_STR   "Invalid Identity Header"

Definition at line 61 of file res_pjsip_stir_shaken.c.

◆ SIP_RESPONSE_CODE_OK_STR

#define SIP_RESPONSE_CODE_OK_STR   "OK"

Definition at line 54 of file res_pjsip_stir_shaken.c.

◆ SIP_RESPONSE_CODE_STALE_DATE_STR

#define SIP_RESPONSE_CODE_STALE_DATE_STR   "Stale Date"

Definition at line 56 of file res_pjsip_stir_shaken.c.

◆ SIP_RESPONSE_CODE_UNSUPPORTED_CREDENTIAL_STR

#define SIP_RESPONSE_CODE_UNSUPPORTED_CREDENTIAL_STR   "Unsupported Credential"

Definition at line 60 of file res_pjsip_stir_shaken.c.

◆ SIP_RESPONSE_CODE_USE_IDENTITY_HEADER_STR

#define SIP_RESPONSE_CODE_USE_IDENTITY_HEADER_STR   "Use Identity Header"

Definition at line 57 of file res_pjsip_stir_shaken.c.

◆ SIP_RESPONSE_CODE_USE_SUPPORTED_PASSPORT_FORMAT_STR

#define SIP_RESPONSE_CODE_USE_SUPPORTED_PASSPORT_FORMAT_STR   "Use Supported PASSporT Format"

Definition at line 58 of file res_pjsip_stir_shaken.c.

◆ translate_code

#define translate_code (   _vs_rc,
  _sip_rc 
)
Value:
case AST_STIR_SHAKEN_VS_ ## _vs_rc: \
return SIP_RESPONSE_CODE_ ## _sip_rc;

Definition at line 83 of file res_pjsip_stir_shaken.c.

Enumeration Type Documentation

◆ process_failure_rc

Enumerator
PROCESS_FAILURE_CONTINUE 
PROCESS_FAILURE_REJECT 
PROCESS_FAILURE_SYSTEM_FAILURE 

Definition at line 136 of file res_pjsip_stir_shaken.c.

136 {
140};
@ PROCESS_FAILURE_SYSTEM_FAILURE
@ PROCESS_FAILURE_CONTINUE
@ PROCESS_FAILURE_REJECT

◆ sip_response_code

Enumerator
SIP_RESPONSE_CODE_OK 
SIP_RESPONSE_CODE_STALE_DATE 
SIP_RESPONSE_CODE_USE_IDENTITY_HEADER 
SIP_RESPONSE_CODE_BAD_IDENTITY_INFO 
SIP_RESPONSE_CODE_UNSUPPORTED_CREDENTIAL 
SIP_RESPONSE_CODE_INVALID_IDENTITY_HEADER 
SIP_RESPONSE_CODE_USE_SUPPORTED_PASSPORT_FORMAT 
SIP_RESPONSE_CODE_INTERNAL_ERROR 

Definition at line 43 of file res_pjsip_stir_shaken.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 500 of file res_pjsip_stir_shaken.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 500 of file res_pjsip_stir_shaken.c.

◆ add_date_header()

static void add_date_header ( const struct ast_sip_session session,
pjsip_tx_data *  tdata 
)
static

Definition at line 368 of file res_pjsip_stir_shaken.c.

369{
370 pjsip_fromto_hdr *old_date;
371 const char *session_name = ast_sip_session_get_name(session);
372 SCOPE_ENTER(1, "%s: Enter\n", session_name);
373
374 old_date = pjsip_msg_find_hdr_by_name(tdata->msg, &date_hdr_str, NULL);
375 if (old_date) {
376 SCOPE_EXIT_RTN("Found existing Date header, no need to add one\n");
377 }
378
380 SCOPE_EXIT_RTN("Done\n");
381}
static struct ast_mansession session
#define SCOPE_EXIT_RTN(...)
#define SCOPE_ENTER(level,...)
void ast_sip_add_date_header(pjsip_tx_data *tdata)
Adds a Date header to the tdata, formatted like: Date: Wed, 01 Jan 2021 14:53:01 GMT.
Definition: res_pjsip.c:90
const char * ast_sip_session_get_name(const struct ast_sip_session *session)
Get the channel or endpoint name associated with the session.
static const pj_str_t date_hdr_str
#define NULL
Definition: resample.c:96

References ast_sip_add_date_header(), ast_sip_session_get_name(), date_hdr_str, NULL, SCOPE_ENTER, SCOPE_EXIT_RTN, and session.

Referenced by stir_shaken_outgoing_request().

◆ add_fingerprints_if_present()

static void add_fingerprints_if_present ( struct ast_sip_session session,
struct ast_stir_shaken_as_ctx ctx 
)
static

Definition at line 304 of file res_pjsip_stir_shaken.c.

306{
307 struct ast_sip_session_media_state *ms = session->pending_media_state;
308 struct ast_sip_session_media *m = NULL;
309 struct ast_rtp_engine_dtls *d = NULL;
310 enum ast_rtp_dtls_hash h;
311 int i;
312 const char *tag = ast_sip_session_get_name(session);
313 size_t count = AST_VECTOR_SIZE(&ms->sessions);
314 SCOPE_ENTER(4, "%s: Check %zu media sessions for fingerprints\n",
315 tag, count);
316
318 SCOPE_EXIT_RTN("%s: Fingerprints not needed\n", tag);
319 }
320
321 for (i = 0; i < count; i++) {
322 const char *f;
323
324 m = AST_VECTOR_GET(&ms->sessions, i);
325 if (!m|| !m->rtp) {
326 ast_trace(1, "Session: %d: No session or rtp instance\n", i);
327 continue;
328 }
330 h = d->get_fingerprint_hash(m->rtp);
331 f = d->get_fingerprint(m->rtp);
332
334 h == AST_RTP_DTLS_HASH_SHA256 ? "sha-256" : "sha-1", f);
335 }
336 SCOPE_EXIT_RTN("%s: Done\n", tag);
337}
#define ast_trace(level,...)
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.
Definition: attestation.c:206
int ast_stir_shaken_as_ctx_wants_fingerprints(struct ast_stir_shaken_as_ctx *ctx)
Indicates if the AS context needs DTLS fingerprints.
Definition: attestation.c:200
ast_rtp_dtls_hash
DTLS fingerprint hashes.
Definition: rtp_engine.h:578
@ AST_RTP_DTLS_HASH_SHA256
Definition: rtp_engine.h:579
struct ast_rtp_engine_dtls * ast_rtp_instance_get_dtls(struct ast_rtp_instance *instance)
Obtain a pointer to the DTLS support present on an RTP instance.
Definition: rtp_engine.c:3211
Structure that represents the optional DTLS SRTP support within an RTP engine.
Definition: rtp_engine.h:621
Structure which contains media state information (streams, sessions)
struct ast_sip_session_media_state::@263 sessions
Mapping of stream to media sessions.
A structure containing SIP session media information.
struct ast_rtp_instance * rtp
RTP instance itself.
static struct test_val d
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680

References AST_RTP_DTLS_HASH_SHA256, ast_rtp_instance_get_dtls(), ast_sip_session_get_name(), ast_stir_shaken_as_ctx_add_fingerprint(), ast_stir_shaken_as_ctx_wants_fingerprints(), ast_trace, AST_VECTOR_GET, AST_VECTOR_SIZE, d, NULL, ast_sip_session_media::rtp, SCOPE_ENTER, SCOPE_EXIT_RTN, session, and ast_sip_session_media_state::sessions.

Referenced by stir_shaken_outgoing_request().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 500 of file res_pjsip_stir_shaken.c.

◆ get_dest_tn()

static char * get_dest_tn ( pjsip_tx_data *  tdata,
const char *  tag 
)
static

Definition at line 339 of file res_pjsip_stir_shaken.c.

340{
341 pjsip_fromto_hdr *to;
342 pjsip_sip_uri *uri;
343 char *dest_tn = NULL;
344 SCOPE_ENTER(4, "%s: Enter\n", tag);
345
346 to = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_TO, NULL);
347 if (!to) {
348 SCOPE_EXIT_RTN_VALUE(NULL, "%s: Failed to find To header\n", tag);
349 }
350
351 uri = pjsip_uri_get_uri(to->uri);
352 if (!uri) {
354 "%s: Failed to retrieve URI from To header\n", tag);
355 }
356
357 dest_tn = ast_malloc(uri->user.slen + 1);
358 if (!dest_tn) {
360 "%s: Failed to allocate memory for dest_tn\n", tag);
361 }
362
363 ast_copy_pj_str(dest_tn, &uri->user, uri->user.slen + 1);
364
365 SCOPE_EXIT_RTN_VALUE(dest_tn, "%s: Done\n", tag);
366}
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition: res_pjsip.c:2201

References ast_copy_pj_str(), ast_malloc, NULL, SCOPE_ENTER, and SCOPE_EXIT_RTN_VALUE.

Referenced by stir_shaken_outgoing_request().

◆ load_module()

static int load_module ( void  )
static

Definition at line 485 of file res_pjsip_stir_shaken.c.

486{
489}
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
#define ast_sip_session_register_supplement(supplement)
static struct ast_sip_session_supplement stir_shaken_supplement

References AST_MODULE_LOAD_SUCCESS, ast_sip_session_register_supplement, and stir_shaken_supplement.

◆ process_failure()

static enum process_failure_rc process_failure ( struct ast_stir_shaken_vs_ctx ctx,
const char *  caller_id,
struct ast_sip_session session,
pjsip_rx_data *  rdata,
enum ast_stir_shaken_vs_response_code  vs_rc 
)
static

Definition at line 149 of file res_pjsip_stir_shaken.c.

152{
153 enum sip_response_code response_code = vs_code_to_sip_code(vs_rc);
154 pj_str_t response_str;
155 const char *response_string =
156 sip_response_code_to_str(response_code);
157 enum stir_shaken_failure_action_enum failure_action =
159 const char *tag = ast_sip_session_get_name(session);
160 SCOPE_ENTER(1, "%s: FA: %d RC: %d\n", tag,
161 failure_action, response_code);
162
163 pj_cstr(&response_str, response_string);
164
165 if (failure_action == stir_shaken_failure_action_REJECT_REQUEST) {
166 reject_incoming_call(session, response_code);
168 "%s: Rejecting request and terminating session\n",
169 tag);
170 }
171
174
178 response_code, response_str.ptr);
179 if (rc != 0) {
181 "%s: Failed to add Reason header\n", tag);
182 }
184 "%s: Attaching reason code to session\n", tag);
185 }
187 "%s: Continuing\n", tag);
188}
int ast_sip_session_add_reason_header(struct ast_sip_session *session, const char *protocol, int code, const char *text)
Adds a Reason header in the next reponse to an incoming INVITE.
static void reject_incoming_call(struct ast_sip_session *session, enum sip_response_code response_code)
static enum sip_response_code vs_code_to_sip_code(enum ast_stir_shaken_vs_response_code vs_rc)
sip_response_code
static const char * sip_response_code_to_str(enum sip_response_code code)
int ast_stir_shaken_add_result_to_channel(struct ast_stir_shaken_vs_ctx *ctx)
Add a STIR/SHAKEN verification result to a channel.
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.
Definition: verification.c:620
int ast_stir_shaken_vs_get_use_rfc9410_responses(struct ast_stir_shaken_vs_ctx *ctx)
Get use_rfc9410_responses from context.
Definition: verification.c:626
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.
Definition: verification.c:632
stir_shaken_failure_action_enum
@ stir_shaken_failure_action_CONTINUE_RETURN_REASON
@ stir_shaken_failure_action_REJECT_REQUEST

References ast_sip_session_add_reason_header(), ast_sip_session_get_name(), ast_stir_shaken_add_result_to_channel(), ast_stir_shaken_vs_ctx_set_response_code(), ast_stir_shaken_vs_get_failure_action(), ast_stir_shaken_vs_get_use_rfc9410_responses(), PROCESS_FAILURE_CONTINUE, PROCESS_FAILURE_REJECT, PROCESS_FAILURE_SYSTEM_FAILURE, reject_incoming_call(), SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, session, sip_response_code_to_str(), stir_shaken_failure_action_CONTINUE_RETURN_REASON, stir_shaken_failure_action_REJECT_REQUEST, and vs_code_to_sip_code().

Referenced by stir_shaken_incoming_request().

◆ reject_incoming_call()

static void reject_incoming_call ( struct ast_sip_session session,
enum sip_response_code  response_code 
)
static

Definition at line 142 of file res_pjsip_stir_shaken.c.

144{
145 ast_sip_session_terminate(session, response_code);
146 ast_hangup(session->channel);
147}
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2560
void ast_sip_session_terminate(struct ast_sip_session *session, int response)
Terminate a session and, if possible, send the provided response code.

References ast_hangup(), ast_sip_session_terminate(), and session.

Referenced by process_failure(), and stir_shaken_incoming_request().

◆ sip_response_code_to_str()

static const char * sip_response_code_to_str ( enum sip_response_code  code)
static

◆ stir_shaken_incoming_request()

static int stir_shaken_incoming_request ( struct ast_sip_session session,
pjsip_rx_data *  rdata 
)
static

Definition at line 200 of file res_pjsip_stir_shaken.c.

201{
203 RAII_VAR(char *, header, NULL, ast_free);
204 RAII_VAR(char *, payload, NULL, ast_free);
205 char *identity_hdr_val;
206 char *date_hdr_val;
207 char *caller_id = session->id.number.str;
208 const char *session_name = ast_sip_session_get_name(session);
209 struct ast_channel *chan = session->channel;
211 enum process_failure_rc p_rc;
212 SCOPE_ENTER(1, "%s: Enter\n", session_name);
213
214 if (!session) {
215 SCOPE_EXIT_LOG_RTN_VALUE(1, LOG_ERROR, "No session\n");
216 }
217 if (!session->channel) {
218 SCOPE_EXIT_LOG_RTN_VALUE(1, LOG_ERROR, "%s: No channel\n", session_name);
219 }
220 if (!rdata) {
221 SCOPE_EXIT_LOG_RTN_VALUE(1, LOG_ERROR, "%s: No rdata\n", session_name);
222 }
223
224 /* Check if this is a reinvite. If it is, we don't need to do anything */
225 if (rdata->msg_info.to->tag.slen) {
226 SCOPE_EXIT_RTN_VALUE(0, "%s: Reinvite. No action needed\n", session_name);
227 }
228
229 /*
230 * Shortcut: If there's no callerid or profile name,
231 * just bail now.
232 */
233 if (ast_strlen_zero(caller_id)
234 || ast_strlen_zero(session->endpoint->stir_shaken_profile)) {
235 SCOPE_EXIT_RTN_VALUE(0, "%s: No callerid or profile name. No action needed\n", session_name);
236 }
237
238 vs_rc = ast_stir_shaken_vs_ctx_create(caller_id, chan,
239 session->endpoint->stir_shaken_profile,
240 session_name, &ctx);
241 if (vs_rc == AST_STIR_SHAKEN_VS_DISABLED) {
242 SCOPE_EXIT_RTN_VALUE(0, "%s: VS Disabled\n", session_name);
243 } else if (vs_rc != AST_STIR_SHAKEN_VS_SUCCESS) {
245 SCOPE_EXIT_RTN_VALUE(1, "%s: Unable to create context. Call terminated\n",
246 session_name);
247 }
248
249 identity_hdr_val = ast_sip_rdata_get_header_value(rdata, identity_hdr_str);
250 if (ast_strlen_zero(identity_hdr_val)) {
251 p_rc = process_failure(ctx, caller_id, session, rdata,
253 if (p_rc == PROCESS_FAILURE_CONTINUE) {
254 SCOPE_EXIT_RTN_VALUE(0, "%s: No Identity header found. Call continuing\n",
255 session_name);
256 }
257 SCOPE_EXIT_LOG_RTN_VALUE(1, LOG_ERROR, "%s: No Identity header found. Call terminated\n",
258 session_name);
259 }
260
261 vs_rc = ast_stir_shaken_vs_ctx_add_identity_hdr(ctx, identity_hdr_val);
262 if (vs_rc != AST_STIR_SHAKEN_VS_SUCCESS) {
264 SCOPE_EXIT_LOG_RTN_VALUE(1, LOG_ERROR, "%s: Unable to add Identity header. Call terminated.\n",
265 session_name);
266 }
267
268 date_hdr_val = ast_sip_rdata_get_header_value(rdata, date_hdr_str);
269 if (ast_strlen_zero(date_hdr_val)) {
270 p_rc = process_failure(ctx, caller_id, session, rdata,
272 if (p_rc == PROCESS_FAILURE_CONTINUE) {
273 SCOPE_EXIT_RTN_VALUE(0, "%s: No Date header found. Call continuing\n",
274 session_name);
275 }
276 SCOPE_EXIT_LOG_RTN_VALUE(1, LOG_ERROR, "%s: No Date header found. Call terminated\n",
277 session_name);
278 }
279
280 ast_stir_shaken_vs_ctx_add_date_hdr(ctx, date_hdr_val);
281 if (vs_rc != AST_STIR_SHAKEN_VS_SUCCESS) {
283 SCOPE_EXIT_LOG_RTN_VALUE(1, LOG_ERROR, "%s: Unable to add Date header. Call terminated.\n",
284 session_name);
285 }
286
287 vs_rc = ast_stir_shaken_vs_verify(ctx);
288 if (vs_rc != AST_STIR_SHAKEN_VS_SUCCESS) {
289 p_rc = process_failure(ctx, caller_id, session, rdata, vs_rc);
290 if (p_rc == PROCESS_FAILURE_CONTINUE) {
291 SCOPE_EXIT_RTN_VALUE(0, "%s: Verification failed. Call continuing\n",
292 session_name);
293 }
294 SCOPE_EXIT_LOG_RTN_VALUE(1, LOG_ERROR, "%s: Verification failed. Call terminated\n",
295 session_name);
296
297 }
298
300
301 SCOPE_EXIT_RTN_VALUE(0, "Passed\n");
302}
#define ast_free(a)
Definition: astmm.h:180
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define SCOPE_EXIT_LOG_RTN_VALUE(__value, __log_level,...)
#define LOG_ERROR
char * ast_sip_rdata_get_header_value(pjsip_rx_data *rdata, const pj_str_t str)
Get a specific header value from rdata.
Definition: res_pjsip.c:345
process_failure_rc
static const pj_str_t identity_hdr_str
static enum process_failure_rc process_failure(struct ast_stir_shaken_vs_ctx *ctx, const char *caller_id, struct ast_sip_session *session, pjsip_rx_data *rdata, enum ast_stir_shaken_vs_response_code vs_rc)
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.
Definition: verification.c:612
enum ast_stir_shaken_vs_response_code ast_stir_shaken_vs_verify(struct ast_stir_shaken_vs_ctx *ctx)
Perform incoming call verification.
Definition: verification.c:882
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.
Definition: verification.c:650
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.
Definition: verification.c:604
ast_stir_shaken_vs_response_code
@ AST_STIR_SHAKEN_VS_NO_DATE_HDR
@ AST_STIR_SHAKEN_VS_SUCCESS
@ AST_STIR_SHAKEN_VS_NO_IDENTITY_HDR
@ AST_STIR_SHAKEN_VS_DISABLED
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Main Channel structure associated with a channel.
#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_free, ast_sip_rdata_get_header_value(), ast_sip_session_get_name(), ast_stir_shaken_add_result_to_channel(), ast_stir_shaken_vs_ctx_add_date_hdr(), ast_stir_shaken_vs_ctx_add_identity_hdr(), ast_stir_shaken_vs_ctx_create(), AST_STIR_SHAKEN_VS_DISABLED, AST_STIR_SHAKEN_VS_NO_DATE_HDR, AST_STIR_SHAKEN_VS_NO_IDENTITY_HDR, AST_STIR_SHAKEN_VS_SUCCESS, ast_stir_shaken_vs_verify(), ast_strlen_zero(), date_hdr_str, identity_hdr_str, LOG_ERROR, NULL, process_failure(), PROCESS_FAILURE_CONTINUE, RAII_VAR, reject_incoming_call(), SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, and session.

◆ stir_shaken_outgoing_request()

static void stir_shaken_outgoing_request ( struct ast_sip_session session,
pjsip_tx_data *  tdata 
)
static

Definition at line 383 of file res_pjsip_stir_shaken.c.

385{
386 struct ast_party_id effective_id;
387 struct ast_party_id connected_id;
388 pjsip_generic_string_hdr *old_identity;
389 pjsip_generic_string_hdr *identity_hdr;
390 pj_str_t identity_val;
391 char *dest_tn;
392 char *identity_str;
393 struct ast_stir_shaken_as_ctx *ctx = NULL;
395 const char *session_name = ast_sip_session_get_name(session);
396 SCOPE_ENTER(1, "%s: Enter\n", session_name);
397
398 if (!session) {
399 SCOPE_EXIT_LOG_RTN(LOG_ERROR, "No session\n");
400 }
401 if (!session->channel) {
402 SCOPE_EXIT_LOG_RTN(LOG_ERROR, "%s: No channel\n", session_name);
403 }
404 if (!tdata) {
405 SCOPE_EXIT_LOG_RTN(LOG_ERROR, "%s: No tdata\n", session_name);
406 }
407
408 old_identity = pjsip_msg_find_hdr_by_name(tdata->msg, &identity_hdr_str, NULL);
409 if (old_identity) {
410 SCOPE_EXIT_RTN("Found an existing Identity header\n");
411 }
412
413 dest_tn = get_dest_tn(tdata, session_name);
414 if (!dest_tn) {
415 SCOPE_EXIT_LOG_RTN(LOG_ERROR, "%s: Unable to find destination tn\n",
416 session_name);
417 }
418
419 ast_party_id_init(&connected_id);
420 ast_channel_lock(session->channel);
421 effective_id = ast_channel_connected_effective_id(session->channel);
422 ast_party_id_copy(&connected_id, &effective_id);
423 ast_channel_unlock(session->channel);
424
425 if (!ast_sip_can_present_connected_id(session, &connected_id)) {
427 ast_party_id_free(&connected_id);
428 SCOPE_EXIT_RTN("Unable to get caller id\n");
429 }
430
431 as_rc = ast_stir_shaken_as_ctx_create(connected_id.number.str,
432 dest_tn, session->channel,
433 session->endpoint->stir_shaken_profile,
434 session_name, &ctx);
435
437 ast_party_id_free(&connected_id);
438
439 if (as_rc == AST_STIR_SHAKEN_AS_DISABLED) {
440 SCOPE_EXIT_RTN("%s: AS Disabled\n", session_name);
441 } else if (as_rc != AST_STIR_SHAKEN_AS_SUCCESS) {
442 SCOPE_EXIT_RTN("%s: Unable to create context\n",
443 session_name);
444 }
445
446 add_date_header(session, tdata);
448
449 as_rc = ast_stir_shaken_attest(ctx, &identity_str);
450 if (as_rc != AST_STIR_SHAKEN_AS_SUCCESS) {
451 ao2_cleanup(ctx);
453 "%s: Failed to create attestation\n", session_name);
454 }
455
456 ast_trace(1, "%s: Identity header: %s\n", session_name, identity_str);
457 identity_val = pj_str(identity_str);
458 identity_hdr = pjsip_generic_string_hdr_create(tdata->pool, &identity_hdr_str, &identity_val);
459 ast_free(identity_str);
460 if (!identity_hdr) {
461 ao2_cleanup(ctx);
463 "%s: Unable to create Identity header\n", session_name);
464 }
465
466 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)identity_hdr);
467
468 ao2_cleanup(ctx);
469 SCOPE_EXIT_RTN("Done\n");
470}
void ast_party_id_init(struct ast_party_id *init)
Initialize the given party id structure.
Definition: channel.c:1776
#define ast_channel_lock(chan)
Definition: channel.h:2968
void ast_party_id_free(struct ast_party_id *doomed)
Destroy the party id contents.
Definition: channel.c:1830
void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_id *src)
Copy the source party id information to the destination party id.
Definition: channel.c:1784
struct ast_party_id ast_channel_connected_effective_id(struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2969
#define SCOPE_EXIT_LOG(__log_level,...)
#define SCOPE_EXIT_LOG_RTN(__log_level,...)
int ast_sip_can_present_connected_id(const struct ast_sip_session *session, const struct ast_party_id *id)
Determines if the Connected Line info can be presented for this session.
static void add_date_header(const struct ast_sip_session *session, pjsip_tx_data *tdata)
static char * get_dest_tn(pjsip_tx_data *tdata, const char *tag)
static void add_fingerprints_if_present(struct ast_sip_session *session, struct ast_stir_shaken_as_ctx *ctx)
ast_stir_shaken_as_response_code
@ AST_STIR_SHAKEN_AS_DISABLED
@ AST_STIR_SHAKEN_AS_SUCCESS
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.
Definition: attestation.c:66
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.
Definition: attestation.c:364
Information needed to identify an endpoint in a call.
Definition: channel.h:340
const ast_string_field dest_tn
Definition: attestation.h:29

References add_date_header(), add_fingerprints_if_present(), ao2_cleanup, ast_channel_connected_effective_id(), ast_channel_lock, ast_channel_unlock, ast_free, ast_party_id_copy(), ast_party_id_free(), ast_party_id_init(), ast_sip_can_present_connected_id(), ast_sip_session_get_name(), ast_stir_shaken_as_ctx_create(), AST_STIR_SHAKEN_AS_DISABLED, AST_STIR_SHAKEN_AS_SUCCESS, ast_stir_shaken_attest(), ast_trace, ast_stir_shaken_as_ctx::dest_tn, get_dest_tn(), identity_hdr_str, LOG_ERROR, NULL, ast_party_id::number, SCOPE_ENTER, SCOPE_EXIT_LOG, SCOPE_EXIT_LOG_RTN, SCOPE_EXIT_RTN, session, and ast_party_number::str.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 479 of file res_pjsip_stir_shaken.c.

480{
482 return 0;
483}
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
Definition: pjsip_session.c:63

References ast_sip_session_unregister_supplement(), and stir_shaken_supplement.

◆ vs_code_to_sip_code()

static enum sip_response_code vs_code_to_sip_code ( enum ast_stir_shaken_vs_response_code  vs_rc)
static

Definition at line 87 of file res_pjsip_stir_shaken.c.

89{
90 /*
91 * We want to use a switch/case statement here because
92 * it'll spit out an error if VS codes are added to the
93 * enum but aren't present here.
94 */
95 switch (vs_rc) {
97 translate_code(DISABLED, OK)
98 translate_code(INVALID_ARGUMENTS, INTERNAL_ERROR)
99 translate_code(INTERNAL_ERROR, INTERNAL_ERROR)
100 translate_code(NO_IDENTITY_HDR, USE_IDENTITY_HEADER)
101 translate_code(NO_DATE_HDR, STALE_DATE)
102 translate_code(DATE_HDR_PARSE_FAILURE, STALE_DATE)
103 translate_code(DATE_HDR_EXPIRED, STALE_DATE)
104 translate_code(NO_JWT_HDR, INVALID_IDENTITY_HEADER)
105 translate_code(INVALID_OR_NO_X5U, INVALID_IDENTITY_HEADER)
106 translate_code(CERT_CACHE_MISS, INVALID_IDENTITY_HEADER)
107 translate_code(CERT_CACHE_INVALID, INVALID_IDENTITY_HEADER)
108 translate_code(CERT_CACHE_EXPIRED, INVALID_IDENTITY_HEADER)
109 translate_code(CERT_RETRIEVAL_FAILURE, BAD_IDENTITY_INFO)
110 translate_code(CERT_CONTENTS_INVALID, UNSUPPORTED_CREDENTIAL)
111 translate_code(CERT_NOT_TRUSTED, UNSUPPORTED_CREDENTIAL)
112 translate_code(CERT_DATE_INVALID, UNSUPPORTED_CREDENTIAL)
113 translate_code(CERT_NO_TN_AUTH_EXT, UNSUPPORTED_CREDENTIAL)
114 translate_code(CERT_NO_SPC_IN_TN_AUTH_EXT, UNSUPPORTED_CREDENTIAL)
115 translate_code(NO_RAW_KEY, UNSUPPORTED_CREDENTIAL)
116 translate_code(SIGNATURE_VALIDATION, INVALID_IDENTITY_HEADER)
117 translate_code(NO_IAT, INVALID_IDENTITY_HEADER)
118 translate_code(IAT_EXPIRED, STALE_DATE)
119 translate_code(INVALID_OR_NO_PPT, INVALID_IDENTITY_HEADER)
120 translate_code(INVALID_OR_NO_ALG, INVALID_IDENTITY_HEADER)
121 translate_code(INVALID_OR_NO_TYP, INVALID_IDENTITY_HEADER)
122 translate_code(INVALID_OR_NO_ATTEST, INVALID_IDENTITY_HEADER)
123 translate_code(NO_ORIGID, INVALID_IDENTITY_HEADER)
124 translate_code(NO_ORIG_TN, INVALID_IDENTITY_HEADER)
125 translate_code(NO_DEST_TN, INVALID_IDENTITY_HEADER)
126 translate_code(INVALID_HEADER, INVALID_IDENTITY_HEADER)
127 translate_code(INVALID_GRANT, INVALID_IDENTITY_HEADER)
128 translate_code(INVALID_OR_NO_GRANTS, INVALID_IDENTITY_HEADER)
129 translate_code(CID_ORIG_TN_MISMATCH, INVALID_IDENTITY_HEADER)
130 translate_code(RESPONSE_CODE_MAX, INVALID_IDENTITY_HEADER)
131 }
132
133 return 500;
134}
@ SUCCESS
#define translate_code(_vs_rc, _sip_rc)

References SUCCESS, and translate_code.

Referenced by process_failure().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "PJSIP STIR/SHAKEN Module for Asterisk" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .requires = "res_pjsip,res_pjsip_session,res_stir_shaken", }
static

Definition at line 500 of file res_pjsip_stir_shaken.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 500 of file res_pjsip_stir_shaken.c.

◆ date_hdr_str

const pj_str_t date_hdr_str = { "Date", 4 }
static

Definition at line 40 of file res_pjsip_stir_shaken.c.

Referenced by add_date_header(), and stir_shaken_incoming_request().

◆ identity_hdr_str

const pj_str_t identity_hdr_str = { "Identity", 8 }
static

◆ stir_shaken_supplement

struct ast_sip_session_supplement stir_shaken_supplement
static

Definition at line 472 of file res_pjsip_stir_shaken.c.

Referenced by load_module(), and unload_module().