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

📄 ntlmssp.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
 it only occours for LM_KEY connections, and this is controlled by the client lanman auth/lanman auth parameters, it isn't too bad.*/DATA_BLOB ntlmssp_weaken_keys(NTLMSSP_STATE *ntlmssp_state, TALLOC_CTX *mem_ctx){	DATA_BLOB weakened_key = data_blob_talloc(mem_ctx,					ntlmssp_state->session_key.data,					ntlmssp_state->session_key.length);	/* Nothing to weaken.  We certainly don't want to 'extend' the length... */	if (weakened_key.length < 16) {		/* perhaps there was no key? */		return weakened_key;	}	/* Key weakening not performed on the master key for NTLM2	   and does not occour for NTLM1.  Therefore we only need	   to do this for the LM_KEY.	*/	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {		/* LM key doesn't support 128 bit crypto, so this is		 * the best we can do.  If you negotiate 128 bit, but		 * not 56, you end up with 40 bit... */		if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) {			weakened_key.data[7] = 0xa0;		} else { /* forty bits */			weakened_key.data[5] = 0xe5;			weakened_key.data[6] = 0x38;			weakened_key.data[7] = 0xb0;		}		weakened_key.length = 8;	}	return weakened_key;}/** * Next state function for the Negotiate packet *  * @param ntlmssp_state NTLMSSP State * @param request The request, as a DATA_BLOB * @param request The reply, as an allocated DATA_BLOB, caller to free. * @return Errors or MORE_PROCESSING_REQUIRED if a reply is sent.  */static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,					 const DATA_BLOB request, DATA_BLOB *reply) {	DATA_BLOB struct_blob;	fstring dnsname, dnsdomname;	uint32 neg_flags = 0;	uint32 ntlmssp_command, chal_flags;	const uint8 *cryptkey;	const char *target_name;	/* parse the NTLMSSP packet */#if 0	file_save("ntlmssp_negotiate.dat", request.data, request.length);#endif	if (request.length) {		if ((request.length < 16) || !msrpc_parse(&request, "Cdd",							"NTLMSSP",							&ntlmssp_command,							&neg_flags)) {			DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate of length %u\n",				(unsigned int)request.length));			dump_data(2, (const char *)request.data, request.length);			return NT_STATUS_INVALID_PARAMETER;		}		debug_ntlmssp_flags(neg_flags);	}		ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, lp_lanman_auth());	/* Ask our caller what challenge they would like in the packet */	cryptkey = ntlmssp_state->get_challenge(ntlmssp_state);	/* Check if we may set the challenge */	if (!ntlmssp_state->may_set_challenge(ntlmssp_state)) {		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;	}	/* The flags we send back are not just the negotiated flags,	 * they are also 'what is in this packet'.  Therfore, we	 * operate on 'chal_flags' from here on 	 */	chal_flags = ntlmssp_state->neg_flags;	/* get the right name to fill in as 'target' */	target_name = ntlmssp_target_name(ntlmssp_state, 					  neg_flags, &chal_flags); 	if (target_name == NULL) 		return NT_STATUS_INVALID_PARAMETER;	ntlmssp_state->chal = data_blob_talloc(ntlmssp_state->mem_ctx, cryptkey, 8);	ntlmssp_state->internal_chal = data_blob_talloc(ntlmssp_state->mem_ctx, cryptkey, 8);		/* This should be a 'netbios domain -> DNS domain' mapping */	dnsdomname[0] = '\0';	get_mydnsdomname(dnsdomname);	strlower_m(dnsdomname);		dnsname[0] = '\0';	get_mydnsfullname(dnsname);		/* This creates the 'blob' of names that appears at the end of the packet */	if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) 	{		msrpc_gen(&struct_blob, "aaaaa",			  NTLMSSP_NAME_TYPE_DOMAIN, target_name,			  NTLMSSP_NAME_TYPE_SERVER, ntlmssp_state->get_global_myname(),			  NTLMSSP_NAME_TYPE_DOMAIN_DNS, dnsdomname,			  NTLMSSP_NAME_TYPE_SERVER_DNS, dnsname,			  0, "");	} else {		struct_blob = data_blob(NULL, 0);	}	{		/* Marshel the packet in the right format, be it unicode or ASCII */		const char *gen_string;		if (ntlmssp_state->unicode) {			gen_string = "CdUdbddB";		} else {			gen_string = "CdAdbddB";		}				msrpc_gen(reply, gen_string,			  "NTLMSSP", 			  NTLMSSP_CHALLENGE,			  target_name,			  chal_flags,			  cryptkey, 8,			  0, 0,			  struct_blob.data, struct_blob.length);	}			data_blob_free(&struct_blob);	ntlmssp_state->expected_state = NTLMSSP_AUTH;	return NT_STATUS_MORE_PROCESSING_REQUIRED;}/** * Next state function for the Authenticate packet *  * @param ntlmssp_state NTLMSSP State * @param request The request, as a DATA_BLOB * @param request The reply, as an allocated DATA_BLOB, caller to free. * @return Errors or NT_STATUS_OK.  */static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,				    const DATA_BLOB request, DATA_BLOB *reply) {	DATA_BLOB encrypted_session_key = data_blob(NULL, 0);	DATA_BLOB user_session_key = data_blob(NULL, 0);	DATA_BLOB lm_session_key = data_blob(NULL, 0);	DATA_BLOB session_key = data_blob(NULL, 0);	uint32 ntlmssp_command, auth_flags;	NTSTATUS nt_status = NT_STATUS_OK;	/* used by NTLM2 */	BOOL doing_ntlm2 = False;	uchar session_nonce[16];	uchar session_nonce_hash[16];	const char *parse_string;	char *domain = NULL;	char *user = NULL;	char *workstation = NULL;	/* parse the NTLMSSP packet */	*reply = data_blob(NULL, 0);#if 0	file_save("ntlmssp_auth.dat", request.data, request.length);#endif	if (ntlmssp_state->unicode) {		parse_string = "CdBBUUUBd";	} else {		parse_string = "CdBBAAABd";	}	data_blob_free(&ntlmssp_state->lm_resp);	data_blob_free(&ntlmssp_state->nt_resp);	ntlmssp_state->user = NULL;	ntlmssp_state->domain = NULL;	ntlmssp_state->workstation = NULL;	/* now the NTLMSSP encoded auth hashes */	if (!msrpc_parse(&request, parse_string,			 "NTLMSSP", 			 &ntlmssp_command, 			 &ntlmssp_state->lm_resp,			 &ntlmssp_state->nt_resp,			 &domain, 			 &user, 			 &workstation,			 &encrypted_session_key,			 &auth_flags)) {		SAFE_FREE(domain);		SAFE_FREE(user);		SAFE_FREE(workstation);		data_blob_free(&encrypted_session_key);		auth_flags = 0;				/* Try again with a shorter string (Win9X truncates this packet) */		if (ntlmssp_state->unicode) {			parse_string = "CdBBUUU";		} else {			parse_string = "CdBBAAA";		}		/* now the NTLMSSP encoded auth hashes */		if (!msrpc_parse(&request, parse_string,				 "NTLMSSP", 				 &ntlmssp_command, 				 &ntlmssp_state->lm_resp,				 &ntlmssp_state->nt_resp,				 &domain, 				 &user, 				 &workstation)) {			DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP (tried both formats):\n"));			dump_data(2, (const char *)request.data, request.length);			SAFE_FREE(domain);			SAFE_FREE(user);			SAFE_FREE(workstation);			return NT_STATUS_INVALID_PARAMETER;		}	}	if (auth_flags)		ntlmssp_handle_neg_flags(ntlmssp_state, auth_flags, lp_lanman_auth());	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {		SAFE_FREE(domain);		SAFE_FREE(user);		SAFE_FREE(workstation);		data_blob_free(&encrypted_session_key);		return nt_status;	}	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {		SAFE_FREE(domain);		SAFE_FREE(user);		SAFE_FREE(workstation);		data_blob_free(&encrypted_session_key);		return nt_status;	}	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_workstation(ntlmssp_state, workstation))) {		SAFE_FREE(domain);		SAFE_FREE(user);		SAFE_FREE(workstation);		data_blob_free(&encrypted_session_key);		return nt_status;	}	SAFE_FREE(domain);	SAFE_FREE(user);	SAFE_FREE(workstation);	DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n",		 ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, (unsigned long)ntlmssp_state->lm_resp.length, (unsigned long)ntlmssp_state->nt_resp.length));#if 0	file_save("nthash1.dat",  &ntlmssp_state->nt_resp.data,  &ntlmssp_state->nt_resp.length);	file_save("lmhash1.dat",  &ntlmssp_state->lm_resp.data,  &ntlmssp_state->lm_resp.length);#endif	/* NTLM2 uses a 'challenge' that is made of up both the server challenge, and a 	   client challenge 		   However, the NTLM2 flag may still be set for the real NTLMv2 logins, be careful.	*/	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {		if (ntlmssp_state->nt_resp.length == 24 && ntlmssp_state->lm_resp.length == 24) {			struct MD5Context md5_session_nonce_ctx;			SMB_ASSERT(ntlmssp_state->internal_chal.data && ntlmssp_state->internal_chal.length == 8);						doing_ntlm2 = True;			memcpy(session_nonce, ntlmssp_state->internal_chal.data, 8);			memcpy(&session_nonce[8], ntlmssp_state->lm_resp.data, 8);						MD5Init(&md5_session_nonce_ctx);			MD5Update(&md5_session_nonce_ctx, session_nonce, 16);			MD5Final(session_nonce_hash, &md5_session_nonce_ctx);						ntlmssp_state->chal = data_blob_talloc(ntlmssp_state->mem_ctx, session_nonce_hash, 8);			/* LM response is no longer useful */			data_blob_free(&ntlmssp_state->lm_resp);			/* We changed the effective challenge - set it */			if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->set_challenge(ntlmssp_state, &ntlmssp_state->chal))) {				data_blob_free(&encrypted_session_key);				return nt_status;			}			/* LM Key is incompatible. */			ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;		}	}	/*	 * Note we don't check here for NTLMv2 auth settings. If NTLMv2 auth	 * is required (by "ntlm auth = no" and "lm auth = no" being set in the	 * smb.conf file) and no NTLMv2 response was sent then the password check	 * will fail here. JRA.	 */	/* Finally, actually ask if the password is OK */	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state, 								       &user_session_key, &lm_session_key))) {		data_blob_free(&encrypted_session_key);		return nt_status;	}	dump_data_pw("NT session key:\n", user_session_key.data, user_session_key.length);	dump_data_pw("LM first-8:\n", lm_session_key.data, lm_session_key.length);	/* Handle the different session key derivation for NTLM2 */	if (doing_ntlm2) {		if (user_session_key.data && user_session_key.length == 16) {			session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);			hmac_md5(user_session_key.data, session_nonce, 				 sizeof(session_nonce), session_key.data);			DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n"));			dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);					} else {			DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n"));			session_key = data_blob(NULL, 0);		}	} else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {		if (lm_session_key.data && lm_session_key.length >= 8) {			if (ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) {				session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);				SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data, 							  session_key.data);				DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));				dump_data_pw("LM session key:\n", session_key.data, session_key.length);			} else {				/* use the key unmodified - it's				 * probably a NULL key from the guest				 * login */				session_key = lm_session_key;			}		} else {			DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n"));			session_key = data_blob(NULL, 0);		}	} else if (user_session_key.data) {		session_key = user_session_key;		DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n"));		dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);	} else if (lm_session_key.data) {		session_key = lm_session_key;		DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n"));		dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);	} else {		DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n"));		session_key = data_blob(NULL, 0);	}	/* With KEY_EXCH, the client supplies the proposed session key, 	   but encrypts it with the long-term key */	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {		if (!encrypted_session_key.data || encrypted_session_key.length != 16) {			data_blob_free(&encrypted_session_key);			DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n", 				  (unsigned int)encrypted_session_key.length));			return NT_STATUS_INVALID_PARAMETER;		} else if (!session_key.data || session_key.length != 16) {			DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n", 				  (unsigned int)session_key.length));

⌨️ 快捷键说明

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