⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rlm_sql.c

📁 RADIUS认证协议
💻 C
📖 第 1 页 / 共 3 页
字号:
 * *	We don't call the escape function here. The resulting string *	will be escaped later in the queries xlat so we don't need to *	escape it twice. (it will make things wrong if we have an *	escape candidate character in the username) */static int sql_set_user(SQL_INST *inst, REQUEST *request, char *sqlusername, const char *username){	VALUE_PAIR *vp=NULL;	char tmpuser[MAX_STRING_LEN];	tmpuser[0] = '\0';	sqlusername[0]= '\0';	/* Remove any user attr we added previously */	pairdelete(&request->packet->vps, PW_SQL_USER_NAME);	if (username != NULL) {		strNcpy(tmpuser, username, MAX_STRING_LEN);	} else if (strlen(inst->config->query_user)) {		radius_xlat(tmpuser, sizeof(tmpuser), inst->config->query_user, request, NULL);	} else {		return 0;	}	if (*tmpuser) {		strNcpy(sqlusername, tmpuser, MAX_STRING_LEN);		DEBUG2("rlm_sql (%s): sql_set_user escaped user --> '%s'",		       inst->config->xlat_name, sqlusername);		vp = pairmake("SQL-User-Name", sqlusername, 0);		if (vp == NULL) {			radlog(L_ERR, "%s", librad_errstr);			return -1;		}		pairadd(&request->packet->vps, vp);		return 0;	}	return -1;}/* * sql groupcmp function. That way we can do group comparisons (in the users file for example) * with the group memberships reciding in sql * The group membership query should only return one element which is the username. The returned * username will then be checked with the passed check string. */static int sql_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check,			VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs){	SQLSOCK *sqlsocket;	SQL_ROW row;	SQL_INST *inst = instance;	char querystr[MAX_QUERY_LEN];	char sqlusername[MAX_STRING_LEN];	check_pairs = check_pairs;	reply_pairs = reply_pairs;	DEBUG("rlm_sql (%s): - sql_groupcmp", inst->config->xlat_name);	if (!check || !check->strvalue || !check->length){		DEBUG("rlm_sql (%s): sql_groupcmp: Illegal group name",		      inst->config->xlat_name);		return 1;	}	if (req == NULL){		DEBUG("rlm_sql (%s): sql_groupcmp: NULL request",		      inst->config->xlat_name);		return 1;	}	if (inst->config->groupmemb_query[0] == 0)		return 1;	/*	 * Set, escape, and check the user attr here	 */	if (sql_set_user(inst, req, sqlusername, NULL) < 0)		return 1;	if (!radius_xlat(querystr, sizeof(querystr), inst->config->groupmemb_query, req, sql_escape_func)){		radlog(L_ERR, "rlm_sql (%s): xlat failed.",		       inst->config->xlat_name);		/* Remove the username we (maybe) added above */		pairdelete(&req->packet->vps, PW_SQL_USER_NAME);		return 1;	}	/* Remove the username we (maybe) added above */	pairdelete(&req->packet->vps, PW_SQL_USER_NAME);	sqlsocket = sql_get_socket(inst);	if (sqlsocket == NULL)		return 1;	if ((inst->module->sql_select_query)(sqlsocket,inst->config,querystr) <0){		radlog(L_ERR, "rlm_sql (%s): database query error, %s: %s",		       inst->config->xlat_name,querystr,		       (char *)(inst->module->sql_error)(sqlsocket,inst->config));		sql_release_socket(inst,sqlsocket);		return 1;	}	while (rlm_sql_fetch_row(sqlsocket, inst) == 0) {		row = sqlsocket->row;		if (row == NULL)			break;		if (row[0] == NULL){			DEBUG("rlm_sql (%s): row[0] returned NULL",			      inst->config->xlat_name);			(inst->module->sql_finish_select_query)(sqlsocket, inst->config);			sql_release_socket(inst, sqlsocket);			return 1;		}		if (strcmp(row[0],check->strvalue) == 0){			DEBUG("rlm_sql (%s): - sql_groupcmp finished: User belongs in group %s",			      inst->config->xlat_name,			      (char *)check->strvalue);			(inst->module->sql_finish_select_query)(sqlsocket, inst->config);			sql_release_socket(inst, sqlsocket);			return 0;		}	}	(inst->module->sql_finish_select_query)(sqlsocket, inst->config);	sql_release_socket(inst,sqlsocket);	DEBUG("rlm_sql (%s): - sql_groupcmp finished: User does not belong in group %s",	      inst->config->xlat_name, (char *)check->strvalue);	return 1;}static int rlm_sql_detach(void *instance){	SQL_INST *inst = instance;	if (inst->sqlpool) {		sql_poolfree(inst);	}	if (inst->config->xlat_name) {		xlat_unregister(inst->config->xlat_name,sql_xlat);		free(inst->config->xlat_name);	}	paircompare_unregister(PW_SQL_GROUP, sql_groupcmp);	if (inst->config) {		int i;		/*		 *	Free up dynamically allocated string pointers.		 */		for (i = 0; module_config[i].name != NULL; i++) {			char **p;			if (module_config[i].type != PW_TYPE_STRING_PTR) {				continue;			}			/*			 *	Treat 'config' as an opaque array of bytes,			 *	and take the offset into it.  There's a			 *      (char*) pointer at that offset, and we want			 *	to point to it.			 */			p = (char **) (((char *)inst->config) + module_config[i].offset);			if (!*p) { /* nothing allocated */				continue;			}			free(*p);			*p = NULL;		}		free(inst->config);		inst->config = NULL;	}	if (inst->handle) {#if 0		/*		 *	FIXME: Call the modules 'destroy' function?		 */		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;	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, 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_destroy(void){	return 0;}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;	SQLSOCK *sqlsocket;	SQL_INST *inst = instance;	char    querystr[MAX_QUERY_LEN];	char	sqlusername[MAX_STRING_LEN];	/*	 *	They MUST have a user name to do SQL authorization.	 */	if ((request->username == NULL) ||	    (request->username->length == 0)) {		radlog(L_ERR, "rlm_sql (%s): zero length username not permitted\n", inst->config->xlat_name);		return RLM_MODULE_INVALID;	}	/*	 *  After this point, ALL 'return's MUST release the SQL socket!	 */	/*	 * Set, escape, and check the user attr here	 */	if (sql_set_user(inst, request, sqlusername, NULL) < 0)		return RLM_MODULE_FAIL;	radius_xlat(querystr, sizeof(querystr), inst->config->authorize_check_query, request, sql_escape_func);	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);	}	found = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr, PW_VP_USERDATA);	/*	 *      Find the entry for the user.	 */	if (found > 0) {		radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_check_query, request, sql_escape_func);		sql_getvpdata(inst, sqlsocket, &check_tmp, querystr, PW_VP_GROUPDATA);		radius_xlat(querystr, sizeof(querystr), inst->config->authorize_reply_query, request, sql_escape_func);		sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr, PW_VP_USERDATA);		radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func);		sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr, PW_VP_GROUPDATA);	} else if (found < 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);		return RLM_MODULE_FAIL;	} else {		radlog(L_DBG, "rlm_sql (%s): User %s not found in radcheck",		       inst->config->xlat_name, sqlusername);                /*		 * We didn't find the user in radcheck, so we try looking		 * for radgroupcheck entry		 */                radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_check_query, request, sql_escape_func);                found = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr, PW_VP_GROUPDATA);                radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func);                sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr, PW_VP_GROUPDATA);        }	if (!found)		radlog(L_DBG, "rlm_sql (%s): User %s not found in radgroupcheck",		       inst->config->xlat_name, sqlusername);	if (found || (!found && inst->config->query_on_not_found)){		int def_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->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, sqlusername, profile) < 0) {					return RLM_MODULE_FAIL;				}				radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_check_query,									request, sql_escape_func);				def_found = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr, PW_VP_GROUPDATA);				if (def_found)					found = 1;				radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query,									request, sql_escape_func);				sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr, PW_VP_GROUPDATA);			}		}	}	if (!found) {		radlog(L_DBG, "rlm_sql (%s): User not found",		       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_NOTFOUND;	}	/*	 * Uncomment these lines for debugging	 * Recompile, and run 'radiusd -X'	 */	/*	DEBUG2("rlm_sql:  check items");	vp_listdebug(check_tmp);	DEBUG2("rlm_sql:  reply items");	vp_listdebug(reply_tmp);	*/	if (paircmp(request, request->packet->vps, check_tmp, &reply_tmp) != 0) {		radlog(L_INFO, "rlm_sql (%s): No matching entry in the database for request from user [%s]",		       inst->config->xlat_name, sqlusername);		/* Remove the username we (maybe) added above */		pairdelete(&request->packet->vps, PW_SQL_USER_NAME);		sql_release_socket(inst, sqlsocket);		pairfree(&reply_tmp);		pairfree(&check_tmp);		return RLM_MODULE_NOTFOUND;	}	pairxlatmove(request, &request->reply->vps, &reply_tmp);	pairxlatmove(request, &request->config_items, &check_tmp);	pairfree(&reply_tmp);	pairfree(&check_tmp);	/* Remove the username we (maybe) added above */	pairdelete(&request->packet->vps, PW_SQL_USER_NAME);	sql_release_socket(inst, sqlsocket);	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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -