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

📄 auth.c

📁 radius server在linux下的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		}		/*		 *	Challenges are punted back to the NAS		 *	without any further processing.		 */		if (request->proxy_reply->code == PW_ACCESS_CHALLENGE) {			request->reply->code = PW_ACCESS_CHALLENGE;			return RLM_MODULE_HANDLED;		}		/*		 *	Reply of ACCEPT means accept, ALL other		 *	replies mean reject.  This is fail-safe.		 */		if (request->proxy_reply->code == PW_AUTHENTICATION_ACK)			tmp->lvalue = PW_AUTHTYPE_ACCEPT;		else			tmp->lvalue = PW_AUTHTYPE_REJECT;		pairadd(&request->config_items, tmp);		/*		 *	If it's an Access-Reject, then do NOT do any		 *	authorization or authentication.  They're being		 *	rejected, so we minimize the amount of work		 *	done by the server, by rejecting them here.		 */		if ((request->proxy_reply->code != PW_AUTHENTICATION_ACK) &&		    (request->proxy_reply->code != PW_ACCESS_CHALLENGE)) {			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:	r = module_authorize(autz_type, request);	if (r != RLM_MODULE_NOTFOUND &&	    r != RLM_MODULE_NOOP &&	    r != RLM_MODULE_OK &&	    r != RLM_MODULE_UPDATED) {		if (r != RLM_MODULE_FAIL && r != RLM_MODULE_HANDLED) {			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 r;	}	if (!autz_retry){		VALUE_PAIR	*autz_type_item = NULL;		autz_type_item = pairfind(request->config_items, PW_AUTZ_TYPE);		if (autz_type_item){			autz_type = autz_type_item->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) {		VALUE_PAIR	*session_type;		int		sess_type = 0;		session_type = pairfind(request->config_items, PW_SESSION_TYPE);		if (session_type)			sess_type = session_type->lvalue;		/*		 *	User authenticated O.K. Now we have to check		 *	for the Simultaneous-Use parameter.		 */		if (namepair &&		    (r = module_checksimul(sess_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) {		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,					umsg, sizeof(umsg),					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, or >0 if the exec'ed program			 *	had a non-zero exit status.			 */			if (umsg[0] == '\0') {				user_msg = "\r\nAccess denied (external check failed).";			} else {				user_msg = &umsg[0];			}			request->reply->code = PW_AUTHENTICATION_REJECT;			tmp = pairmake("Reply-Message", user_msg, T_OP_SET);			pairadd(&request->reply->vps, tmp);			rad_authlog("Login incorrect (external check failed)",					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 + -