static int _map_proc_client_get_vp(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request, vp_map_t const *map, void *uctx) { client_get_vp_ctx_t *client = uctx; VALUE_PAIR *head = NULL, *vp; fr_cursor_t cursor; fr_dict_attr_t const *da; CONF_PAIR const *cp; rad_assert(ctx != NULL); fr_cursor_init(&cursor, &head); /* * FIXME: allow multiple entries. */ if (map->lhs->type == TMPL_TYPE_ATTR) { da = map->lhs->tmpl_da; } else { char *attr; if (tmpl_aexpand(ctx, &attr, request, map->lhs, NULL, NULL) <= 0) { RWDEBUG("Failed expanding string"); return -1; } da = fr_dict_attr_by_name(request->dict, attr); if (!da) { RWDEBUG("No such attribute '%s'", attr); return -1; } talloc_free(attr); } for (cp = client->cp; cp; cp = cf_pair_find_next(client->cs, cp, client->field)) { char const *value = cf_pair_value(cp); MEM(vp = fr_pair_afrom_da(ctx, da)); if (fr_pair_value_from_str(vp, value, talloc_array_length(value) - 1, '\0', false) < 0) { RWDEBUG("Failed parsing value \"%pV\" for attribute %s: %s", fr_box_strvalue(value), map->lhs->tmpl_da->name, fr_strerror()); fr_pair_list_free(&head); talloc_free(vp); return -1; } vp->op = map->op; fr_cursor_append(&cursor, vp); if (map->op != T_OP_ADD) break; /* Create multiple attribute for multiple CONF_PAIRs */ } *out = head; return 0; }
static int rad_load_transforms(struct Protocol *prot, CONF_SECTION *cf) { CONF_PAIR *cp; int option_exists = 0; int i = 0; rad_assert(prot); rad_assert(cf); DEBUG(IKEv2_LOG_PREFIX "Begin load transforms"); while(config_transforms[i].name) { uint8_t id; uint16_t keylen; for(cp = cf_pair_find(cf,config_transforms[i].name); cp; cp = cf_pair_find_next(cf,cp,config_transforms[i].name)) { if (TransformFromName(cf_pair_value(cp),config_transforms[i].type,&id,&keylen)) { ERROR(IKEv2_LOG_PREFIX "Unsupported %s transform: %s ", config_transforms[i].name,cf_pair_value(cp)); return -1; } if (!AddTransform(prot,config_transforms[i].type,id,keylen)) { ERROR(IKEv2_LOG_PREFIX "Problem with transform %s:%s", config_transforms[i].name,cf_pair_value(cp)); return -1; } option_exists |= config_transforms[i].exist_flag; } i++; } if ((option_exists & OPT_NEEDED) != OPT_NEEDED) { ERROR(IKEv2_LOG_PREFIX "Not all mandatory transforms are set properly"); DEBUG(IKEv2_LOG_PREFIX "Option flags: 0x%02X",option_exists); return -1; } return 0; }
/* * Generic function for failing between a bunch of queries. * * Uses the same principle as rlm_linelog, expanding the 'reference' config * item using xlat to figure out what query it should execute. * * If the reference matches multiple config items, and a query fails or * doesn't update any rows, the next matching config item is used. * */ static int acct_redundant(rlm_sql_t *inst, REQUEST *request, sql_acct_section_t *section) { rlm_rcode_t rcode = RLM_MODULE_OK; rlm_sql_handle_t *handle = NULL; int sql_ret; int numaffected = 0; CONF_ITEM *item; CONF_PAIR *pair; char const *attr = NULL; char const *value; char path[MAX_STRING_LEN]; char *p = path; char *expanded = NULL; rad_assert(section); if (section->reference[0] != '.') { *p++ = '.'; } if (radius_xlat(p, sizeof(path) - (p - path), request, section->reference, NULL, NULL) < 0) { rcode = RLM_MODULE_FAIL; goto finish; } item = cf_reference_item(NULL, section->cs, path); if (!item) { rcode = RLM_MODULE_FAIL; goto finish; } if (cf_item_is_section(item)){ REDEBUG("Sections are not supported as references"); rcode = RLM_MODULE_FAIL; goto finish; } pair = cf_itemtopair(item); attr = cf_pair_attr(pair); RDEBUG2("Using query template '%s'", attr); handle = sql_get_socket(inst); if (!handle) { rcode = RLM_MODULE_FAIL; goto finish; } sql_set_user(inst, request, NULL); while (true) { value = cf_pair_value(pair); if (!value) { RDEBUG("Ignoring null query"); rcode = RLM_MODULE_NOOP; goto finish; } if (radius_axlat(&expanded, request, value, sql_escape_func, inst) < 0) { rcode = RLM_MODULE_FAIL; goto finish; } if (!*expanded) { RDEBUG("Ignoring null query"); rcode = RLM_MODULE_NOOP; talloc_free(expanded); goto finish; } rlm_sql_query_log(inst, request, section, expanded); /* * If rlm_sql_query cannot use the socket it'll try and * reconnect. Reconnecting will automatically release * the current socket, and try to select a new one. * * If we get RLM_SQL_RECONNECT it means all connections in the pool * were exhausted, and we couldn't create a new connection, * so we do not need to call sql_release_socket. */ sql_ret = rlm_sql_query(&handle, inst, expanded); TALLOC_FREE(expanded); if (sql_ret == RLM_SQL_RECONNECT) { rcode = RLM_MODULE_FAIL; goto finish; } rad_assert(handle); /* * Assume all other errors are incidental, and just meant our * operation failed and its not a client or SQL syntax error. * * @fixme We should actually be able to distinguish between key * constraint violations (which we expect) and other errors. */ if (sql_ret == RLM_SQL_OK) { numaffected = (inst->module->sql_affected_rows)(handle, inst->config); if (numaffected > 0) { break; /* A query succeeded, were done! */ } RDEBUG("No records updated"); } (inst->module->sql_finish_query)(handle, inst->config); /* * We assume all entries with the same name form a redundant * set of queries. */ pair = cf_pair_find_next(section->cs, pair, attr); if (!pair) { RDEBUG("No additional queries configured"); rcode = RLM_MODULE_NOOP; goto finish; } RDEBUG("Trying next query..."); } (inst->module->sql_finish_query)(handle, inst->config); finish: talloc_free(expanded); sql_release_socket(inst, handle); return rcode; }
/* * Parse the module config sections, and load * and call each module's init() function. * * Libtool makes your life a LOT easier, especially with libltdl. * see: http://www.gnu.org/software/libtool/ */ int setup_modules(void) { int comp; CONF_SECTION *cs; /* * FIXME: This should be pulled from somewhere else. */ const char *filename="radiusd.conf"; /* * No current list of modules: Go initialize libltdl. */ if (!module_list) { /* * Set the default list of preloaded symbols. * This is used to initialize libltdl's list of * preloaded modules. * * i.e. Static modules. */ LTDL_SET_PRELOADED_SYMBOLS(); if (lt_dlinit() != 0) { radlog(L_ERR|L_CONS, "Failed to initialize libraries: %s\n", lt_dlerror()); exit(1); /* FIXME */ } /* * Set the search path to ONLY our library directory. * This prevents the modules from being found from * any location on the disk. */ lt_dlsetsearchpath(radlib_dir); DEBUG2("Module: Library search path is %s", lt_dlgetsearchpath()); /* * Initialize the components. */ for (comp = 0; comp < RLM_COMPONENT_COUNT; comp++) { components[comp] = NULL; } } else { detach_modules(); } /* * Create any DICT_VALUE's for the types. See * 'doc/configurable_failover' for examples of 'authtype' * used to create new Auth-Type values. In order to * let the user create new names, we've got to look for * those names, and create DICT_VALUE's for them. */ for (comp = 0; section_type_value[comp].section != NULL; comp++) { const char *name2; DICT_ATTR *dattr; DICT_VALUE *dval; CONF_SECTION *sub, *next; CONF_PAIR *cp; /* * Big-time YUCK */ static int my_value = 32767; cs = cf_section_find(section_type_value[comp].section); if (!cs) continue; sub = NULL; do { /* * See if there's a sub-section by that * name. */ next = cf_subsection_find_next(cs, sub, section_type_value[comp].typename); /* * Allow some old names, too. */ if (!next && (comp <= 4)) { next = cf_subsection_find_next(cs, sub, old_section_type_value[comp].typename); } sub = next; /* * If so, look for it to define a new * value. */ name2 = cf_section_name2(sub); if (!name2) continue; /* * If the value already exists, don't * create it again. */ dval = dict_valbyname(section_type_value[comp].attr, name2); if (dval) continue; /* * Find the attribute for the value. */ dattr = dict_attrbyvalue(section_type_value[comp].attr); if (!dattr) continue; /* * Finally, create the new attribute. */ if (dict_addvalue(name2, dattr->name, my_value++) < 0) { radlog(L_ERR, "%s", librad_errstr); exit(1); } } while (sub != NULL); /* * Loop over the non-sub-sections, too. */ cp = NULL; do { /* * See if there's a conf-pair by that * name. */ cp = cf_pair_find_next(cs, cp, NULL); if (!cp) break; /* * If the value already exists, don't * create it again. */ name2 = cf_pair_attr(cp); dval = dict_valbyname(section_type_value[comp].attr, name2); if (dval) continue; /* * Find the attribute for the value. */ dattr = dict_attrbyvalue(section_type_value[comp].attr); if (!dattr) continue; /* * Finally, create the new attribute. */ if (dict_addvalue(name2, dattr->name, my_value++) < 0) { radlog(L_ERR, "%s", librad_errstr); exit(1); } } while (cp != NULL); } /* over the sections which can have redundent sub-sections */
/* * Generic function for failing between a bunch of queries. * * Uses the same principle as rlm_linelog, expanding the 'reference' config * item using xlat to figure out what query it should execute. * * If the reference matches multiple config items, and a query fails or * doesn't update any rows, the next matching config item is used. * */ static int acct_redundant(rlm_sql_t *inst, REQUEST *request, sql_acct_section_t *section) { int ret = RLM_MODULE_OK; rlm_sql_handle_t *handle = NULL; int sql_ret; int numaffected = 0; CONF_ITEM *item; CONF_PAIR *pair; const char *attr = NULL; const char *value; char path[MAX_STRING_LEN]; char querystr[MAX_QUERY_LEN]; char *p = path; rad_assert(section); if (section->reference[0] != '.') *p++ = '.'; if (!radius_xlat(p, (sizeof(path) - (p - path)) - 1, section->reference, request, NULL, NULL)) return RLM_MODULE_FAIL; item = cf_reference_item(NULL, section->cs, path); if (!item) return RLM_MODULE_FAIL; if (cf_item_is_section(item)){ radlog(L_ERR, "Sections are not supported as references"); return RLM_MODULE_FAIL; } pair = cf_itemtopair(item); attr = cf_pair_attr(pair); RDEBUG2("Using query template '%s'", attr); handle = sql_get_socket(inst); if (handle == NULL) return RLM_MODULE_FAIL; sql_set_user(inst, request, NULL); while (TRUE) { value = cf_pair_value(pair); if (!value) { RDEBUG("Ignoring null query"); ret = RLM_MODULE_NOOP; goto release; } radius_xlat(querystr, sizeof(querystr), value, request, sql_escape_func, inst); if (!*querystr) { RDEBUG("Ignoring null query"); ret = RLM_MODULE_NOOP; goto release; } rlm_sql_query_log(inst, request, section, querystr); /* * If rlm_sql_query cannot use the socket it'll try and * reconnect. Reconnecting will automatically release * the current socket, and try to select a new one. * * If we get SQL_DOWN it means all connections in the pool * were exhausted, and we couldn't create a new connection, * so we do not need to call sql_release_socket. */ sql_ret = rlm_sql_query(&handle, inst, querystr); if (sql_ret == SQL_DOWN) return RLM_MODULE_FAIL; rad_assert(handle); /* * Assume all other errors are incidental, and just meant our * operation failed and its not a client or SQL syntax error. */ if (sql_ret == 0) { numaffected = (inst->module->sql_affected_rows) (handle, inst->config); if (numaffected > 0) break; RDEBUG("No records updated"); } (inst->module->sql_finish_query)(handle, inst->config); /* * We assume all entries with the same name form a redundant * set of queries. */ pair = cf_pair_find_next(section->cs, pair, attr); if (!pair) { RDEBUG("No additional queries configured"); ret = RLM_MODULE_NOOP; goto release; } RDEBUG("Trying next query..."); } (inst->module->sql_finish_query)(handle, inst->config); release: sql_release_socket(inst, handle); return ret; }
int rlm_yubikey_ykclient_init(CONF_SECTION *conf, rlm_yubikey_t *inst) { ykclient_rc status; CONF_SECTION *servers; char prefix[100]; int count = 0; if (!inst->client_id) { ERROR("rlm_yubikey (%s): validation.client_id must be set (to a valid id) when validation is enabled", inst->name); return -1; } if (!inst->api_key || !*inst->api_key || is_zero(inst->api_key)) { ERROR("rlm_yubikey (%s): validation.api_key must be set (to a valid key) when validation is enabled", inst->name); return -1; } DEBUG("rlm_yubikey (%s): Initialising ykclient", inst->name); status = ykclient_global_init(); if (status != YKCLIENT_OK) { yk_error: ERROR("rlm_yubikey (%s): %s", ykclient_strerror(status), inst->name); return -1; } status = ykclient_init(&inst->ykc); if (status != YKCLIENT_OK) { goto yk_error; } servers = cf_section_sub_find(conf, "servers"); if (servers) { CONF_PAIR *uri, *first; /* * If there were no uris configured we just use the default * ykclient uris which point to the yubico servers. */ first = uri = cf_pair_find(servers, "uri"); if (!uri) { goto init; } while (uri) { count++; uri = cf_pair_find_next(servers, uri, "uri"); } inst->uris = talloc_zero_array(inst, char const *, count); uri = first; count = 0; while (uri) { inst->uris[count++] = cf_pair_value(uri); uri = cf_pair_find_next(servers, uri, "uri"); } if (count) { status = ykclient_set_url_templates(inst->ykc, count, inst->uris); if (status != YKCLIENT_OK) { goto yk_error; } } } init: status = ykclient_set_client_b64(inst->ykc, inst->client_id, inst->api_key); if (status != YKCLIENT_OK) { ERROR("rlm_yubikey (%s): Failed setting API credentials: %s", ykclient_strerror(status), inst->name); return -1; } snprintf(prefix, sizeof(prefix), "rlm_yubikey (%s)", inst->name); inst->pool = module_connection_pool_init(conf, inst, mod_conn_create, NULL, prefix); if (!inst->pool) { ykclient_done(&inst->ykc); return -1; } return 0; }
/* * Generic function for failing between a bunch of queries. * * Uses the same principle as rlm_linelog, expanding the 'reference' config * item using xlat to figure out what query it should execute. * * If the reference matches multiple config items, and a query fails or * doesn't update any rows, the next matching config item is used. * */ static int acct_redundant(rlm_sql_t *inst, REQUEST *request, sql_acct_section_t *section) { rlm_rcode_t rcode = RLM_MODULE_OK; rlm_sql_handle_t *handle = NULL; int sql_ret; int numaffected = 0; CONF_ITEM *item; CONF_PAIR *pair; char const *attr = NULL; char const *value; char path[MAX_STRING_LEN]; char *p = path; char *expanded = NULL; rad_assert(section); if (section->reference[0] != '.') { *p++ = '.'; } if (radius_xlat(p, sizeof(path) - (p - path), request, section->reference, NULL, NULL) < 0) { rcode = RLM_MODULE_FAIL; goto finish; } /* * If we can't find a matching config item we do * nothing so return RLM_MODULE_NOOP. */ item = cf_reference_item(NULL, section->cs, path); if (!item) { RWDEBUG("No such configuration item %s", path); rcode = RLM_MODULE_NOOP; goto finish; } if (cf_item_is_section(item)){ RWDEBUG("Sections are not supported as references"); rcode = RLM_MODULE_NOOP; goto finish; } pair = cf_item_to_pair(item); attr = cf_pair_attr(pair); RDEBUG2("Using query template '%s'", attr); handle = fr_connection_get(inst->pool); if (!handle) { rcode = RLM_MODULE_FAIL; goto finish; } sql_set_user(inst, request, NULL); while (true) { value = cf_pair_value(pair); if (!value) { RDEBUG("Ignoring null query"); rcode = RLM_MODULE_NOOP; goto finish; } if (radius_axlat(&expanded, request, value, inst->sql_escape_func, handle) < 0) { rcode = RLM_MODULE_FAIL; goto finish; } if (!*expanded) { RDEBUG("Ignoring null query"); rcode = RLM_MODULE_NOOP; talloc_free(expanded); goto finish; } rlm_sql_query_log(inst, request, section, expanded); sql_ret = rlm_sql_query(inst, request, &handle, expanded); TALLOC_FREE(expanded); RDEBUG("SQL query returned: %s", fr_int2str(sql_rcode_table, sql_ret, "<INVALID>")); switch (sql_ret) { /* * Query was a success! Now we just need to check if it did anything. */ case RLM_SQL_OK: break; /* * A general, unrecoverable server fault. */ case RLM_SQL_ERROR: /* * If we get RLM_SQL_RECONNECT it means all connections in the pool * were exhausted, and we couldn't create a new connection, * so we do not need to call fr_connection_release. */ case RLM_SQL_RECONNECT: rcode = RLM_MODULE_FAIL; goto finish; /* * Query was invalid, this is a terminal error, but we still need * to do cleanup, as the connection handle is still valid. */ case RLM_SQL_QUERY_INVALID: rcode = RLM_MODULE_INVALID; goto finish; /* * Driver found an error (like a unique key constraint violation) * that hinted it might be a good idea to try an alternative query. */ case RLM_SQL_ALT_QUERY: goto next; } rad_assert(handle); /* * We need to have updated something for the query to have been * counted as successful. */ numaffected = (inst->module->sql_affected_rows)(handle, inst->config); (inst->module->sql_finish_query)(handle, inst->config); RDEBUG("%i record(s) updated", numaffected); if (numaffected > 0) break; /* A query succeeded, were done! */ next: /* * We assume all entries with the same name form a redundant * set of queries. */ pair = cf_pair_find_next(section->cs, pair, attr); if (!pair) { RDEBUG("No additional queries configured"); rcode = RLM_MODULE_NOOP; goto finish; } RDEBUG("Trying next query..."); } finish: talloc_free(expanded); fr_connection_release(inst->pool, handle); sql_unset_user(inst, request); return rcode; }