From e663ee6a905f64c1d26954fa896bbc1461001163 Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Mon, 6 Jul 2020 17:30:50 +0300 Subject: [PATCH] permissions: Integrate with 'db_default_url' * DB partitions now inherit their DB URL (if not given explicitly) from 'db_url' -> 'db_default_url' * the above is similar for the 'table_name' property (inherit from the 'address_table' modparam) * rewrite the 'partitions' parser: no more coding style limitations * backwards-compatible: the 'db_url' is still mandatory if you are not specifying a partition definition! This is due to the fact that the module has a non-DB based usage mode Part of a series of patches for #2117 (cherry picked from commit bb57cc1c375b9325138154eb415cebc2fa971ec0) --- modules/permissions/address.c | 57 ++++++++- modules/permissions/address.h | 18 ++- modules/permissions/partitions.c | 185 ++++++++++++------------------ modules/permissions/partitions.h | 3 +- modules/permissions/permissions.c | 60 ++-------- modules/permissions/permissions.h | 11 -- 6 files changed, 157 insertions(+), 177 deletions(-) diff --git a/modules/permissions/address.c b/modules/permissions/address.c index 9a95d070b45..1440e3d132e 100644 --- a/modules/permissions/address.c +++ b/modules/permissions/address.c @@ -47,6 +47,20 @@ str def_part = str_init("default"); +/* table & column names */ +str db_url; +str address_table = str_init("address"); /* Name of address table */ +str ip_col = str_init("ip"); /* Name of ip column */ +str proto_col = str_init("proto"); /* Name of protocol column */ +str pattern_col = str_init("pattern"); /* Name of pattern column */ +str info_col = str_init("context_info"); /* Name of context info column */ +str grp_col = str_init("grp"); /* Name of address group column */ +str mask_col = str_init("mask"); /* Name of mask column */ +str port_col = str_init("port"); /* Name of port column */ +str id_col = str_init("id"); /* Name of id column */ + +int init_address_part(struct pm_partition*); + int proto_char2int(str *proto) { int ret_proto; @@ -57,6 +71,45 @@ int proto_char2int(str *proto) { return ret_proto; } + +int init_address(void) +{ + struct pm_partition *el, *prev_el; + + if (db_url.s) + db_url.len = strlen(db_url.s); + + address_table.len = strlen(address_table.s); + ip_col.len = strlen(ip_col.s); + proto_col.len = strlen(proto_col.s); + pattern_col.len = strlen(pattern_col.s); + info_col.len = strlen(info_col.s); + grp_col.len = strlen(grp_col.s); + mask_col.len = strlen(mask_col.s); + port_col.len = strlen(port_col.s); + + if (init_address_df_part() != 0) { + LM_ERR("failed to init the 'default' partition\n"); + return -1; + } + + el = get_partitions(); + + while (el) { + if (init_address_part(el) != 0) { + LM_ERR("failed to initialize the '%.*s' partition\n", + el->name.len, el->name.s); + return -1; + } + prev_el = el; + el = el->next; + pkg_free(prev_el); + } + + return 0; +} + + /* * Reload address table to new hash table and when done, make new hash table * current one. @@ -288,7 +341,7 @@ int reload_address_table(struct pm_part_struct *part_struct) /* * Initialize data structures */ -int init_address(struct pm_partition *partition) +int init_address_part(struct pm_partition *partition) { struct pm_part_struct *part_struct; /* Check if hash table needs to be loaded from address table */ @@ -310,7 +363,7 @@ int init_address(struct pm_partition *partition) part_struct->table = partition->table; if (db_bind_mod(&partition->url, &part_struct->perm_dbf) < 0) { - LM_ERR("load a database support module\n"); + LM_ERR("failed to load a database support module\n"); return -1; } diff --git a/modules/permissions/address.h b/modules/permissions/address.h index b173cdc3d05..83c7c33a833 100644 --- a/modules/permissions/address.h +++ b/modules/permissions/address.h @@ -26,12 +26,26 @@ #include "../../parser/msg_parser.h" #include "partitions.h" +extern str def_part; +extern str db_url; /* Database URL */ +extern str address_table; /* Name of address table */ +extern str ip_col; /* Name of IP address column */ +extern str proto_col; /* Name of protocol column */ +extern str pattern_col; /* Name of pattern column */ +extern str info_col; /* Name of context_info column */ +extern str grp_col; /* Name of address group column */ +extern str mask_col; /* Name of mask column */ +extern str port_col; /* Name of port column */ +extern str id_col; /* Name of id column */ + + int proto_char2int(str *proto); + /* - * Initialize data structures + * Initialize partitions & load data, if necessary */ -int init_address(struct pm_partition*); +int init_address(void); /* diff --git a/modules/permissions/partitions.c b/modules/permissions/partitions.c index fd307dd2466..dbeac28d265 100644 --- a/modules/permissions/partitions.c +++ b/modules/permissions/partitions.c @@ -22,22 +22,24 @@ * */ #include +#include "address.h" #include "partitions.h" #include "../../str.h" #include "../../mem/mem.h" #include "../../ut.h" #include "../../db/db.h" +#include "../../lib/csv.h" #define ERR 1 -str part_db_url = {"db_url", sizeof("db_url") - 1}; -str part_table_name = {"table_name", sizeof("table_name") - 1}; +str part_db_url = str_init("db_url"); +str part_table_name = str_init("table_name"); /* since default partition will probably be used the most * it deserves a pointer for its own*/ -struct pm_partition *partitions=NULL, *default_partition=NULL; +struct pm_partition *partitions, *default_partition; -struct pm_part_struct *part_structs=NULL; +struct pm_part_struct *part_structs; static void *alloc_partitions(void) { @@ -52,8 +54,7 @@ static void *alloc_default_partition(void) default_partition = pkg_malloc(sizeof(struct pm_partition)); if (default_partition) { memset(default_partition, 0, sizeof(struct pm_partition)); - default_partition->name.s = "default"; - default_partition->name.len = sizeof("default") - 1; + default_partition->name = def_part; default_partition->next = partitions; partitions = default_partition; @@ -85,72 +86,33 @@ struct pm_partition *partition_set(void) return partitions; } -/* - * set default partition url - */ -int set_default_db_url(modparam_t type, void *val) +int init_address_df_part(void) { - str db_str; - - db_str.s = (char *)val; - db_str.len = strlen(db_str.s); - - str_trim_spaces_lr(db_str); - - if (default_partition == NULL) - if (alloc_default_partition() == NULL) - goto out_nomem; - - default_partition->url.s = (char *)val; - init_db_url( default_partition->url, 1 /* can be null */); + if (!db_url.s || default_partition) + return 0; - return 0; - -out_nomem: - LM_ERR("no more memory!\n"); - return -1; - -} - -/* - * set default partition table - */ -int set_default_table(modparam_t type, void *val) -{ - str db_table; - - db_table.s = (char *)val; - db_table.len = strlen(db_table.s); - - str_trim_spaces_lr(db_table); - - if (default_partition == NULL) - if (alloc_default_partition() == NULL) - goto out_nomem; - - default_partition->table = db_table; + if (!alloc_default_partition()) { + LM_ERR("oom\n"); + return -1; + } + default_partition->url = db_url; + default_partition->table = address_table; return 0; - -out_nomem: - LM_ERR("no more memory!\n"); - return -1; - } - /* * parse a partition parameter of type - * : attr1=val1; attr2=val2; + * : attr1=val1; attr2=val2 */ int parse_partition(modparam_t t, void *val) { - str type, value, token; - char *tok_end; - struct pm_partition *el, *it; + csv_record *name, *props, *params, *it; + str rem; + struct pm_partition *el, *part; - str decl = {(char*)val, strlen((char *)val)}; + str in = {(char*)val, strlen((char *)val)}; if (get_partitions() == NULL) { if (alloc_partitions() == NULL) @@ -162,71 +124,76 @@ int parse_partition(modparam_t t, void *val) goto out_memfault; memset(el, 0, sizeof(struct pm_partition)); - for (it=get_partitions(); it->next; it=it->next); - it->next = el; + for (part=get_partitions(); part->next; part=part->next); + part->next = el; } - tok_end = q_memchr(decl.s, ':', decl.len); - if (tok_end == NULL) - goto out_invdef; - - value.s = decl.s; - value.len = tok_end - decl.s; - - str_trim_spaces_lr(value); + name = __parse_csv_record(&in, 0, ':'); + if (!name) + goto bad_input; - el->name = value; + el->name = name->s; + if (str_match(&name->s, &def_part)) + default_partition = el; - decl.len = decl.len - (++tok_end - decl.s); - decl.s = tok_end; - - while (decl.len > 0 && decl.s) { - tok_end = q_memchr(decl.s, ';', decl.len); - if (tok_end == NULL) - break; - - token.s = decl.s; - token.len = tok_end - token.s; - - tok_end = q_memchr(token.s, '=', token.len); - if (tok_end == NULL) - break; - - type.s = token.s; - type.len = tok_end - type.s; - - value.s = tok_end + 1; - value.len = (token.s + token.len) - value.s; - - decl.s += token.len + 1; - decl.len -= (token.len + 1); + if (!name->next) { + free_csv_record(name); + goto empty_part; + } - str_trim_spaces_lr(type); - str_trim_spaces_lr(value); + rem.s = name->next->s.s; + rem.len = in.len - (rem.s - in.s); + props = __parse_csv_record(&rem, 0, ';'); + if (!props) + goto bad_input; + + free_csv_record(name); + + for (it = props; it; it = it->next) { + params = __parse_csv_record(&it->s, 0, '='); + if (!params) + goto bad_input; + + if (str_match(¶ms->s, &part_db_url)) { + el->url = params->next->s; + } else if (str_match(¶ms->s, &part_table_name)) { + el->table = params->next->s; + } else if (!ZSTR(params->s)) { + LM_ERR("invalid token '%.*s' in partition '%.*s'\n", + params->s.len, params->s.s, el->name.len, el->name.s); + goto bad_input; + } - if (!str_strcmp( &type, &part_db_url)) - el->url = value; - else if (!str_strcmp( &type, &part_table_name)) - el->table = value; - else - goto out_invdef; + free_csv_record(params); } - if (el->url.s == NULL) { - LM_ERR("you should define an URL for this partition %.*s\n", - el->name.len, el->name.s); - return -1; + free_csv_record(props); + +empty_part: + if (!el->url.s) { + if (db_url.s) { + init_str(&el->url, db_url.s); + } else if (db_default_url) { + init_str(&el->url, db_default_url); + } else { + LM_ERR("partition '%.*s' has no 'db_url'\n", + el->name.len, el->name.s); + return -1; + } } + if (!el->table.s) + init_str(&el->table, address_table.s); + return 0; -out_invdef: - LM_ERR("invalid partition definition!\n"); - return -ERR; +bad_input: + LM_ERR("failed to parse partition: '%.*s'\n", in.len, in.s); + return -1; out_memfault: LM_ERR("no more memory\n"); - return -ERR; + return -1; } diff --git a/modules/permissions/partitions.h b/modules/permissions/partitions.h index 33d885a9fb9..918a2a54b07 100644 --- a/modules/permissions/partitions.h +++ b/modules/permissions/partitions.h @@ -58,9 +58,8 @@ struct pm_part_struct { }; +int init_address_df_part(void); int parse_partition(modparam_t, void*); -int set_default_table(modparam_t, void *val); -int set_default_db_url(modparam_t, void *val); struct pm_partition *partition_set(void); struct pm_part_struct *get_part_structs(void); struct pm_part_struct *get_part_struct(str *name); diff --git a/modules/permissions/permissions.c b/modules/permissions/permissions.c index 726a5c5ab5c..aff17103ee2 100644 --- a/modules/permissions/permissions.c +++ b/modules/permissions/permissions.c @@ -45,7 +45,6 @@ #include "../../ut.h" - static rule_file_t allow[MAX_RULE_FILES]; /* Parsed allow files */ static rule_file_t deny[MAX_RULE_FILES]; /* Parsed deny files */ static int rules_num; /* Number of parsed allow/deny files */ @@ -58,20 +57,6 @@ char* allow_suffix = ".allow"; static char* deny_suffix = ".deny"; -/* for allow_address and allow_address function */ -str db_url = {NULL, 0}; /* Don't connect to the database by default */ - -/* for allow_address function */ -str address_table = str_init("address"); /* Name of address table */ -str ip_col = str_init("ip"); /* Name of ip column */ -str proto_col = str_init("proto"); /* Name of protocol column */ -str pattern_col = str_init("pattern"); /* Name of pattern column */ -str info_col = str_init("context_info"); /* Name of context info column */ -str grp_col = str_init("grp"); /* Name of address group column */ -str mask_col = str_init("mask"); /* Name of mask column */ -str port_col = str_init("port"); /* Name of port column */ -str id_col = str_init("id"); /* Name of id column */ - /* * By default we check all branches */ @@ -168,10 +153,8 @@ static param_export_t params[] = { {"deny_suffix", STR_PARAM, &deny_suffix }, {"partition", STR_PARAM|USE_FUNC_PARAM, (void *)parse_partition }, - {"db_url", STR_PARAM|USE_FUNC_PARAM, - (void *)set_default_db_url }, - {"address_table", STR_PARAM|USE_FUNC_PARAM, - (void *)set_default_table }, + {"db_url", STR_PARAM, &db_url }, + {"address_table", STR_PARAM, &address_table }, {"ip_col", STR_PARAM, &ip_col.s }, {"proto_col", STR_PARAM, &proto_col.s }, {"pattern_col", STR_PARAM, &pattern_col.s }, @@ -287,23 +270,21 @@ static int fix_proto(void** param) static int fix_part(void** param) { - str def_part_name = str_init("default"); str *s=(str*)*param; struct pm_part_struct *part; /* handle the special case when the fix is triggered for missing parameter */ - if (s==NULL) - s = &def_part_name; + if (!s) + s = &def_part; - part = get_part_struct( s ); - if (part==NULL) { + part = get_part_struct(s); + if (!part) { LM_ERR("invoked partition <%.*s> not defined\n", s->len, s->s); return -1; } *param = part; - return 1; } @@ -613,18 +594,8 @@ static int fix_filename(void** param) */ static int mod_init(void) { - struct pm_partition *el, *prev_el=NULL; - LM_DBG("initializing...\n"); - ip_col.len = strlen(ip_col.s); - proto_col.len = strlen(proto_col.s); - pattern_col.len = strlen(pattern_col.s); - info_col.len = strlen(info_col.s); - grp_col.len = strlen(grp_col.s); - mask_col.len = strlen(mask_col.s); - port_col.len = strlen(port_col.s); - allow[0].filename = get_pathname(default_allow_file); allow[0].rules = parse_config_file(allow[0].filename); @@ -645,22 +616,9 @@ static int mod_init(void) deny[0].filename); } - - el = get_partitions(); - while (el) { - /* initialize table name if not done from script */ - if (el->table.s == NULL) { - el->table.s = "address"; - el->table.len = strlen(el->table.s); - } - - if (init_address(el) != 0) { - LM_ERR("failed to initialize the allow_address function\n"); - return -1; - } - prev_el = el; - el = el->next; - pkg_free(prev_el); + if (init_address() != 0) { + LM_ERR("failed to init or load DB partitions\n"); + return -1; } rules_num = 1; diff --git a/modules/permissions/permissions.h b/modules/permissions/permissions.h index 195f4238c78..37948088692 100644 --- a/modules/permissions/permissions.h +++ b/modules/permissions/permissions.h @@ -47,17 +47,6 @@ typedef struct rule_file { */ #define MAX_RULE_FILES 64 -extern str db_url; /* Database URL */ -extern str address_table; /* Name of address table */ -extern str ip_col; /* Name of IP address column */ -extern str proto_col; /* Name of protocol column */ -extern str pattern_col; /* Name of pattern column */ -extern str info_col; /* Name of context_info column */ -extern str grp_col; /* Name of address group column */ -extern str mask_col; /* Name of mask column */ -extern str port_col; /* Name of port column */ -extern str id_col; /* Name of id column */ - typedef struct int_or_pvar { unsigned int i; pv_spec_t *pvar; /* zero if int */