Asterisk - The Open Source Telephony Project GIT-master-b023714
Loading...
Searching...
No Matches
Data Structures | Macros | Functions | Variables
res_stir_shaken.c File Reference
#include "asterisk.h"
#include "asterisk/app.h"
#include "asterisk/cli.h"
#include "asterisk/conversions.h"
#include "asterisk/module.h"
#include "asterisk/global_datastores.h"
#include "asterisk/pbx.h"
#include "res_stir_shaken/stir_shaken.h"
Include dependency graph for res_stir_shaken.c:

Go to the source code of this file.

Data Structures

struct  stir_datastore
 

Macros

#define _TRACE_PREFIX_   "rss",__LINE__, ""
 
#define TN_AUTH_LIST_LONG   "TNAuthorizationList"
 
#define TN_AUTH_LIST_OID   "1.3.6.1.5.5.7.1.26"
 
#define TN_AUTH_LIST_SHORT   "TNAuthList"
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
int ast_stir_shaken_add_result_to_channel (struct ast_stir_shaken_vs_ctx *ctx)
 Add a STIR/SHAKEN verification result to a channel.
 
static int check_for_old_config (void)
 
static int func_read (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
 Retrieves STIR/SHAKEN verification information for the channel via dialplan. Examples:
 
int get_tn_auth_nid (void)
 Retrieves the OpenSSL NID for the TN Auth list extension.
 
static int load_module (void)
 
static int reload_module (void)
 
static void stir_datastore_destroy_cb (void *data)
 The callback to destroy a stir_shaken_datastore.
 
static void stir_datastore_free (struct stir_datastore *datastore)
 Frees a stir_shaken_datastore structure.
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "STIR/SHAKEN Module for Asterisk" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND - 1, .requires = "res_curl", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const struct ast_datastore_info stir_shaken_datastore_info
 
static struct ast_custom_function stir_shaken_function
 
static int tn_auth_list_nid
 

Macro Definition Documentation

◆ _TRACE_PREFIX_

#define _TRACE_PREFIX_   "rss",__LINE__, ""

Definition at line 26 of file res_stir_shaken.c.

◆ TN_AUTH_LIST_LONG

#define TN_AUTH_LIST_LONG   "TNAuthorizationList"

Definition at line 300 of file res_stir_shaken.c.

◆ TN_AUTH_LIST_OID

#define TN_AUTH_LIST_OID   "1.3.6.1.5.5.7.1.26"

Definition at line 298 of file res_stir_shaken.c.

◆ TN_AUTH_LIST_SHORT

#define TN_AUTH_LIST_SHORT   "TNAuthList"

Definition at line 299 of file res_stir_shaken.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 390 of file res_stir_shaken.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 390 of file res_stir_shaken.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 390 of file res_stir_shaken.c.

◆ 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:2357
#define ast_channel_lock(chan)
Definition channel.h:2982
#define ast_channel_unlock(chan)
Definition channel.h:2983
#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
const ast_string_field identity_hdr
struct ast_channel * chan
enum ast_stir_shaken_vs_response_code failure_reason
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().

◆ check_for_old_config()

static int check_for_old_config ( void  )
static

Definition at line 302 of file res_stir_shaken.c.

303{
304 const char *error_msg = "There appears to be a 'stir_shaken.conf' file"
305 " with old configuration options in it. Please see the new config"
306 " file format in the configs/samples/stir_shaken.conf.sample file"
307 " in the source tree at https://github.com/asterisk/asterisk/raw/master/configs/samples/stir_shaken.conf.sample"
308 " or visit https://docs.asterisk.org/Deployment/STIR-SHAKEN for more information.";
310 struct ast_flags config_flags = { 0 };
311 char *cat = NULL;
312
313 cfg = ast_config_load("stir_shaken.conf", config_flags);
314 if (cfg == CONFIG_STATUS_FILEMISSING) {
315 /*
316 * They may be loading from realtime so the fact that there's
317 * no stir-shaken.conf file isn't an issue for this purpose.
318 */
320 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
321 cfg = NULL;
322 ast_log(LOG_ERROR, "The stir_shaken.conf file is invalid\n");
324 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
325 /* This can never happen but is included for completeness */
326 cfg = NULL;
328 }
329
330 while ((cat = ast_category_browse(cfg, cat))) {
331 const char *val;
332 if (strcasecmp(cat, "general") == 0) {
333 ast_log(LOG_ERROR, "%s\n", error_msg);
335 }
336 val = ast_variable_retrieve(cfg, cat, "type");
337 if (val && (strcasecmp(val, "store") == 0 ||
338 strcasecmp(val, "certificate") == 0)) {
339 ast_log(LOG_ERROR, "%s\n", error_msg);
341 }
342 }
343
345}
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition extconf.c:3324
#define CONFIG_STATUS_FILEMISSING
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition extconf.c:1287
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
@ 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
Structure used to handle boolean flags.
Definition utils.h:217
#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:978

References ast_category_browse(), ast_config_destroy(), ast_config_load, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_variable_retrieve(), CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, LOG_ERROR, NULL, and RAII_VAR.

Referenced by load_module().

◆ func_read()

static int func_read ( struct ast_channel chan,
const char *  function,
char *  data,
char *  buf,
size_t  len 
)
static

Retrieves STIR/SHAKEN verification information for the channel via dialplan. Examples:

STIR_SHAKEN(count) STIR_SHAKEN(0, identity) STIR_SHAKEN(1, attestation) STIR_SHAKEN(27, verify_result)

Return values
-1on failure
0on success

Definition at line 169 of file res_stir_shaken.c.

171{
173 struct ast_datastore *chan_datastore;
174 char *parse;
175 char *first;
176 char *second;
177 unsigned int target_index, current_index = 0;
179 AST_APP_ARG(first_param);
180 AST_APP_ARG(second_param);
181 );
182
183 if (ast_strlen_zero(data)) {
184 ast_log(LOG_WARNING, "%s requires at least one argument\n", function);
185 return -1;
186 }
187
188 if (!chan) {
189 ast_log(LOG_ERROR, "No channel for %s function\n", function);
190 return -1;
191 }
192
193 parse = ast_strdupa(data);
194
196
197 first = ast_strip(args.first_param);
198 if (ast_strlen_zero(first)) {
199 ast_log(LOG_ERROR, "An argument must be passed to %s\n", function);
200 return -1;
201 }
202
203 second = ast_strip(args.second_param);
204
205 /* Check if we are only looking for the number of STIR/SHAKEN verification results */
206 if (!strcasecmp(first, "count")) {
207 size_t count = 0;
208
209 if (!ast_strlen_zero(second)) {
210 ast_log(LOG_ERROR, "%s only takes 1 paramater for 'count'\n", function);
211 return -1;
212 }
213
214 ast_channel_lock(chan);
215 AST_LIST_TRAVERSE(ast_channel_datastores(chan), chan_datastore, entry) {
216 if (chan_datastore->info != &stir_shaken_datastore_info) {
217 continue;
218 }
219 count++;
220 }
221 ast_channel_unlock(chan);
222
223 snprintf(buf, len, "%zu", count);
224 return 0;
225 }
226
227 /* If we aren't doing a count, then there should be two parameters. The field
228 * we are searching for will be the second parameter. The index is the first.
229 */
230 if (ast_strlen_zero(second)) {
231 ast_log(LOG_ERROR, "Retrieving a value using %s requires two paramaters (index, value) "
232 "- only index was given\n", function);
233 return -1;
234 }
235
236 if (ast_str_to_uint(first, &target_index)) {
237 ast_log(LOG_ERROR, "Failed to convert index %s to integer for function %s\n",
238 first, function);
239 return -1;
240 }
241
242 /* We don't store by uid for the datastore, so just search for the specified index */
243 ast_channel_lock(chan);
244 AST_LIST_TRAVERSE(ast_channel_datastores(chan), chan_datastore, entry) {
245 if (chan_datastore->info != &stir_shaken_datastore_info) {
246 continue;
247 }
248
249 if (current_index == target_index) {
250 break;
251 }
252
253 current_index++;
254 }
255 ast_channel_unlock(chan);
256 if (current_index != target_index || !chan_datastore) {
257 ast_log(LOG_WARNING, "No STIR/SHAKEN results for index '%s'\n", first);
258 return -1;
259 }
260 stir_datastore = chan_datastore->data;
261
262 if (!strcasecmp(second, "identity")) {
264 } else if (!strcasecmp(second, "attestation")) {
266 } else if (!strcasecmp(second, "verify_result")) {
268 } else {
269 ast_log(LOG_ERROR, "No such value '%s' for %s\n", second, function);
270 return -1;
271 }
272
273 return 0;
274}
struct sla_ringing_trunk * first
Definition app_sla.c:338
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
struct ast_datastore_list * ast_channel_datastores(struct ast_channel *chan)
int ast_str_to_uint(const char *str, unsigned int *res)
Convert the given string to an unsigned integer.
Definition conversions.c:56
char buf[BUFSIZE]
Definition eagi_proxy.c:66
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define LOG_WARNING
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
static struct @519 args
const char * vs_response_code_to_str(enum ast_stir_shaken_vs_response_code vs_rc)
Return string version of VS response code.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition strings.h:223
const struct ast_datastore_info * info
Definition datastore.h:67
struct ast_datastore::@227 entry

