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

📄 rlm_mschap.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * rlm_mschap.c * * Version:	$Id: rlm_mschap.c,v 1.99 2008/01/09 13:20:56 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * Copyright 2000,2001,2006  The FreeRADIUS server project *//* *  mschap.c    MS-CHAP module * *  This implements MS-CHAP, as described in RFC 2548 * *  http://www.freeradius.org/rfc/rfc2548.txt * *//* *  If you have any questions on NTLM (Samba) passwords *  support, LM authentication and MS-CHAP v2 support *  please contact * *  Vladimir Dubrovin	vlad@sandy.ru *  aka *  ZARAZA		3APA3A@security.nnov.ru *//*  MPPE support from Takahiro Wagatsuma <waga@sic.shibaura-it.ac.jp> */#include	<freeradius-devel/ident.h>RCSID("$Id: rlm_mschap.c,v 1.99 2008/01/09 13:20:56 aland Exp $")#include	<freeradius-devel/radiusd.h>#include	<freeradius-devel/modules.h>#include	<freeradius-devel/rad_assert.h>#include        <freeradius-devel/md5.h>#include 	<ctype.h>#include	"smbdes.h"#ifdef __APPLE__extern int od_mschap_auth(REQUEST *request, VALUE_PAIR *challenge, VALUE_PAIR * usernamepair);#endif/* Allowable account control bits */#define ACB_DISABLED   0x0001  /* 1 = User account disabled */#define ACB_HOMDIRREQ  0x0002  /* 1 = Home directory required */#define ACB_PWNOTREQ   0x0004  /* 1 = User password not required */#define ACB_TEMPDUP    0x0008  /* 1 = Temporary duplicate account */#define ACB_NORMAL     0x0010  /* 1 = Normal user account */#define ACB_MNS        0x0020  /* 1 = MNS logon user account */#define ACB_DOMTRUST   0x0040  /* 1 = Interdomain trust account */#define ACB_WSTRUST    0x0080  /* 1 = Workstation trust account */#define ACB_SVRTRUST   0x0100  /* 1 = Server trust account */#define ACB_PWNOEXP    0x0200  /* 1 = User password does not expire */#define ACB_AUTOLOCK   0x0400  /* 1 = Account auto locked */static int pdb_decode_acct_ctrl(const char *p){	int acct_ctrl = 0;	int finished = 0;	/*	 * Check if the account type bits have been encoded after the	 * NT password (in the form [NDHTUWSLXI]).	 */	if (*p != '[') return 0;	for (p++; *p && !finished; p++) {		switch (*p) {			case 'N': /* 'N'o password. */			  acct_ctrl |= ACB_PWNOTREQ;			  break;			case 'D':  /* 'D'isabled. */			  acct_ctrl |= ACB_DISABLED ;			  break;			case 'H':  /* 'H'omedir required. */			  acct_ctrl |= ACB_HOMDIRREQ;			  break;			case 'T': /* 'T'emp account. */			  acct_ctrl |= ACB_TEMPDUP;			  break;			case 'U': /* 'U'ser account (normal). */			  acct_ctrl |= ACB_NORMAL;			  break;			case 'M': /* 'M'NS logon user account. What is this? */			  acct_ctrl |= ACB_MNS;			  break;			case 'W': /* 'W'orkstation account. */			  acct_ctrl |= ACB_WSTRUST;			  break;			case 'S': /* 'S'erver account. */			  acct_ctrl |= ACB_SVRTRUST;			  break;			case 'L': /* 'L'ocked account. */			  acct_ctrl |= ACB_AUTOLOCK;			  break;			case 'X': /* No 'X'piry on password */			  acct_ctrl |= ACB_PWNOEXP;			  break;			case 'I': /* 'I'nterdomain trust account. */			  acct_ctrl |= ACB_DOMTRUST;			  break;		        case ' ': /* ignore spaces */			  break;			case ':':			case '\n':			case '\0':			case ']':			default:			  finished = 1;			  break;		}	}	return acct_ctrl;}/* *	ntpwdhash converts Unicode password to 16-byte NT hash *	with MD4 */static void ntpwdhash (uint8_t *szHash, const char *szPassword){	char szUnicodePass[513];	int nPasswordLen;	int i;	/*	 *	NT passwords are unicode.  Convert plain text password	 *	to unicode by inserting a zero every other byte	 */	nPasswordLen = strlen(szPassword);	for (i = 0; i < nPasswordLen; i++) {		szUnicodePass[i << 1] = szPassword[i];		szUnicodePass[(i << 1) + 1] = 0;	}	/* Encrypt Unicode password to a 16-byte MD4 hash */	fr_md4_calc(szHash, (uint8_t *) szUnicodePass, (nPasswordLen<<1) );}/* *	challenge_hash() is used by mschap2() and auth_response() *	implements RFC2759 ChallengeHash() *	generates 64 bit challenge */static void challenge_hash( const uint8_t *peer_challenge,			    const uint8_t *auth_challenge,			    const char *user_name, uint8_t *challenge ){	fr_SHA1_CTX Context;	uint8_t hash[20];	fr_SHA1Init(&Context);	fr_SHA1Update(&Context, peer_challenge, 16);	fr_SHA1Update(&Context, auth_challenge, 16);	fr_SHA1Update(&Context, (const uint8_t *) user_name,		      strlen(user_name));	fr_SHA1Final(hash, &Context);	memcpy(challenge, hash, 8);}/* *	auth_response() generates MS-CHAP v2 SUCCESS response *	according to RFC 2759 GenerateAuthenticatorResponse() *	returns 42-octet response string */static void auth_response(const char *username,			  const uint8_t *nt_hash_hash,			  uint8_t *ntresponse,			  uint8_t *peer_challenge, uint8_t *auth_challenge,			  char *response){	fr_SHA1_CTX Context;	static const uint8_t magic1[39] =	{0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,	 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,	 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,	 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74};	static const uint8_t magic2[41] =	{0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,	 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,	 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,	 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,	 0x6E};	static const char hex[16] = "0123456789ABCDEF";	size_t i;        uint8_t challenge[8];	uint8_t digest[20];	fr_SHA1Init(&Context);	fr_SHA1Update(&Context, nt_hash_hash, 16);	fr_SHA1Update(&Context, ntresponse, 24);	fr_SHA1Update(&Context, magic1, 39);	fr_SHA1Final(digest, &Context);	challenge_hash(peer_challenge, auth_challenge, username, challenge);	fr_SHA1Init(&Context);	fr_SHA1Update(&Context, digest, 20);	fr_SHA1Update(&Context, challenge, 8);	fr_SHA1Update(&Context, magic2, 41);	fr_SHA1Final(digest, &Context);	/*	 *	Encode the value of 'Digest' as "S=" followed by	 *	40 ASCII hexadecimal digits and return it in	 *	AuthenticatorResponse.	 *	For example,	 *	"S=0123456789ABCDEF0123456789ABCDEF01234567"	 */ 	response[0] = 'S';	response[1] = '=';	/*	 *	The hexadecimal digits [A-F] MUST be uppercase.	 */	for (i = 0; i < sizeof(digest); i++) {		response[2 + (i * 2)] = hex[(digest[i] >> 4) & 0x0f];		response[3 + (i * 2)] = hex[digest[i] & 0x0f];	}}typedef struct rlm_mschap_t {	int use_mppe;	int require_encryption;        int require_strong;        int with_ntdomain_hack;	/* this should be in another module */	char *passwd_file;	const char *xlat_name;	char *ntlm_auth;	const char *auth_type;#ifdef __APPLE__	int  open_directory;#endif  } rlm_mschap_t;/* *	Does dynamic translation of strings. * *	Pulls NT-Response, LM-Response, or Challenge from MSCHAP *	attributes. */static size_t mschap_xlat(void *instance, REQUEST *request,		       char *fmt, char *out, size_t outlen,		       RADIUS_ESCAPE_STRING func){	size_t		i, data_len;	uint8_t		*data = NULL;	uint8_t		buffer[32];	VALUE_PAIR	*user_name;	VALUE_PAIR	*chap_challenge, *response;	rlm_mschap_t	*inst = instance;	chap_challenge = response = NULL;	func = func;		/* -Wunused */	/*	 *	Challenge means MS-CHAPv1 challenge, or	 *	hash of MS-CHAPv2 challenge, and peer challenge.	 */	if (strncasecmp(fmt, "Challenge", 9) == 0) {		chap_challenge = pairfind(request->packet->vps,					  PW_MSCHAP_CHALLENGE);		if (!chap_challenge) {			DEBUG2("  rlm_mschap: No MS-CHAP-Challenge in the request.");			return 0;		}		/*		 *	MS-CHAP-Challenges are 8 octets,		 *	for MS-CHAPv2		 */		if (chap_challenge->length == 8) {			DEBUG2(" mschap1: %02x",			       chap_challenge->vp_octets[0]);			data = chap_challenge->vp_octets;			data_len = 8;			/*			 *	MS-CHAP-Challenges are 16 octets,			 *	for MS-CHAPv2.			 */		} else if (chap_challenge->length == 16) {			char *username_string;			DEBUG2(" mschap2: %02x", chap_challenge->vp_octets[0]);			response = pairfind(request->packet->vps,					    PW_MSCHAP2_RESPONSE);			if (!response) {				DEBUG2("  rlm_mschap: MS-CHAP2-Response is required to calculate MS-CHAPv1 challenge.");				return 0;			}			/*			 *	Responses are 50 octets.			 */			if (response->length < 50) {				radlog(L_AUTH, "rlm_mschap: MS-CHAP-Response has the wrong format.");				return 0;			}			user_name = pairfind(request->packet->vps,					     PW_USER_NAME);			if (!user_name) {				DEBUG2("  rlm_mschap: User-Name is required to calculateMS-CHAPv1 Challenge.");				return 0;			}			/*			 *	with_ntdomain_hack moved here, too.			 */			if ((username_string = strchr(user_name->vp_strvalue, '\\')) != NULL) {				if (inst->with_ntdomain_hack) {					username_string++;				} else {					DEBUG2("  rlm_mschap: NT Domain delimeter found, should we have enabled with_ntdomain_hack?");					username_string = user_name->vp_strvalue;				}			} else {				username_string = user_name->vp_strvalue;			}			/*			 *	Get the MS-CHAPv1 challenge			 *	from the MS-CHAPv2 peer challenge,			 *	our challenge, and the user name.			 */			challenge_hash(response->vp_octets + 2,				       chap_challenge->vp_octets,				       username_string, buffer);			data = buffer;			data_len = 8;		} else {			DEBUG2("  rlm_mschap: Invalid MS-CHAP challenge length");			return 0;		}		/*		 *	Get the MS-CHAPv1 response, or the MS-CHAPv2		 *	response.		 */	} else if (strncasecmp(fmt, "NT-Response", 11) == 0) {		response = pairfind(request->packet->vps,				    PW_MSCHAP_RESPONSE);		if (!response) response = pairfind(request->packet->vps,						   PW_MSCHAP2_RESPONSE);		if (!response) {			DEBUG2("  rlm_mschap: No MS-CHAP-Response or MS-CHAP2-Response was found in the request.");			return 0;		}		/*		 *	For MS-CHAPv1, the NT-Response exists only		 *	if the second octet says so.		 */		if ((response->attribute == PW_MSCHAP_RESPONSE) &&		    ((response->vp_octets[1] & 0x01) == 0)) {			DEBUG2("  rlm_mschap: No NT-Response in MS-CHAP-Response");			return 0;		}		/*		 *	MS-CHAP-Response and MS-CHAP2-Response have		 *	the NT-Response at the same offset, and are		 *	the same length.		 */		data = response->vp_octets + 26;		data_len = 24;		/*		 *	LM-Response is deprecated, and exists only		 *	in MS-CHAPv1, and not often there.		 */	} else if (strncasecmp(fmt, "LM-Response", 11) == 0) {		response = pairfind(request->packet->vps,				    PW_MSCHAP_RESPONSE);		if (!response) {			DEBUG2("  rlm_mschap: No MS-CHAP-Response was found in the request.");			return 0;		}		/*		 *	For MS-CHAPv1, the NT-Response exists only		 *	if the second octet says so.		 */		if ((response->vp_octets[1] & 0x01) != 0) {			DEBUG2("  rlm_mschap: No LM-Response in MS-CHAP-Response");			return 0;		}		data = response->vp_octets + 2;		data_len = 24;		/*		 *	Pull the NT-Domain out of the User-Name, if it exists.		 */	} else if (strncasecmp(fmt, "NT-Domain", 9) == 0) {		char *p, *q;		user_name = pairfind(request->packet->vps, PW_USER_NAME);		if (!user_name) {			DEBUG2("  rlm_mschap: No User-Name was found in the request.");			return 0;		}		/*		 *	First check to see if this is a host/ style User-Name		 *	(a la Kerberos host principal)		 */		if (strncmp(user_name->vp_strvalue, "host/", 5) == 0) {			/*			 *	If we're getting a User-Name formatted in this way,			 *	it's likely due to PEAP.  The Windows Domain will be			 *	the first domain component following the hostname,			 *	or the machine name itself if only a hostname is supplied			 */			p = strchr(user_name->vp_strvalue, '.');			if (!p) {				DEBUG2("  rlm_mschap: setting NT-Domain to same as machine name");				strlcpy(out, user_name->vp_strvalue + 5, outlen);			} else {				p++;	/* skip the period */				q = strchr(p, '.');				/*				 * use the same hack as below				 * only if another period was found				 */				if (q) *q = '\0';				strlcpy(out, p, outlen);				if (q) *q = '.';			}		} else {			p = strchr(user_name->vp_strvalue, '\\');			if (!p) {				DEBUG2("  rlm_mschap: No NT-Domain was found in the User-Name.");

⌨️ 快捷键说明

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