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

📄 auth.c

📁 新的radius程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	 */	if (request->proxy_reply) {		switch (request->proxy_reply->code) {		/*		 *	Reply of ACCEPT means accept, thus set Auth-Type		 *	accordingly.		 */		case PW_AUTHENTICATION_ACK:			tmp = paircreate(PW_AUTH_TYPE, PW_TYPE_INTEGER);			if (tmp == NULL) {				radlog(L_ERR|L_CONS, "Not enough memory");				exit(1);			}			tmp->lvalue = PW_AUTHTYPE_ACCEPT;			pairadd(&request->config_items, tmp);			break;		/*		 *	Challenges are punted back to the NAS without any		 *	further processing.		 */		case PW_ACCESS_CHALLENGE:			request->reply->code = PW_ACCESS_CHALLENGE;			return RLM_MODULE_OK;		/*		 *	ALL other replies mean reject. (this is fail-safe)		 *		 *	Do NOT do any authorization or authentication. They		 *	are being rejected, so we minimize the amount of work		 *	done by the server, by rejecting them here.		 */		case PW_AUTHENTICATION_REJECT:		default:			rad_authlog("Login incorrect (Home Server says so)",				    request, 0);			request->reply->code = PW_AUTHENTICATION_REJECT;			rad_postauth_reject(request);			return RLM_MODULE_REJECT;		}	}	/*	 *	Get the username from the request.	 *	 *	Note that namepair MAY be NULL, in which case there	 *	is no User-Name attribute in the request.	 */	namepair = request->username;	/*	 *	Look for, and cache, passwords.	 */	if (!request->password) {		request->password = pairfind(request->packet->vps,					     PW_PASSWORD);	}	/*	 *	Discover which password we want to use.	 */	auth_item = request->password;	if (auth_item) {		password = (const char *)auth_item->strvalue;	} else {		/*		 *	Maybe there's a CHAP-Password?		 */		if ((auth_item = pairfind(request->packet->vps,				PW_CHAP_PASSWORD)) != NULL) {			password = "<CHAP-PASSWORD>";		} else {			/*			 *	No password we recognize.			 */			password = "<NO-PASSWORD>";		}	}	request->password = auth_item;	/*	 *	Get the user's authorization information from the database	 */autz_redo:	result = module_authorize(autz_type, request);	switch (result) {		case RLM_MODULE_NOOP:		case RLM_MODULE_NOTFOUND:		case RLM_MODULE_OK:		case RLM_MODULE_UPDATED:			break;		case RLM_MODULE_FAIL:		case RLM_MODULE_HANDLED:			return result;		case RLM_MODULE_INVALID:		case RLM_MODULE_REJECT:		case RLM_MODULE_USERLOCK:		default:			if ((module_msg = pairfind(request->packet->vps,					PW_MODULE_FAILURE_MESSAGE)) != NULL) {				char msg[MAX_STRING_LEN + 16];				snprintf(msg, sizeof(msg), "Invalid user (%s)",					 module_msg->strvalue);				rad_authlog(msg,request,0);			} else {				rad_authlog("Invalid user", request, 0);			}			request->reply->code = PW_AUTHENTICATION_REJECT;			return result;	}	if (!autz_retry) {		tmp = pairfind(request->config_items, PW_AUTZ_TYPE);		if (tmp) {			DEBUG2("  Found Autz-Type %s", tmp->strvalue);			autz_type = tmp->lvalue;			autz_retry = 1;			goto autz_redo;		}	}	/*	 *	If we haven't already proxied the packet, then check	 *	to see if we should.  Maybe one of the authorize	 *	modules has decided that a proxy should be used. If	 *	so, get out of here and send the packet.	 */	if ((request->proxy == NULL) &&	    ((tmp = pairfind(request->config_items, PW_PROXY_TO_REALM)) != NULL)) {		REALM *realm;		/*		 *	Catch users who set Proxy-To-Realm to a LOCAL		 *	realm (sigh).		 */		realm = realm_find(tmp->strvalue, 0);		if (realm && (realm->ipaddr == htonl(INADDR_NONE))) {			DEBUG2("  WARNING: You set Proxy-To-Realm = %s, but it is a LOCAL realm!  Cancelling invalid proxy request.", realm->realm);		} else {			/*			 *	Don't authenticate, as the request is			 *	proxied.			 */			return RLM_MODULE_OK;		}	}	/*	 *	Perhaps there is a Stripped-User-Name now.	 */	namepair = request->username;	/*	 *	Validate the user	 */	do {		if ((result = check_expiration(request)) < 0)				break;		result = rad_check_password(request);		if (result > 0) {			/* don't reply! */			return RLM_MODULE_HANDLED;		}	} while(0);	/*	 *	Failed to validate the user.	 *	 *	We PRESUME that the code which failed will clean up	 *	request->reply->vps, to be ONLY the reply items it	 *	wants to send back.	 */	if (result < 0) {		DEBUG2("auth: Failed to validate the user.");		request->reply->code = PW_AUTHENTICATION_REJECT;		if ((module_msg = pairfind(request->packet->vps,PW_MODULE_FAILURE_MESSAGE)) != NULL){			char msg[MAX_STRING_LEN+19];			snprintf(msg, sizeof(msg), "Login incorrect (%s)",				 module_msg->strvalue);			rad_authlog(msg, request, 0);		} else {			rad_authlog("Login incorrect", request, 0);		}		/* double check: maybe the secret is wrong? */		if ((debug_flag > 1) && (auth_item != NULL) &&				(auth_item->attribute == PW_PASSWORD)) {			u_char *p;			p = auth_item->strvalue;			while (*p != '\0') {				if (!isprint((int) *p)) {					log_debug("  WARNING: Unprintable characters in the password.\n\t  Double-check the shared secret on the server and the NAS!");					break;				}				p++;			}		}	}	if (result >= 0 &&	    (check_item = pairfind(request->config_items, PW_SIMULTANEOUS_USE)) != NULL) {		int session_type = 0;		tmp = pairfind(request->config_items, PW_SESSION_TYPE);		if (tmp) {			DEBUG2("  Found Session-Type %s", tmp->strvalue);			session_type = tmp->lvalue;		}		/*		 *	User authenticated O.K. Now we have to check		 *	for the Simultaneous-Use parameter.		 */		if (namepair &&		    (r = module_checksimul(session_type, request, check_item->lvalue)) != 0) {			char mpp_ok = 0;			if (r == 2){				/* Multilink attempt. Check if port-limit > simultaneous-use */				VALUE_PAIR *port_limit;				if ((port_limit = pairfind(request->reply->vps, PW_PORT_LIMIT)) != NULL &&					port_limit->lvalue > check_item->lvalue){					DEBUG2("main auth: MPP is OK");					mpp_ok = 1;				}			}			if (!mpp_ok){				if (check_item->lvalue > 1) {		  		snprintf(umsg, sizeof(umsg),							"\r\nYou are already logged in %d times  - access denied\r\n\n",							(int)check_item->lvalue);					user_msg = umsg;				} else {					user_msg = "\r\nYou are already logged in - access denied\r\n\n";				}				request->reply->code = PW_AUTHENTICATION_REJECT;				/*				 *	They're trying to log in too many times.				 *	Remove ALL reply attributes.				 */				pairfree(&request->reply->vps);				tmp = pairmake("Reply-Message", user_msg, T_OP_SET);				request->reply->vps = tmp;				snprintf(logstr, sizeof(logstr), "Multiple logins (max %d) %s",					check_item->lvalue,					r == 2 ? "[MPP attempt]" : "");				rad_authlog(logstr, request, 1);				result = -1;			}		}	}	if (result >= 0 &&	    (check_item = pairfind(request->config_items, PW_LOGIN_TIME)) != NULL) {		/*		 *	Authentication is OK. Now see if this		 *	user may login at this time of the day.		 */		r = timestr_match((char *)check_item->strvalue,				  request->timestamp);		if (r == 0) {	/* unlimited */			/*			 *	Do nothing: login-time is OK.			 */			/*			 *	Session-Timeout needs to be at least			 *	60 seconds, some terminal servers			 *	ignore smaller values.			 */		} else if (r < 60) {			/*			 *	User called outside allowed time interval.			 */			result = -1;			user_msg = "You are calling outside your allowed timespan\r\n";			request->reply->code = PW_AUTHENTICATION_REJECT;			pairfree(&request->reply->vps);			tmp = pairmake("Reply-Message", user_msg, T_OP_SET);			request->reply->vps = tmp;			snprintf(logstr, sizeof(logstr), "Outside allowed timespan (time allowed %s)",				 check_item->strvalue);			rad_authlog(logstr, request, 1);		} else if (r > 0) {			/*			 *	User is allowed, but set Session-Timeout.			 */			if ((reply_item = pairfind(request->reply->vps,					PW_SESSION_TIMEOUT)) != NULL) {				if (reply_item->lvalue > (unsigned) r)					reply_item->lvalue = r;			} else {				if ((reply_item = paircreate(						PW_SESSION_TIMEOUT,						PW_TYPE_INTEGER)) == NULL) {					radlog(L_ERR|L_CONS, "no memory");					exit(1);				}				reply_item->lvalue = r;				pairadd(&request->reply->vps, reply_item);			}		}	}	/*	 *	Result should be >= 0 here - if not, it means the user	 *	is rejected, so we just process post-auth and return.	 */	if (result < 0) {		rad_postauth_reject(request);		return RLM_MODULE_REJECT;	}	/*	 *	We might need this later.  The 'password' string	 *	is NOT used anywhere below here, except for logging,	 *	so it should be safe...	 */	if ((auth_item != NULL) && (auth_item->attribute == PW_CHAP_PASSWORD)) {		password = "CHAP-Password";	}	/*	 *	Add the port number to the Framed-IP-Address if	 *	vp->addport is set.	 */	if (((tmp = pairfind(request->reply->vps,			     PW_FRAMED_IP_ADDRESS)) != NULL) &&	    (tmp->flags.addport != 0)) {		VALUE_PAIR *vpPortId;		/*		 *  Find the NAS port ID.		 */		if ((vpPortId = pairfind(request->packet->vps,					 PW_NAS_PORT)) != NULL) {		  unsigned long tvalue = ntohl(tmp->lvalue);		  tmp->lvalue = htonl(tvalue + vpPortId->lvalue);		  tmp->flags.addport = 0;		  ip_ntoa(tmp->strvalue, tmp->lvalue);		} else {			DEBUG2("WARNING: No NAS-Port attribute in request.  CANNOT return a Framed-IP-Address + NAS-Port.\n");			pairdelete(&request->reply->vps, PW_FRAMED_IP_ADDRESS);		}	}	/*	 *	See if we need to execute a program.	 *	FIXME: somehow cache this info, and only execute the	 *	program when we receive an Accounting-START packet.	 *	Only at that time we know dynamic IP etc.	 */	exec_program = NULL;	exec_wait = 0;	if ((auth_item = pairfind(request->reply->vps, PW_EXEC_PROGRAM)) != NULL) {		exec_wait = 0;		exec_program = strdup((char *)auth_item->strvalue);		pairdelete(&request->reply->vps, PW_EXEC_PROGRAM);	}	if ((auth_item = pairfind(request->reply->vps, PW_EXEC_PROGRAM_WAIT)) != NULL) {		free(exec_program);		exec_wait = 1;		exec_program = strdup((char *)auth_item->strvalue);		pairdelete(&request->reply->vps, PW_EXEC_PROGRAM_WAIT);	}	/*	 *	Hack - allow % expansion in certain value strings.	 *	This is nice for certain Exec-Program programs.	 */	seen_callback_id = 0;	if ((auth_item = pairfind(request->reply->vps, PW_CALLBACK_ID)) != NULL) {		seen_callback_id = 1;		radius_xlat(buf, sizeof(auth_item->strvalue),			    (char *)auth_item->strvalue, request, NULL);		strNcpy((char *)auth_item->strvalue, buf,			sizeof(auth_item->strvalue));		auth_item->length = strlen((char *)auth_item->strvalue);	}	/*	 *	If we want to exec a program, but wait for it,	 *	do it first before sending the reply.	 */	if (exec_program && exec_wait) {		r = radius_exec_program(exec_program, request,					exec_wait,					NULL, 0,					request->packet->vps, &tmp);		free(exec_program);		exec_program = NULL;		/*		 *	Always add the value-pairs to the reply.		 */		pairmove(&request->reply->vps, &tmp);		pairfree(&tmp);		if (r < 0) {			/*			 *	Error. radius_exec_program() returns -1 on			 *	fork/exec errors.			 */			user_msg = "Access denied (external check failed)";			tmp = pairmake("Reply-Message", user_msg, T_OP_SET);			pairadd(&request->reply->vps, tmp);			request->reply->code = PW_AUTHENTICATION_REJECT;			rad_authlog("Login incorrect (external check failed)",				    request, 0);			rad_postauth_reject(request);			return RLM_MODULE_REJECT;		}		if (r > 0) {			/*			 *	Reject. radius_exec_program() returns >0			 *	if the exec'ed program had a non-zero			 *	exit status.			 */			request->reply->code = PW_AUTHENTICATION_REJECT;			rad_authlog("Login incorrect (external check said so)",				    request, 0);			rad_postauth_reject(request);			return RLM_MODULE_REJECT;		}	}	/*	 *	Delete "normal" A/V pairs when using callback.	 *	 *	FIXME: This is stupid. The portmaster should accept	 *	these settings instead of insisting on using a	 *	dialout location.	 *	 *	FIXME2: Move this into the above exec thingy?	 *	(if you knew how I use the exec_wait, you'd understand).	 */	if (seen_callback_id) {		pairdelete(&request->reply->vps, PW_FRAMED_PROTOCOL);		pairdelete(&request->reply->vps, PW_FRAMED_IP_ADDRESS);		pairdelete(&request->reply->vps, PW_FRAMED_IP_NETMASK);		pairdelete(&request->reply->vps, PW_FRAMED_ROUTE);		pairdelete(&request->reply->vps, PW_FRAMED_MTU);		pairdelete(&request->reply->vps, PW_FRAMED_COMPRESSION);		pairdelete(&request->reply->vps, PW_FILTER_ID);		pairdelete(&request->reply->vps, PW_PORT_LIMIT);		pairdelete(&request->reply->vps, PW_CALLBACK_NUMBER);	}	/*	 *	Filter (possibly multiple) Reply-Message attributes	 *	through radius_xlat, modifying them in place.	 */	if (user_msg == NULL) {		reply_item = pairfind(request->reply->vps, PW_REPLY_MESSAGE);		while (reply_item) {			radius_xlat(buf, sizeof(reply_item->strvalue),				    (char *)reply_item->strvalue, request, NULL);			strNcpy((char *)reply_item->strvalue, buf,				sizeof(reply_item->strvalue));			reply_item->length = strlen((char *)reply_item->strvalue);			user_msg = NULL;			reply_item = pairfind(reply_item->next, PW_REPLY_MESSAGE);		}	}	/*	 *	Set the reply to Access-Accept, if it hasn't already	 *	been set to something.  (i.e. Access-Challenge)	 */	if (request->reply->code == 0)	  request->reply->code = PW_AUTHENTICATION_ACK;	if ((module_msg = pairfind(request->packet->vps,PW_MODULE_SUCCESS_MESSAGE)) != NULL){		char msg[MAX_STRING_LEN+12];		snprintf(msg, sizeof(msg), "Login OK (%s)",			 module_msg->strvalue);		rad_authlog(msg, request, 1);	} else {		rad_authlog("Login OK", request, 1);	}	if (exec_program && !exec_wait) {		/*		 *	No need to check the exit status here.		 */		radius_exec_program(exec_program, request, exec_wait,				    NULL, 0, request->packet->vps, NULL);	}	if (exec_program)		free(exec_program);	result = rad_postauth(request);	return result;}

⌨️ 快捷键说明

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