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

📄 auth.c

📁 radius server在linux下的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * auth.c	User authentication. * * Version:	$Id: auth.c,v 1.136.2.1 2004/12/29 23:08:42 phampson 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * Copyright 2000  The FreeRADIUS server project * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl> * Copyright 2000  Jeff Carneal <jeff@apex.net> */static const char rcsid[] = "$Id: auth.c,v 1.136.2.1 2004/12/29 23:08:42 phampson Exp $";#include "autoconf.h"#include "libradius.h"#include <stdlib.h>#include <string.h>#include <ctype.h>#ifdef HAVE_NETINET_IN_H#	include <netinet/in.h>#endif#include "radiusd.h"#include "modules.h"/* *	Return a short string showing the terminal server, port *	and calling station ID. */char *auth_name(char *buf, size_t buflen, REQUEST *request, int do_cli) {	VALUE_PAIR	*cli;	VALUE_PAIR	*pair;	int		port = 0;	if ((cli = pairfind(request->packet->vps, PW_CALLING_STATION_ID)) == NULL)		do_cli = 0;	if ((pair = pairfind(request->packet->vps, PW_NAS_PORT)) != NULL)		port = pair->lvalue;	snprintf(buf, buflen, "from client %.128s port %u%s%.128s",			client_name(request->packet->src_ipaddr), port,			(do_cli ? " cli " : ""), (do_cli ? (char *)cli->strvalue : ""));	return buf;}/* *	Check if account has expired, and if user may login now. */static int check_expiration(REQUEST *request){	int result;	VALUE_PAIR *check_item = request->config_items;	result = 0;	while (result == 0 && check_item != NULL) {		/*		 *	Check expiration date if we are doing password aging.		 */		if (check_item->attribute == PW_EXPIRATION) {			/*			 *	Has this user's password expired?			 *			 *	If so, remove ALL reply attributes,			 *	and add our own Reply-Message, saying			 *	why they're being rejected.			 */			if (check_item->lvalue < (unsigned) time(NULL)) {				VALUE_PAIR *vp;				result = -1;				vp = pairmake("Reply-Message",						"Password Has Expired\r\n",						T_OP_ADD);				pairfree(&request->reply->vps);				request->reply->vps = vp;				break;			}		}		check_item = check_item->next;	}	return result;}/* * Make sure user/pass are clean * and then log them */static int rad_authlog(const char *msg, REQUEST *request, int goodpass) {	char clean_password[1024];	char clean_username[1024];	char buf[1024];	VALUE_PAIR *username = NULL;	if (!mainconfig.log_auth) {		return 0;	}	/*	 * Get the correct username based on the configured value	 */	if (log_stripped_names == 0) {		username = pairfind(request->packet->vps, PW_USER_NAME);	} else {		username = request->username;	}	/*	 *	Clean up the username	 */	if (username == NULL) {		strcpy(clean_username, "<no User-Name attribute>");	} else {		librad_safeprint((char *)username->strvalue,				username->length,				clean_username, sizeof(clean_username));	}	/*	 *	Clean up the password	 */	if (mainconfig.log_auth_badpass || mainconfig.log_auth_goodpass) {		if (!request->password) {			strcpy(clean_password, "<no User-Password attribute>");		} else if (request->password->attribute == PW_CHAP_PASSWORD) {			strcpy(clean_password, "<CHAP-Password>");		} else {			librad_safeprint((char *)request->password->strvalue,					 request->password->length,					 clean_password, sizeof(clean_password));		}	}	if (goodpass) {		radlog(L_AUTH, "%s: [%s%s%s] (%s)",				msg,				clean_username,				mainconfig.log_auth_goodpass ? "/" : "",				mainconfig.log_auth_goodpass ? clean_password : "",				auth_name(buf, sizeof(buf), request, 1));	} else {		radlog(L_AUTH, "%s: [%s%s%s] (%s)",				msg,				clean_username,				mainconfig.log_auth_badpass ? "/" : "",				mainconfig.log_auth_badpass ? clean_password : "",				auth_name(buf, sizeof(buf), request, 1));	}	return 0;}/* *	Check password. * *	Returns:	0  OK *			-1 Password fail *			-2 Rejected (Auth-Type = Reject, send Port-Message back) *			1  End check & return, don't reply * *	NOTE: NOT the same as the RLM_ values ! */int rad_check_password(REQUEST *request){	VALUE_PAIR *auth_type_pair;	VALUE_PAIR *cur_config_item;	VALUE_PAIR *password_pair;	VALUE_PAIR *auth_item;	char string[MAX_STRING_LEN];	int auth_type = -1;	int result;	int auth_type_count = 0;	result = 0;	/*	 *	Look for matching check items. We skip the whole lot	 *	if the authentication type is PW_AUTHTYPE_ACCEPT or	 *	PW_AUTHTYPE_REJECT.	 */	cur_config_item = request->config_items;	while(((auth_type_pair = pairfind(cur_config_item, PW_AUTH_TYPE))) != NULL) {		auth_type = auth_type_pair->lvalue;		auth_type_count++;		DEBUG2("  rad_check_password:  Found Auth-Type %s",				auth_type_pair->strvalue);		cur_config_item = auth_type_pair->next;		if (auth_type == PW_AUTHTYPE_REJECT) {			DEBUG2("  rad_check_password: Auth-Type = Reject, rejecting user");			return -2;		}	}	if (( auth_type_count > 1) && (debug_flag)) {		radlog(L_ERR, "Warning:  Found %d auth-types on request for user '%s'",			auth_type_count, request->username->strvalue);	}	/*	 *	This means we have a proxy reply or an accept	 *  and it wasn't rejected in the above loop.  So	 *  that means it is accepted and we do no further	 *  authentication	 */	if ((auth_type == PW_AUTHTYPE_ACCEPT) || (request->proxy)) {		DEBUG2("  rad_check_password: Auth-Type = Accept, accepting the user");		return 0;	}	/*	 *	Find the password from the users file.	 */	if ((password_pair = pairfind(request->config_items, PW_CRYPT_PASSWORD)) != NULL) {		/*		 *	Re-write Auth-Type, but ONLY if it isn't already		 *	set.		 */		if (auth_type == -1) auth_type = PW_AUTHTYPE_CRYPT;	} else {		password_pair = pairfind(request->config_items, PW_PASSWORD);	}	if (auth_type < 0) {		if (password_pair) {			auth_type = PW_AUTHTYPE_LOCAL;		} else {			/*		 	*	The admin hasn't told us how to		 	*	authenticate the user, so we reject them!		 	*		 	*	This is fail-safe.		 	*/			DEBUG2("auth: No authenticate method (Auth-Type) configuration found for the request: Rejecting the user");			return -2;		}	}	switch(auth_type) {		case PW_AUTHTYPE_CRYPT:			/*			 *	Find the password sent by the user. It			 *	SHOULD be there, if it's not			 *	authentication fails.			 */			auth_item = request->password;			if (auth_item == NULL) {				DEBUG2("auth: No User-Password or CHAP-Password attribute in the request");				return -1;			}			DEBUG2("auth: type Crypt");			if (password_pair == NULL) {				DEBUG2("No Crypt-Password configured for the user");				rad_authlog("Login incorrect "					"(No Crypt-Password configured for the user)", request, 0);				return -1;			}			switch (lrad_crypt_check((char *)auth_item->strvalue,									 (char *)password_pair->strvalue)) {			case -1:			  rad_authlog("Login incorrect "						  "(system failed to supply an encrypted password for comparison)", request, 0);			case 1:			  return -1;			}			break;		case PW_AUTHTYPE_LOCAL:			DEBUG2("auth: type Local");			/*			 *	Find the password sent by the user. It			 *	SHOULD be there, if it's not			 *	authentication fails.			 */			auth_item = request->password;			if (auth_item == NULL) {				DEBUG2("auth: No User-Password or CHAP-Password attribute in the request");				return -1;			}			/*			 *	Plain text password.			 */			if (password_pair == NULL) {				DEBUG2("auth: No password configured for the user");				rad_authlog("Login incorrect "					"(No password configured for the user)", request, 0);				return -1;			}			/*			 *	Local password is just plain text.	 		 */			if (auth_item->attribute == PW_PASSWORD) {				if (strcmp((char *)password_pair->strvalue,					   (char *)auth_item->strvalue) != 0) {					DEBUG2("auth: user supplied User-Password does NOT match local User-Password");					return -1;				}				DEBUG2("auth: user supplied User-Password matches local User-Password");				break;			} else if (auth_item->attribute != PW_CHAP_PASSWORD) {				DEBUG2("The user did not supply a User-Password or a CHAP-Password attribute");				rad_authlog("Login incorrect "					"(no User-Password or CHAP-Password attribute)", request, 0);				return -1;			}			rad_chap_encode(request->packet, string,					auth_item->strvalue[0], password_pair);			/*			 *	Compare them			 */			if (memcmp(string + 1, auth_item->strvalue + 1,				   CHAP_VALUE_LENGTH) != 0) {				DEBUG2("auth: user supplied CHAP-Password does NOT match local User-Password");				return -1;			}			DEBUG2("auth: user supplied CHAP-Password matches local User-Password");			break;		default:			DEBUG2("auth: type \"%s\"",					dict_valbyattr(PW_AUTH_TYPE, auth_type)->name);			/*			 *	See if there is a module that handles			 *	this type, and turn the RLM_ return			 *	status into the values as defined at			 *	the top of this function.			 */			result = module_authenticate(auth_type, request);			switch (result) {				/*				 *	An authentication module FAIL				 *	return code, or any return code that				 *	is not expected from authentication,				 *	is the same as an explicit REJECT!				 */				case RLM_MODULE_FAIL:				case RLM_MODULE_REJECT:				case RLM_MODULE_USERLOCK:				case RLM_MODULE_INVALID:				case RLM_MODULE_NOTFOUND:				case RLM_MODULE_NOOP:				case RLM_MODULE_UPDATED:					result = -1;					break;				case RLM_MODULE_OK:					result = 0;					break;				case RLM_MODULE_HANDLED:					result = 1;					break;			}			break;	}	return result;}/* *	Post-authentication step processes the response before it is *	sent to the NAS. It can receive both Access-Accept and Access-Reject *	replies. */int rad_postauth(REQUEST *request){	int	result;	int	postauth_type = 0;	VALUE_PAIR	*postauth_type_item = NULL;	/*	 *	Do post-authentication calls. ignoring the return code.	 */	postauth_type_item = pairfind(request->config_items, PW_POST_AUTH_TYPE);	if (postauth_type_item)		postauth_type = postauth_type_item->lvalue;	result = module_post_auth(postauth_type, request);	switch (result) {	default:	  break;	  /*	   *	The module failed, or said to reject the user: Do so.	   */	case RLM_MODULE_FAIL:	case RLM_MODULE_REJECT:	case RLM_MODULE_USERLOCK:	case RLM_MODULE_INVALID:	  request->reply->code = PW_AUTHENTICATION_REJECT;	  result = RLM_MODULE_REJECT;	  break;	  /*	   *	The module had a number of OK return codes.	   */	case RLM_MODULE_NOTFOUND:	case RLM_MODULE_NOOP:	case RLM_MODULE_UPDATED:	case RLM_MODULE_OK:	case RLM_MODULE_HANDLED:	  result = RLM_MODULE_OK;	  break;	}	return result;}/* *	Before sending an Access-Reject, call the modules in the *	Post-Auth-Type REJECT stanza. */static int rad_postauth_reject(REQUEST *request){	int		result;	VALUE_PAIR	*tmp;	DICT_VALUE	*dval;	dval = dict_valbyname(PW_POST_AUTH_TYPE, "REJECT");	if (dval) {		/* Overwrite the Post-Auth-Type with the value REJECT */		pairdelete(&request->config_items, PW_POST_AUTH_TYPE);		tmp = paircreate(PW_POST_AUTH_TYPE, PW_TYPE_INTEGER);		tmp->lvalue = dval->value;		pairadd(&request->config_items, tmp);		result = rad_postauth(request);	} else {		/* No REJECT stanza */		result = RLM_MODULE_OK;	}	return result;}/* *	Process and reply to an authentication request * *	The return value of this function isn't actually used right now, so *	it's not entirely clear if it is returning the right things. --Pac. */int rad_authenticate(REQUEST *request){	VALUE_PAIR	*namepair;	VALUE_PAIR	*check_item;	VALUE_PAIR	*reply_item;	VALUE_PAIR	*auth_item;	VALUE_PAIR	*module_msg;	VALUE_PAIR	*tmp = NULL;	int		result, r;	char		umsg[MAX_STRING_LEN + 1];	const char	*user_msg = NULL;	const char	*password;	char		*exec_program;	int		exec_wait;	int		seen_callback_id;	char		buf[1024], logstr[1024];	char		autz_retry = 0;	int		autz_type = 0;	password = "";	/*	 *	If this request got proxied to another server,	 *	AND it was an authentication request, then we need	 *	to add an initial Auth-Type: Auth-Accept for success,	 *	Auth-Reject for fail. We also need to add the reply	 *	pairs from the server to the initial reply.	 *	 *	Huh?  If the request wasn't an authentication request,	 *	WTF are we doing here?	 */	if ((request->proxy_reply) &&	    (request->packet->code == PW_AUTHENTICATION_REQUEST)) {		tmp = paircreate(PW_AUTH_TYPE, PW_TYPE_INTEGER);		if (tmp == NULL) {			radlog(L_ERR|L_CONS, "no memory");			exit(1);

⌨️ 快捷键说明

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