📄 rlm_sql.c
字号:
*/ lt_dlclose(inst->handle); /* ignore any errors */#endif } free(inst); 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)); /* * 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); if (xlat_name){ inst->config->xlat_name = strdup(xlat_name); xlat_register(xlat_name, (RAD_XLAT_FUNC)sql_xlat, inst); } if (inst->config->num_sql_socks > MAX_SQL_SOCKS) { radlog(L_ERR | L_CONS, "rlm_sql (%s): sql_instantiate: number of sqlsockets cannot exceed MAX_SQL_SOCKS, %d", inst->config->xlat_name, MAX_SQL_SOCKS); rlm_sql_detach(inst); return -1; } /* * Sanity check for crazy people. */ if (strncmp(inst->config->sql_driver, "rlm_sql_", 8) != 0) { radlog(L_ERR, "rlm_sql (%s): \"%s\" is NOT an SQL driver!", inst->config->xlat_name, 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, "rlm_sql (%s): Could not link driver %s: %s", inst->config->xlat_name, inst->config->sql_driver, lt_dlerror()); radlog(L_ERR, "rlm_sql (%s): Make sure it (and all its dependent libraries!) are in the search path of your system's ld.", inst->config->xlat_name); 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, "rlm_sql (%s): Could not link symbol %s: %s", inst->config->xlat_name, 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; } 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, "rlm_sql (%s): generate_sql_clients() returned error",inst->config->xlat_name); rlm_sql_detach(inst); return -1; } } allowed_chars = inst->config->allowed_chars; *instance = inst; return RLM_MODULE_OK;}static int rlm_sql_authorize(void *instance, REQUEST * request){ VALUE_PAIR *check_tmp = NULL; VALUE_PAIR *reply_tmp = NULL; VALUE_PAIR *user_profile = NULL; int found = 0; int dofallthrough = 1; int rows; SQLSOCK *sqlsocket; SQL_INST *inst = instance; char querystr[MAX_QUERY_LEN]; char sqlusername[MAX_STRING_LEN]; /* * the profile username is used as the sqlusername during * profile checking so that we don't overwrite the orignal * sqlusername string */ char profileusername[MAX_STRING_LEN]; /* * Set, escape, and check the user attr here */ if (sql_set_user(inst, request, sqlusername, NULL) < 0) return RLM_MODULE_FAIL; /* * reserve a socket */ sqlsocket = sql_get_socket(inst); if (sqlsocket == NULL) { /* Remove the username we (maybe) added above */ pairdelete(&request->packet->vps, PW_SQL_USER_NAME); return RLM_MODULE_FAIL; } /* * After this point, ALL 'return's MUST release the SQL socket! */ /* * Alright, start by getting the specific entry for the user */ if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_check_query, request, sql_escape_func)) { radlog(L_ERR, "rlm_sql (%s): Error generating query; rejecting user", inst->config->xlat_name); sql_release_socket(inst, sqlsocket); /* Remove the username we (maybe) added above */ pairdelete(&request->packet->vps, PW_SQL_USER_NAME); return RLM_MODULE_FAIL; } rows = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr); if (rows < 0) { radlog(L_ERR, "rlm_sql (%s): SQL query error; rejecting user", inst->config->xlat_name); sql_release_socket(inst, sqlsocket); /* Remove the username we (maybe) added above */ pairdelete(&request->packet->vps, PW_SQL_USER_NAME); pairfree(&check_tmp); return RLM_MODULE_FAIL; } else if (rows > 0) { /* * Only do this if *some* check pairs were returned */ if (paircompare(request, request->packet->vps, check_tmp, &request->reply->vps) == 0) { found = 1; DEBUG2("rlm_sql (%s): User found in radcheck table", inst->config->xlat_name); /* * Now get the reply pairs since the paircompare matched */ if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_reply_query, request, sql_escape_func)) { radlog(L_ERR, "rlm_sql (%s): Error generating query; rejecting user", inst->config->xlat_name); sql_release_socket(inst, sqlsocket); /* Remove the username we (maybe) added above */ pairdelete(&request->packet->vps, PW_SQL_USER_NAME); pairfree(&check_tmp); return RLM_MODULE_FAIL; } if (sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr) < 0) { radlog(L_ERR, "rlm_sql (%s): SQL query error; rejecting user", inst->config->xlat_name); sql_release_socket(inst, sqlsocket); /* Remove the username we (maybe) added above */ pairdelete(&request->packet->vps, PW_SQL_USER_NAME); pairfree(&check_tmp); pairfree(&reply_tmp); return RLM_MODULE_FAIL; } if (!inst->config->read_groups) dofallthrough = fallthrough(reply_tmp); pairxlatmove(request, &request->reply->vps, &reply_tmp); pairxlatmove(request, &request->config_items, &check_tmp); } } /* * Clear out the pairlists */ pairfree(&check_tmp); pairfree(&reply_tmp); /* * dofallthrough is set to 1 by default so that if the user information * is not found, we will still process groups. If the user information, * however, *is* found, Fall-Through must be set in order to process * the groups as well */ if (dofallthrough) { rows = rlm_sql_process_groups(inst, request, sqlsocket, &dofallthrough); if (rows < 0) { radlog(L_ERR, "rlm_sql (%s): Error processing groups; rejecting user", inst->config->xlat_name); sql_release_socket(inst, sqlsocket); /* Remove the username we (maybe) added above */ pairdelete(&request->packet->vps, PW_SQL_USER_NAME); return RLM_MODULE_FAIL; } else if (rows > 0) { found = 1; } } /* * repeat the above process with the default profile or User-Profile */ if (dofallthrough) { int profile_found = 0; /* * Check for a default_profile or for a User-Profile. */ user_profile = pairfind(request->config_items, PW_USER_PROFILE); if (inst->config->default_profile[0] != 0 || user_profile != NULL){ char *profile = inst->config->default_profile; if (user_profile != NULL) profile = user_profile->vp_strvalue; if (profile && strlen(profile)){ radlog(L_DBG, "rlm_sql (%s): Checking profile %s", inst->config->xlat_name, profile); if (sql_set_user(inst, request, profileusername, profile) < 0) { radlog(L_ERR, "rlm_sql (%s): Error setting profile; rejecting user", inst->config->xlat_name); sql_release_socket(inst, sqlsocket); /* Remove the username we (maybe) added above */ pairdelete(&request->packet->vps, PW_SQL_USER_NAME); return RLM_MODULE_FAIL; } else { profile_found = 1; } } } if (profile_found) { rows = rlm_sql_process_groups(inst, request, sqlsocket, &dofallthrough); if (rows < 0) { radlog(L_ERR, "rlm_sql (%s): Error processing profile groups; rejecting user", inst->config->xlat_name); sql_release_socket(inst, sqlsocket); /* Remove the username we (maybe) added above */ pairdelete(&request->packet->vps, PW_SQL_USER_NAME); return RLM_MODULE_FAIL; } else if (rows > 0) { found = 1; } } } /* Remove the username we (maybe) added above */ pairdelete(&request->packet->vps, PW_SQL_USER_NAME); sql_release_socket(inst, sqlsocket); if (!found) { radlog(L_DBG, "rlm_sql (%s): User %s not found", inst->config->xlat_name, sqlusername); return RLM_MODULE_NOTFOUND; } else { return RLM_MODULE_OK; }}/* * Accounting: save the account data to our sql table */static int rlm_sql_accounting(void *instance, REQUEST * request) { SQLSOCK *sqlsocket = NULL; VALUE_PAIR *pair; SQL_INST *inst = instance; int ret = RLM_MODULE_OK; int numaffected = 0; int acctstatustype = 0; char querystr[MAX_QUERY_LEN]; char logstr[MAX_QUERY_LEN]; char sqlusername[MAX_STRING_LEN];#ifdef CISCO_ACCOUNTING_HACK int acctsessiontime = 0;#endif memset(querystr, 0, MAX_QUERY_LEN); /* * Find the Acct Status Type */ if ((pair = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) != NULL) { acctstatustype = pair->vp_integer; } else { radius_xlat(logstr, sizeof(logstr), "packet has no accounting status type. [user '%{User-Name}', nas '%{NAS-IP-Address}']", request, NULL); radlog(L_ERR, "rlm_sql (%s) in sql_accounting: %s", inst->config->xlat_name, logstr); return RLM_MODULE_INVALID; } switch (acctstatustype) { /* * The Terminal server informed us that it was rebooted * STOP all records from this NAS */ case PW_STATUS_ACCOUNTING_ON: case PW_STATUS_ACCOUNTING_OFF: radlog(L_INFO, "rlm_sql (%s): received Acct On/Off packet", inst->config->xlat_name); radius_xlat(querystr, sizeof(querystr), inst->config->accounting_onoff_query, request, sql_escape_func); query_log(request, inst, querystr); sqlsocket = sql_get_socket(inst); if (sqlsocket == NULL) return(RLM_MODULE_FAIL); if (*querystr) { /* non-empty query */ if (rlm_sql_query(sqlsocket, inst, querystr)) { radlog(L_ERR, "rlm_sql (%s): Couldn't update SQL accounting for Acct On/Off packet - %s", inst->config->xlat_name, (inst->module->sql_error)(sqlsocket, inst->config)); ret = RLM_MODULE_FAIL; } (inst->module->sql_finish_query)(sqlsocket, inst->config); } break; /* * Got an update accounting packet */ case PW_STATUS_ALIVE: /* * Set, escape, and check the user attr here */ sql_set_user(inst, request, sqlusername, NULL); radius_xlat(querystr, sizeof(querystr), inst->config->accounting_update_query, request, sql_escape_func); query_log(request, inst, querystr); sqlsocket = sql_get_socket(inst); if (sqlsocket == NULL) return(RLM_MODULE_FAIL); if (*querystr) { /* non-empty query */ if (rlm_sql_query(sqlsocket, inst, querystr)) { radlog(L_ERR, "rlm_sql (%s): Couldn't update SQL accounting ALIVE record - %s", inst->config->xlat_name, (inst->module->sql_error)(sqlsocket, inst->config)); ret = RLM_MODULE_FAIL; } else { numaffected = (inst->module->sql_affected_rows)(sqlsocket, inst->config); if (numaffected < 1) { /* * If our update above didn't match anything * we assume it's because we haven't seen a * matching Start record. So we have to * insert this update rather than do an update */ radius_xlat(querystr, sizeof(querystr), inst->config->accounting_update_query_alt, request, sql_escape_func); query_log(request, inst, querystr); if (*querystr) { /* non-empty query */ if (rlm_sql_query(sqlsocket, inst, querystr)) { radlog(L_ERR, "rlm_sql (%s): Couldn't insert SQL accounting ALIVE record - %s", inst->config->xlat_name, (inst->module->sql_error)(sqlsocket, inst->config)); ret = RLM_MODULE_FAIL; } (inst->module->sql_finish_query)(sqlsocket, inst->config); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -