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

📄 rlm_mschap.c

📁 RADIUS 服务器介绍 RADIUS服务器支持标准的RADIUS协议
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * rlm_mschap.c	 * * Version:	$Id: rlm_mschap.c,v 1.41 2003/07/07 19:08:09 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,2001  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	"autoconf.h"#include	"libradius.h"#include	<stdio.h>#include	<stdlib.h>#include    	<string.h>#include 	<ctype.h>#include	"radiusd.h"#include	"modules.h"#include        "md4.h"#include        "md5.h"#include	"sha1.h"#include	"rad_assert.h"#define PW_MSCHAP_RESPONSE	((311 << 16) | 1)#define PW_MSCHAP_CHALLENGE	((311 << 16) | 11)#define PW_MSCHAP2_RESPONSE	((311 << 16) | 25)static const char *letters = "0123456789ABCDEF";/* *	hex2bin converts hexadecimal strings into binary */static int hex2bin (const char *szHex, unsigned char* szBin, int len){	char * c1, * c2;	int i;      	for (i = 0; i < len; i++) {		if( !(c1 = memchr(letters, toupper((int) szHex[i << 1]), 16)) ||		    !(c2 = memchr(letters, toupper((int) szHex[(i << 1) + 1]), 16)))		     break;                 szBin[i] = ((c1-letters)<<4) + (c2-letters);        }        return i;}/* *	bin2hex creates hexadecimal presentation *	of binary data */ static void bin2hex (const unsigned char *szBin, char *szHex, int len){	int i;	for (i = 0; i < len; i++) {		szHex[i<<1] = letters[szBin[i] >> 4];		szHex[(i<<1) + 1] = letters[szBin[i] & 0x0F];	}}/* 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 (char *szHash, const char *szPassword){	char szUnicodePass[513];	char 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 */	md4_calc(szHash, szUnicodePass, (nPasswordLen<<1) );}/* *	challenge_hash() is used by mschap2() and auth_response() *	implements RFC2759 ChallengeHash() *	generates 64 bit challenge */static void challenge_hash( const char *peer_challenge,			    const char *auth_challenge,			    const char *user_name, char *challenge ){	SHA1_CTX Context;	char hash[20];		SHA1Init(&Context);	SHA1Update(&Context, peer_challenge, 16);	SHA1Update(&Context, auth_challenge, 16);	SHA1Update(&Context, user_name, strlen(user_name));	SHA1Final(hash, &Context);	memcpy(challenge, hash, 8);}static void mschap2(const char *peer_challenge, const char *auth_challenge,		    const char *user_name, const char *nt_password,		    char *response){	char challenge[8];		challenge_hash(peer_challenge, auth_challenge, user_name,		       challenge);	lrad_mschap(nt_password, challenge, response);}/* *	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 char *nt_password,			  char *ntresponse,			  char *peer_challenge, char *auth_challenge,			  char *response){	SHA1_CTX Context;	char hashhash[16];	const char 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};                                             	const char 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};        char challenge[8];        char digest[20];	/*	 * Hash password hash into hashhash	 */	md4_calc(hashhash, nt_password, 16);	SHA1Init(&Context);	SHA1Update(&Context, hashhash, 16);	SHA1Update(&Context, ntresponse, 24);	SHA1Update(&Context, magic1, 39);	SHA1Final(digest, &Context);	challenge_hash(peer_challenge, auth_challenge, username, challenge);	SHA1Init(&Context);	SHA1Update(&Context, digest, 20);	SHA1Update(&Context, challenge, 8);	SHA1Update(&Context, magic2, 41);	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] = '=';	bin2hex(digest, response + 2, 20);}struct mschap_instance {	int use_mppe;	int require_encryption;	int require_strong;	char *passwd_file;	char *auth_type;};static CONF_PARSER module_config[] = {	/*	 *	Cache the password by default.	 */	{ "use_mppe",    PW_TYPE_BOOLEAN,	  offsetof(struct mschap_instance,use_mppe), NULL, "yes" },	{ "require_encryption",    PW_TYPE_BOOLEAN,	  offsetof(struct mschap_instance,require_encryption), NULL, "no" },	{ "require_strong",    PW_TYPE_BOOLEAN,	  offsetof(struct mschap_instance,require_strong), NULL, "no" },	{ "passwd",   PW_TYPE_STRING_PTR,	  offsetof(struct mschap_instance, passwd_file), NULL,  NULL },	{ "authtype",   PW_TYPE_STRING_PTR,	  offsetof(struct mschap_instance, auth_type), NULL,  NULL },		{ NULL, -1, 0, NULL, NULL }		/* end the list */};/* *	deinstantiate module, free all memory allocated during *	mschap_instantiate() */static int mschap_detach(void *instance){#define inst ((struct mschap_instance *)instance)	if (inst->passwd_file) free(inst->passwd_file);	if (inst->auth_type) free(inst->auth_type);	free(instance);	return 0;#undef inst}	/* *	Create instance for our module. Allocate space for *	instance structure and read configuration parameters */static int mschap_instantiate(CONF_SECTION *conf, void **instance){	struct mschap_instance *inst;	inst = *instance = rad_malloc(sizeof(*inst));	if (!inst) {		return -1;	}	memset(inst, 0, sizeof(*inst));	if (cf_section_parse(conf, inst, module_config) < 0) {		free(inst);		return -1;	}	/*	 *	This module used to support SMB Password files, but it	 *	made it too complicated.  If the user tries to	 *	configure an SMB Password file, then die, with an	 *	error message.	 */	if (inst->passwd_file) {		radlog(L_ERR, "rlm_mschap: SMB password file is no longer supported in this module.  Use rlm_passwd module instead");		mschap_detach(inst);		return -1;	}	return 0;}/* *	add_reply() adds either MS-CHAP2-Success or MS-CHAP-Error *	attribute to reply packet */static void add_reply(VALUE_PAIR** vp, unsigned char ident,		      const char* name, const char* value, int len){	VALUE_PAIR *reply_attr;	reply_attr = pairmake(name, "", T_OP_EQ);	if (!reply_attr) {		DEBUG("  rlm_mschap: Failed to create attribute %s: %s\n", name, librad_errstr);		return;	}	reply_attr->strvalue[0] = ident;	memcpy(reply_attr->strvalue + 1, value, len);	reply_attr->length = len + 1;	pairadd(vp, reply_attr);}/* *	Add MPPE attributes to the reply. */static void mppe_add_reply(VALUE_PAIR** vp,			   const char* name, const char* value, int len){       VALUE_PAIR *reply_attr;       reply_attr = pairmake(name, "", T_OP_EQ);       if (!reply_attr) {	       DEBUG("rlm_mschap: mppe_add_reply failed to create attribute %s: %s\n", name, librad_errstr);	       return;       }       memcpy(reply_attr->strvalue, value, len);       reply_attr->length = len;       pairadd(vp, reply_attr);}static const uint8_t SHSpad1[40] =               { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };static const uint8_t SHSpad2[40] =               { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,                 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 };static const uint8_t magic1[27] =               { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,                 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,                 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 };static const uint8_t magic2[84] =               { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,                 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,                 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,                 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,                 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,                 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,                 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,                 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,                 0x6b, 0x65, 0x79, 0x2e };static const uint8_t magic3[84] =               { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,                 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,                 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,                 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,                 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,                 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,                 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,                 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,                 0x6b, 0x65, 0x79, 0x2e };static void mppe_GetMasterKey(uint8_t *nt_hashhash,uint8_t *nt_response,			      uint8_t *masterkey){       uint8_t digest[20];       SHA1_CTX Context;       SHA1Init(&Context);       SHA1Update(&Context,nt_hashhash,16);       SHA1Update(&Context,nt_response,24);       SHA1Update(&Context,magic1,27);       SHA1Final(digest,&Context);       memcpy(masterkey,digest,16);}static void mppe_GetAsymmetricStartKey(uint8_t *masterkey,uint8_t *sesskey,				       int keylen,int issend){       uint8_t digest[20];       const uint8_t *s;       SHA1_CTX Context;       memset(digest,0,20);       if(issend) {               s = magic3;       } else {               s = magic2;       }       SHA1Init(&Context);       SHA1Update(&Context,masterkey,16);       SHA1Update(&Context,SHSpad1,40);       SHA1Update(&Context,s,84);       SHA1Update(&Context,SHSpad2,40);       SHA1Final(digest,&Context);       memcpy(sesskey,digest,keylen);}

⌨️ 快捷键说明

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