28 #define AST_API_MODULE
29 #include "stir_shaken.h"
39 #define generate_bool_handler_functions(param_name) \
40 static const char *param_name ## _map[] = { \
41 [ param_name ## _NOT_SET ] = "not_set", \
42 [ param_name ## _YES ] = "yes", \
43 [ param_name ## _NO ] = "no", \
45 enum param_name ## _enum \
46 param_name ## _from_str(const char *value) \
48 if (!strcasecmp(value, param_name ## _map[param_name ## _NOT_SET])) { \
49 return param_name ## _NOT_SET; \
50 } else if (ast_true(value)) { \
51 return param_name ## _YES; \
52 } else if (ast_false(value)) { \
53 return param_name ## _NO; \
55 ast_log(LOG_WARNING, "Unknown " #param_name " response value '%s'\n", value); \
56 return param_name ## _UNKNOWN; \
58 const char *param_name ## _to_str(enum param_name ## _enum value) \
60 return ARRAY_IN_BOUNDS(value, param_name ## _map) ? \
61 param_name ## _map[value] : NULL; \
64 generate_bool_handler_functions(use_rfc9410_responses);
65 generate_bool_handler_functions(send_mky);
66 generate_bool_handler_functions(check_tn_cert_public_url);
67 generate_bool_handler_functions(relax_x5u_port_scheme_restrictions);
68 generate_bool_handler_functions(relax_x5u_path_restrictions);
70 generate_bool_handler_functions(load_system_certs);
77 #define generate_enum_string_functions(param_name, default_value, ...)\
78 static struct enum_name_xref_entry param_name ## _map[] = { \
81 enum param_name ## _enum param_name ## _from_str( \
85 for (i = 0; i < ARRAY_LEN(param_name ## _map); i++) { \
86 if (strcasecmp(value, param_name ##_map[i].name) == 0) { \
87 return param_name ##_map[i].value; \
90 return param_name ## _ ## default_value; \
92 const char *param_name ## _to_str( \
93 enum param_name ## _enum value) \
96 for (i = 0; i < ARRAY_LEN(param_name ## _map); i++) { \
97 if (value == param_name ## _map[i].value) return param_name ## _map[i].name; \
102 generate_enum_string_functions(attest_level, UNKNOWN,
103 {attest_level_A,
"A"},
104 {attest_level_B,
"B"},
105 {attest_level_C,
"C"},
108 generate_enum_string_functions(endpoint_behavior, OFF,
109 {endpoint_behavior_OFF,
"off"},
110 {endpoint_behavior_OFF,
"none"},
111 {endpoint_behavior_ATTEST,
"attest"},
112 {endpoint_behavior_VERIFY,
"verify"},
113 {endpoint_behavior_ON,
"on"},
114 {endpoint_behavior_ON,
"both"}
117 generate_enum_string_functions(stir_shaken_failure_action, CONTINUE,
118 {stir_shaken_failure_action_CONTINUE,
"continue"},
119 {stir_shaken_failure_action_REJECT_REQUEST,
"reject_request"},
120 {stir_shaken_failure_action_CONTINUE_RETURN_REASON,
"continue_return_reason"},
123 static const char *translate_value(
const char *
val)
127 || strcmp(val,
"not_set") == 0) {
134 static void print_acl(
int fd,
struct ast_acl_list *acl_list,
const char *prefix)
140 if (ast_strlen_zero(acl->
name)) {
141 ast_cli(fd,
"%s(permit/deny)\n", prefix);
143 ast_cli(fd,
"%s%s\n", prefix, acl->
name);
150 #define print_acl_cert_store(cfg, a, max_name_len) \
152 if (cfg->vcfg_common.acl) { \
153 ast_cli(a->fd, "x5u_acl:\n"); \
154 print_acl(a->fd, cfg->vcfg_common.acl, " "); \
156 ast_cli(a->fd, "%-*s: (none)\n", max_name_len, "x5u_acl"); \
158 if (cfg->vcfg_common.tcs) { \
160 ast_cli(a->fd, "%-*s:\n", max_name_len, "Verification CA certificate store"); \
161 count = crypto_show_cli_store(cfg->vcfg_common.tcs, a->fd); \
162 if (count == 0 && (!ast_strlen_zero(cfg->vcfg_common.ca_path) \
163 || !ast_strlen_zero(cfg->vcfg_common.crl_path))) { \
164 ast_cli(a->fd, " Note: Certs in ca_path or crl_path won't show until used.\n"); \
167 ast_cli(a->fd, "%-*s: (none)\n", max_name_len, "Verification CA certificate store"); \
171 int config_object_cli_show(
void *obj,
void *arg,
void *data,
int flags)
177 const char *title = NULL;
178 const char *cfg_name = NULL;
179 int max_name_len = 0;
182 ast_cli(a->fd,
"No stir/shaken configuration found\n");
186 if (!ast_strlen_zero(cli_data->title)) {
187 title = cli_data->title;
191 max_name_len = strlen(title);
193 if (cli_data->object_type == config_object_type_profile
194 || cli_data->object_type == config_object_type_tn) {
196 max_name_len += strlen(cfg_name) + 2 ;
205 for (i = options; i; i = i->
next) {
206 int nlen = strlen(i->
name);
207 max_name_len = (nlen > max_name_len) ? nlen : max_name_len;
210 ast_cli(a->fd,
"\n==============================================================================\n");
211 if (ast_strlen_zero(cfg_name)) {
212 ast_cli(a->fd,
"%s\n", title);
214 ast_cli(a->fd,
"%s: %s\n", title, cfg_name);
216 ast_cli(a->fd,
"------------------------------------------------------------------------------\n");
218 for (i = options; i; i = i->
next) {
220 ast_cli(a->fd,
"%-*s: %s\n", max_name_len, i->
name,
221 translate_value(i->
value));
227 if (cli_data->object_type == config_object_type_profile) {
229 print_acl_cert_store(cfg, a, max_name_len);
230 }
else if (cli_data->object_type == config_object_type_verification) {
232 print_acl_cert_store(cfg, a, max_name_len);
234 ast_cli(a->fd,
"---------------------------------------------\n\n"); \
243 int wordlen = strlen(word);
247 while ((obj = ao2_iterator_next(&it))) {
262 int common_config_reload(
void)
264 SCOPE_ENTER(2,
"Stir Shaken Reload\n");
273 if (tn_config_reload()) {
277 if (profile_reload()) {
284 int common_config_unload(
void)
291 if (named_acl_changed_sub) {
293 named_acl_changed_sub = NULL;
301 static void named_acl_changed_cb(
void *data,
307 ast_log(LOG_NOTICE,
"Named acl changed. Reloading verification and profile\n");
308 common_config_reload();
311 int common_config_load(
void)
313 SCOPE_ENTER(2,
"Stir Shaken Load\n");
316 common_config_unload();
321 common_config_unload();
326 common_config_unload();
330 if (tn_config_load()) {
331 common_config_unload();
335 if (profile_load()) {
336 common_config_unload();
340 if (!named_acl_changed_sub) {
342 named_acl_changed_cb, NULL);
343 if (!named_acl_changed_sub) {
344 common_config_unload();
357 char *canonicalize_tn(
const char *tn,
char *dest_tn)
361 size_t len = tn ? strlen(tn) : 0;
362 char *new_tn = dest_tn;
363 SCOPE_ENTER(3,
"tn: %s\n",
S_OR(tn,
"(null)"));
365 if (ast_strlen_zero(tn)) {
367 SCOPE_EXIT_RTN_VALUE(NULL,
"Empty TN\n");
371 SCOPE_EXIT_RTN_VALUE(NULL,
"No destination buffer\n");
374 for (i = 0; i < len; i++) {
375 if (isdigit(*s) || *s ==
'#' || *s ==
'*') {
381 SCOPE_EXIT_RTN_VALUE(dest_tn,
"Canonicalized '%s' -> '%s'\n", tn, dest_tn);
384 char *canonicalize_tn_alloc(
const char *tn)
386 char *canon_tn = ast_strlen_zero(tn) ? NULL :
ast_malloc(strlen(tn) + 1);
390 return canonicalize_tn(tn, canon_tn);
struct ast_variable * next
struct ast_variable * ast_variable_list_sort(struct ast_variable *head)
Performs an in-place sort on the variable list by ascending name.
Security Event Reporting API.
#define AST_LIST_LOCK(head)
Locks a list.
struct ast_variable * ast_sorcery_objectset_create2(const struct ast_sorcery *sorcery, const void *object, enum ast_sorcery_field_handler_flags flags)
Create an object set (KVP list) for an object.
Asterisk main include file. File version handling, generic pbx functions.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
char name[ACL_NAME_LENGTH]
Structure for variables, used for configurations and for channel variables.
Full structure for sorcery.
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
struct stasis_message_type * ast_named_acl_change_type(void)
a stasis_message_type for changes against a named ACL or the set of all named ACLs ...
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
Wrapper for an ast_acl linked list.
#define ast_strdup(str)
A wrapper for strdup()
const char * ast_sorcery_object_get_type(const void *object)
Get the type of a sorcery object.
#define ast_sorcery_unref(sorcery)
Decrease the reference count of a sorcery structure.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
#define ast_malloc(len)
A wrapper for malloc()
struct ao2_container * container
an ast_acl is a linked list node of ast_ha structs which may have names.
int ast_strings_equal(const char *str1, const char *str2)
Compare strings for equality checking for NULL.
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Support for logging to various files, console and syslog Configuration in file logger.conf.
Module has failed to load, may be in an inconsistent state.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Standard Command Line Interface.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
void ast_ha_output(int fd, const struct ast_ha *ha, const char *prefix)
output an HA to the provided fd
Profile configuration for stir/shaken.
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
#define ast_sorcery_open()
Open a new sorcery structure.
struct stasis_topic * ast_security_topic(void)
A stasis_topic which publishes messages for security related issues.
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Asterisk module definitions.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.