/* * Do any per-module initialization that is separate to each * configured instance of the module. e.g. set up connections * to external databases, read configuration files, set up * dictionary entries, etc. * * If configuration information is given in the config section * that must be referenced in later calls, store a handle to it * in *instance otherwise put a null pointer there. */ static int mod_instantiate(CONF_SECTION *conf, void *instance) { rlm_example_t *inst = instance; ATTR_FLAGS flags; memset(&flags, 0, sizeof(flags)); /* * Do more work here */ if (!inst->boolean) { cf_log_err_cs(conf, "Boolean is false: forcing error!"); return -1; } if (dict_addattr("Example-Paircmp", -1, 0, PW_TYPE_STRING, flags) < 0) { ERROR("Failed creating paircmp attribute: %s", fr_strerror()); return -1; } paircompare_register(dict_attrbyname("Example-Paircmp"), dict_attrbyvalue(PW_USER_NAME, 0), false, rlm_example_cmp, inst); return 0; }
/** Instantiate the module * * Creates a new instance of the module reading parameters from a configuration section. * * @param conf to parse. * @param instance Where to write pointer to configuration data. * @return 0 on success < 0 on failure. */ static int mod_instantiate(CONF_SECTION *conf, void *instance) { static bool version_done; CONF_SECTION *options; ldap_instance_t *inst = instance; inst->cs = conf; options = cf_section_sub_find(conf, "options"); if (!options || !cf_pair_find(options, "chase_referrals")) { inst->chase_referrals_unset = true; /* use OpenLDAP defaults */ } inst->xlat_name = cf_section_name2(conf); if (!inst->xlat_name) { inst->xlat_name = cf_section_name1(conf); } /* * Only needs to be done once, prevents races in environment * initialisation within libldap. * * See: https://github.com/arr2036/ldapperf/issues/2 */ #ifdef HAVE_LDAP_INITIALIZE ldap_initialize(&inst->handle, ""); #else inst->handle = ldap_init("", 0); #endif /* * Get version info from the LDAP API. */ if (!version_done) { static LDAPAPIInfo info; /* static to quiet valgrind about this being uninitialised */ int ldap_errno; version_done = true; ldap_errno = ldap_get_option(NULL, LDAP_OPT_API_INFO, &info); if (ldap_errno == LDAP_OPT_SUCCESS) { if (strcmp(info.ldapai_vendor_name, LDAP_VENDOR_NAME) != 0) { WARN("rlm_ldap: libldap vendor changed since the server was built"); WARN("rlm_ldap: linked: %s, built: %s", info.ldapai_vendor_name, LDAP_VENDOR_NAME); } if (info.ldapai_vendor_version != LDAP_VENDOR_VERSION) { WARN("rlm_ldap: libldap version changed since the server was built"); WARN("rlm_ldap: linked: %i, built: %i", info.ldapai_vendor_version, LDAP_VENDOR_VERSION); } INFO("rlm_ldap: libldap vendor: %s, version: %i", info.ldapai_vendor_name, info.ldapai_vendor_version); ldap_memfree(info.ldapai_vendor_name); ldap_memfree(info.ldapai_extensions); } else { DEBUG("rlm_ldap: Falling back to build time libldap version info. Query for LDAP_OPT_API_INFO " "returned: %i", ldap_errno); INFO("rlm_ldap: libldap vendor: %s, version: %i.%i.%i", LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION_MAJOR, LDAP_VENDOR_VERSION_MINOR, LDAP_VENDOR_VERSION_PATCH); } } /* * If the configuration parameters can't be parsed, then fail. */ if ((parse_sub_section(inst, conf, &inst->accounting, RLM_COMPONENT_ACCT) < 0) || (parse_sub_section(inst, conf, &inst->postauth, RLM_COMPONENT_POST_AUTH) < 0)) { cf_log_err_cs(conf, "Failed parsing configuration"); goto error; } /* * Sanity checks for cacheable groups code. */ if (inst->cacheable_group_name && inst->groupobj_membership_filter) { if (!inst->groupobj_name_attr) { cf_log_err_cs(conf, "Directive 'group.name_attribute' must be set if cacheable " "group names are enabled"); goto error; } } /* * Split original server value out into URI, server and port * so whatever initialization function we use later will have * the server information in the format it needs. */ if (ldap_is_ldap_url(inst->server)) { LDAPURLDesc *ldap_url; int port; if (ldap_url_parse(inst->server, &ldap_url)){ cf_log_err_cs(conf, "Parsing LDAP URL \"%s\" failed", inst->server); return -1; } /* * Figure out the port from the URL */ if (ldap_url->lud_port == 0) { if (strcmp(ldap_url->lud_scheme, "ldaps://") == 0) { if (inst->start_tls == true) { start_tls_error: cf_log_err_cs(conf, "ldaps:// scheme is not compatible with 'start_tls'"); return -1; } port = 636; } else { port = 384; } } else { port = ldap_url->lud_port; } inst->uri = inst->server; inst->server = talloc_strdup(inst, ldap_url->lud_host); if ((inst->port != 384) && (port != inst->port)) { WARN("Non-default 'port' directive %i set to %i by LDAP URI", inst->port, port); } inst->port = port; /* * @todo We could set a few other top level * directives using the URL, like base_dn * and scope. */ ldap_free_urldesc(ldap_url); /* * We need to construct an LDAP URI */ } else { switch (inst->port) { default: case 384: inst->uri = talloc_asprintf(inst, "ldap://%s:%i/", inst->server, inst->port); break; case 636: if (inst->start_tls == true) goto start_tls_error; inst->uri = talloc_asprintf(inst, "ldaps://%s:%i/", inst->server, inst->port); break; } } #ifdef LDAP_OPT_X_TLS_NEVER /* * Workaround for servers which support LDAPS but not START TLS */ if (inst->port == LDAPS_PORT || inst->tls_mode) { inst->tls_mode = LDAP_OPT_X_TLS_HARD; } else { inst->tls_mode = 0; } #endif /* * Convert dereference strings to enumerated constants */ if (inst->dereference_str) { inst->dereference = fr_str2int(ldap_dereference, inst->dereference_str, -1); if (inst->dereference < 0) { cf_log_err_cs(conf, "Invalid 'dereference' value \"%s\", expected 'never', 'searching', " "'finding' or 'always'", inst->dereference_str); goto error; } } #if LDAP_SET_REBIND_PROC_ARGS != 3 /* * The 2-argument rebind doesn't take an instance variable. Our rebind function needs the instance * variable for the username, password, etc. */ if (inst->rebind == true) { cf_log_err_cs(conf, "Cannot use 'rebind' directive as this version of libldap " "does not support the API that we need"); goto error; } #endif /* * Convert scope strings to enumerated constants */ inst->userobj_scope = fr_str2int(ldap_scope, inst->userobj_scope_str, -1); if (inst->userobj_scope < 0) { cf_log_err_cs(conf, "Invalid 'user.scope' value \"%s\", expected 'sub', 'one'" #ifdef LDAP_SCOPE_CHILDREN ", 'base' or 'children'" #else " or 'base'" #endif , inst->userobj_scope_str); goto error; } inst->groupobj_scope = fr_str2int(ldap_scope, inst->groupobj_scope_str, -1); if (inst->groupobj_scope < 0) { cf_log_err_cs(conf, "Invalid 'group.scope' value \"%s\", expected 'sub', 'one'" #ifdef LDAP_SCOPE_CHILDREN ", 'base' or 'children'" #else " or 'base'" #endif , inst->groupobj_scope_str); goto error; } inst->clientobj_scope = fr_str2int(ldap_scope, inst->clientobj_scope_str, -1); if (inst->clientobj_scope < 0) { cf_log_err_cs(conf, "Invalid 'client.scope' value \"%s\", expected 'sub', 'one'" #ifdef LDAP_SCOPE_CHILDREN ", 'base' or 'children'" #else " or 'base'" #endif , inst->clientobj_scope_str); goto error; } if (inst->tls_require_cert_str) { #ifdef LDAP_OPT_X_TLS_NEVER /* * Convert cert strictness to enumerated constants */ inst->tls_require_cert = fr_str2int(ldap_tls_require_cert, inst->tls_require_cert_str, -1); if (inst->tls_require_cert < 0) { cf_log_err_cs(conf, "Invalid 'tls.require_cert' value \"%s\", expected 'never', " "'demand', 'allow', 'try' or 'hard'", inst->tls_require_cert_str); goto error; } #else cf_log_err_cs(conf, "Modifying 'tls.require_cert' is not supported by current " "version of libldap. Please upgrade or substitute current libldap and " "rebuild this module"); goto error; #endif } /* * Build the attribute map */ if (map_afrom_cs(&inst->user_map, cf_section_sub_find(inst->cs, "update"), PAIR_LIST_REPLY, PAIR_LIST_REQUEST, rlm_ldap_map_verify, inst, LDAP_MAX_ATTRMAP) < 0) { return -1; } /* * Group comparison checks. */ if (cf_section_name2(conf)) { static ATTR_FLAGS flags; char buffer[256]; snprintf(buffer, sizeof(buffer), "%s-Ldap-Group", inst->xlat_name); if (dict_addattr(buffer, -1, 0, PW_TYPE_STRING, flags) < 0) { LDAP_ERR("Error creating group attribute: %s", fr_strerror()); return -1; } inst->group_da = dict_attrbyname(buffer); if (!inst->group_da) { LDAP_ERR("Failed creating attribute %s", buffer); goto error; } paircompare_register(inst->group_da, dict_attrbyvalue(PW_USER_NAME, 0), false, rlm_ldap_groupcmp, inst); /* * Were the default instance */ } else { inst->group_da = dict_attrbyvalue(PW_LDAP_GROUP, 0); paircompare_register(dict_attrbyvalue(PW_LDAP_GROUP, 0), dict_attrbyvalue(PW_USER_NAME, 0), false, rlm_ldap_groupcmp, inst); } xlat_register(inst->xlat_name, ldap_xlat, rlm_ldap_escape_func, inst); /* * Setup the cache attribute */ if (inst->cache_attribute) { static ATTR_FLAGS flags; if (dict_addattr(inst->cache_attribute, -1, 0, PW_TYPE_STRING, flags) < 0) { LDAP_ERR("Error creating cache attribute: %s", fr_strerror()); goto error; } inst->cache_da = dict_attrbyname(inst->cache_attribute); } else { inst->cache_da = inst->group_da; /* Default to the group_da */ } /* * Initialize the socket pool. */ inst->pool = fr_connection_pool_module_init(inst->cs, inst, mod_conn_create, NULL, NULL); if (!inst->pool) goto error; /* * Bulk load dynamic clients. */ if (inst->do_clients) { CONF_SECTION *cs; cs = cf_section_sub_find(inst->cs, "client"); if (!cs) { cf_log_err_cs(conf, "Told to load clients but no client section found"); goto error; } cs = cf_section_sub_find(cs, "attribute"); if (!cs) { cf_log_err_cs(conf, "Told to load clients but no attribute section found"); goto error; } if (rlm_ldap_client_load(inst, cs) < 0) { cf_log_err_cs(conf, "Error loading clients"); return -1; } } return 0; error: return -1; }
static int mod_instantiate(CONF_SECTION *conf, void *instance) { rlm_sql_t *inst = instance; /* * Hack... */ inst->config = &inst->myconfig; inst->cs = conf; inst->config->xlat_name = cf_section_name2(conf); if (!inst->config->xlat_name) { inst->config->xlat_name = cf_section_name1(conf); } else { char *group_name; DICT_ATTR const *da; ATTR_FLAGS flags; /* * Allocate room for <instance>-SQL-Group */ group_name = talloc_typed_asprintf(inst, "%s-SQL-Group", inst->config->xlat_name); DEBUG("rlm_sql (%s): Creating new attribute %s", inst->config->xlat_name, group_name); memset(&flags, 0, sizeof(flags)); if (dict_addattr(group_name, -1, 0, PW_TYPE_STRING, flags) < 0) { ERROR("rlm_sql (%s): Failed to create " "attribute %s: %s", inst->config->xlat_name, group_name, fr_strerror()); return -1; } da = dict_attrbyname(group_name); if (!da) { ERROR("rlm_sql (%s): Failed to create " "attribute %s", inst->config->xlat_name, group_name); return -1; } if (inst->config->groupmemb_query && inst->config->groupmemb_query[0]) { DEBUG("rlm_sql (%s): Registering sql_groupcmp for %s", inst->config->xlat_name, group_name); paircompare_register(da, dict_attrbyvalue(PW_USER_NAME, 0), false, sql_groupcmp, inst); } } rad_assert(inst->config->xlat_name); /* * If the configuration parameters can't be parsed, then fail. */ if ((parse_sub_section(conf, inst, &inst->config->accounting, RLM_COMPONENT_ACCT) < 0) || (parse_sub_section(conf, inst, &inst->config->postauth, RLM_COMPONENT_POST_AUTH) < 0)) { cf_log_err_cs(conf, "Invalid configuration"); return -1; } /* * Cache the SQL-User-Name DICT_ATTR, so we can be slightly * more efficient about creating SQL-User-Name attributes. */ inst->sql_user = dict_attrbyname("SQL-User-Name"); if (!inst->sql_user) { return -1; } /* * Export these methods, too. This avoids RTDL_GLOBAL. */ inst->sql_set_user = sql_set_user; inst->sql_get_socket = sql_get_socket; inst->sql_release_socket = sql_release_socket; inst->sql_escape_func = sql_escape_func; inst->sql_query = rlm_sql_query; inst->sql_select_query = rlm_sql_select_query; inst->sql_fetch_row = rlm_sql_fetch_row; /* * Register the SQL xlat function */ xlat_register(inst->config->xlat_name, sql_xlat, sql_escape_func, inst); /* * Sanity check for crazy people. */ if (strncmp(inst->config->sql_driver_name, "rlm_sql_", 8) != 0) { ERROR("rlm_sql (%s): \"%s\" is NOT an SQL driver!", inst->config->xlat_name, inst->config->sql_driver_name); return -1; } /* * Load the appropriate driver for our database */ inst->handle = lt_dlopenext(inst->config->sql_driver_name); if (!inst->handle) { ERROR("Could not link driver %s: %s", inst->config->sql_driver_name, dlerror()); ERROR("Make sure it (and all its dependent libraries!)" "are in the search path of your system's ld"); return -1; } inst->module = (rlm_sql_module_t *) dlsym(inst->handle, inst->config->sql_driver_name); if (!inst->module) { ERROR("Could not link symbol %s: %s", inst->config->sql_driver_name, dlerror()); return -1; } if (inst->module->mod_instantiate) { CONF_SECTION *cs; char const *name; name = strrchr(inst->config->sql_driver_name, '_'); if (!name) { name = inst->config->sql_driver_name; } else { name++; } cs = cf_section_sub_find(conf, name); if (!cs) { cs = cf_section_alloc(conf, name, NULL); if (!cs) { return -1; } } /* * It's up to the driver to register a destructor */ if (inst->module->mod_instantiate(cs, inst->config) < 0) { return -1; } } inst->lf = fr_logfile_init(inst); if (!inst->lf) { cf_log_err_cs(conf, "Failed creating log file context"); return -1; } INFO("rlm_sql (%s): Driver %s (module %s) loaded and linked", inst->config->xlat_name, inst->config->sql_driver_name, inst->module->name); /* * Initialise the connection pool for this instance */ INFO("rlm_sql (%s): Attempting to connect to database \"%s\"", inst->config->xlat_name, inst->config->sql_db); if (sql_socket_pool_init(inst) < 0) return -1; if (inst->config->groupmemb_query && inst->config->groupmemb_query[0]) { paircompare_register(dict_attrbyvalue(PW_SQL_GROUP, 0), dict_attrbyvalue(PW_USER_NAME, 0), false, sql_groupcmp, inst); } if (inst->config->do_clients) { if (generate_sql_clients(inst) == -1){ ERROR("Failed to load clients from SQL"); return -1; } } return RLM_MODULE_OK; }
/* * Do any per-module initialization that is separate to each * configured instance of the module. e.g. set up connections * to external databases, read configuration files, set up * dictionary entries, etc. * * If configuration information is given in the config section * that must be referenced in later calls, store a handle to it * in *instance otherwise put a null pointer there. */ static int sqlcounter_instantiate(CONF_SECTION *conf, void **instance) { rlm_sqlcounter_t *data; DICT_ATTR *dattr; ATTR_FLAGS flags; time_t now; char buffer[MAX_STRING_LEN]; /* * Set up a storage area for instance data */ data = rad_malloc(sizeof(*data)); if (!data) { return -1; } memset(data, 0, sizeof(*data)); /* * If the configuration parameters can't be parsed, then * fail. */ if (cf_section_parse(conf, data, module_config) < 0) { free(data); return -1; } /* * No query, die. */ if (data->query == NULL) { radlog(L_ERR, "rlm_sqlcounter: 'query' must be set."); return -1; } /* * Safe characters list for sql queries. Everything else is * replaced rwith their mime-encoded equivalents. */ allowed_chars = data->allowed_chars; /* * Discover the attribute number of the key. */ if (data->key_name == NULL) { radlog(L_ERR, "rlm_sqlcounter: 'key' must be set."); return -1; } sql_escape_func(buffer, sizeof(buffer), data->key_name); if (strcmp(buffer, data->key_name) != 0) { radlog(L_ERR, "rlm_sqlcounter: The value for option 'key' is too long or contains unsafe characters."); return -1; } dattr = dict_attrbyname(data->key_name); if (dattr == NULL) { radlog(L_ERR, "rlm_sqlcounter: No such attribute %s", data->key_name); return -1; } data->key_attr = dattr->attr; /* * Check the "sqlmod-inst" option. */ if (data->sqlmod_inst == NULL) { radlog(L_ERR, "rlm_sqlcounter: 'sqlmod-inst' must be set."); return -1; } sql_escape_func(buffer, sizeof(buffer), data->sqlmod_inst); if (strcmp(buffer, data->sqlmod_inst) != 0) { radlog(L_ERR, "rlm_sqlcounter: The value for option 'sqlmod-inst' is too long or contains unsafe characters."); return -1; } /* * Create a new attribute for the counter. */ if (data->counter_name == NULL) { radlog(L_ERR, "rlm_sqlcounter: 'counter-name' must be set."); return -1; } memset(&flags, 0, sizeof(flags)); dict_addattr(data->counter_name, 0, PW_TYPE_INTEGER, -1, flags); dattr = dict_attrbyname(data->counter_name); if (dattr == NULL) { radlog(L_ERR, "rlm_sqlcounter: Failed to create counter attribute %s", data->counter_name); return -1; } data->dict_attr = dattr->attr; DEBUG2("rlm_sqlcounter: Counter attribute %s is number %d", data->counter_name, data->dict_attr); /* * Create a new attribute for the check item. */ if (data->check_name == NULL) { radlog(L_ERR, "rlm_sqlcounter: 'check-name' must be set."); return -1; } dict_addattr(data->check_name, 0, PW_TYPE_INTEGER, -1, flags); dattr = dict_attrbyname(data->check_name); if (dattr == NULL) { radlog(L_ERR, "rlm_sqlcounter: Failed to create check attribute %s", data->counter_name); return -1; } DEBUG2("rlm_sqlcounter: Check attribute %s is number %d", data->check_name, dattr->attr); /* * Discover the end of the current time period. */ if (data->reset == NULL) { radlog(L_ERR, "rlm_sqlcounter: 'reset' must be set."); return -1; } now = time(NULL); data->reset_time = 0; if (find_next_reset(data,now) == -1) return -1; /* * Discover the beginning of the current time period. */ data->last_reset = 0; if (find_prev_reset(data,now) == -1) return -1; /* * Register the counter comparison operation. */ paircompare_register(data->dict_attr, 0, sqlcounter_cmp, data); *instance = data; return 0; }
/** Instantiate the module * * Creates a new instance of the module reading parameters from a configuration section. * * @param conf to parse. * @param instance Where to write pointer to configuration data. * @return 0 on success < 0 on failure. */ static int mod_instantiate(CONF_SECTION *conf, void *instance) { CONF_SECTION *options; ldap_instance_t *inst = instance; inst->cs = conf; options = cf_section_sub_find(conf, "options"); if (!options || !cf_pair_find(options, "chase_referrals")) { inst->chase_referrals_unset = true; /* use OpenLDAP defaults */ } inst->xlat_name = cf_section_name2(conf); if (!inst->xlat_name) { inst->xlat_name = cf_section_name1(conf); } /* * If the configuration parameters can't be parsed, then fail. */ if ((parse_sub_section(inst, conf, &inst->accounting, RLM_COMPONENT_ACCT) < 0) || (parse_sub_section(inst, conf, &inst->postauth, RLM_COMPONENT_POST_AUTH) < 0)) { LDAP_ERR("Failed parsing configuration"); goto error; } /* * Sanity checks for cacheable groups code. */ if (inst->cacheable_group_name && inst->groupobj_membership_filter) { if (!inst->groupobj_name_attr) { LDAP_ERR("Directive 'group.name_attribute' must be set if cacheable group names are enabled"); goto error; } } /* * Check for URLs. If they're used and the library doesn't support them, then complain. */ inst->is_url = 0; if (ldap_is_ldap_url(inst->server)) { #ifdef HAVE_LDAP_INITIALIZE inst->is_url = 1; inst->port = 0; #else LDAP_ERR("Directive 'server' is in URL form but ldap_initialize() is not available"); goto error; #endif } /* * Workaround for servers which support LDAPS but not START TLS */ if (inst->port == LDAPS_PORT || inst->tls_mode) { inst->tls_mode = LDAP_OPT_X_TLS_HARD; } else { inst->tls_mode = 0; } #if LDAP_SET_REBIND_PROC_ARGS != 3 /* * The 2-argument rebind doesn't take an instance variable. Our rebind function needs the instance * variable for the username, password, etc. */ if (inst->rebind == true) { LDAP_ERR("Cannot use 'rebind' directive as this version of libldap does not support the API " "that we need"); goto error; } #endif /* * Convert scope strings to enumerated constants */ inst->userobj_scope = fr_str2int(ldap_scope, inst->userobj_scope_str, -1); if (inst->userobj_scope < 0) { LDAP_ERR("Invalid 'user.scope' value \"%s\", expected 'sub', 'one', 'base' or 'children'", inst->userobj_scope_str); goto error; } inst->groupobj_scope = fr_str2int(ldap_scope, inst->groupobj_scope_str, -1); if (inst->groupobj_scope < 0) { LDAP_ERR("Invalid 'group.scope' value \"%s\", expected 'sub', 'one', 'base' or 'children'", inst->groupobj_scope_str); goto error; } inst->clientobj_scope = fr_str2int(ldap_scope, inst->clientobj_scope_str, -1); if (inst->clientobj_scope < 0) { LDAP_ERR("Invalid 'client.scope' value \"%s\", expected 'sub', 'one', 'base' or 'children'", inst->clientobj_scope_str); goto error; } if (inst->tls_require_cert_str) { #ifdef LDAP_OPT_X_TLS_NEVER /* * Convert cert strictness to enumerated constants */ inst->tls_require_cert = fr_str2int(ldap_tls_require_cert, inst->tls_require_cert_str, -1); if (inst->tls_require_cert < 0) { LDAP_ERR("Invalid 'tls.require_cert' value \"%s\", expected 'never', 'demand', 'allow', " "'try' or 'hard'", inst->tls_require_cert_str); goto error; } #else LDAP_ERR("Modifying 'tls.require_cert' is not supported by current version of libldap. " "Please upgrade libldap and rebuild this module"); goto error; #endif } /* * Build the attribute map */ if (rlm_ldap_map_verify(inst, &(inst->user_map)) < 0) { goto error; } /* * Group comparison checks. */ if (cf_section_name2(conf)) { ATTR_FLAGS flags; char buffer[256]; snprintf(buffer, sizeof(buffer), "%s-Ldap-Group", inst->xlat_name); memset(&flags, 0, sizeof(flags)); if (dict_addattr(buffer, -1, 0, PW_TYPE_STRING, flags) < 0) { LDAP_ERR("Error creating group attribute: %s", fr_strerror()); return -1; } inst->group_da = dict_attrbyname(buffer); if (!inst->group_da) { LDAP_ERR("Failed creating attribute %s", buffer); goto error; } paircompare_register(inst->group_da, dict_attrbyvalue(PW_USER_NAME, 0), false, rlm_ldap_groupcmp, inst); /* * Were the default instance */ } else { inst->group_da = dict_attrbyvalue(PW_LDAP_GROUP, 0); paircompare_register(dict_attrbyvalue(PW_LDAP_GROUP, 0), dict_attrbyvalue(PW_USER_NAME, 0), false, rlm_ldap_groupcmp, inst); } xlat_register(inst->xlat_name, ldap_xlat, rlm_ldap_escape_func, inst); /* * Setup the cache attribute */ if (inst->cache_attribute) { ATTR_FLAGS flags; memset(&flags, 0, sizeof(flags)); if (dict_addattr(inst->cache_attribute, -1, 0, PW_TYPE_STRING, flags) < 0) { LDAP_ERR("Error creating cache attribute: %s", fr_strerror()); return -1; } inst->cache_da = dict_attrbyname(inst->cache_attribute); } else { inst->cache_da = inst->group_da; /* Default to the group_da */ } /* * Initialize the socket pool. */ inst->pool = fr_connection_pool_init(inst->cs, inst, mod_conn_create, NULL, mod_conn_delete, NULL); if (!inst->pool) { return -1; } /* * Bulk load dynamic clients. */ if (inst->do_clients) { if (rlm_ldap_load_clients(inst) < 0) { LDAP_ERR("Error loading clients"); return -1; } } return 0; error: return -1; }
/* * Process the ATTRIBUTE command */ static int process_attribute(const char* fn, const int line, const int block_vendor, DICT_ATTR *block_tlv, char **argv, int argc) { int vendor = 0; int value; int type; ATTR_FLAGS flags; if ((argc < 3) || (argc > 4)) { fr_strerror_printf("dict_init: %s[%d]: invalid ATTRIBUTE line", fn, line); return -1; } /* * Validate all entries */ if (!sscanf_i(argv[1], &value)) { fr_strerror_printf("dict_init: %s[%d]: invalid value", fn, line); return -1; } /* * find the type of the attribute. */ type = fr_str2int(type_table, argv[2], -1); if (type < 0) { fr_strerror_printf("dict_init: %s[%d]: invalid type \"%s\"", fn, line, argv[2]); return -1; } /* * Only look up the vendor if the string * is non-empty. */ memset(&flags, 0, sizeof(flags)); if (argc == 4) { char *key, *next, *last; key = argv[3]; do { next = strchr(key, ','); if (next) *(next++) = '\0'; if (strcmp(key, "has_tag") == 0 || strcmp(key, "has_tag=1") == 0) { /* Boolean flag, means this is a tagged attribute */ flags.has_tag = 1; } else if (strncmp(key, "encrypt=", 8) == 0) { /* Encryption method, defaults to 0 (none). Currently valid is just type 2, Tunnel-Password style, which can only be applied to strings. */ flags.encrypt = strtol(key + 8, &last, 0); if (*last) { fr_strerror_printf( "dict_init: %s[%d] invalid option %s", fn, line, key); return -1; } } else if (strncmp(key, "array", 8) == 0) { flags.array = 1; switch (type) { case PW_TYPE_IPADDR: case PW_TYPE_BYTE: case PW_TYPE_SHORT: case PW_TYPE_INTEGER: case PW_TYPE_DATE: break; default: fr_strerror_printf( "dict_init: %s[%d] Only IP addresses can have the \"array\" flag set.", fn, line); return -1; } /* * The only thing is the vendor name, * and it's a known name: allow it. */ } else if ((key == argv[3]) && !next && !block_vendor && ((vendor = dict_vendorbyname(key)) !=0)) { break; } else { fr_strerror_printf( "dict_init: %s[%d]: unknown option \"%s\"", fn, line, key); return -1; } key = next; if (key && !*key) break; } while (key); } if (block_vendor) vendor = block_vendor; /* * Special checks for tags, they make our life much more * difficult. */ if (flags.has_tag) { /* * Only string, octets, and integer can be tagged. */ switch (type) { case PW_TYPE_STRING: case PW_TYPE_INTEGER: break; default: fr_strerror_printf("dict_init: %s[%d]: Attributes of type %s cannot be tagged.", fn, line, fr_int2str(type_table, type, "?Unknown?")); return -1; } } if (type == PW_TYPE_TLV) { flags.has_tlv = 1; } if (block_tlv) { /* * TLV's can be only one octet. */ if ((value <= 0) || (value > 255)) { fr_strerror_printf( "dict_init: %s[%d]: sub-tlv's cannot have value > 255", fn, line); return -1; } if (flags.encrypt != FLAG_ENCRYPT_NONE) { fr_strerror_printf( "dict_init: %s[%d]: sub-tlv's cannot be encrypted", fn, line); return -1; } /* * */ value <<= 8; value |= (block_tlv->attr & 0xffff); flags.is_tlv = 1; } #ifdef WITH_DICTIONARY_WARNINGS /* * Hack to help us discover which vendors have illegal * attributes. */ if (!vendor && (value < 256) && !strstr(fn, "rfc") && !strstr(fn, "illegal")) { fprintf(stderr, "WARNING: Illegal Attribute %s in %s\n", argv[0], fn); } #endif /* * Add it in. */ if (dict_addattr(argv[0], vendor, type, value, flags) < 0) { char buffer[256]; strlcpy(buffer, fr_strerror(), sizeof(buffer)); fr_strerror_printf("dict_init: %s[%d]: %s", fn, line, buffer); return -1; } return 0; }
/* * Do any per-module initialization that is separate to each * configured instance of the module. e.g. set up connections * to external databases, read configuration files, set up * dictionary entries, etc. * * If configuration information is given in the config section * that must be referenced in later calls, store a handle to it * in *instance otherwise put a null pointer there. */ static int checkval_instantiate(CONF_SECTION *conf, void **instance) { rlm_checkval_t *data; DICT_ATTR *dattr; ATTR_FLAGS flags; static const LRAD_NAME_NUMBER names[] = { { "string", PW_TYPE_STRING }, { "integer", PW_TYPE_INTEGER }, { "ipaddr", PW_TYPE_IPADDR }, { "date", PW_TYPE_DATE }, { "abinary", PW_TYPE_OCTETS }, { "octets", PW_TYPE_OCTETS }, { "binary", PW_TYPE_OCTETS }, { NULL, 0 } }; /* * Set up a storage area for instance data */ data = rad_malloc(sizeof(*data)); if (!data) { return -1; } memset(data, 0, sizeof(*data)); /* * If the configuration parameters can't be parsed, then * fail. */ if (cf_section_parse(conf, data, module_config) < 0) { checkval_detach(data); return -1; } /* * Check if data_type exists */ if (!data->data_type || !strlen(data->data_type)){ radlog(L_ERR, "rlm_checkval: Data type not defined"); checkval_detach(data); return -1; } if (!data->item_name || !strlen(data->item_name)){ radlog(L_ERR, "rlm_checkval: Item name not defined"); checkval_detach(data); return -1; } if (!data->check_name || !strlen(data->check_name)){ radlog(L_ERR, "rlm_checkval: Check item name not defined"); checkval_detach(data); return -1; } /* * Discover the attribute number of the item name */ dattr = dict_attrbyname(data->item_name); if (!dattr) { radlog(L_ERR, "rlm_checkval: No such attribute %s", data->item_name); checkval_detach(data); return -1; } data->item_attr = dattr->attr; /* * Add the check attribute name to the dictionary * if it does not already exists. dict_addattr() handles that */ memset(&flags, 0, sizeof(flags)); dict_addattr(data->check_name, 0, PW_TYPE_STRING, -1,flags); dattr = dict_attrbyname(data->check_name); if (!dattr){ radlog(L_ERR, "rlm_checkval: No such attribute %s", data->check_name); checkval_detach(data); return -1; } data->chk_attr = dattr->attr; DEBUG2("rlm_checkval: Registered name %s for attribute %d", dattr->name,dattr->attr); /* * Convert the string type to an integer type, * so we don't have to do string comparisons on each * packet. */ data->dat_type = lrad_str2int(names, data->data_type, -1); if (data->dat_type < 0) { radlog(L_ERR, "rlm_checkval: Data type %s in not known",data->data_type); checkval_detach(data); return -1; } *instance = data; return 0; }
/* * Do any per-module initialization that is separate to each * configured instance of the module. e.g. set up connections * to external databases, read configuration files, set up * dictionary entries, etc. * * If configuration information is given in the config section * that must be referenced in later calls, store a handle to it * in *instance otherwise put a null pointer there. */ static int sqlcounter_instantiate(CONF_SECTION *conf, void **instance) { rlm_sqlcounter_t *data; DICT_ATTR *dattr; ATTR_FLAGS flags; time_t now; /* * Set up a storage area for instance data */ data = rad_malloc(sizeof(*data)); if (!data) { radlog(L_ERR, "rlm_sqlcounter: Not enough memory."); return -1; } memset(data, 0, sizeof(*data)); /* * If the configuration parameters can't be parsed, then * fail. */ if (cf_section_parse(conf, data, module_config) < 0) { radlog(L_ERR, "rlm_sqlcounter: Unable to parse parameters."); sqlcounter_detach(data); return -1; } /* * No query, die. */ if (data->query == NULL) { radlog(L_ERR, "rlm_sqlcounter: 'query' must be set."); sqlcounter_detach(data); return -1; } /* * Discover the attribute number of the key. */ if (data->key_name == NULL) { radlog(L_ERR, "rlm_sqlcounter: 'key' must be set."); sqlcounter_detach(data); return -1; } dattr = dict_attrbyname(data->key_name); if (dattr == NULL) { radlog(L_ERR, "rlm_sqlcounter: No such attribute %s", data->key_name); sqlcounter_detach(data); return -1; } data->key_attr = dattr; dattr = dict_attrbyname(data->reply_name); if (dattr == NULL) { radlog(L_ERR, "rlm_sqlcounter: No such attribute %s", data->reply_name); sqlcounter_detach(data); return -1; } data->reply_attr = dattr; DEBUG2("rlm_sqlcounter: Reply attribute %s is number %d", data->reply_name, dattr->attr); /* * Check the "sqlmod-inst" option. */ if (data->sqlmod_inst == NULL) { radlog(L_ERR, "rlm_sqlcounter: 'sqlmod-inst' must be set."); sqlcounter_detach(data); return -1; } /* * Create a new attribute for the counter. */ if (data->counter_name == NULL) { radlog(L_ERR, "rlm_sqlcounter: 'counter-name' must be set."); sqlcounter_detach(data); return -1; } memset(&flags, 0, sizeof(flags)); dict_addattr(data->counter_name, -1, 0, PW_TYPE_INTEGER, flags); dattr = dict_attrbyname(data->counter_name); if (dattr == NULL) { radlog(L_ERR, "rlm_sqlcounter: Failed to create counter attribute %s", data->counter_name); sqlcounter_detach(data); return -1; } if (dattr->vendor != 0) { radlog(L_ERR, "Counter attribute must not be a VSA"); sqlcounter_detach(data); return -1; } data->dict_attr = dattr; /* * Create a new attribute for the check item. */ if (data->check_name == NULL) { radlog(L_ERR, "rlm_sqlcounter: 'check-name' must be set."); sqlcounter_detach(data); return -1; } dict_addattr(data->check_name, 0, PW_TYPE_INTEGER, -1, flags); dattr = dict_attrbyname(data->check_name); if (dattr == NULL) { radlog(L_ERR, "rlm_sqlcounter: Failed to create check attribute %s", data->check_name); sqlcounter_detach(data); return -1; } DEBUG2("rlm_sqlcounter: Check attribute %s is number %d", data->check_name, dattr->attr); /* * Discover the end of the current time period. */ if (data->reset == NULL) { radlog(L_ERR, "rlm_sqlcounter: 'reset' must be set."); sqlcounter_detach(data); return -1; } now = time(NULL); data->reset_time = 0; if (find_next_reset(data,now) == -1) { radlog(L_ERR, "rlm_sqlcounter: Failed to find the next reset time."); sqlcounter_detach(data); return -1; } /* * Discover the beginning of the current time period. */ data->last_reset = 0; if (find_prev_reset(data,now) == -1) { radlog(L_ERR, "rlm_sqlcounter: Failed to find the previous reset time."); sqlcounter_detach(data); return -1; } /* * Register the counter comparison operation. */ paircompare_register(data->dict_attr->attr, 0, sqlcounter_cmp, data); *instance = data; return 0; }
static int mod_instantiate(CONF_SECTION *conf, void *instance) { rlm_sql_t *inst = instance; /* * Hack... */ inst->config = &inst->myconfig; inst->cs = conf; inst->config->xlat_name = cf_section_name2(conf); if (!inst->config->xlat_name) { inst->config->xlat_name = cf_section_name1(conf); } else { char *group_name; DICT_ATTR const *da; ATTR_FLAGS flags; /* * Allocate room for <instance>-SQL-Group */ group_name = talloc_typed_asprintf(inst, "%s-SQL-Group", inst->config->xlat_name); DEBUG("rlm_sql (%s): Creating new attribute %s", inst->config->xlat_name, group_name); memset(&flags, 0, sizeof(flags)); if (dict_addattr(group_name, -1, 0, PW_TYPE_STRING, flags) < 0) { ERROR("rlm_sql (%s): Failed to create " "attribute %s: %s", inst->config->xlat_name, group_name, fr_strerror()); return -1; } da = dict_attrbyname(group_name); if (!da) { ERROR("rlm_sql (%s): Failed to create " "attribute %s", inst->config->xlat_name, group_name); return -1; } if (inst->config->groupmemb_query) { DEBUG("rlm_sql (%s): Registering sql_groupcmp for %s", inst->config->xlat_name, group_name); paircompare_register(da, dict_attrbyvalue(PW_USER_NAME, 0), false, sql_groupcmp, inst); } } rad_assert(inst->config->xlat_name); /* * Sanity check for crazy people. */ if (strncmp(inst->config->sql_driver_name, "rlm_sql_", 8) != 0) { ERROR("rlm_sql (%s): \"%s\" is NOT an SQL driver!", inst->config->xlat_name, inst->config->sql_driver_name); return -1; } /* * We need authorize_group_check_query or authorize_group_reply_query * if group_membership_query is set. * * Or we need group_membership_query if authorize_group_check_query or * authorize_group_reply_query is set. */ if (!inst->config->groupmemb_query) { if (inst->config->authorize_group_check_query) { WARN("rlm_sql (%s): Ignoring authorize_group_reply_query as group_membership_query " "is not configured", inst->config->xlat_name); } if (inst->config->authorize_group_reply_query) { WARN("rlm_sql (%s): Ignoring authorize_group_check_query as group_membership_query " "is not configured", inst->config->xlat_name); } } else { if (!inst->config->authorize_group_check_query) { ERROR("rlm_sql (%s): authorize_group_check_query must be configured as group_membership_query " "is configured", inst->config->xlat_name); return -1; } if (!inst->config->authorize_group_reply_query) { ERROR("rlm_sql (%s): authorize_group_reply_query must be configured as group_membership_query " "is configured", inst->config->xlat_name); return -1; } } /* * This will always exist, as cf_section_parse_init() * will create it if it doesn't exist. However, the * "reference" config item won't exist in an auto-created * configuration. So if that doesn't exist, we ignore * the whole subsection. */ inst->config->accounting.cs = cf_section_sub_find(conf, "accounting"); inst->config->accounting.reference_cp = (cf_pair_find(inst->config->accounting.cs, "reference") != NULL); inst->config->postauth.cs = cf_section_sub_find(conf, "post-auth"); inst->config->postauth.reference_cp = (cf_pair_find(inst->config->postauth.cs, "reference") != NULL); /* * Cache the SQL-User-Name DICT_ATTR, so we can be slightly * more efficient about creating SQL-User-Name attributes. */ inst->sql_user = dict_attrbyname("SQL-User-Name"); if (!inst->sql_user) { return -1; } /* * Export these methods, too. This avoids RTDL_GLOBAL. */ inst->sql_set_user = sql_set_user; inst->sql_escape_func = sql_escape_func; inst->sql_query = rlm_sql_query; inst->sql_select_query = rlm_sql_select_query; inst->sql_fetch_row = rlm_sql_fetch_row; /* * Register the SQL xlat function */ xlat_register(inst->config->xlat_name, sql_xlat, sql_escape_func, inst); /* * Load the appropriate driver for our database */ inst->handle = lt_dlopenext(inst->config->sql_driver_name); if (!inst->handle) { ERROR("Could not link driver %s: %s", inst->config->sql_driver_name, dlerror()); ERROR("Make sure it (and all its dependent libraries!) are in the search path of your system's ld"); return -1; } inst->module = (rlm_sql_module_t *) dlsym(inst->handle, inst->config->sql_driver_name); if (!inst->module) { ERROR("Could not link symbol %s: %s", inst->config->sql_driver_name, dlerror()); return -1; } if (inst->module->mod_instantiate) { CONF_SECTION *cs; char const *name; name = strrchr(inst->config->sql_driver_name, '_'); if (!name) { name = inst->config->sql_driver_name; } else { name++; } cs = cf_section_sub_find(conf, name); if (!cs) { cs = cf_section_alloc(conf, name, NULL); if (!cs) { return -1; } } /* * It's up to the driver to register a destructor */ if (inst->module->mod_instantiate(cs, inst->config) < 0) { return -1; } } inst->ef = exfile_init(inst, 64, 30); if (!inst->ef) { cf_log_err_cs(conf, "Failed creating log file context"); return -1; } INFO("rlm_sql (%s): Driver %s (module %s) loaded and linked", inst->config->xlat_name, inst->config->sql_driver_name, inst->module->name); /* * Initialise the connection pool for this instance */ INFO("rlm_sql (%s): Attempting to connect to database \"%s\"", inst->config->xlat_name, inst->config->sql_db); inst->pool = fr_connection_pool_module_init(inst->cs, inst, mod_conn_create, NULL, NULL); if (!inst->pool) return -1; if (inst->config->groupmemb_query) { paircompare_register(dict_attrbyvalue(PW_SQL_GROUP, 0), dict_attrbyvalue(PW_USER_NAME, 0), false, sql_groupcmp, inst); } if (inst->config->do_clients) { if (generate_sql_clients(inst) == -1){ ERROR("Failed to load clients from SQL"); return -1; } } return RLM_MODULE_OK; }
/* * Do any per-module initialization that is separate to each * configured instance of the module. e.g. set up connections * to external databases, read configuration files, set up * dictionary entries, etc. * * If configuration information is given in the config section * that must be referenced in later calls, store a handle to it * in *instance otherwise put a null pointer there. */ static int mod_instantiate(CONF_SECTION *conf, void *instance) { rlm_sqlcounter_t *inst = instance; DICT_ATTR const *da; ATTR_FLAGS flags; time_t now; rad_assert(inst->query && *inst->query); da = dict_attrbyname(inst->key_name); if (!da) { cf_log_err_cs(conf, "Invalid attribute '%s'", inst->key_name); return -1; } inst->key_attr = da; da = dict_attrbyname(inst->reply_name); if (!da) { cf_log_err_cs(conf, "Invalid attribute '%s'", inst->reply_name); return -1; } inst->reply_attr = da; /* * Create a new attribute for the counter. */ rad_assert(inst->counter_name && *inst->counter_name); memset(&flags, 0, sizeof(flags)); dict_addattr(inst->counter_name, -1, 0, PW_TYPE_INTEGER, flags); da = dict_attrbyname(inst->counter_name); if (!da) { cf_log_err_cs(conf, "Failed to create counter attribute %s", inst->counter_name); return -1; } inst->dict_attr = da; /* * Create a new attribute for the check item. */ rad_assert(inst->limit_name && *inst->limit_name); dict_addattr(inst->limit_name, -1, 0, PW_TYPE_INTEGER, flags); da = dict_attrbyname(inst->limit_name); if (!da) { cf_log_err_cs(conf, "Failed to create check attribute %s", inst->limit_name); return -1; } now = time(NULL); inst->reset_time = 0; if (find_next_reset(inst,now) == -1) { cf_log_err_cs(conf, "Invalid reset '%s'", inst->reset); return -1; } /* * Discover the beginning of the current time period. */ inst->last_reset = 0; if (find_prev_reset(inst, now) < 0) { cf_log_err_cs(conf, "Invalid reset '%s'", inst->reset); return -1; } /* * Register the counter comparison operation. */ paircompare_register(inst->dict_attr, NULL, true, sqlcounter_cmp, inst); return 0; }
static int rlm_redisn_instantiate(CONF_SECTION * conf, void **instance) { static size_t query2Queries[]= { offsetof(REDIS_INST,accounting_on_query), offsetof(REDIS_INST,accounting_on_queries), offsetof(REDIS_INST,accounting_off_query), offsetof(REDIS_INST,accounting_off_queries), offsetof(REDIS_INST,accounting_update_query), offsetof(REDIS_INST,accounting_update_queries), offsetof(REDIS_INST,accounting_start_query), offsetof(REDIS_INST,accounting_start_queries), offsetof(REDIS_INST,accounting_stop_query), offsetof(REDIS_INST,accounting_stop_queries), 0 }; REDIS_INST *inst; const char *xlat_name; inst = rad_malloc(sizeof(REDIS_INST)); memset(inst, 0, sizeof(REDIS_INST)); /* * Export these methods, too. This avoids RTDL_GLOBAL. */ inst->redisn_set_user = redisn_set_user; inst->redisn_get_socket = redisn_get_socket; inst->redisn_release_socket = redisn_release_socket; inst->redisn_escape_func = redisn_escape_func; inst->redisn_query = rlm_redisn_query; inst->redisn_finish_query = rlm_redisn_finish_query; inst->redisn_fetch_row = rlm_redisn_fetch_row; /* * If the configuration parameters can't be parsed, then * fail. */ if (cf_section_parse(conf, inst, module_config) < 0) { rlm_redisn_detach(inst); return -1; } DEBUG("rlm_redisn (%s): vp_separator=%s\n",inst->xlat_name,inst->vp_separator); if (inst->vp_separator==NULL || inst->vp_separator[0]=='\0') { radlog(L_CONS | L_ERR, "rlm_redisn (%s): Bad vp_separator", inst->xlat_name); free(inst); return -1; } if (inst->vp_separator[0]=='0' && inst->vp_separator[1]=='x') { long int sep=strtol(inst->vp_separator+2,NULL,16); if (sep<=0 || sep>255) { radlog(L_CONS | L_ERR, "rlm_redisn (%s): Bad vp_separator", inst->xlat_name); free(inst); return -1; } else { //we have space as len is at least 2 inst->vp_separator[0]=(char)sep; inst->vp_separator[1]=0; } } else if (inst->vp_separator[1]!='\0') { radlog(L_CONS | L_ERR, "rlm_redisn (%s): Bad vp_separator", inst->xlat_name); free(inst); return -1; } if (explode_servers(inst)!=0){ free(inst); return -1; } { int q=0; while(query2Queries[q]>0) { DEBUG("rlm_redisn (%s): query #%d\n",inst->xlat_name,q); char **queryPtr = (char **) (((char *)inst) + query2Queries[q]); char ***queriesPtr = (char ***) (((char *)inst) + query2Queries[q+1]); if (*queryPtr && **queryPtr!='\0') { DEBUG("rlm_redisn (%s): query #%d: %s\n",inst->xlat_name,q,*queryPtr); redisn_split_string(queriesPtr,*queryPtr,'\n',1); DEBUG("rlm_redisn (%s): query #%d: q0=%s\n",inst->xlat_name,q,*queriesPtr[0]); } q+=2; }; } xlat_name = cf_section_name2(conf); if (xlat_name == NULL) { xlat_name = cf_section_name1(conf); } else { char *group_name; DICT_ATTR *dattr; ATTR_FLAGS flags; /* * Allocate room for <instance>-REDISN-Group */ group_name = rad_malloc((strlen(xlat_name) + 1 + 11) * sizeof(char)); sprintf(group_name,"%s-REDISN-Group",xlat_name); DEBUG("rlm_redisn Creating new attribute %s",group_name); memset(&flags, 0, sizeof(flags)); dict_addattr(group_name, 0, PW_TYPE_STRING, -1, flags); dattr = dict_attrbyname(group_name); if (dattr == NULL){ radlog(L_ERR, "rlm_redisn: Failed to create attribute %s",group_name); free(group_name); free(inst); /* FIXME: detach */ return -1; } if (inst->groupmemb_query && inst->groupmemb_query[0]) { DEBUG("rlm_redisn: Registering redisn_groupcmp for %s",group_name); paircompare_register(dattr->attr, PW_USER_NAME, redisn_groupcmp, inst); } free(group_name); } if (xlat_name){ inst->xlat_name = strdup(xlat_name); xlat_register(xlat_name, (RAD_XLAT_FUNC)redisn_xlat, inst); } if (inst->num_redisn_socks > MAX_REDISN_SOCKS) { radlog(L_ERR, "rlm_redisn (%s): redisn_instantiate: number of redis_sockets cannot exceed MAX_REDISN_SOCKS, %d", inst->xlat_name, MAX_REDISN_SOCKS); rlm_redisn_detach(inst); return -1; } radlog(L_INFO, "rlm_redisn (%s): Attempting to connect to servers %s", inst->xlat_name, inst->redisn_servers); if (redisn_init_socketpool(inst) < 0) { rlm_redisn_detach(inst); return -1; } if (inst->groupmemb_query && inst->groupmemb_query[0]) { paircompare_register(PW_REDIS_GROUP, PW_USER_NAME, redisn_groupcmp, inst); } if (inst->do_clients){ if (generate_redisn_clients(inst) == -1){ radlog(L_ERR, "Failed to load clients from REDISN."); rlm_redisn_detach(inst); return -1; } } allowed_chars = inst->allowed_chars; *instance = inst; return RLM_MODULE_OK; }
/* * Do any per-module initialization that is separate to each * configured instance of the module. e.g. set up connections * to external databases, read configuration files, set up * dictionary entries, etc. * * If configuration information is given in the config section * that must be referenced in later calls, store a handle to it * in *instance otherwise put a null pointer there. */ static int mod_instantiate(CONF_SECTION *conf, void *instance) { rlm_sqlcounter_t *inst = instance; DICT_ATTR const *dattr; ATTR_FLAGS flags; time_t now; rad_assert(inst->query && *inst->query); dattr = dict_attrbyname(inst->key_name); rad_assert(dattr != NULL); if (dattr->vendor != 0) { cf_log_err_cs(conf, "Configuration item 'key' cannot be a VSA"); return -1; } inst->key_attr = dattr; dattr = dict_attrbyname(inst->reply_name); rad_assert(dattr != NULL); if (dattr->vendor != 0) { cf_log_err_cs(conf, "Configuration item 'reply_name' cannot be a VSA"); return -1; } inst->reply_attr = dattr; DEBUG2("rlm_sqlcounter: Reply attribute %s is number %d", inst->reply_name, dattr->attr); /* * Create a new attribute for the counter. */ rad_assert(inst->counter_name && *inst->counter_name); memset(&flags, 0, sizeof(flags)); dict_addattr(inst->counter_name, -1, 0, PW_TYPE_INTEGER, flags); dattr = dict_attrbyname(inst->counter_name); if (!dattr) { cf_log_err_cs(conf, "Failed to create counter attribute %s", inst->counter_name); return -1; } if (dattr->vendor != 0) { cf_log_err_cs(conf, "Counter attribute must not be a VSA"); return -1; } inst->dict_attr = dattr; /* * Create a new attribute for the check item. */ rad_assert(inst->check_name && *inst->check_name); dict_addattr(inst->check_name, 0, PW_TYPE_INTEGER, -1, flags); dattr = dict_attrbyname(inst->check_name); if (!dattr) { cf_log_err_cs(conf, "Failed to create check attribute %s", inst->check_name); return -1; } DEBUG2("rlm_sqlcounter: Check attribute %s is number %d", inst->check_name, dattr->attr); now = time(NULL); inst->reset_time = 0; if (find_next_reset(inst,now) == -1) { cf_log_err_cs(conf, "Invalid reset '%s'", inst->reset); return -1; } /* * Discover the beginning of the current time period. */ inst->last_reset = 0; if (find_prev_reset(inst, now) < 0) { cf_log_err_cs(conf, "Invalid reset '%s'", inst->reset); return -1; } /* * Register the counter comparison operation. */ paircompare_register(inst->dict_attr, NULL, true, sqlcounter_cmp, inst); return 0; }
/* * Do any per-module initialization that is separate to each * configured instance of the module. e.g. set up connections * to external databases, read configuration files, set up * dictionary entries, etc. * * If configuration information is given in the config section * that must be referenced in later calls, store a handle to it * in *instance otherwise put a null pointer there. */ static int mod_instantiate(CONF_SECTION *conf, void *instance) { rlm_counter_t *inst = instance; DICT_ATTR const *da; DICT_VALUE *dval; ATTR_FLAGS flags; time_t now; int cache_size; int ret; datum key_datum; datum time_datum; char const *default1 = "DEFAULT1"; char const *default2 = "DEFAULT2"; cache_size = inst->cache_size; da = dict_attrbyname(inst->key_name); rad_assert(da != NULL); inst->key_attr = da; /* * Discover the attribute number of the counter. */ da = dict_attrbyname(inst->count_attribute); rad_assert(da != NULL); inst->count_attr = da; /* * Discover the attribute number of the reply attribute. */ if (inst->reply_name != NULL) { da = dict_attrbyname(inst->reply_name); if (!da) { cf_log_err_cs(conf, "No such attribute %s", inst->reply_name); return -1; } if (da->type != PW_TYPE_INTEGER) { cf_log_err_cs(conf, "Reply attribute' %s' is not of type integer", inst->reply_name); return -1; } inst->reply_attr = da; } else { inst->reply_attr = NULL; } /* * Create a new attribute for the counter. */ rad_assert(inst->counter_name && *inst->counter_name); memset(&flags, 0, sizeof(flags)); if (dict_addattr(inst->counter_name, -1, 0, PW_TYPE_INTEGER, flags) < 0) { ERROR("rlm_counter: Failed to create counter attribute %s: %s", inst->counter_name, fr_strerror()); return -1; } da = dict_attrbyname(inst->counter_name); if (!da) { cf_log_err_cs(conf, "Failed to find counter attribute %s", inst->counter_name); return -1; } inst->dict_attr = da; DEBUG2("rlm_counter: Counter attribute %s is number %d", inst->counter_name, inst->dict_attr->attr); /* * Create a new attribute for the check item. */ rad_assert(inst->check_name && *inst->check_name); if (dict_addattr(inst->check_name, -1, 0, PW_TYPE_INTEGER, flags) < 0) { ERROR("rlm_counter: Failed to create check attribute %s: %s", inst->counter_name, fr_strerror()); return -1; } da = dict_attrbyname(inst->check_name); if (!da) { ERROR("rlm_counter: Failed to find check attribute %s", inst->counter_name); return -1; } inst->check_attr = da; /* * Find the attribute for the allowed protocol */ if (inst->service_type != NULL) { if ((dval = dict_valbyname(PW_SERVICE_TYPE, 0, inst->service_type)) == NULL) { ERROR("rlm_counter: Failed to find attribute number for %s", inst->service_type); return -1; } inst->service_val = dval->value; } /* * Find when to reset the database. */ rad_assert(inst->reset && *inst->reset); now = time(NULL); inst->reset_time = 0; inst->last_reset = now; if (find_next_reset(inst,now) == -1) { ERROR("rlm_counter: find_next_reset() returned -1. Exiting"); return -1; } { char *filename; memcpy(&filename, &inst->filename, sizeof(filename)); inst->gdbm = gdbm_open(filename, sizeof(int), GDBM_NEWDB | GDBM_COUNTER_OPTS, 0600, NULL); } if (!inst->gdbm) { ERROR("rlm_counter: Failed to open file %s: %s", inst->filename, fr_syserror(errno)); return -1; } if (gdbm_setopt(inst->gdbm, GDBM_CACHESIZE, &cache_size, sizeof(cache_size)) == -1) { ERROR("rlm_counter: Failed to set cache size"); } /* * Look for the DEFAULT1 entry. This entry if it exists contains the * time of the next database reset. This time is set each time we reset * the database. If next_reset < now then we reset the database. * That way we can overcome the problem where radiusd is down during a database * reset time. If we did not keep state information in the database then the reset * would be extended and that would create problems. * * We also store the time of the last reset in the DEFAULT2 entry. * * If DEFAULT1 and DEFAULT2 do not exist (new database) we add them to the database */ memcpy(&key_datum.dptr, &default1, sizeof(key_datum.dptr)); key_datum.dsize = strlen(key_datum.dptr); time_datum = gdbm_fetch(inst->gdbm, key_datum); if (time_datum.dptr != NULL) { time_t next_reset = 0; memcpy(&next_reset, time_datum.dptr, sizeof(time_t)); free(time_datum.dptr); time_datum.dptr = NULL; if (next_reset && next_reset <= now) { inst->last_reset = now; ret = reset_db(inst); if (ret != RLM_MODULE_OK) { ERROR("rlm_counter: reset_db() failed"); return -1; } } else { inst->reset_time = next_reset; } memcpy(&key_datum.dptr, &default2, sizeof(key_datum.dptr)); key_datum.dsize = strlen(key_datum.dptr); time_datum = gdbm_fetch(inst->gdbm, key_datum); if (time_datum.dptr != NULL) { memcpy(&inst->last_reset, time_datum.dptr, sizeof(time_t)); free(time_datum.dptr); } } else { ret = add_defaults(inst); if (ret != RLM_MODULE_OK) { ERROR("rlm_counter: add_defaults() failed"); return -1; } } /* * Register the counter comparison operation. * FIXME: move all attributes to DA */ paircompare_register(inst->dict_attr, NULL, true, counter_cmp, inst); /* * Init the mutex */ pthread_mutex_init(&inst->mutex, NULL); return 0; }
static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance) { SQL_INST *inst; const char *xlat_name; inst = rad_malloc(sizeof(SQL_INST)); memset(inst, 0, sizeof(SQL_INST)); inst->config = rad_malloc(sizeof(SQL_CONFIG)); memset(inst->config, 0, sizeof(SQL_CONFIG)); inst->cs = conf; /* * Export these methods, too. This avoids RTDL_GLOBAL. */ inst->sql_set_user = sql_set_user; inst->sql_get_socket = sql_get_socket; inst->sql_release_socket = sql_release_socket; inst->sql_escape_func = sql_escape_func; inst->sql_query = rlm_sql_query; inst->sql_select_query = rlm_sql_select_query; inst->sql_fetch_row = rlm_sql_fetch_row; /* * If the configuration parameters can't be parsed, then * fail. */ if (cf_section_parse(conf, inst->config, module_config) < 0) { rlm_sql_detach(inst); return -1; } xlat_name = cf_section_name2(conf); if (xlat_name == NULL) { xlat_name = cf_section_name1(conf); } else { char *group_name; DICT_ATTR *dattr; ATTR_FLAGS flags; /* * Allocate room for <instance>-SQL-Group */ group_name = rad_malloc((strlen(xlat_name) + 1 + 11) * sizeof(char)); sprintf(group_name,"%s-SQL-Group",xlat_name); DEBUG("rlm_sql Creating new attribute %s",group_name); memset(&flags, 0, sizeof(flags)); dict_addattr(group_name, 0, PW_TYPE_STRING, -1, flags); dattr = dict_attrbyname(group_name); if (dattr == NULL){ radlog(L_ERR, "rlm_sql: Failed to create attribute %s",group_name); free(group_name); free(inst); /* FIXME: detach */ return -1; } if (inst->config->groupmemb_query && inst->config->groupmemb_query[0]) { DEBUG("rlm_sql: Registering sql_groupcmp for %s",group_name); paircompare_register(dattr->attr, PW_USER_NAME, sql_groupcmp, inst); } free(group_name); } if (xlat_name){ inst->config->xlat_name = strdup(xlat_name); xlat_register(xlat_name, (RAD_XLAT_FUNC)sql_xlat, inst); } /* * Sanity check for crazy people. */ if (strncmp(inst->config->sql_driver, "rlm_sql_", 8) != 0) { radlog(L_ERR, "\"%s\" is NOT an SQL driver!", inst->config->sql_driver); rlm_sql_detach(inst); return -1; } inst->handle = lt_dlopenext(inst->config->sql_driver); if (inst->handle == NULL) { radlog(L_ERR, "Could not link driver %s: %s", inst->config->sql_driver, lt_dlerror()); radlog(L_ERR, "Make sure it (and all its dependent libraries!) are in the search path of your system's ld."); rlm_sql_detach(inst); return -1; } inst->module = (rlm_sql_module_t *) lt_dlsym(inst->handle, inst->config->sql_driver); if (!inst->module) { radlog(L_ERR, "Could not link symbol %s: %s", inst->config->sql_driver, lt_dlerror()); rlm_sql_detach(inst); return -1; } radlog(L_INFO, "rlm_sql (%s): Driver %s (module %s) loaded and linked", inst->config->xlat_name, inst->config->sql_driver, inst->module->name); radlog(L_INFO, "rlm_sql (%s): Attempting to connect to %s@%s:%s/%s", inst->config->xlat_name, inst->config->sql_login, inst->config->sql_server, inst->config->sql_port, inst->config->sql_db); if (sql_init_socketpool(inst) < 0) { rlm_sql_detach(inst); return -1; } if (inst->config->groupmemb_query && inst->config->groupmemb_query[0]) { paircompare_register(PW_SQL_GROUP, PW_USER_NAME, sql_groupcmp, inst); } if (inst->config->do_clients){ if (generate_sql_clients(inst) == -1){ radlog(L_ERR, "Failed to load clients from SQL."); rlm_sql_detach(inst); return -1; } } allowed_chars = inst->config->allowed_chars; *instance = inst; return RLM_MODULE_OK; }
/* * Do any per-module initialization that is separate to each * configured instance of the module. e.g. set up connections * to external databases, read configuration files, set up * dictionary entries, etc. * * If configuration information is given in the config section * that must be referenced in later calls, store a handle to it * in *instance otherwise put a null pointer there. */ static int checkval_instantiate(CONF_SECTION *conf, void **instance) { rlm_checkval_t *inst; const DICT_ATTR *da; ATTR_FLAGS flags; /* * Set up a storage area for instance data */ *instance = inst = talloc_zero(conf, rlm_checkval_t); if (!inst) { return -1; } /* * If the configuration parameters can't be parsed, then * fail. */ if (cf_section_parse(conf, inst, module_config) < 0) { return -1; } /* * Check if data_type exists */ if (!inst->data_type || !*inst->data_type){ radlog(L_ERR, "rlm_checkval: Data type not defined"); return -1; } if (!inst->item_name || !*inst->item_name){ radlog(L_ERR, "rlm_checkval: Item name not defined"); return -1; } if (!inst->check_name || !*inst->check_name){ radlog(L_ERR, "rlm_checkval: Check item name not defined"); return -1; } /* * Discover the attribute number of the item name */ da = dict_attrbyname(inst->item_name); if (!da) { radlog(L_ERR, "rlm_checkval: No such attribute %s", inst->item_name); return -1; } inst->item = da; /* * Add the check attribute name to the dictionary * if it does not already exists. dict_addattr() handles that */ memset(&flags, 0, sizeof(flags)); dict_addattr(inst->check_name, -1, 0, PW_TYPE_STRING, flags); da = dict_attrbyname(inst->check_name); if (!da){ radlog(L_ERR, "rlm_checkval: No such attribute %s", inst->check_name); return -1; } inst->check = da; DEBUG2("rlm_checkval: Registered name %s for attribute %d", da->name,da->attr); /* * Convert the string type to an integer type, * so we don't have to do string comparisons on each * packet. */ inst->type = fr_str2int(dict_attr_types, inst->data_type, 0); if (!inst->type) { radlog(L_ERR, "rlm_checkval: Data type %s in not known", inst->data_type); return -1; } return 0; }