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

📄 rlm_sql.c

📁 RADIUS认证协议
💻 C
📖 第 1 页 / 共 3 页
字号:
	 */	if ((pair = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) != NULL) {		acctstatustype = pair->lvalue;	} else {		radius_xlat(logstr, sizeof(logstr), "rlm_sql: packet has no account status type.  [user '%{User-Name}', nas '%{NAS-IP-Address}']", request, sql_escape_func);		radlog(L_ERR, 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,					       (char *)(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,					       (char *)(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,									   (char *)(inst->module->sql_error)(sqlsocket, inst->config));								ret = RLM_MODULE_FAIL;							}							(inst->module->sql_finish_query)(sqlsocket, inst->config);						}					}				}				(inst->module->sql_finish_query)(sqlsocket, inst->config);			}			break;			/*			 * Got accounting start packet			 */		case PW_STATUS_START:			/*			 * Set, escape, and check the user attr here			 */			sql_set_user(inst, request, sqlusername, NULL);			radius_xlat(querystr, sizeof(querystr), inst->config->accounting_start_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 insert SQL accounting START record - %s",					       inst->config->xlat_name,					       (char *)(inst->module->sql_error)(sqlsocket, inst->config));					/*					 * We failed the insert above.  It's probably because					 * the stop record came before the start.  We try					 * our alternate query now (typically an UPDATE)					 */					radius_xlat(querystr, sizeof(querystr), inst->config->accounting_start_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 update SQL accounting START record - %s",							       inst->config->xlat_name,							       (char *)(inst->module->sql_error)(sqlsocket, inst->config));							ret = RLM_MODULE_FAIL;						}						(inst->module->sql_finish_query)(sqlsocket, inst->config);					}				}				(inst->module->sql_finish_query)(sqlsocket, inst->config);			}			break;			/*			 * Got accounting stop packet			 */		case PW_STATUS_STOP:			/*			 * Set, escape, and check the user attr here			 */			sql_set_user(inst, request, sqlusername, NULL);			radius_xlat(querystr, sizeof(querystr), inst->config->accounting_stop_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 STOP record - %s",					       inst->config->xlat_name,					       (char *)(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 stop rather than do an update						 */#ifdef CISCO_ACCOUNTING_HACK					        /*					         * If stop but zero session length AND no previous					         * session found, drop it as in invalid packet				        	 * This is to fix CISCO's aaa from filling our				        	 * table with bogus crap					         */					        if ((pair = pairfind(request->packet->vps, PW_ACCT_SESSION_TIME)) != NULL)					                acctsessiontime = pair->lvalue;					        if (acctsessiontime <= 0) {				        	        radius_xlat(logstr, sizeof(logstr), "rlm_sql: Stop packet with zero session length.  (user '%{User-Name}', nas '%{NAS-IP-Address}')", request, sql_escape_func);					                radlog(L_ERR, logstr);				        	        sql_release_socket(inst, sqlsocket);				                	ret = RLM_MODULE_NOOP;					        }#endif						radius_xlat(querystr, sizeof(querystr), inst->config->accounting_stop_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 STOP record - %s",										inst->config->xlat_name,										(char *)(inst->module->sql_error)(sqlsocket, inst->config));								ret = RLM_MODULE_FAIL;							}							(inst->module->sql_finish_query)(sqlsocket, inst->config);						}					}				}				(inst->module->sql_finish_query)(sqlsocket, inst->config);			}			break;			/*			 *	Anything else is ignored.			 */		default:			radlog(L_INFO, "rlm_sql (%s): Unsupported Acct-Status-Type = %d", inst->config->xlat_name, acctstatustype);			return RLM_MODULE_NOOP;			break;	}	sql_release_socket(inst, sqlsocket);	return ret;}/* *        See if a user is already logged in. Sets request->simul_count to the *        current session count for this user. * *        Check twice. If on the first pass the user exceeds his *        max. number of logins, do a second pass and validate all *        logins by querying the terminal server (using eg. SNMP). */static int rlm_sql_checksimul(void *instance, REQUEST * request) {	SQLSOCK 	*sqlsocket;	SQL_INST	*inst = instance;	SQL_ROW		row;	char		querystr[MAX_QUERY_LEN];	char		sqlusername[MAX_STRING_LEN];	int		check = 0;        uint32_t        ipno = 0;        char            *call_num = NULL;	VALUE_PAIR      *vp;	int		ret;	uint32_t	nas_addr = 0;	int		nas_port = 0;	/* If simul_count_query is not defined, we don't do any checking */	if (inst->config->simul_count_query[0] == 0) {		return RLM_MODULE_NOOP;	}	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;	}	if(sql_set_user(inst, request, sqlusername, NULL) < 0)		return RLM_MODULE_FAIL;	radius_xlat(querystr, sizeof(querystr), inst->config->simul_count_query, request, sql_escape_func);	/* initialize the sql socket */	sqlsocket = sql_get_socket(inst);	if(sqlsocket == NULL)		return RLM_MODULE_FAIL;	if(rlm_sql_select_query(sqlsocket, inst, querystr)) {		radlog(L_ERR, "rlm_sql (%s) sql_checksimul: Database query failed", inst->config->xlat_name);		sql_release_socket(inst, sqlsocket);		return RLM_MODULE_FAIL;	}	ret = rlm_sql_fetch_row(sqlsocket, inst);	if (ret != 0) {		(inst->module->sql_finish_select_query)(sqlsocket, inst->config);		sql_release_socket(inst, sqlsocket);		return RLM_MODULE_FAIL;	}	row = sqlsocket->row;	if (row == NULL) {		(inst->module->sql_finish_select_query)(sqlsocket, inst->config);		sql_release_socket(inst, sqlsocket);		return RLM_MODULE_FAIL;	}	request->simul_count = atoi(row[0]);	(inst->module->sql_finish_select_query)(sqlsocket, inst->config);	if(request->simul_count < request->simul_max) {		sql_release_socket(inst, sqlsocket);		return RLM_MODULE_OK;	}	/* Looks like too many sessions, so lets start verifying them */	if (inst->config->simul_verify_query[0] == 0) {		/* No verify query defined, so skip verify step and rely on count query only */		sql_release_socket(inst, sqlsocket);		return RLM_MODULE_OK;	}	radius_xlat(querystr, sizeof(querystr), inst->config->simul_verify_query, request, sql_escape_func);	if(rlm_sql_select_query(sqlsocket, inst, querystr)) {		radlog(L_ERR, "rlm_sql (%s): sql_checksimul: Database query error", inst->config->xlat_name);		sql_release_socket(inst, sqlsocket);		return RLM_MODULE_FAIL;	}        /*         *      Setup some stuff, like for MPP detection.         */	request->simul_count = 0;        if ((vp = pairfind(request->packet->vps, PW_FRAMED_IP_ADDRESS)) != NULL)                ipno = vp->lvalue;        if ((vp = pairfind(request->packet->vps, PW_CALLING_STATION_ID)) != NULL)                call_num = vp->strvalue;	while (rlm_sql_fetch_row(sqlsocket, inst) == 0) {		row = sqlsocket->row;		if (row == NULL)			break;		if (!row[2]){			(inst->module->sql_finish_select_query)(sqlsocket, inst->config);			sql_release_socket(inst, sqlsocket);			DEBUG("rlm_sql (%s): Cannot zap stale entry. No username present in entry.", inst->config->xlat_name);			return RLM_MODULE_FAIL;		}		if (!row[1]){			(inst->module->sql_finish_select_query)(sqlsocket, inst->config);			sql_release_socket(inst, sqlsocket);			DEBUG("rlm_sql (%s): Cannot zap stale entry. No session id in entry.", inst->config->xlat_name);			return RLM_MODULE_FAIL;		}		if (row[3])			nas_addr = inet_addr(row[3]);		if (row[4])			nas_port = atoi(row[4]);		check = rad_check_ts(nas_addr, nas_port, row[2], row[1]);                /*                 *      Failed to check the terminal server for                 *      duplicate logins: Return an error.                 */		if (check < 0) {			(inst->module->sql_finish_select_query)(sqlsocket, inst->config);			sql_release_socket(inst, sqlsocket);			DEBUG("rlm_sql (%s) rad_check_ts() failed.",			      inst->config->xlat_name);			return RLM_MODULE_FAIL;		}		if(check == 1) {			++request->simul_count;                        /*                         *      Does it look like a MPP attempt?                         */                        if (row[5] && ipno && inet_addr(row[5]) == ipno)                                request->simul_mpp = 2;                        else if (row[6] && call_num &&                                !strncmp(row[6],call_num,16))                                request->simul_mpp = 2;		}		else {                        /*                         *      Stale record - zap it.                         */			uint32_t framed_addr = 0;			char proto = 'P';			if (row[5])				framed_addr = inet_addr(row[5]);			if (row[7])				if (strcmp(row[7],"SLIP") == 0)					proto = 'S';			session_zap(request,				    nas_addr,nas_port,row[2],row[1],				    framed_addr, proto);		}	}	(inst->module->sql_finish_select_query)(sqlsocket, inst->config);	sql_release_socket(inst, sqlsocket);	/* The Auth module apparently looks at request->simul_count, not the return value	   of this module when deciding to deny a call for too many sessions */	return RLM_MODULE_OK;}/* *	Execute postauth_query after authentication */static int rlm_sql_postauth(void *instance, REQUEST *request) {	SQLSOCK 	*sqlsocket = NULL;	SQL_INST	*inst = instance;	char		querystr[MAX_QUERY_LEN];	char		sqlusername[MAX_STRING_LEN];	DEBUG("rlm_sql (%s): Processing sql_postauth", inst->config->xlat_name);	if(sql_set_user(inst, request, sqlusername, NULL) < 0)		return RLM_MODULE_FAIL;	/* If postauth_query is not defined, we stop here */	if (inst->config->postauth_query[0] == '\0')		return RLM_MODULE_NOOP;	/* Expand variables in the query */	memset(querystr, 0, MAX_QUERY_LEN);	radius_xlat(querystr, sizeof(querystr), inst->config->postauth_query,		    request, sql_escape_func);	query_log(request, inst, querystr);	DEBUG2("rlm_sql (%s) in sql_postauth: query is %s",	       inst->config->xlat_name, querystr);	/* Initialize the sql socket */	sqlsocket = sql_get_socket(inst);	if (sqlsocket == NULL)		return RLM_MODULE_FAIL;	/* Process the query */	if (rlm_sql_query(sqlsocket, inst, querystr)) {		radlog(L_ERR, "rlm_sql (%s) in sql_postauth: Database query error - %s",		       inst->config->xlat_name,		       (char *)(inst->module->sql_error)(sqlsocket, inst->config));		sql_release_socket(inst, sqlsocket);		return RLM_MODULE_FAIL;	}	(inst->module->sql_finish_query)(sqlsocket, inst->config);	sql_release_socket(inst, sqlsocket);	return RLM_MODULE_OK;}/* globally exported name */module_t rlm_sql = {	"SQL",	RLM_TYPE_THREAD_SAFE,	/* type: reserved */	rlm_sql_init,		/* initialization */	rlm_sql_instantiate,	/* instantiation */	{		NULL,			/* authentication */		rlm_sql_authorize,	/* authorization */		NULL,			/* preaccounting */		rlm_sql_accounting,	/* accounting */		rlm_sql_checksimul,	/* checksimul */		NULL,			/* pre-proxy */		NULL,			/* post-proxy */		rlm_sql_postauth	/* post-auth */	},	rlm_sql_detach,		/* detach */	rlm_sql_destroy,	/* destroy */};

⌨️ 快捷键说明

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