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

📄 rlm_sql.c

📁 freeradius-server-2.1.3.tar.gz安装源文件
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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 *request, VALUE_PAIR *request_vp, VALUE_PAIR *check,			VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs){	SQLSOCK *sqlsocket;	SQL_INST *inst = instance;	char sqlusername[MAX_STRING_LEN];	SQL_GROUPLIST *group_list, *group_list_tmp;	check_pairs = check_pairs;	reply_pairs = reply_pairs;	request_vp = request_vp;	RDEBUG("sql_groupcmp");	if (!check || !check->vp_strvalue || !check->length){		RDEBUG("sql_groupcmp: Illegal group name");		return 1;	}	if (!request){		RDEBUG("sql_groupcmp: NULL request");		return 1;	}	/*	 * Set, escape, and check the user attr here	 */	if (sql_set_user(inst, request, sqlusername, NULL) < 0)		return 1;	/*	 *	Get a socket for this lookup	 */	sqlsocket = sql_get_socket(inst);	if (sqlsocket == NULL) {		/* Remove the username we (maybe) added above */		pairdelete(&request->packet->vps, PW_SQL_USER_NAME);		return 1;	}	/*	 *	Get the list of groups this user is a member of	 */	if (sql_get_grouplist(inst, sqlsocket, request, &group_list) < 0) {		radlog_request(L_ERR, 0, request,			       "Error getting group membership");		/* Remove the username we (maybe) added above */		pairdelete(&request->packet->vps, PW_SQL_USER_NAME);		sql_release_socket(inst, sqlsocket);		return 1;	}	for (group_list_tmp = group_list; group_list_tmp != NULL; group_list_tmp = group_list_tmp->next) {		if (strcmp(group_list_tmp->groupname, check->vp_strvalue) == 0){			RDEBUG("sql_groupcmp finished: User is a member of group %s",			       check->vp_strvalue);			/* Free the grouplist */			sql_grouplist_free(&group_list);			/* Remove the username we (maybe) added above */			pairdelete(&request->packet->vps, PW_SQL_USER_NAME);			sql_release_socket(inst, sqlsocket);			return 0;		}	}	/* Free the grouplist */	sql_grouplist_free(&group_list);	/* Remove the username we (maybe) added above */	pairdelete(&request->packet->vps, PW_SQL_USER_NAME);	sql_release_socket(inst,sqlsocket);	RDEBUG("sql_groupcmp finished: User is NOT a member of group %s",	       check->vp_strvalue);	return 1;}static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sqlsocket, int *dofallthrough){	VALUE_PAIR *check_tmp = NULL;	VALUE_PAIR *reply_tmp = NULL;	SQL_GROUPLIST *group_list, *group_list_tmp;	VALUE_PAIR *sql_group = NULL;	char    querystr[MAX_QUERY_LEN];	int found = 0;	int rows;	/*	 *	Get the list of groups this user is a member of	 */	if (sql_get_grouplist(inst, sqlsocket, request, &group_list) < 0) {		radlog_request(L_ERR, 0, request, "Error retrieving group list");		return -1;	}	for (group_list_tmp = group_list; group_list_tmp != NULL && *dofallthrough != 0; group_list_tmp = group_list_tmp->next) {		/*		 *	Add the Sql-Group attribute to the request list so we know		 *	which group we're retrieving attributes for		 */		sql_group = pairmake("Sql-Group", group_list_tmp->groupname, T_OP_EQ);		if (!sql_group) {			radlog_request(L_ERR, 0, request,				       "Error creating Sql-Group attribute");			return -1;		}		pairadd(&request->packet->vps, sql_group);		if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_check_query, request, sql_escape_func)) {			radlog_request(L_ERR, 0, request,				       "Error generating query; rejecting user");			/* Remove the grouup we added above */			pairdelete(&request->packet->vps, PW_SQL_GROUP);			return -1;		}		rows = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr);		if (rows < 0) {			radlog_request(L_ERR, 0, request, "Error retrieving check pairs for group %s",			       group_list_tmp->groupname);			/* Remove the grouup we added above */			pairdelete(&request->packet->vps, PW_SQL_GROUP);			pairfree(&check_tmp);			return -1;		} 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;				RDEBUG2("User found in group %s",					group_list_tmp->groupname);				/*				 *	Now get the reply pairs since the paircompare matched				 */				if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func)) {					radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");					/* Remove the grouup we added above */					pairdelete(&request->packet->vps, PW_SQL_GROUP);					pairfree(&check_tmp);					return -1;				}				if (sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr) < 0) {					radlog_request(L_ERR, 0, request, "Error retrieving reply pairs for group %s",					       group_list_tmp->groupname);					/* Remove the grouup we added above */					pairdelete(&request->packet->vps, PW_SQL_GROUP);					pairfree(&check_tmp);					pairfree(&reply_tmp);					return -1;				}				*dofallthrough = fallthrough(reply_tmp);				pairxlatmove(request, &request->reply->vps, &reply_tmp);				pairxlatmove(request, &request->config_items, &check_tmp);			}		} else {			/*			 *	rows == 0.  This is like having the username on a line			 * 	in the user's file with no check vp's.  As such, we treat			 *	it as found and add the reply attributes, so that we			 *	match expected behavior			 */			found = 1;			RDEBUG2("User found in group %s",				group_list_tmp->groupname);			/*			 *	Now get the reply pairs since the paircompare matched			 */			if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func)) {				radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");				/* Remove the grouup we added above */				pairdelete(&request->packet->vps, PW_SQL_GROUP);				pairfree(&check_tmp);				return -1;			}			if (sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr) < 0) {				radlog_request(L_ERR, 0, request, "Error retrieving reply pairs for group %s",				       group_list_tmp->groupname);				/* Remove the grouup we added above */				pairdelete(&request->packet->vps, PW_SQL_GROUP);				pairfree(&check_tmp);				pairfree(&reply_tmp);				return -1;			}			*dofallthrough = fallthrough(reply_tmp);			pairxlatmove(request, &request->reply->vps, &reply_tmp);			pairxlatmove(request, &request->config_items, &check_tmp);		}		/*		 * Delete the Sql-Group we added above		 * And clear out the pairlists		 */		pairdelete(&request->packet->vps, PW_SQL_GROUP);		pairfree(&check_tmp);		pairfree(&reply_tmp);	}	sql_grouplist_free(&group_list);	return found;}static int rlm_sql_detach(void *instance){	SQL_INST *inst = instance;	paircompare_unregister(PW_SQL_GROUP, sql_groupcmp);	if (inst->config) {		int i;		if (inst->sqlpool) {			sql_poolfree(inst);		}		if (inst->config->xlat_name) {			xlat_unregister(inst->config->xlat_name,(RAD_XLAT_FUNC)sql_xlat);			free(inst->config->xlat_name);		}		/*		 *	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;		}		allowed_chars = 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;	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));	/*	 *	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;	/*	 * 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, "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, "\"%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;	}	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;}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_request(L_ERR, 0, request, "Error generating query; rejecting user");		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_request(L_ERR, 0, request, "SQL query error; rejecting user");		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;			RDEBUG2("User found in radcheck table");			if (inst->config->authorize_reply_query &&			    *inst->config->authorize_reply_query) {			/*			 *	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_request(L_ERR, 0, request, "Error generating query; rejecting user");				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_request(L_ERR, 0, request, "SQL query error; rejecting user");				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_request(L_ERR, 0, request, "Error processing groups; rejecting user");			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)){				RDEBUG("Checking profile %s", profile);				if (sql_set_user(inst, request, profileusername, profile) < 0) {					radlog_request(L_ERR, 0, request, "Error setting profile; rejecting user");					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 {

⌨️ 快捷键说明

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