26 #define _TRACE_PREFIX_ "rss",__LINE__, ""
37 #include "res_stir_shaken/stir_shaken.h"
39 static int tn_auth_list_nid;
41 int get_tn_auth_nid(
void)
43 return tn_auth_list_nid;
53 enum ast_stir_shaken_vs_response_code verify_result;
67 ast_free(datastore->identity);
68 ast_free(datastore->attestation);
77 static void stir_datastore_destroy_cb(
void *data)
80 stir_datastore_free(datastore);
85 .
type =
"STIR/SHAKEN VERIFICATION",
86 .destroy = stir_datastore_destroy_cb,
89 int ast_stir_shaken_add_result_to_channel(
94 const char *chan_name;
97 ast_log(LOG_ERROR,
"Channel is required to add STIR/SHAKEN verification\n");
101 chan_name = ast_channel_name(ctx->chan);
103 if (!ctx->identity_hdr) {
104 ast_log(LOG_ERROR,
"No identity to add STIR/SHAKEN verification to channel "
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);
115 stir_datastore =
ast_calloc(1,
sizeof(*stir_datastore));
116 if (!stir_datastore) {
117 ast_log(LOG_ERROR,
"Failed to allocate space for STIR/SHAKEN datastore for "
118 "channel %s\n", chan_name);
122 stir_datastore->identity =
ast_strdup(ctx->identity_hdr);
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);
126 stir_datastore_free(stir_datastore);
130 stir_datastore->attestation =
ast_strdup(ctx->attestation);
131 if (!stir_datastore->attestation) {
132 ast_log(LOG_ERROR,
"Failed to allocate space for STIR/SHAKEN datastore "
133 "attestation for channel %s\n", chan_name);
134 stir_datastore_free(stir_datastore);
138 stir_datastore->verify_result = ctx->failure_reason;
140 chan_datastore = ast_datastore_alloc(&stir_shaken_datastore_info, NULL);
141 if (!chan_datastore) {
142 ast_log(LOG_ERROR,
"Failed to allocate space for datastore for channel "
144 stir_datastore_free(stir_datastore);
148 chan_datastore->
data = stir_datastore;
150 ast_channel_lock(ctx->chan);
152 ast_channel_unlock(ctx->chan);
169 static int func_read(
struct ast_channel *chan,
const char *
function,
170 char *
data,
char *buf,
size_t len)
172 struct stir_datastore *stir_datastore;
177 unsigned int target_index, current_index = 0;
183 if (ast_strlen_zero(data)) {
184 ast_log(LOG_WARNING,
"%s requires at least one argument\n",
function);
189 ast_log(LOG_ERROR,
"No channel for %s function\n",
function);
198 if (ast_strlen_zero(first)) {
199 ast_log(LOG_ERROR,
"An argument must be passed to %s\n",
function);
206 if (!strcasecmp(first,
"count")) {
209 if (!ast_strlen_zero(second)) {
210 ast_log(LOG_ERROR,
"%s only takes 1 paramater for 'count'\n",
function);
214 ast_channel_lock(chan);
216 if (chan_datastore->
info != &stir_shaken_datastore_info) {
221 ast_channel_unlock(chan);
223 snprintf(buf, len,
"%zu", count);
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);
237 ast_log(LOG_ERROR,
"Failed to convert index %s to integer for function %s\n",
243 ast_channel_lock(chan);
245 if (chan_datastore->
info != &stir_shaken_datastore_info) {
249 if (current_index == target_index) {
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);
260 stir_datastore = chan_datastore->
data;
262 if (!strcasecmp(second,
"identity")) {
264 }
else if (!strcasecmp(second,
"attestation")) {
266 }
else if (!strcasecmp(second,
"verify_result")) {
267 ast_copy_string(buf, vs_response_code_to_str(stir_datastore->verify_result), len);
269 ast_log(LOG_ERROR,
"No such value '%s' for %s\n", second,
function);
277 .
name =
"STIR_SHAKEN",
281 static int reload_module(
void)
283 return common_config_reload();
286 static int unload_module(
void)
290 common_config_unload();
298 #define TN_AUTH_LIST_OID "1.3.6.1.5.5.7.1.26"
299 #define TN_AUTH_LIST_SHORT "TNAuthList"
300 #define TN_AUTH_LIST_LONG "TNAuthorizationList"
302 static int check_for_old_config(
void)
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.";
323 if (strcasecmp(cat,
"general") == 0) {
324 ast_log(LOG_ERROR,
"%s\n", error_msg);
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);
338 static int load_module(
void)
342 if (check_for_old_config()) {
351 tn_auth_list_nid = crypto_register_x509_extension(TN_AUTH_LIST_OID,
352 TN_AUTH_LIST_SHORT, TN_AUTH_LIST_LONG);
353 if (tn_auth_list_nid < 0) {
358 if (common_config_load()) {
368 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER,
"STIR/SHAKEN Module for Asterisk",
369 .support_level = AST_MODULE_SUPPORT_CORE,
371 .unload = unload_module,
372 .reload = reload_module,
374 .requires =
"res_curl",
Main Channel structure associated with a channel.
Asterisk main include file. File version handling, generic pbx functions.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
globally accessible channel datastores
Structure for a data store type.
#define ast_strdup(str)
A wrapper for strdup()
Structure for a data store object.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
#define ast_config_load(filename, flags)
Load a config file.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Data structure associated with a custom dialplan function.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
const struct ast_datastore_info * info
Conversion utility functions.
Core PBX routines and definitions.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define ast_calloc(num, len)
A wrapper for calloc()
static void crypto_load(int ifd, int ofd)
refresh RSA keys from file
Module has failed to load, may be in an inconsistent state.
int ast_str_to_uint(const char *str, unsigned int *res)
Convert the given string to an unsigned integer.
Structure used to handle boolean flags.
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define ast_custom_function_register(acf)
Register a custom function.
#define AST_APP_ARG(name)
Define an application argument.