Asterisk - The Open Source Telephony Project GIT-master-7e7a603
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. More...
 
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: More...
 
int get_tn_auth_nid (void)
 Retrieves the OpenSSL NID for the TN Auth list extension. More...
 
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. More...
 
static void stir_datastore_free (struct stir_datastore *datastore)
 Frees a stir_shaken_datastore structure. More...
 
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 = "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 = 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 375 of file res_stir_shaken.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 375 of file res_stir_shaken.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 375 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:2385
#define ast_channel_lock(chan)
Definition: channel.h:2922
#define ast_channel_unlock(chan)
Definition: channel.h:2923
#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().

◆ 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 == NULL) {
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 }
321 while ((cat = ast_category_browse(cfg, cat))) {
322 const char *val;
323 if (strcasecmp(cat, "general") == 0) {
324 ast_log(LOG_ERROR, "%s\n", error_msg);
326 }
327 val = ast_variable_retrieve(cfg, cat, "type");
328 if (val && (strcasecmp(val, "store") == 0 ||
329 strcasecmp(val, "certificate") == 0)) {
330 ast_log(LOG_ERROR, "%s\n", error_msg);
332 }
333 }
334
336}
#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:3326
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:783
@ 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:199
Definition: ast_expr2.c:325
#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 ast_category_browse(), ast_config_destroy(), ast_config_load, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_variable_retrieve(), 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:332
#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.
Definition: linkedlists.h:491
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 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
Definition: search.h:40
const char * args

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, 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 338 of file res_stir_shaken.c.

339{
340 int res = 0;
341
342 if (check_for_old_config()) {
344 }
345
346 if (crypto_load()) {
349 }
350
353 if (tn_auth_list_nid < 0) {
356 }
357
358 if (common_config_load()) {
361 }
362
364
365 return res;
366}
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.
Definition: crypto_utils.c:76
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
static void crypto_load(int ifd, int ofd)
refresh RSA keys from file
Definition: res_crypto.c:819
#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, 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.
Definition: crypto_utils.c:514
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 = "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 = 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 375 of file res_stir_shaken.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 375 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.

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.

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