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

📄 rlm_mschap.c

📁 RADIUS 服务器介绍 RADIUS服务器支持标准的RADIUS协议
💻 C
📖 第 1 页 / 共 2 页
字号:
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 *secret,uint8_t *vector,                               uint8_t *nt_hash,uint8_t *response,                               uint8_t *sendkey,uint8_t *recvkey){	uint8_t enckey1[16];	uint8_t enckey2[16];	/* uint8_t salt[2]; */	uint8_t nt_hashhash[16];	md4_calc(nt_hashhash,nt_hash,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);	memcpy (recvkey, enckey2, 16);}/* *	mschap_authorize() - authorize user if we can authenticate *	it later. Add Auth-Type attribute if present in module *	configuration (usually Auth-Type must be "MS-CHAP") */static int mschap_authorize(void * instance, REQUEST *request){#define inst ((struct mschap_instance *)instance)	VALUE_PAIR *challenge = NULL, *response = NULL;	VALUE_PAIR *vp;	const char *authtype_name = "MS-CHAP";	challenge = pairfind(request->packet->vps, PW_MSCHAP_CHALLENGE);	if (!challenge) {		return RLM_MODULE_NOOP;	}			response = pairfind(request->packet->vps, PW_MSCHAP_RESPONSE);	if (!response)		response = pairfind(request->packet->vps, PW_MSCHAP2_RESPONSE);	/*	 *	Nothing we recognize.  Don't do anything.	 */	if (!response) {		DEBUG2("  rlm_mschap: Found MS-CHAP-Challenge, but no MS-CHAP-Response.");		return RLM_MODULE_NOOP;	}	/*	 *	Choose MS-CHAP, or whatever else they told us to use.	 */	if (inst->auth_type) {		authtype_name = inst->auth_type;	}	DEBUG2("  rlm_mschap: Found MS-CHAP attributes.  Setting 'Auth-Type := %s'", authtype_name);	/*	 *	Set Auth-Type to MS-CHAP.  The authentication code	 *	will take care of turning clear-text passwords into	 *	NT/LM passwords.	 */	pairdelete(&request->config_items, PW_AUTHTYPE);	vp = pairmake("Auth-Type", authtype_name, T_OP_SET);	rad_assert(vp != NULL);	pairadd(&request->config_items, vp);	return RLM_MODULE_OK;#undef inst}/* *	mschap_authenticate() - authenticate user based on given *	attributes and configuration. *	We will try to find out password in configuration *	or in configured passwd file. *	If one is found we will check paraneters given by NAS. * *	If PW_SMB_ACCOUNT_CTRL is not set to ACB_PWNOTREQ we must have  *	one of: *		PAP:      PW_PASSWORD or *		MS-CHAP:  PW_MSCHAP_CHALLENGE and PW_MSCHAP_RESPONSE or *		MS-CHAP2: PW_MSCHAP_CHALLENGE and PW_MSCHAP2_RESPONSE *	In case of password mismatch or locked account we MAY return *	PW_MSCHAP_ERROR for MS-CHAP or MS-CHAP v2 *	If MS-CHAP2 succeeds we MUST return *	PW_MSCHAP2_SUCCESS */static int mschap_authenticate(void * instance, REQUEST *request){#define inst ((struct mschap_instance *)instance)	VALUE_PAIR *challenge = NULL, *response = NULL;	VALUE_PAIR *password = NULL;	VALUE_PAIR *lm_password, *nt_password, *smb_ctrl;	VALUE_PAIR *reply_attr;	uint8_t calculated[32];	uint8_t msch2resp[42];        uint8_t mppe_sendkey[34];        uint8_t mppe_recvkey[34];	int chap = 0;		/*	 *	Find the SMB-Account-Ctrl attribute, or the	 *	SMB-Account-Ctrl-Text attribute.	 */	smb_ctrl = pairfind(request->config_items, PW_SMB_ACCOUNT_CTRL);	if (!smb_ctrl) {		password = pairfind(request->config_items,				    PW_SMB_ACCOUNT_CTRL_TEXT);		if (password) {			smb_ctrl = pairmake("SMB-Account-CTRL", "", T_OP_SET);			pairadd(&request->config_items, smb_ctrl);			smb_ctrl->lvalue = pdb_decode_acct_ctrl(password->strvalue);		}	}	/*	 *	We're configured to do MS-CHAP authentication.	 *	and account control information exists.  Enforce it.	 */	if (smb_ctrl) {		/*		 *	Password is not required.		 */		if ((smb_ctrl->lvalue & ACB_PWNOTREQ) != 0) {			DEBUG2("  rlm_mschap: SMB-Account-Ctrl says no password is required.");			return RLM_MODULE_OK;		}	}	/*	 *	Decide how to get the passwords.	 */	password = pairfind(request->config_items, PW_PASSWORD);	/*	 *	We need an LM-Password.	 */	lm_password = pairfind(request->config_items, PW_LM_PASSWORD);	if (lm_password) {		/*		 *	Allow raw octets.		 */		if ((lm_password->length == 16) ||		    ((lm_password->length == 32) &&		     (hex2bin(lm_password->strvalue,			      lm_password->strvalue, 16) == 16))) {			DEBUG2("  rlm_mschap: Found LM-Password");			lm_password->length = 16;		} else {			radlog(L_ERR, "rlm_mschap: Invalid LM-Password");			lm_password = NULL;		}	} else if (!password) {		DEBUG2("  rlm_mschap: No User-Password configured.  Cannot create LM-Password.");	} else {		/* there is a configured User-Password */		lm_password = pairmake("LM-Password", "", T_OP_EQ);		if (!lm_password) {			radlog(L_ERR, "No memory");		} else {			lrad_lmpwdhash(password->strvalue,				       lm_password->strvalue);			lm_password->length = 16;			pairadd(&request->config_items, lm_password);		}	}	/*	 *	We need an NT-Password.	 */	nt_password = pairfind(request->config_items, PW_NT_PASSWORD);	if (nt_password) {		if ((nt_password->length == 16) ||		    ((nt_password->length == 32) &&		     (hex2bin(nt_password->strvalue,			      nt_password->strvalue, 16) == 16))) {			DEBUG2("  rlm_mschap: Found NT-Password");			nt_password->length = 16;                } else {			radlog(L_ERR, "rlm_mschap: Invalid NT-Password");			nt_password = NULL;		}	} else if (!password) {		DEBUG2("  rlm_mschap: No User-Password configured.  Cannot create NT-Password.");	} else {		/* there is a configured User-Password */		nt_password = pairmake("NT-Password", "", T_OP_EQ);		if (!nt_password) {			radlog(L_ERR, "No memory");		} else {			ntpwdhash(nt_password->strvalue, password->strvalue);			nt_password->length = 16;			pairadd(&request->config_items, nt_password);		}	}	/*	 *	No NT or LM Passwords, die.	 */	if (!lm_password && !nt_password) {		DEBUG2("  rlm_mschap: No LM-Password or NT-Password attribute found.  Cannot perform MS-CHAP authentication.");		return RLM_MODULE_FAIL;	}		/*	 *	We MAY be asked to take a User-Password attribute from	 *	the packet, and compare it to passwords retrieved from	 *	an SMB Password file.	 */	password = pairfind(request->packet->vps, PW_PASSWORD);	if (password) {		if (lm_password) {			lrad_lmpwdhash(calculated,				       password->strvalue);			if (memcmp(calculated,				   lm_password->strvalue, 16) == 0) {				DEBUG2("  rlm_mschap: User-Password matches LM-Password.");				return RLM_MODULE_OK;			} else {				DEBUG2("  rlm_mschap: FAILED: User-Password does NOT match LM-Password.");			}		} else if (nt_password) {			ntpwdhash(calculated, password->strvalue);			if (memcmp(calculated,				   nt_password->strvalue, 16) == 0) {				DEBUG2("  rlm_mschap: User-Password matches NT-Password.");				return RLM_MODULE_OK;			} else {				DEBUG2("  rlm_mschap: FAILED: User-Password does NOT match NT-Password.");			}		}		return RLM_MODULE_REJECT;	} /* compare User-Password in packet to configured NT/LM-Password */	challenge = pairfind(request->packet->vps, PW_MSCHAP_CHALLENGE);	if (!challenge) {		DEBUG2("  rlm_mschap: No MS-CHAP-Challenge in the request");		return RLM_MODULE_REJECT;	}	/*	 *	We also require an MS-CHAP-Response.	 */	response = pairfind(request->packet->vps, PW_MSCHAP_RESPONSE);	/*	 *	MS-CHAP-Response, means MS-CHAPv1	 */	if (response) {		int offset;		/*		 *	MS-CHAPv1 challenges are 8 octets.		 */		if (challenge->length < 8) {			radlog(L_AUTH, "rlm_mschap: MS-CHAP-Challenge has the wrong format.");			return RLM_MODULE_INVALID;		}			/*		 *	Responses are 50 octets.		 */		if (response->length < 50) {			radlog(L_AUTH, "rlm_mschap: MS-CHAP-Response has the wrong format.");			return RLM_MODULE_INVALID;		}	    		/*		 *	We are doing MS-CHAP.  Calculate the MS-CHAP		 *	response		 */		if (response->strvalue[1] & 0x01) {			DEBUG2("  rlm_mschap: doing MS-CHAPv1 with NT-Password");			password = nt_password;			offset = 26;		} else {			DEBUG2("  rlm_mschap: doing MS-CHAPv1 with LM-Password");			password = lm_password;			offset = 2;		}		/*		 *	No password configured.  Die.		 */		if (!password) {			DEBUG2("  rlm_mschap: FAILED: No NT/LM-Password");			return RLM_MODULE_REJECT;		}				/*		 *	Calculate the expected response.		 */		lrad_mschap(password->strvalue, challenge->strvalue,			    calculated);		if (memcmp(response->strvalue + offset,			   calculated, 24) != 0) {			DEBUG("  rlm_mschap: FAILED: MS-CHAP-Response is incorrect");			return RLM_MODULE_FAIL;		}		chap = 1;	} else if ((response = pairfind(request->packet->vps, PW_MSCHAP2_RESPONSE)) != NULL) {		/*		 *	MS-CHAPv2 challenges are 16 octets.		 */		if (challenge->length < 16) {			radlog(L_AUTH, "rlm_mschap: MS-CHAP-Challenge has the wrong format.");			return RLM_MODULE_INVALID;		}			/*		 *	Responses are 50 octets.		 */		if (response->length < 50) {			radlog(L_AUTH, "rlm_mschap: MS-CHAP-Response has the wrong format.");			return RLM_MODULE_INVALID;		}		/*		 *	We also require a User-Name		 */		if (!request->username) {			radlog(L_AUTH, "rlm_mschap: We require a User-Name for MS-CHAPv2");			return RLM_MODULE_INVALID;		}	    		/*		 *	We are doing MS-CHAPv2		 *	We need NT hash for it to calculate response		 */		if (!nt_password) {			DEBUG2("  rlm_mschap: No NT-Password configured.  Cannot perform MS-CHAPv2 authentication.");			return RLM_MODULE_INVALID;		}		DEBUG2("  rlm_mschap: doing MS-CHAPv2 with NT-Password");		mschap2(response->strvalue + 2, challenge->strvalue,			request->username->strvalue, nt_password->strvalue,			calculated);		if (memcmp(response->strvalue + 26, calculated, 24) != 0) {			DEBUG2("  rlm_mschap: FAILED: MS-CHAP2-Response is incorrect");			add_reply(&request->reply->vps, *response->strvalue,				  "MS-CHAP-Error", "E=691 R=1", 9);			return RLM_MODULE_REJECT;		}		auth_response(request->username->strvalue,			      nt_password->strvalue, calculated,			      response->strvalue + 2,			      challenge->strvalue,			      msch2resp);		add_reply( &request->reply->vps, *response->strvalue,			   "MS-CHAP2-Success", msch2resp, 42);		chap = 2;			} else {		/* Neither CHAPv1 or CHAPv2 response: die */		radlog(L_AUTH, "rlm_mschap: No MS-CHAP response found");		return RLM_MODULE_INVALID;	}	/*	 *	We have a CHAP response, but the account may be	 *	disabled.  Reject the user with the same error code	 *	we use when their password is invalid.	 */	if (smb_ctrl) {		/*		 *	Account is disabled.		 *		 *	They're found, but they don't exist, so we		 *	return 'not found'.		 */		if (((smb_ctrl->lvalue & ACB_DISABLED) != 0) ||		    ((smb_ctrl->lvalue & ACB_NORMAL) == 0)) {			DEBUG2("  rlm_mschap: SMB-Account-Ctrl says that the account is disabled, or is not a normal account.");			add_reply( &request->reply->vps, *response->strvalue,				   "MS-CHAP-Error", "E=691 R=1", 9);			return RLM_MODULE_NOTFOUND;		}		/*		 *	User is locked out.		 */		if ((smb_ctrl->lvalue & ACB_AUTOLOCK) != 0) {			DEBUG2("  rlm_mschap: SMB-Account-Ctrl says that the account is locked out.");			add_reply( &request->reply->vps, *response->strvalue,				   "MS-CHAP-Error", "E=647 R=0", 9);			return RLM_MODULE_USERLOCK;		}	}	/* now create MPPE attributes */	if (inst->use_mppe) {		if (chap == 1){			DEBUG2("rlm_mschap: adding MS-CHAPv1 MPPE keys");			memset(mppe_sendkey, 0, 32);			if (lm_password) {				memcpy(mppe_sendkey, lm_password->strvalue, 8);			}			if (nt_password) {				/* 				 *	According to RFC 2548 we				 *	should send NT hash.  But in				 *	practice it doesn't work.				 *	Instead, we should send nthashhash				 *				 *	This is an error on RFC 2548.				 */				md4_calc(mppe_sendkey + 8,					 nt_password->strvalue, 16);				mppe_add_reply(&request->reply->vps,					       "MS-CHAP-MPPE-Keys",					       mppe_sendkey, 32);			}		} else if (chap == 2) {			DEBUG2("rlm_mschap: adding MS-CHAPv2 MPPE keys");			mppe_chap2_gen_keys128(request->secret,					       request->packet->vector,					       nt_password->strvalue,					       response->strvalue + 26,					       mppe_sendkey, mppe_recvkey);						mppe_add_reply(&request->reply->vps,				       "MS-MPPE-Recv-Key",				       mppe_recvkey, 16);			mppe_add_reply(&request->reply->vps,				       "MS-MPPE-Send-Key",				       mppe_sendkey, 16);					}		reply_attr = pairmake("MS-MPPE-Encryption-Policy",				      (inst->require_encryption)? "0x00000002":"0x00000001",				      T_OP_EQ);		rad_assert(reply_attr != NULL);		pairadd(&request->reply->vps, reply_attr);		reply_attr = pairmake("MS-MPPE-Encryption-Types",				      (inst->require_strong)? "0x00000004":"0x00000006",				      T_OP_EQ);		rad_assert(reply_attr != NULL);		pairadd(&request->reply->vps, reply_attr);			} /* else we weren't asked to use MPPE */	return RLM_MODULE_OK;#undef inst}module_t rlm_mschap = {  "MS-CHAP",  RLM_TYPE_THREAD_SAFE,		/* type */  NULL,				/* initialize */  mschap_instantiate,		/* instantiation */  {	  mschap_authenticate,	/* authenticate */	  mschap_authorize,	/* authorize */	  NULL,			/* pre-accounting */	  NULL,			/* accounting */	  NULL,			/* checksimul */	  NULL,			/* pre-proxy */	  NULL,			/* post-proxy */	  NULL			/* post-auth */  },  mschap_detach,		/* detach */  NULL,				/* destroy */};

⌨️ 快捷键说明

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