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

📄 auth.c

📁 新的radius程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * auth.c	User authentication. * * Version:	$Id: auth.c,v 1.136.2.5.2.2 2007/03/05 14:30:04 aland 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.5.2.2 2007/03/05 14:30:04 aland 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){	VALUE_PAIR *check_item;	VALUE_PAIR *vp;	check_item = pairfind(request->config_items, PW_EXPIRATION);	if (!check_item)  return 0;	/*	 *	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 (((time_t) check_item->lvalue) <= request->timestamp) {		vp = pairmake("Reply-Message",			      "Password Has Expired\r\n",			      T_OP_ADD);		pairfree(&request->reply->vps);		request->reply->vps = vp;		return -1;	}#define EXP_TIMEOUT ((uint32_t) (((time_t) check_item->lvalue) - request->timestamp))	/*	 *	Otherwise, set the Session-Timeout based on expiration.	 */	vp = pairfind(request->reply->vps, PW_SESSION_TIMEOUT);	if (!vp) {		vp = pairmake("Session-Timeout", "0", T_OP_SET);		if (!vp) return -1; /* out of memory */				vp->lvalue = EXP_TIMEOUT;		pairadd(&request->reply->vps, vp);	} else if (vp->lvalue > EXP_TIMEOUT) {		vp->lvalue = EXP_TIMEOUT;	} /* else Session-Timeout is smaller than Expiration, leave it alone */	return 0;}/* * 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 (!password_pair) {			password_pair = pairfind(request->config_items,						 PW_CLEARTEXT_PASSWORD);			if (password_pair) {				VALUE_PAIR *old;				old = pairmake("User-Password",					       password_pair->strvalue,					       T_OP_SET);				if (old) pairadd(&request->config_items, old);			}		}			}	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) {		DICT_VALUE *dval;		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:			dval = dict_valbyattr(PW_AUTH_TYPE, auth_type);			if (dval) {				DEBUG2("auth: type \"%s\"", dval->name);			} else {				DEBUG2("auth: type UNKNOWN-%d", auth_type);			}			/*			 *	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_INVALID:				case RLM_MODULE_NOOP:				case RLM_MODULE_NOTFOUND:				case RLM_MODULE_REJECT:				case RLM_MODULE_UPDATED:				case RLM_MODULE_USERLOCK:				default:					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 *vp;	/*	 *	Do post-authentication calls. ignoring the return code.	 */	vp = pairfind(request->config_items, PW_POST_AUTH_TYPE);	if (vp) {		DEBUG2("  Found Post-Auth-Type %s", vp->strvalue);		postauth_type = vp->lvalue;	}	result = module_post_auth(postauth_type, request);	switch (result) {		/*		 *	The module failed, or said to reject the user: Do so.		 */		case RLM_MODULE_FAIL:		case RLM_MODULE_INVALID:		case RLM_MODULE_REJECT:		case RLM_MODULE_USERLOCK:		default:			request->reply->code = PW_AUTHENTICATION_REJECT;			result = RLM_MODULE_REJECT;			break;		/*		 *	The module handled the request, cancel the reply.		 */		case RLM_MODULE_HANDLED:			/* FIXME */			result = RLM_MODULE_OK;			break;		/*		 *	The module had a number of OK return codes.		 */		case RLM_MODULE_NOOP:		case RLM_MODULE_NOTFOUND:		case RLM_MODULE_OK:		case RLM_MODULE_UPDATED:			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, we need	 *	to check whether it authenticated the request or not.

⌨️ 快捷键说明

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