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

📄 rlm_radutmp.c

📁 radius服务器
💻 C
📖 第 1 页 / 共 2 页
字号:
		return RLM_MODULE_OK;	}	/*	 *	If we don't know this type of entry pretend we succeeded.	 */	if (status != PW_STATUS_START &&	    status != PW_STATUS_STOP &&	    status != PW_STATUS_ALIVE) {		radlog(L_ERR, "rlm_radutmp: NAS %s port %u unknown packet type %d)",		       nas, ut.nas_port, status);		return RLM_MODULE_NOOP;	}	/*	 *	Translate the User-Name attribute, or whatever else	 *	they told us to use.	 */	*buffer = '\0';	radius_xlat(buffer, sizeof(buffer), inst->username, request, NULL);	/*	 *  Copy the previous translated user name.	 */	strncpy(ut.login, buffer, RUT_NAMESIZE);	/*	 *	Perhaps we don't want to store this record into	 *	radutmp. We skip records:	 *	 *	- without a NAS-Port (telnet / tcp access)	 *	- with the username "!root" (console admin login)	 */	if (!port_seen) {		DEBUG2("  rlm_radutmp: No NAS-Port seen.  Cannot do anything.");		DEBUG2("  rlm_radumtp: WARNING: checkrad will probably not work!");		return RLM_MODULE_NOOP;	}	if (strncmp(ut.login, "!root", RUT_NAMESIZE) == 0) {		DEBUG2("  rlm_radutmp: Not recording administrative user");		return RLM_MODULE_NOOP;	}	/*	 *	Enter into the radutmp file.	 */	fd = open(filename, O_RDWR|O_CREAT, inst->permission);	if (fd < 0) {		radlog(L_ERR, "rlm_radutmp: Error accessing file %s: %s",		       filename, strerror(errno));		return RLM_MODULE_FAIL;	}	/*	 *	Lock the utmp file, prefer lockf() over flock().	 */	rad_lockfd(fd, LOCK_LEN);	/*	 *	Find the entry for this NAS / portno combination.	 */	if ((cache = nas_port_find(inst->nas_port_list, ut.nas_address,				   ut.nas_port)) != NULL) {		lseek(fd, (off_t)cache->offset, SEEK_SET);	}	r = 0;	off = 0;	while (read(fd, &u, sizeof(u)) == sizeof(u)) {		off += sizeof(u);		if (u.nas_address != ut.nas_address ||		    u.nas_port	  != ut.nas_port)			continue;		/*		 *	Don't compare stop records to unused entries.		 */		if (status == PW_STATUS_STOP &&		    u.type == P_IDLE) {			continue;		}		if (status == PW_STATUS_STOP &&		    strncmp(ut.session_id, u.session_id,			    sizeof(u.session_id)) != 0) {			/*			 *	Don't complain if this is not a			 *	login record (some clients can			 *	send _only_ logout records).			 */			if (u.type == P_LOGIN)				radlog(L_ERR, "rlm_radutmp: Logout entry for NAS %s port %u has wrong ID",				       nas, u.nas_port);			r = -1;			break;		}		if (status == PW_STATUS_START &&		    strncmp(ut.session_id, u.session_id,			    sizeof(u.session_id)) == 0  &&		    u.time >= ut.time) {			if (u.type == P_LOGIN) {				radlog(L_INFO, "rlm_radutmp: Login entry for NAS %s port %u duplicate",				       nas, u.nas_port);				r = -1;				break;			}			radlog(L_ERR, "rlm_radutmp: Login entry for NAS %s port %u wrong order",			       nas, u.nas_port);			r = -1;			break;		}		/*		 *	FIXME: the ALIVE record could need		 *	some more checking, but anyway I'd		 *	rather rewrite this mess -- miquels.		 */		if (status == PW_STATUS_ALIVE &&		    strncmp(ut.session_id, u.session_id,			    sizeof(u.session_id)) == 0  &&		    u.type == P_LOGIN) {			/*			 *	Keep the original login time.			 */			ut.time = u.time;			if (u.login[0] != 0)				just_an_update = 1;		}		if (lseek(fd, -(off_t)sizeof(u), SEEK_CUR) < 0) {			radlog(L_ERR, "rlm_radutmp: negative lseek!");			lseek(fd, (off_t)0, SEEK_SET);			off = 0;		} else			off -= sizeof(u);		r = 1;		break;	} /* read the file until we find a match */	/*	 *	Found the entry, do start/update it with	 *	the information from the packet.	 */	if (r >= 0 &&  (status == PW_STATUS_START ||			status == PW_STATUS_ALIVE)) {		/*		 *	Remember where the entry was, because it's		 *	easier than searching through the entire file.		 */		if (cache == NULL) {			cache = rad_malloc(sizeof(NAS_PORT));			cache->nasaddr = ut.nas_address;			cache->port = ut.nas_port;			cache->offset = off;			cache->next = inst->nas_port_list;			inst->nas_port_list = cache;		}		ut.type = P_LOGIN;		write(fd, &ut, sizeof(u));	}	/*	 *	The user has logged off, delete the entry by	 *	re-writing it in place.	 */	if (status == PW_STATUS_STOP) {		if (r > 0) {			u.type = P_IDLE;			u.time = ut.time;			u.delay = ut.delay;			write(fd, &u, sizeof(u));		} else if (r == 0) {			radlog(L_ERR, "rlm_radutmp: Logout for NAS %s port %u, but no Login record",			       nas, ut.nas_port);			r = -1;		}	}	close(fd);	/* and implicitely release the locks */	return RLM_MODULE_OK;}/* *	See if a user is already logged in. Sets request->simul_count to the *	current session count for this user and sets request->simul_mpp to 2 *	if it looks like a multilink attempt based on the requested IP *	address, otherwise leaves request->simul_mpp alone. * *	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 radutmp_checksimul(void *instance, REQUEST *request){	struct radutmp	u;	int		fd;	VALUE_PAIR	*vp;	uint32_t	ipno = 0;	char		*call_num = NULL;	int		rcode;	rlm_radutmp_t	*inst = instance;	char		login[256];	char		filename[1024];	/*	 *	Get the filename, via xlat.	 */	radius_xlat(filename, sizeof(filename), inst->filename, request, NULL);	if ((fd = open(filename, O_RDWR)) < 0) {		/*		 *	If the file doesn't exist, then no users		 *	are logged in.		 */		if (errno == ENOENT) {			request->simul_count=0;			return RLM_MODULE_OK;		}		/*		 *	Error accessing the file.		 */		radlog(L_ERR, "rlm_radumtp: Error accessing file %s: %s",		       filename, strerror(errno));		return RLM_MODULE_FAIL;	}	*login = '\0';	radius_xlat(login, sizeof(login), inst->username, request, NULL);	if (!*login) {		return RLM_MODULE_NOOP;	}	/*	 *	WTF?  This is probably wrong... we probably want to	 *	be able to check users across multiple session accounting	 *	methods.	 */	request->simul_count = 0;	/*	 *	Loop over utmp, counting how many people MAY be logged in.	 */	while (read(fd, &u, sizeof(u)) == sizeof(u)) {		if (((strncmp(login, u.login, RUT_NAMESIZE) == 0) ||		     (!inst->case_sensitive &&		      (strncasecmp(login, u.login, RUT_NAMESIZE) == 0))) &&		    (u.type == P_LOGIN)) {			++request->simul_count;		}	}	/*	 *	The number of users logged in is OK,	 *	OR, we've been told to not check the NAS.	 */	if ((request->simul_count < request->simul_max) ||	    !inst->check_nas) {		close(fd);		return RLM_MODULE_OK;	}	lseek(fd, (off_t)0, SEEK_SET);	/*	 *	Setup some stuff, like for MPP detection.	 */	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;	/*	 *	lock the file while reading/writing.	 */	rad_lockfd(fd, LOCK_LEN);	/*	 *	FIXME: If we get a 'Start' for a user/nas/port which is	 *	listed, but for which we did NOT get a 'Stop', then	 *	it's not a duplicate session.  This happens with	 *	static IP's like DSL.	 */	request->simul_count = 0;	while (read(fd, &u, sizeof(u)) == sizeof(u)) {		if (((strncmp(login, u.login, RUT_NAMESIZE) == 0) ||		     (!inst->case_sensitive &&		      (strncasecmp(login, u.login, RUT_NAMESIZE) == 0))) &&		    (u.type == P_LOGIN)) {			char session_id[sizeof(u.session_id) + 1];			char utmp_login[sizeof(u.login) + 1];			strNcpy(session_id, u.session_id, sizeof(session_id));			/*			 *	The login name MAY fill the whole field,			 *	and thus won't be zero-filled.			 *			 *	Note that we take the user name from			 *	the utmp file, as that's the canonical			 *	form.  The 'login' variable may contain			 *	a string which is an upper/lowercase			 *	version of u.login.  When we call the			 *	routine to check the terminal server,			 *	the NAS may be case sensitive.			 *			 *	e.g. We ask if "bob" is using a port,			 *	and the NAS says "no", because "BOB"			 *	is using the port.			 */			strNcpy(utmp_login, u.login, sizeof(u.login));			/*			 *	rad_check_ts may take seconds			 *	to return, and we don't want			 *	to block everyone else while			 *	that's happening.  */			rad_unlockfd(fd, LOCK_LEN);			rcode = rad_check_ts(u.nas_address, u.nas_port,					     utmp_login, session_id);			rad_lockfd(fd, LOCK_LEN);			/*			 *	Failed to check the terminal server for			 *	duplicate logins: Return an error.			 */			if (rcode < 0) {				close(fd);				return RLM_MODULE_FAIL;			}			if (rcode == 1) {				++request->simul_count;				/*				 *	Does it look like a MPP attempt?				 */				if (strchr("SCPA", u.proto) &&				    ipno && u.framed_address == ipno)					request->simul_mpp = 2;				else if (strchr("SCPA", u.proto) && call_num &&					!strncmp(u.caller_id,call_num,16))					request->simul_mpp = 2;			}			else {				/*				 *	False record - zap it.				 */				session_zap(request,					    u.nas_address, u.nas_port, login,					    session_id, u.framed_address,					    u.proto);			}		}	}	close(fd);		/* and implicitely release the locks */	return RLM_MODULE_OK;}/* globally exported name */module_t rlm_radutmp = {  "radutmp",  0,                            /* type: reserved */  NULL,                 	/* initialization */  radutmp_instantiate,          /* instantiation */  {	  NULL,                 /* authentication */	  NULL,                 /* authorization */	  NULL,                 /* preaccounting */	  radutmp_accounting,   /* accounting */	  radutmp_checksimul,	/* checksimul */	  NULL,			/* pre-proxy */	  NULL,			/* post-proxy */	  NULL			/* post-auth */  },  radutmp_detach,               /* detach */  NULL,         	        /* destroy */};

⌨️ 快捷键说明

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