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

📄 rlm_mschap.c

📁 RADIUS认证协议
💻 C
📖 第 1 页 / 共 3 页
字号:
			return 0;		}		data = response->strvalue + 2;		data_len = 24;		/*		 *	Pull the NT-Domain out of the User-Name, if it exists.		 */	} else if (strcasecmp(fmt, "NT-Domain") == 0) {		char *p;		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;		}				p = strchr(user_name->strvalue, '\\');		if (!p) {			DEBUG2("  rlm_mschap: No NT-Domain was found in the User-Name.");			return 0;		}		/*		 *	Hack.  This is simpler than the alternatives.		 */		*p = '\0';		strNcpy(out, user_name->strvalue, outlen);		*p = '\\';		return strlen(out);		/*		 *	Pull the User-Name out of the User-Name...		 */	} else if (strcasecmp(fmt, "User-Name") == 0) {		char *p;		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;		}				p = strchr(user_name->strvalue, '\\');		if (p) {			p++;	/* skip the backslash */		} else {			p = user_name->strvalue; /* use the whole User-Name */		}		strNcpy(out, p, outlen);		return strlen(out);	} else {		DEBUG2("  rlm_mschap: Unknown expansion string \"%s\"",		       fmt);		return 0;	}	if (outlen == 0) return 0; /* nowhere to go, don't do anything */	/*	 *	Didn't set anything: this is bad.	 */	if (!data) {		DEBUG2("  rlm_mschap: Failed to do anything intelligent");		return 0;	}	/*	 *	Check the output length.	 */	if (outlen < ((data_len * 2) + 1)) {		data_len = (outlen - 1) / 2;	}	/*	 *		 */	for (i = 0; i < data_len; i++) {		sprintf(out + (2 * i), "%02x", data[i]);	}	out[data_len * 2] = '\0';		return data_len * 2;}static CONF_PARSER module_config[] = {	/*	 *	Cache the password by default.	 */	{ "use_mppe",    PW_TYPE_BOOLEAN,	  offsetof(rlm_mschap_t,use_mppe), NULL, "yes" },	{ "require_encryption",    PW_TYPE_BOOLEAN,	  offsetof(rlm_mschap_t,require_encryption), NULL, "no" },	{ "require_strong",    PW_TYPE_BOOLEAN,	  offsetof(rlm_mschap_t,require_strong), NULL, "no" },	{ "with_ntdomain_hack",     PW_TYPE_BOOLEAN,	  offsetof(rlm_mschap_t,with_ntdomain_hack), NULL, "no" },	{ "passwd",   PW_TYPE_STRING_PTR,	  offsetof(rlm_mschap_t, passwd_file), NULL,  NULL },	{ "authtype",   PW_TYPE_STRING_PTR,	  offsetof(rlm_mschap_t, auth_type), NULL,  NULL },	{ "ntlm_auth",   PW_TYPE_STRING_PTR,	  offsetof(rlm_mschap_t, ntlm_auth), 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 ((rlm_mschap_t *)instance)	if (inst->passwd_file) free(inst->passwd_file);	if (inst->auth_type) free(inst->auth_type);	if (inst->ntlm_auth) free(inst->ntlm_auth);	if (inst->xlat_name) {		xlat_unregister(inst->xlat_name, mschap_xlat);		free(inst->xlat_name);	}	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){	const char *xlat_name;	rlm_mschap_t *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;	}	/*	 *	Create the dynamic translation.	 */	xlat_name = cf_section_name2(conf);	if (xlat_name == NULL)		xlat_name = cf_section_name1(conf);	if (xlat_name){		inst->xlat_name = strdup(xlat_name);		xlat_register(xlat_name, mschap_xlat, inst);	}	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);}/* *	Do the MS-CHAP stuff. * *	This function is here so that all of the MS-CHAP related *	authentication is in one place, and we can perhaps later replace *	it with code to call winbindd, or something similar. */static int do_mschap(rlm_mschap_t *inst,		     REQUEST *request, VALUE_PAIR *password,		     uint8_t *challenge, uint8_t *response,		     uint8_t *nthashhash){	int		do_ntlm_auth = 0;	uint8_t		calculated[24];	VALUE_PAIR	*vp = NULL;	/*	 *	If we have ntlm_auth configured, use it unless told	 *	otherwise	 */	if (inst->ntlm_auth) do_ntlm_auth = 1;	/*	 *	If we have an ntlm_auth configuration, then we may	 *	want to use it.	 */	vp = pairfind(request->config_items,		      PW_MS_CHAP_USE_NTLM_AUTH);	if (vp) do_ntlm_auth = vp->lvalue;	/*	 *	No ntlm_auth configured, attribute to tell us to	 *	use it exists, and we're told to use it.  We don't	 *	know what to do...	 */	if (!inst->ntlm_auth && do_ntlm_auth) {		DEBUG2("  rlm_mschap: Asked to use ntlm_auth, but it was not configured in the mschap{} section.");		return -1;	}	/*	 *	Do normal authentication.	 */	if (!do_ntlm_auth) {		/*		 *	No password: can't do authentication.		 */		if (!password) {			DEBUG2("  rlm_mschap: FAILED: No NT/LM-Password.  Cannot perform authentication.");			return -1;		}				smbdes_mschap(password->strvalue, challenge, calculated);		if (memcmp(response, calculated, 24) != 0) {			return -1;		}				/*		 *	If the password exists, and is an NT-Password,		 *	then calculate the hash of the NT hash.  Doing this		 *	here minimizes work for later.		 */		if (password && (password->attribute == PW_NT_PASSWORD)) {			md4_calc(nthashhash, password->strvalue, 16);		} else {			memset(nthashhash, 0, 16);		}	} else {		/* run ntlm_auth */		int	result;		char	buffer[256];		memset(nthashhash, 0, 16);		/*		 *	Run the program, and expect that we get 16 		 */		result = radius_exec_program(inst->ntlm_auth, request,					     TRUE, /* wait */					     buffer, sizeof(buffer),					     NULL, NULL);		if (result != 0) {			DEBUG2("  rlm_mschap: External script failed.");			return -1;		}		/*		 *	Parse the answer as an nthashhash.		 *		 *	ntlm_auth currently returns:		 *	NT_KEY: 000102030405060708090a0b0c0d0e0f		 */		if (memcmp(buffer, "NT_KEY: ", 8) != 0) {			DEBUG2("  rlm_mschap: Invalid output from ntlm_auth: expecting NT_KEY");			return -1;		}		/*		 *	Check the length.  It should be at least 32,		 *	with an LF at the end.		 */		if (strlen(buffer + 8) < 32) {			DEBUG2("  rlm_mschap: Invalid output from ntlm_auth: NT_KEY has unexpected length");			return -1;		}		/*		 *	Update the NT hash hash, from the NT key.		 */		if (hex2bin(buffer + 8, nthashhash, 16) != 16) {			DEBUG2("  rlm_mschap: Invalid output from ntlm_auth: NT_KEY has non-hex values");			return -1;		}	}	return 0;}/* *	Data for the hashes. */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);}static void mppe_chap2_get_keys128(uint8_t *nt_hashhash,uint8_t *nt_response,				   uint8_t *sendkey,uint8_t *recvkey){       uint8_t masterkey[16];       mppe_GetMasterKey(nt_hashhash,nt_response,masterkey);       mppe_GetAsymmetricStartKey(masterkey,sendkey,16,1);       mppe_GetAsymmetricStartKey(masterkey,recvkey,16,0);}/* *	Generate MPPE keys. */static void mppe_chap2_gen_keys128(uint8_t *nt_hashhash,uint8_t *response,				   uint8_t *sendkey,uint8_t *recvkey){	uint8_t enckey1[16];	uint8_t enckey2[16];	mppe_chap2_get_keys128(nt_hashhash,response,enckey1,enckey2);	/*	 *	dictionary.microsoft defines these attributes as	 *	'encrypt=2'.  The functions in src/lib/radius.c will	 *	take care of encrypting/decrypting them as appropriate,	 *	so that we don't have to.	 */	memcpy (sendkey, enckey1, 16);

⌨️ 快捷键说明

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