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

📄 rlm_sql.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * rlm_sql.c		SQL Module * 		Main SQL module file. Most ICRADIUS code is located in sql.c * * Version:	$Id: rlm_sql.c,v 1.179 2008/04/29 08:10:37 aland Exp $ * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * Copyright 2000,2006  The FreeRADIUS server project * Copyright 2000  Mike Machado <mike@innercite.com> * Copyright 2000  Alan DeKok <aland@ox.org> */#include <freeradius-devel/ident.h>RCSID("$Id: rlm_sql.c,v 1.179 2008/04/29 08:10:37 aland Exp $")#include <freeradius-devel/radiusd.h>#include <freeradius-devel/modules.h>#include <freeradius-devel/rad_assert.h>#include <sys/stat.h>#include "rlm_sql.h"static char *allowed_chars = NULL;static const CONF_PARSER module_config[] = {	{"driver",PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,sql_driver), NULL, "mysql"},	{"server",PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,sql_server), NULL, "localhost"},	{"port",PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,sql_port), NULL, ""},	{"login", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,sql_login), NULL, ""},	{"password", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,sql_password), NULL, ""},	{"radius_db", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,sql_db), NULL, "radius"},	{"read_groups", PW_TYPE_BOOLEAN,	 offsetof(SQL_CONFIG,read_groups), NULL, "yes"},	{"sqltrace", PW_TYPE_BOOLEAN,	 offsetof(SQL_CONFIG,sqltrace), NULL, "no"},	{"sqltracefile", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,tracefile), NULL, SQLTRACEFILE},	{"readclients", PW_TYPE_BOOLEAN,	 offsetof(SQL_CONFIG,do_clients), NULL, "no"},	{"deletestalesessions", PW_TYPE_BOOLEAN,	 offsetof(SQL_CONFIG,deletestalesessions), NULL, "yes"},	{"num_sql_socks", PW_TYPE_INTEGER,	 offsetof(SQL_CONFIG,num_sql_socks), NULL, "5"},	{"sql_user_name", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,query_user), NULL, ""},	{"default_user_profile", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,default_profile), NULL, ""},	{"nas_query", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,nas_query), NULL, "SELECT id,nasname,shortname,type,secret FROM nas"},	{"authorize_check_query", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,authorize_check_query), NULL, ""},	{"authorize_reply_query", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,authorize_reply_query), NULL, ""},	{"authorize_group_check_query", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,authorize_group_check_query), NULL, ""},	{"authorize_group_reply_query", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,authorize_group_reply_query), NULL, ""},	{"accounting_onoff_query", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,accounting_onoff_query), NULL, ""},	{"accounting_update_query", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,accounting_update_query), NULL, ""},	{"accounting_update_query_alt", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,accounting_update_query_alt), NULL, ""},	{"accounting_start_query", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,accounting_start_query), NULL, ""},	{"accounting_start_query_alt", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,accounting_start_query_alt), NULL, ""},	{"accounting_stop_query", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,accounting_stop_query), NULL, ""},	{"accounting_stop_query_alt", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,accounting_stop_query_alt), NULL, ""},	{"group_membership_query", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,groupmemb_query), NULL, NULL},	{"connect_failure_retry_delay", PW_TYPE_INTEGER,	 offsetof(SQL_CONFIG,connect_failure_retry_delay), NULL, "60"},	{"simul_count_query", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,simul_count_query), NULL, ""},	{"simul_verify_query", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,simul_verify_query), NULL, ""},	{"postauth_query", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,postauth_query), NULL, ""},	{"safe-characters", PW_TYPE_STRING_PTR,	 offsetof(SQL_CONFIG,allowed_chars), NULL,	"@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /"},	{NULL, -1, 0, NULL, NULL}};/* *	Fall-Through checking function from rlm_files.c */static int fallthrough(VALUE_PAIR *vp){	VALUE_PAIR *tmp;	tmp = pairfind(vp, PW_FALL_THROUGH);	return tmp ? tmp->vp_integer : 0;}/* *	Yucky prototype. */static int generate_sql_clients(SQL_INST *inst);static size_t sql_escape_func(char *out, size_t outlen, const char *in);/* *	sql xlat function. Right now only SELECTs are supported. Only *	the first element of the SELECT result will be used. */static int sql_xlat(void *instance, REQUEST *request,		    char *fmt, char *out, size_t freespace,		    UNUSED RADIUS_ESCAPE_STRING func){	SQLSOCK *sqlsocket;	SQL_ROW row;	SQL_INST *inst = instance;	char querystr[MAX_QUERY_LEN];	char sqlusername[MAX_STRING_LEN];	size_t ret = 0;	DEBUG("rlm_sql (%s): - sql_xlat", inst->config->xlat_name);	/*         * Add SQL-User-Name attribute just in case it is needed         *  We could search the string fmt for SQL-User-Name to see if this is         *  needed or not         */	sql_set_user(inst, request, sqlusername, NULL);	/*	 * Do an xlat on the provided string (nice recursive operation).	 */	if (!radius_xlat(querystr, sizeof(querystr), fmt, request, sql_escape_func)) {		radlog(L_ERR, "rlm_sql (%s): xlat failed.",		       inst->config->xlat_name);		return 0;	}	query_log(request, inst,querystr);	sqlsocket = sql_get_socket(inst);	if (sqlsocket == NULL)		return 0;	if (rlm_sql_select_query(sqlsocket,inst,querystr)){		radlog(L_ERR, "rlm_sql (%s): database query error, %s: %s",		       inst->config->xlat_name,querystr,		       (inst->module->sql_error)(sqlsocket, inst->config));		sql_release_socket(inst,sqlsocket);		return 0;	}	ret = rlm_sql_fetch_row(sqlsocket, inst);	if (ret) {		DEBUG("rlm_sql (%s): SQL query did not succeed",		      inst->config->xlat_name);		(inst->module->sql_finish_select_query)(sqlsocket, inst->config);		sql_release_socket(inst,sqlsocket);		return 0;	}	row = sqlsocket->row;	if (row == NULL) {		DEBUG("rlm_sql (%s): SQL query did not return any results",		      inst->config->xlat_name);		(inst->module->sql_finish_select_query)(sqlsocket, inst->config);		sql_release_socket(inst,sqlsocket);		return 0;	}	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 0;	}	ret = strlen(row[0]);	if (ret >= freespace){		DEBUG("rlm_sql (%s): sql_xlat:: Insufficient string space",		      inst->config->xlat_name);		(inst->module->sql_finish_select_query)(sqlsocket, inst->config);		sql_release_socket(inst,sqlsocket);		return 0;	}	strlcpy(out,row[0],freespace);	DEBUG("rlm_sql (%s): - sql_xlat finished",	      inst->config->xlat_name);	(inst->module->sql_finish_select_query)(sqlsocket, inst->config);	sql_release_socket(inst,sqlsocket);	return ret;}static int generate_sql_clients(SQL_INST *inst){	SQLSOCK *sqlsocket;	SQL_ROW row;	char querystr[MAX_QUERY_LEN];	RADCLIENT *c;	char *prefix_ptr = NULL;	unsigned int i = 0;	int numf = 0;	DEBUG("rlm_sql (%s): Processing generate_sql_clients",	      inst->config->xlat_name);	/* NAS query isn't xlat'ed */	strlcpy(querystr, inst->config->nas_query, sizeof(querystr));	DEBUG("rlm_sql (%s) in generate_sql_clients: query is %s",	      inst->config->xlat_name, querystr);	sqlsocket = sql_get_socket(inst);	if (sqlsocket == NULL)		return -1;	if (rlm_sql_select_query(sqlsocket,inst,querystr)){		radlog(L_ERR, "rlm_sql (%s): database query error, %s: %s",		       inst->config->xlat_name,querystr,		       (inst->module->sql_error)(sqlsocket, inst->config));		sql_release_socket(inst,sqlsocket);		return -1;	}	while(rlm_sql_fetch_row(sqlsocket, inst) == 0) {		i++;		row = sqlsocket->row;		if (row == NULL)			break;	/*	 *  The return data for each row MUST be in the following order:	 *	 *  0. Row ID (currently unused)	 *  1. Name (or IP address)	 *  2. Shortname	 *  3. Type	 *  4. Secret	 *  5. Virtual Server (optional)	 */		if (!row[0]){			radlog(L_ERR, "rlm_sql (%s): No row id found on pass %d",inst->config->xlat_name,i);			continue;		}		if (!row[1]){			radlog(L_ERR, "rlm_sql (%s): No nasname found for row %s",inst->config->xlat_name,row[0]);			continue;		}		if (!row[2]){			radlog(L_ERR, "rlm_sql (%s): No short name found for row %s",inst->config->xlat_name,row[0]);			continue;		}		if (!row[4]){			radlog(L_ERR, "rlm_sql (%s): No secret found for row %s",inst->config->xlat_name,row[0]);			continue;		}		DEBUG("rlm_sql (%s): Read entry nasname=%s,shortname=%s,secret=%s",inst->config->xlat_name,			row[1],row[2],row[4]);		c = rad_malloc(sizeof(*c));		memset(c, 0, sizeof(*c));		/*		 *	Look for prefixes		 */		c->prefix = -1;		prefix_ptr = strchr(row[1], '/');		if (prefix_ptr) {			c->prefix = atoi(prefix_ptr + 1);			if ((c->prefix < 0) || (c->prefix > 128)) {				radlog(L_ERR, "rlm_sql (%s): Invalid Prefix value '%s' for IP.",				       inst->config->xlat_name, prefix_ptr + 1);				free(c);				continue;			}			/* Replace '/' with '\0' */			*prefix_ptr = '\0';		}		/*		 *	Always get the numeric representation of IP		 */		if (ip_hton(row[1], AF_UNSPEC, &c->ipaddr) < 0) {			radlog(L_CONS|L_ERR, "rlm_sql (%s): Failed to look up hostname %s: %s",			       inst->config->xlat_name,			       row[1], librad_errstr);			free(c);			continue;		} else {			char buffer[256];			ip_ntoh(&c->ipaddr, buffer, sizeof(buffer));			c->longname = strdup(buffer);		}		if (c->prefix < 0) switch (c->ipaddr.af) {		case AF_INET:			c->prefix = 32;			break;		case AF_INET6:			c->prefix = 128;			break;		default:			break;		}		/*		 *	Other values (secret, shortname, nastype, virtual_server)		 */		c->secret = strdup(row[4]);		c->shortname = strdup(row[2]);		if(row[3] != NULL)			c->nastype = strdup(row[3]);		numf = (inst->module->sql_num_fields)(sqlsocket, inst->config);		if ((numf > 5) && (row[5] != NULL)) c->server = strdup(row[5]);		DEBUG("rlm_sql (%s): Adding client %s (%s, server=%s) to clients list",		      inst->config->xlat_name,		      c->longname,c->shortname, c->server ? c->server : "<none>");		if (!client_add(NULL, c)) {			DEBUG("rlm_sql (%s): Failed to add client %s (%s) to clients list.  Maybe there's a duplicate?",			      inst->config->xlat_name,			      c->longname,c->shortname);			client_free(c);			return -1;		}	}	(inst->module->sql_finish_select_query)(sqlsocket, inst->config);	sql_release_socket(inst, sqlsocket);	return 0;}/* *	Translate the SQL queries. */static size_t sql_escape_func(char *out, size_t outlen, const char *in){	size_t len = 0;	while (in[0]) {		/*		 *	Non-printable characters get replaced with their		 *	mime-encoded equivalents.		 */		if ((in[0] < 32) ||		    strchr(allowed_chars, *in) == NULL) {			/*			 *	Only 3 or less bytes available.			 */			if (outlen <= 3) {				break;			}			snprintf(out, outlen, "=%02X", (unsigned char) in[0]);			in++;			out += 3;			outlen -= 3;			len += 3;			continue;		}		/*		 *	Only one byte left.		 */		if (outlen <= 1) {

⌨️ 快捷键说明

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