Named Access Control Lists. More...
#include "asterisk.h"#include "asterisk/config.h"#include "asterisk/config_options.h"#include "asterisk/event.h"#include "asterisk/utils.h"#include "asterisk/module.h"#include "asterisk/cli.h"#include "asterisk/acl.h"#include "asterisk/astobj2.h"#include "asterisk/paths.h"
Go to the source code of this file.
Data Structures | |
| struct | named_acl |
| struct | named_acl_config |
| struct | named_acl_global_config |
Defines | |
| #define | ACL_FAMILY "acls" |
| #define | NACL_CONFIG "acl.conf" |
Functions | |
| static int | acl_order_comparator (struct ast_category *p, struct ast_category *q) |
| static | AO2_GLOBAL_OBJ_STATIC (globals) |
| struct ast_ha * | ast_named_acl_find (const char *name, int *is_realtime, int *is_undefined) |
| Retrieve a named ACL. | |
| int | ast_named_acl_init () |
| Initialize and configure the named ACL system. | |
| int | ast_named_acl_reload (void) |
| reload/reconfigure the named ACL system. | |
| static void | cli_display_named_acl (int fd, const char *name) |
| static void | cli_display_named_acl_list (int fd) |
| CONFIG_INFO_STANDARD (cfg_info, globals, named_acl_config_alloc,.files=ACO_FILES(&named_acl_conf),) | |
| static void | destroy_named_acl (void *obj) |
| Destroy a named ACL object. | |
| static char * | handle_show_named_acl_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static void * | named_acl_alloc (const char *cat) |
| Create a named ACL structure. | |
| static void | named_acl_cleanup (void) |
| static int | named_acl_cmp_fn (void *obj, void *arg, const int flags) |
| static void * | named_acl_config_alloc (void) |
| allocator callback for named_acl_config. Notice it returns void * since it is used by the backend config code | |
| static void | named_acl_config_destructor (void *obj) |
| destructor for named_acl_config | |
| static void * | named_acl_find (struct ao2_container *container, const char *cat) |
| Find a named ACL in a container by its name. | |
| static struct named_acl * | named_acl_find_realtime (const char *name) |
| static void | named_acl_global_config_destructor (void *obj) |
| static int | named_acl_hash_fn (const void *obj, const int flags) |
| static int | push_acl_change_event (char *name) |
Variables | |
| static struct ast_cli_entry | cli_named_acl [] |
| static struct aco_type | global_option |
| struct aco_type * | global_options [] = ACO_TYPES(&global_option) |
| struct aco_file | named_acl_conf |
| static struct aco_type | named_acl_type |
| struct aco_type * | named_acl_types [] = ACO_TYPES(&named_acl_type) |
Named Access Control Lists.
Definition in file named_acl.c.
| #define ACL_FAMILY "acls" |
Definition at line 45 of file named_acl.c.
Referenced by ast_named_acl_find(), and named_acl_find_realtime().
| #define NACL_CONFIG "acl.conf" |
Definition at line 44 of file named_acl.c.
| static int acl_order_comparator | ( | struct ast_category * | p, |
| struct ast_category * | q | ||
| ) | [static] |
Definition at line 220 of file named_acl.c.
References ast_category_first(), ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by named_acl_find_realtime().
{
int p_value = 0, q_value = 0;
struct ast_variable *p_var = ast_category_first(p);
struct ast_variable *q_var = ast_category_first(q);
while (p_var) {
if (!strcasecmp(p_var->name, "rule_order")) {
p_value = atoi(p_var->value);
break;
}
p_var = p_var->next;
}
while (q_var) {
if (!strcasecmp(q_var->name, "rule_order")) {
q_value = atoi(q_var->value);
break;
}
q_var = q_var->next;
}
if (p_value < q_value) {
return -1;
} else if (q_value < p_value) {
return 1;
}
return 0;
}
| static AO2_GLOBAL_OBJ_STATIC | ( | globals | ) | [static] |
| struct ast_ha* ast_named_acl_find | ( | const char * | name, |
| int * | is_realtime, | ||
| int * | is_undefined | ||
| ) | [read] |
Retrieve a named ACL.
This function attempts to find a named ACL. If found, a copy of the requested ACL will be made which must be freed by the caller.
| name | Name of the ACL sought | |
| [out] | is_realtime | will be true if the ACL being returned is from realtime |
| [out] | is_undefined | will be true if no ACL profile can be found for the requested name |
| A | copy of the named ACL as an ast_ha |
| NULL | if no ACL could be found. |
Definition at line 312 of file named_acl.c.
References ACL_FAMILY, ao2_cleanup, ao2_global_obj_ref, ast_check_realtime(), ast_duplicate_ha_list(), ast_log(), ast_realtime_is_mapping_defined(), globals, named_acl::ha, LOG_ERROR, LOG_NOTICE, LOG_WARNING, named_acl_find(), and named_acl_find_realtime().
Referenced by ast_append_acl().
{
struct ast_ha *ha = NULL;
RAII_VAR(struct named_acl_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
RAII_VAR(struct named_acl *, named_acl, NULL, ao2_cleanup);
if (is_realtime) {
*is_realtime = 0;
}
if (is_undefined) {
*is_undefined = 0;
}
/* If the config or its named_acl_list hasn't been initialized, abort immediately. */
if ((!cfg) || (!(cfg->named_acl_list))) {
ast_log(LOG_ERROR, "Attempted to find named ACL '%s', but the ACL configuration isn't available.\n", name);
return NULL;
}
named_acl = named_acl_find(cfg->named_acl_list, name);
/* If a named ACL couldn't be retrieved locally, we need to try realtime storage. */
if (!named_acl) {
RAII_VAR(struct named_acl *, realtime_acl, NULL, ao2_cleanup);
/* Attempt to create from realtime */
if ((realtime_acl = named_acl_find_realtime(name))) {
if (is_realtime) {
*is_realtime = 1;
}
ha = ast_duplicate_ha_list(realtime_acl->ha);
return ha;
}
/* Couldn't create from realtime. Raise relevant flags and print relevant warnings. */
if (ast_realtime_is_mapping_defined(ACL_FAMILY) && !ast_check_realtime(ACL_FAMILY)) {
ast_log(LOG_WARNING, "ACL '%s' does not exist. The ACL will be marked as undefined and will automatically fail if applied.\n"
"This ACL may exist in the configured realtime backend, but that backend hasn't been registered yet. "
"Fix this establishing preload for the backend in 'modules.conf'.\n", name);
} else {
ast_log(LOG_WARNING, "ACL '%s' does not exist. The ACL will be marked as undefined and will automatically fail if applied.\n", name);
}
if (is_undefined) {
*is_undefined = 1;
}
return NULL;
}
ha = ast_duplicate_ha_list(named_acl->ha);
if (!ha) {
ast_log(LOG_NOTICE, "ACL '%s' contains no rules. It is valid, but it will accept addresses unconditionally.\n", name);
}
return ha;
}
| int ast_named_acl_init | ( | void | ) |
Initialize and configure the named ACL system.
This function will prepare the named ACL system for use. For this reason, it needs to be called before other things that use ACLs are initialized.
Definition at line 566 of file named_acl.c.
References ACO_EXACT, aco_info_destroy(), aco_info_init(), aco_option_register, aco_process_config(), ARRAY_LEN, ast_cli_register_multiple(), ast_register_atexit(), FLDSET, named_acl_cleanup(), and OPT_ACL_T.
Referenced by main().
{
ast_cli_register_multiple(cli_named_acl, ARRAY_LEN(cli_named_acl));
ast_register_atexit(named_acl_cleanup);
if (aco_info_init(&cfg_info)) {
return 0;
}
/* Register the per level options. */
aco_option_register(&cfg_info, "permit", ACO_EXACT, named_acl_types, NULL, OPT_ACL_T, 1, FLDSET(struct named_acl, ha));
aco_option_register(&cfg_info, "deny", ACO_EXACT, named_acl_types, NULL, OPT_ACL_T, 0, FLDSET(struct named_acl, ha));
if (aco_process_config(&cfg_info, 0)) {
aco_info_destroy(&cfg_info);
return 0;
}
return 0;
}
| int ast_named_acl_reload | ( | void | ) |
reload/reconfigure the named ACL system.
This function is designed to trigger an event upon a successful reload that may update ACL consumers.
Definition at line 407 of file named_acl.c.
References aco_process_config(), ACO_PROCESS_ERROR, ACO_PROCESS_UNCHANGED, ast_log(), LOG_WARNING, push_acl_change_event(), and status.
{
enum aco_process_status status;
status = aco_process_config(&cfg_info, 1);
if (status == ACO_PROCESS_ERROR) {
ast_log(LOG_WARNING, "Could not reload ACL config\n");
return 0;
}
if (status == ACO_PROCESS_UNCHANGED) {
/* We don't actually log anything if the config was unchanged,
* but we don't need to send a config change event either.
*/
return 0;
}
/* We need to push an ACL change event with no ACL name so that all subscribers update with all ACLs */
push_acl_change_event("");
return 0;
}
| static void cli_display_named_acl | ( | int | fd, |
| const char * | name | ||
| ) | [static] |
Definition at line 438 of file named_acl.c.
References ast_ha::addr, ao2_cleanup, ao2_global_obj_ref, ast_cli(), ast_log(), AST_SENSE_ALLOW, ast_sockaddr_stringify_addr(), globals, named_acl::ha, LOG_ERROR, named_acl_find(), named_acl_find_realtime(), ast_ha::netmask, ast_ha::next, and ast_ha::sense.
Referenced by handle_show_named_acl_cmd().
{
struct ast_ha *ha;
int ha_index = 0;
int is_realtime = 0;
RAII_VAR(struct named_acl_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
RAII_VAR(struct named_acl *, named_acl, NULL, ao2_cleanup);
/* If the configuration or the configuration's named_acl_list is unavailable, abort. */
if ((!cfg) || (!cfg->named_acl_list)) {
ast_log(LOG_ERROR, "Attempted to show named ACL '%s', but the acl configuration isn't available.\n", name);
return;
}
named_acl = named_acl_find(cfg->named_acl_list, name);
/* If the named_acl couldn't be found with the search, also abort. */
if (!named_acl) {
if (!(named_acl = named_acl_find_realtime(name))) {
ast_cli(fd, "\nCould not find ACL named '%s'\n", name);
return;
}
is_realtime = 1;
}
ast_cli(fd, "\nACL: %s%s\n---------------------------------------------\n", name, is_realtime ? " (realtime)" : "");
for (ha = named_acl->ha; ha; ha = ha->next) {
char *addr = ast_strdupa(ast_sockaddr_stringify_addr(&ha->addr));
char *mask = ast_sockaddr_stringify_addr(&ha->netmask);
ast_cli(fd, "%3d: %s - %s/%s\n", ha_index, ha->sense == AST_SENSE_ALLOW ? "allow" : " deny", addr, mask);
ha_index++;
}
}
| static void cli_display_named_acl_list | ( | int | fd | ) | [static] |
Definition at line 480 of file named_acl.c.
References ao2_cleanup, ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli(), globals, and named_acl::name.
Referenced by handle_show_named_acl_cmd().
{
struct ao2_iterator i;
void *o;
RAII_VAR(struct named_acl_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
ast_cli(fd, "\nacl\n---\n");
if (!cfg || !cfg->named_acl_list) {
ast_cli(fd, "ACL configuration isn't available.\n");
return;
}
i = ao2_iterator_init(cfg->named_acl_list, 0);
while ((o = ao2_iterator_next(&i))) {
struct named_acl *named_acl = o;
ast_cli(fd, "%s\n", named_acl->name);
ao2_ref(o, -1);
}
ao2_iterator_destroy(&i);
}
| CONFIG_INFO_STANDARD | ( | cfg_info | , |
| globals | , | ||
| named_acl_config_alloc | , | ||
| . | files = ACO_FILES(&named_acl_conf) |
||
| ) |
| static void destroy_named_acl | ( | void * | obj | ) | [static] |
Destroy a named ACL object.
Definition at line 167 of file named_acl.c.
References ast_free_ha(), and named_acl::ha.
Referenced by named_acl_alloc().
{
struct named_acl *named_acl = obj;
ast_free_ha(named_acl->ha);
}
| static char* handle_show_named_acl_cmd | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 504 of file named_acl.c.
References ao2_cleanup, ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli_args::argc, ast_cli_args::argv, ast_strdup, cli_display_named_acl(), cli_display_named_acl_list(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, globals, match(), ast_cli_args::n, named_acl::name, ast_cli_entry::usage, and ast_cli_args::word.
{
RAII_VAR(struct named_acl_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
int length;
int which;
struct ao2_iterator i;
struct named_acl *named_acl;
char *match = NULL;
switch (cmd) {
case CLI_INIT:
e->command = "acl show";
e->usage =
"Usage: acl show [name]\n"
" Shows a list of named ACLs or lists all entries in a given named ACL.\n";
return NULL;
case CLI_GENERATE:
if (!cfg) {
return NULL;
}
length = strlen(a->word);
which = 0;
i = ao2_iterator_init(cfg->named_acl_list, 0);
while ((named_acl = ao2_iterator_next(&i))) {
if (!strncasecmp(a->word, named_acl->name, length) && ++which > a->n) {
match = ast_strdup(named_acl->name);
ao2_ref(named_acl, -1);
break;
}
ao2_ref(named_acl, -1);
}
ao2_iterator_destroy(&i);
return match;
}
if (a->argc == 2) {
cli_display_named_acl_list(a->fd);
return CLI_SUCCESS;
}
if (a->argc == 3) {
cli_display_named_acl(a->fd, a->argv[2]);
return CLI_SUCCESS;
}
return CLI_SHOWUSAGE;
}
| void * named_acl_alloc | ( | const char * | cat | ) | [static] |
Create a named ACL structure.
| cat | name given to the ACL |
| NULL | failure |
| non-NULL | successfully allocated named ACL |
Definition at line 180 of file named_acl.c.
References ao2_alloc, ast_copy_string(), destroy_named_acl(), and named_acl::name.
Referenced by named_acl_find_realtime().
{
struct named_acl *named_acl;
named_acl = ao2_alloc(sizeof(*named_acl), destroy_named_acl);
if (!named_acl) {
return NULL;
}
ast_copy_string(named_acl->name, cat, sizeof(named_acl->name));
return named_acl;
}
| static void named_acl_cleanup | ( | void | ) | [static] |
Definition at line 558 of file named_acl.c.
References aco_info_destroy(), ao2_global_obj_release, ARRAY_LEN, ast_cli_unregister_multiple(), and globals.
Referenced by ast_named_acl_init().
{
ast_cli_unregister_multiple(cli_named_acl, ARRAY_LEN(cli_named_acl));
aco_info_destroy(&cfg_info);
ao2_global_obj_release(globals);
}
| static int named_acl_cmp_fn | ( | void * | obj, |
| void * | arg, | ||
| const int | flags | ||
| ) | [static] |
Definition at line 114 of file named_acl.c.
References CMP_MATCH, CMP_STOP, and named_acl::name.
Referenced by named_acl_config_alloc().
| static void * named_acl_config_alloc | ( | void | ) | [static] |
allocator callback for named_acl_config. Notice it returns void * since it is used by the backend config code
Definition at line 139 of file named_acl.c.
References ao2_alloc, ao2_container_alloc, ao2_ref, ast_string_field_init, named_acl_config::global, named_acl_cmp_fn(), named_acl_config_destructor(), named_acl_global_config_destructor(), named_acl_hash_fn(), and named_acl_config::named_acl_list.
{
struct named_acl_config *cfg;
if (!(cfg = ao2_alloc(sizeof(*cfg), named_acl_config_destructor))) {
return NULL;
}
if (!(cfg->global = ao2_alloc(sizeof(*cfg->global), named_acl_global_config_destructor))) {
goto error;
}
if (ast_string_field_init(cfg->global, 128)) {
goto error;
}
if (!(cfg->named_acl_list = ao2_container_alloc(37, named_acl_hash_fn, named_acl_cmp_fn))) {
goto error;
}
return cfg;
error:
ao2_ref(cfg, -1);
return NULL;
}
| static void named_acl_config_destructor | ( | void * | obj | ) | [static] |
destructor for named_acl_config
Definition at line 123 of file named_acl.c.
References ao2_cleanup, named_acl_config::global, and named_acl_config::named_acl_list.
Referenced by named_acl_config_alloc().
{
struct named_acl_config *cfg = obj;
ao2_cleanup(cfg->named_acl_list);
ao2_cleanup(cfg->global);
}
| void * named_acl_find | ( | struct ao2_container * | container, |
| const char * | cat | ||
| ) | [static] |
Find a named ACL in a container by its name.
| container | ao2container holding the named ACLs |
| name | of the ACL wanted to be found |
| pointer | to the named ACL if available. Null if not found. |
Definition at line 201 of file named_acl.c.
References ao2_find, ast_copy_string(), named_acl::name, and OBJ_POINTER.
Referenced by ast_named_acl_find(), and cli_display_named_acl().
{
struct named_acl tmp;
ast_copy_string(tmp.name, cat, sizeof(tmp.name));
return ao2_find(container, &tmp, OBJ_POINTER);
}
| static struct named_acl* named_acl_find_realtime | ( | const char * | name | ) | [static, read] |
Definition at line 259 of file named_acl.c.
References ACL_FAMILY, acl_order_comparator(), ast_append_ha(), ast_category_browse(), ast_config_AST_SYSTEM_NAME, ast_config_destroy(), ast_config_sort_categories(), ast_free_ha(), ast_load_realtime_multientry(), ast_log(), ast_strlen_zero(), ast_variable_retrieve(), named_acl::ha, LOG_ERROR, named_acl_alloc(), and SENTINEL.
Referenced by ast_named_acl_find(), and cli_display_named_acl().
{
struct ast_config *cfg;
char *item = NULL;
const char *systemname = NULL;
struct ast_ha *built_ha = NULL;
struct named_acl *acl;
/* If we have a systemname set in the global options, we only want to retrieve entries with a matching systemname field. */
systemname = ast_config_AST_SYSTEM_NAME;
if (ast_strlen_zero(systemname)) {
cfg = ast_load_realtime_multientry(ACL_FAMILY, "name", name, SENTINEL);
} else {
cfg = ast_load_realtime_multientry(ACL_FAMILY, "name", name, "systemname", systemname, SENTINEL);
}
if (!cfg) {
return NULL;
}
/* At this point, the configuration must be sorted by the order field. */
ast_config_sort_categories(cfg, 0, acl_order_comparator);
while ((item = ast_category_browse(cfg, item))) {
int append_ha_error = 0;
const char *order = ast_variable_retrieve(cfg, item, "rule_order");
const char *sense = ast_variable_retrieve(cfg, item, "sense");
const char *rule = ast_variable_retrieve(cfg, item, "rule");
built_ha = ast_append_ha(sense, rule, built_ha, &append_ha_error);
if (append_ha_error) {
/* We need to completely reject an ACL that contains any bad rules. */
ast_log(LOG_ERROR, "Rejecting realtime ACL due to bad ACL definition '%s': %s - %s - %s\n", name, order, sense, rule);
ast_free_ha(built_ha);
return NULL;
}
}
ast_config_destroy(cfg);
acl = named_acl_alloc(name);
if (!acl) {
ast_log(LOG_ERROR, "allocation error\n");
ast_free_ha(built_ha);
return NULL;
}
acl->ha = built_ha;
return acl;
}
| static void named_acl_global_config_destructor | ( | void * | obj | ) | [static] |
Definition at line 130 of file named_acl.c.
References ast_string_field_free_memory.
Referenced by named_acl_config_alloc().
{
struct named_acl_global_config *global = obj;
ast_string_field_free_memory(global);
}
| static int named_acl_hash_fn | ( | const void * | obj, |
| const int | flags | ||
| ) | [static] |
Definition at line 108 of file named_acl.c.
References ast_str_hash(), and named_acl::name.
Referenced by named_acl_config_alloc().
{
const struct named_acl *entry = obj;
return ast_str_hash(entry->name);
}
| static int push_acl_change_event | ( | char * | name | ) | [static] |
Definition at line 382 of file named_acl.c.
References AST_EVENT_ACL_CHANGE, ast_event_destroy(), AST_EVENT_IE_DESCRIPTION, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_STR, ast_event_new(), ast_event_queue(), ast_log(), and LOG_ERROR.
Referenced by ast_named_acl_reload().
{
struct ast_event *event = ast_event_new(AST_EVENT_ACL_CHANGE,
AST_EVENT_IE_DESCRIPTION, AST_EVENT_IE_PLTYPE_STR, name,
AST_EVENT_IE_END);
if (!event) {
ast_log(LOG_ERROR, "Failed to allocate acl.conf reload event. Some modules will have out of date ACLs.\n");
return -1;
}
if (ast_event_queue(event)) {
ast_event_destroy(event);
ast_log(LOG_ERROR, "Failed to queue acl.conf reload event. Some modules will have out of date ACLs.\n");
return -1;
}
return 0;
}
struct ast_cli_entry cli_named_acl[] [static] |
{
AST_CLI_DEFINE(handle_show_named_acl_cmd, "Show a named ACL or list all named ACLs"),
}
Definition at line 554 of file named_acl.c.
struct aco_type global_option [static] |
Definition at line 81 of file named_acl.c.
| struct aco_type* global_options[] = ACO_TYPES(&global_option) |
Definition at line 91 of file named_acl.c.
| struct aco_file named_acl_conf |
{
.filename = "acl.conf",
.types = ACO_TYPES(&named_acl_type, &global_option),
}
Definition at line 93 of file named_acl.c.
struct aco_type named_acl_type [static] |
Definition at line 71 of file named_acl.c.
| struct aco_type* named_acl_types[] = ACO_TYPES(&named_acl_type) |
Definition at line 89 of file named_acl.c.