References args, AST_APP_ARG, ast_channel_datastores(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_LIST_TRAVERSE, ast_log, AST_STANDARD_APP_ARGS, ast_str_to_uint(), ast_strdupa, ast_strip(), ast_strlen_zero(), stir_datastore::attestation, buf, ast_datastore::data, ast_datastore::entry, first, stir_datastore::identity, ast_datastore::info, len(), LOG_ERROR, LOG_WARNING, stir_shaken_datastore_info, stir_datastore::verify_result, and vs_response_code_to_str().

◆ get_tn_auth_nid()

int get_tn_auth_nid ( void  )

Retrieves the OpenSSL NID for the TN Auth list extension.

Return values
TheNID

Definition at line 41 of file res_stir_shaken.c.

42{
43 return tn_auth_list_nid;
44}
static int tn_auth_list_nid

References tn_auth_list_nid.

Referenced by check_tn_auth_list().

◆ load_module()

static int load_module ( void  )
static

Definition at line 347 of file res_stir_shaken.c.

348{
349 int res = 0;
350
351 res = check_for_old_config();
352 if (res != AST_MODULE_LOAD_SUCCESS) {
353 return res;
354 }
355
356 res = crypto_load();
357 if (res != AST_MODULE_LOAD_SUCCESS) {
358 return res;
359 }
360
363 if (tn_auth_list_nid < 0) {
366 }
367
368 res = common_config_load();
369 if (res != AST_MODULE_LOAD_SUCCESS) {
371 return res;
372 }
373
375 if (res != 0) {
378 }
379
381}
int common_config_load(void)
int crypto_register_x509_extension(const char *oid, const char *short_name, const char *long_name)
Register a certificate extension to openssl.
int crypto_load(void)
Initialize the crypto utils.
#define ast_custom_function_register(acf)
Register a custom function.
Definition pbx.h:1562
#define TN_AUTH_LIST_SHORT
#define TN_AUTH_LIST_OID
#define TN_AUTH_LIST_LONG
static struct ast_custom_function stir_shaken_function
static int check_for_old_config(void)
static int unload_module(void)

References ast_custom_function_register, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, check_for_old_config(), common_config_load(), crypto_load(), crypto_register_x509_extension(), stir_shaken_function, TN_AUTH_LIST_LONG, tn_auth_list_nid, TN_AUTH_LIST_OID, TN_AUTH_LIST_SHORT, and unload_module().

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 281 of file res_stir_shaken.c.

282{
283 return common_config_reload();
284}
int common_config_reload(void)

References common_config_reload().

◆ stir_datastore_destroy_cb()

static void stir_datastore_destroy_cb ( void *  data)
static

The callback to destroy a stir_shaken_datastore.

Parameters
dataThe stir_shaken_datastore

Definition at line 77 of file res_stir_shaken.c.

78{
79 struct stir_datastore *datastore = data;
80 stir_datastore_free(datastore);
81}

References stir_datastore_free().

◆ stir_datastore_free()

static void stir_datastore_free ( struct stir_datastore datastore)
static

Frees a stir_shaken_datastore structure.

Parameters
datastoreThe datastore to free

Definition at line 61 of file res_stir_shaken.c.

62{
63 if (!datastore) {
64 return;
65 }
66
67 ast_free(datastore->identity);
68 ast_free(datastore->attestation);
69 ast_free(datastore);
70}
#define ast_free(a)
Definition astmm.h:180

References ast_free, stir_datastore::attestation, and stir_datastore::identity.

Referenced by ast_stir_shaken_add_result_to_channel(), and stir_datastore_destroy_cb().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 286 of file res_stir_shaken.c.

287{
288 int res = 0;
289
292
294
295 return 0;
296}
int common_config_unload(void)
int crypto_unload(void)
Clean up the crypto utils.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.

References ast_custom_function_unregister(), common_config_unload(), crypto_unload(), and stir_shaken_function.

Referenced by load_module().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "STIR/SHAKEN Module for Asterisk" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND - 1, .requires = "res_curl", }
static

Definition at line 390 of file res_stir_shaken.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 390 of file res_stir_shaken.c.

◆ stir_shaken_datastore_info

const struct ast_datastore_info stir_shaken_datastore_info
static
Initial value:
= {
.type = "STIR/SHAKEN VERIFICATION",
}
static void stir_datastore_destroy_cb(void *data)
The callback to destroy a stir_shaken_datastore.

Definition at line 84 of file res_stir_shaken.c.

84 {
85 .type = "STIR/SHAKEN VERIFICATION",
87};

Referenced by ast_stir_shaken_add_result_to_channel(), and func_read().

◆ stir_shaken_function

struct ast_custom_function stir_shaken_function
static
Initial value:
= {
.name = "STIR_SHAKEN",
.read = func_read,
}
static int func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
Retrieves STIR/SHAKEN verification information for the channel via dialplan. Examples:

Definition at line 276 of file res_stir_shaken.c.

276 {
277 .name = "STIR_SHAKEN",
278 .read = func_read,
279};

Referenced by load_module(), and unload_module().

◆ tn_auth_list_nid

int tn_auth_list_nid
static

Definition at line 39 of file res_stir_shaken.c.

Referenced by get_tn_auth_nid(), and load_module().