Пример #1
0
BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[16], BOOL unicode)
{
	int new_pw_len = strlen(passwd) * (unicode ? 2 : 1);

	if (new_pw_len > 512)
	{
		DEBUG(0,("make_oem_passwd_hash: new password is too long.\n"));
		return False;
	}

	/*
	 * Now setup the data area.
	 * We need to generate a random fill
	 * for this area to make it harder to
	 * decrypt. JRA.
	 */
	generate_random_buffer((unsigned char *)data, 516, False);
	if (unicode)
	{
		struni2( &data[512 - new_pw_len], passwd);
	}
	else
	{
		fstrcpy( &data[512 - new_pw_len], passwd);
	}
	SIVAL(data, 512, new_pw_len);

#ifdef DEBUG_PASSWORD
	DEBUG(100,("make_oem_passwd_hash\n"));
	dump_data(100, data, 516);
#endif
	SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, True);

	return True;
}
void init_netr_CryptPassword(const char *pwd,
			     unsigned char session_key[16],
			     struct netr_CryptPassword *pwd_buf)
{
	struct samr_CryptPassword password_buf;

	encode_pw_buffer(password_buf.data, pwd, STR_UNICODE);

	SamOEMhash(password_buf.data, session_key, 516);
	memcpy(pwd_buf->data, password_buf.data, 512);
	pwd_buf->length = IVAL(password_buf.data, 512);
}
Пример #3
0
void encode_or_decode_arc4_passwd_buffer(unsigned char pw_buf[532], const DATA_BLOB *psession_key)
{
	struct MD5Context tctx;
	unsigned char key_out[16];

	/* Confounder is last 16 bytes. */

	MD5Init(&tctx);
	MD5Update(&tctx, &pw_buf[516], 16);
	MD5Update(&tctx, psession_key->data, psession_key->length);
	MD5Final(key_out, &tctx);
	/* arc4 with key_out. */
	SamOEMhash(pw_buf, key_out, 516);
}
Пример #4
0
uint8_t * ntlmssp_genauth_keyexchg(uint8_t *session_key, char *challenge_data, unsigned char* nt_hash, uint8_t *new_sess_key)
{
  /* Make up a new session key */
  uint8 client_session_key[16];

  generate_random_buffer_ntlmssp(client_session_key, sizeof(client_session_key));
  /* Encrypt the new session key with the old one */

  size_t length = sizeof(client_session_key);
  uint8_t * encrypted_session_key = emalloc(length);

  memcpy(encrypted_session_key, client_session_key, length);
  SamOEMhash(encrypted_session_key, session_key, length);
  memcpy(new_sess_key, client_session_key, 16);
  return encrypted_session_key;
}
Пример #5
0
/*******************************************************************
 Encode or Decode the sequence number (which is symmetric)
 ********************************************************************/
static void netsec_deal_with_seq_num(struct netsec_auth_struct *a,
				     RPC_AUTH_NETSEC_CHK *verf)
{
	static uchar zeros[4];
	uchar sequence_key[16];
	uchar digest1[16];

	hmac_md5(a->sess_key, zeros, sizeof(zeros), digest1);
	dump_data_pw("(sequence key) digest1:\n", digest1, sizeof(digest1));

	hmac_md5(digest1, verf->packet_digest, 8, sequence_key);

	dump_data_pw("sequence_key:\n", sequence_key, sizeof(sequence_key));

	dump_data_pw("seq_num (before):\n", verf->seq_num, sizeof(verf->seq_num));
	SamOEMhash(verf->seq_num, sequence_key, 8);
	dump_data_pw("seq_num (after):\n", verf->seq_num, sizeof(verf->seq_num));
}
Пример #6
0
/*******************************************************************
 hash a stream.
 ********************************************************************/
BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16])
{
	char *q;

	q = prs_data_p(ps);
        q = &q[offset];

#ifdef DEBUG_PASSWORD
	DEBUG(100, ("prs_hash1\n"));
	dump_data(100, sess_key, 16);
	dump_data(100, q, 68);
#endif
	SamOEMhash((uchar *) q, sess_key, 68);

#ifdef DEBUG_PASSWORD
	dump_data(100, q, 68);
#endif

	return True;
}
Пример #7
0
/***********************************************************
 Code to check the OEM hashed password.

 this function ignores the 516 byte nt OEM hashed password
 but does use the lm OEM password to check the nt hashed-hash.

************************************************************/
BOOL check_oem_password(char *user,
			uchar *lmdata, uchar *lmhash,
			uchar *ntdata, uchar *nthash,
                        struct smb_passwd **psmbpw, char *new_passwd,
                        int new_passwd_size)
{
	static uchar null_pw[16];
	static uchar null_ntpw[16];
	struct smb_passwd *smbpw = NULL;
	int new_pw_len;
	uchar new_ntp16[16];
	uchar unenc_old_ntpw[16];
	uchar new_p16[16];
	uchar unenc_old_pw[16];
	char no_pw[2];

	BOOL nt_pass_set = (ntdata != NULL && nthash != NULL);

	become_root(False);
	*psmbpw = smbpw = getsmbpwnam(user);
	unbecome_root(False);

	if (smbpw == NULL)
	{
		DEBUG(0,("check_oem_password: getsmbpwnam returned NULL\n"));
		return False;
	}

	if (smbpw->acct_ctrl & ACB_DISABLED)
	{
		DEBUG(0,("check_lanman_password: account %s disabled.\n", user));
		return False;
	}

	/* construct a null password (in case one is needed */
	no_pw[0] = 0;
	no_pw[1] = 0;
	nt_lm_owf_gen(no_pw, null_ntpw, null_pw);

	/* check for null passwords */
	if (smbpw->smb_passwd == NULL)
	{
		if (smbpw->acct_ctrl & ACB_PWNOTREQ)
		{
			smbpw->smb_passwd = null_pw;
		}
		else 
		{
			DEBUG(0,("check_oem_password: no lanman password !\n"));
			return False;
		}
	}

	if (smbpw->smb_nt_passwd == NULL && nt_pass_set)
	{
		if (smbpw->acct_ctrl & ACB_PWNOTREQ)
		{
			smbpw->smb_nt_passwd = null_pw;
		}
		else 
		{
			DEBUG(0,("check_oem_password: no ntlm password !\n"));
			return False;
		}
	}

	/* 
	 * Call the hash function to get the new password.
	 */
	SamOEMhash( (uchar *)lmdata, (uchar *)smbpw->smb_passwd, True);

	/* 
	 * The length of the new password is in the last 4 bytes of
	 * the data buffer.
	 */

	new_pw_len = IVAL(lmdata, 512);
	if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1)
	{
		DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len));
		return False;
	}

	if (nt_pass_set)
	{
		/*
		 * nt passwords are in unicode
		 */
		int uni_pw_len = new_pw_len;
		char *pw;
		new_pw_len /= 2;
		pw = dos_unistrn2((uint16*)(&lmdata[512-uni_pw_len]), new_pw_len);
		memcpy(new_passwd, pw, new_pw_len+1);
	}
	else
	{
		memcpy(new_passwd, &lmdata[512-new_pw_len], new_pw_len);
		new_passwd[new_pw_len] = '\0';
	}

	/*
	 * To ensure we got the correct new password, hash it and
	 * use it as a key to test the passed old password.
	 */

	nt_lm_owf_gen(new_passwd, new_ntp16, new_p16);

	if (!nt_pass_set)
	{
		/*
		 * Now use new_p16 as the key to see if the old
		 * password matches.
		 */
		D_P16(new_p16  , lmhash, unenc_old_pw);

		if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16))
		{
			DEBUG(0,("check_oem_password: old lm password doesn't match.\n"));
			return False;
		}

#ifdef DEBUG_PASSWORD
		DEBUG(100,("check_oem_password: password %s ok\n", new_passwd));
#endif
		return True;
	}

	/*
	 * Now use new_p16 as the key to see if the old
	 * password matches.
	 */
	D_P16(new_ntp16, lmhash, unenc_old_pw);
	D_P16(new_ntp16, nthash, unenc_old_ntpw);

	if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16))
	{
		DEBUG(0,("check_oem_password: old lm password doesn't match.\n"));
		return False;
	}

	if (memcmp(smbpw->smb_nt_passwd, unenc_old_ntpw, 16))
	{
		DEBUG(0,("check_oem_password: old nt password doesn't match.\n"));
		return False;
	}
#ifdef DEBUG_PASSWORD
	DEBUG(100,("check_oem_password: password %s ok\n", new_passwd));
#endif
	return True;
}
Пример #8
0
static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, 
					 const DATA_BLOB reply, DATA_BLOB *next_request) 
{
	uint32 chal_flags, ntlmssp_command, unkn1, unkn2;
	DATA_BLOB server_domain_blob;
	DATA_BLOB challenge_blob;
	DATA_BLOB struct_blob = data_blob_null;
	char *server_domain;
	const char *chal_parse_string;
	const char *auth_gen_string;
	DATA_BLOB lm_response = data_blob_null;
	DATA_BLOB nt_response = data_blob_null;
	DATA_BLOB session_key = data_blob_null;
	DATA_BLOB encrypted_session_key = data_blob_null;
	NTSTATUS nt_status = NT_STATUS_OK;

	if (!msrpc_parse(&reply, "CdBd",
			 "NTLMSSP",
			 &ntlmssp_command, 
			 &server_domain_blob,
			 &chal_flags)) {
		DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n"));
		dump_data(2, reply.data, reply.length);

		return NT_STATUS_INVALID_PARAMETER;
	}
	
	data_blob_free(&server_domain_blob);

	DEBUG(3, ("Got challenge flags:\n"));
	debug_ntlmssp_flags(chal_flags);

	ntlmssp_handle_neg_flags(ntlmssp_state, chal_flags, lp_client_lanman_auth());

	if (ntlmssp_state->unicode) {
		if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) {
			chal_parse_string = "CdUdbddB";
		} else {
			chal_parse_string = "CdUdbdd";
		}
		auth_gen_string = "CdBBUUUBd";
	} else {
		if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) {
			chal_parse_string = "CdAdbddB";
		} else {
			chal_parse_string = "CdAdbdd";
		}

		auth_gen_string = "CdBBAAABd";
	}

	DEBUG(3, ("NTLMSSP: Set final flags:\n"));
	debug_ntlmssp_flags(ntlmssp_state->neg_flags);

	if (!msrpc_parse(&reply, chal_parse_string,
			 "NTLMSSP",
			 &ntlmssp_command, 
			 &server_domain,
			 &chal_flags,
			 &challenge_blob, 8,
			 &unkn1, &unkn2,
			 &struct_blob)) {
		DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n"));
		dump_data(2, reply.data, reply.length);
		return NT_STATUS_INVALID_PARAMETER;
	}

	ntlmssp_state->server_domain = talloc_strdup(ntlmssp_state->mem_ctx,
						     server_domain);

	SAFE_FREE(server_domain);
	if (challenge_blob.length != 8) {
		data_blob_free(&struct_blob);
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (!ntlmssp_state->nt_hash || !ntlmssp_state->lm_hash) {
		uchar zeros[16];
		/* do nothing - blobs are zero length */

		ZERO_STRUCT(zeros);

		/* session key is all zeros */
		session_key = data_blob_talloc(ntlmssp_state->mem_ctx, zeros, 16);
		
		/* not doing NLTM2 without a password */
		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
	} else if (ntlmssp_state->use_ntlmv2) {

		if (!struct_blob.length) {
			/* be lazy, match win2k - we can't do NTLMv2 without it */
			DEBUG(1, ("Server did not provide 'target information', required for NTLMv2\n"));
			return NT_STATUS_INVALID_PARAMETER;
		}

		/* TODO: if the remote server is standalone, then we should replace 'domain'
		   with the server name as supplied above */
		
		if (!SMBNTLMv2encrypt_hash(ntlmssp_state->user, 
				      ntlmssp_state->domain, 
				      ntlmssp_state->nt_hash, &challenge_blob, 
				      &struct_blob, 
				      &lm_response, &nt_response, &session_key)) {
			data_blob_free(&challenge_blob);
			data_blob_free(&struct_blob);
			return NT_STATUS_NO_MEMORY;
		}
	} else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
		struct MD5Context md5_session_nonce_ctx;
		uchar session_nonce[16];
		uchar session_nonce_hash[16];
		uchar user_session_key[16];
		
		lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
		generate_random_buffer(lm_response.data, 8);
		memset(lm_response.data+8, 0, 16);

		memcpy(session_nonce, challenge_blob.data, 8);
		memcpy(&session_nonce[8], lm_response.data, 8);
	
		MD5Init(&md5_session_nonce_ctx);
		MD5Update(&md5_session_nonce_ctx, challenge_blob.data, 8);
		MD5Update(&md5_session_nonce_ctx, lm_response.data, 8);
		MD5Final(session_nonce_hash, &md5_session_nonce_ctx);

		DEBUG(5, ("NTLMSSP challenge set by NTLM2\n"));
		DEBUG(5, ("challenge is: \n"));
		dump_data(5, session_nonce_hash, 8);
		
		nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
		SMBNTencrypt_hash(ntlmssp_state->nt_hash,
			     session_nonce_hash,
			     nt_response.data);

		session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);

		SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, NULL, user_session_key);
		hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data);
		dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
	} else {
		/* lanman auth is insecure, it may be disabled */
		if (lp_client_lanman_auth()) {
			lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
			SMBencrypt_hash(ntlmssp_state->lm_hash,challenge_blob.data,
				   lm_response.data);
		}
		
		nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
		SMBNTencrypt_hash(ntlmssp_state->nt_hash,challenge_blob.data,
			     nt_response.data);
		
		session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);
		if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) 
		    && lp_client_lanman_auth()) {
			SMBsesskeygen_lm_sess_key(ntlmssp_state->lm_hash, lm_response.data,
					session_key.data);
			dump_data_pw("LM session key\n", session_key.data, session_key.length);
		} else {
			SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, NULL, session_key.data);
			dump_data_pw("NT session key:\n", session_key.data, session_key.length);
		}
	}
	data_blob_free(&struct_blob);

	/* Key exchange encryptes a new client-generated session key with
	   the password-derived key */
	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
		/* Make up a new session key */
		uint8 client_session_key[16];
		generate_random_buffer(client_session_key, sizeof(client_session_key));

		/* Encrypt the new session key with the old one */
		encrypted_session_key = data_blob(client_session_key, sizeof(client_session_key));
		dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length);
		SamOEMhash(encrypted_session_key.data, session_key.data, encrypted_session_key.length);
		dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);

		/* Mark the new session key as the 'real' session key */
		data_blob_free(&session_key);
		session_key = data_blob_talloc(ntlmssp_state->mem_ctx, client_session_key, sizeof(client_session_key));
	}

	/* this generates the actual auth packet */
	if (!msrpc_gen(next_request, auth_gen_string, 
		       "NTLMSSP", 
		       NTLMSSP_AUTH, 
		       lm_response.data, lm_response.length,
		       nt_response.data, nt_response.length,
		       ntlmssp_state->domain, 
		       ntlmssp_state->user, 
		       ntlmssp_state->get_global_myname(), 
		       encrypted_session_key.data, encrypted_session_key.length,
		       ntlmssp_state->neg_flags)) {
		
		return NT_STATUS_NO_MEMORY;
	}

	data_blob_free(&encrypted_session_key);

	data_blob_free(&ntlmssp_state->chal);

	ntlmssp_state->session_key = session_key;

	ntlmssp_state->chal = challenge_blob;
	ntlmssp_state->lm_resp = lm_response;
	ntlmssp_state->nt_resp = nt_response;

	ntlmssp_state->expected_state = NTLMSSP_DONE;

	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_sign_init(ntlmssp_state))) {
		DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n", nt_errstr(nt_status)));
	}

	return nt_status;
}
Пример #9
0
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;
	DATA_BLOB user_session_key = data_blob_null;
	DATA_BLOB lm_session_key = data_blob_null;
	DATA_BLOB session_key = data_blob_null;
	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;

#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, 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;
		}
	} 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);
				if (session_key.data == NULL) {
					return NT_STATUS_NO_MEMORY;
				}
				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"));
			} else {
				uint8 zeros[24];
				ZERO_STRUCT(zeros);
				session_key = data_blob_talloc(
					ntlmssp_state->mem_ctx, NULL, 16);
				if (session_key.data == NULL) {
					return NT_STATUS_NO_MEMORY;
				}
				SMBsesskeygen_lm_sess_key(
					lm_session_key.data, zeros,
					session_key.data);
			}
			dump_data_pw("LM session key:\n", session_key.data,
				     session_key.length);
		} else {
			DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n"));
			session_key = data_blob_null;
		}
	} 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;
	}

	/* 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));
			ntlmssp_state->session_key = session_key;
		} else {
			dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
			SamOEMhash(encrypted_session_key.data, 
				   session_key.data, 
				   encrypted_session_key.length);
			ntlmssp_state->session_key = data_blob_talloc(ntlmssp_state->mem_ctx, 
								      encrypted_session_key.data, 
								      encrypted_session_key.length);
			dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, 
				     encrypted_session_key.length);
		}
	} else {
		ntlmssp_state->session_key = session_key;
	}

	if (!NT_STATUS_IS_OK(nt_status)) {
		ntlmssp_state->session_key = data_blob_null;
	} else if (ntlmssp_state->session_key.length) {
		nt_status = ntlmssp_sign_init(ntlmssp_state);
	}

	data_blob_free(&encrypted_session_key);
	
	/* Only one authentication allowed per server state. */
	ntlmssp_state->expected_state = NTLMSSP_DONE;

	return nt_status;
}
Пример #10
0
NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *r_u)
{
	NTSTATUS status = NT_STATUS_OK;
	NET_USER_INFO_3 *usr_info = NULL;
	NET_ID_INFO_CTR *ctr = q_u->sam_id.ctr;
	DOM_CRED srv_cred;
	UNISTR2 *uni_samlogon_user = NULL;
	UNISTR2 *uni_samlogon_domain = NULL;
	UNISTR2 *uni_samlogon_workstation = NULL;
	fstring nt_username, nt_domain, nt_workstation;
	auth_usersupplied_info *user_info = NULL;
	auth_serversupplied_info *server_info = NULL;
	extern userdom_struct current_user_info;
	SAM_ACCOUNT *sampw;
	struct auth_context *auth_context = NULL;
	        
	usr_info = (NET_USER_INFO_3 *)talloc(p->mem_ctx, sizeof(NET_USER_INFO_3));
	if (!usr_info)
		return NT_STATUS_NO_MEMORY;

	ZERO_STRUCTP(usr_info);

 	/* store the user information, if there is any. */
	r_u->user = usr_info;
	r_u->switch_value = 0; /* indicates no info */
	r_u->auth_resp = 1; /* authoritative response */
	r_u->switch_value = 3; /* indicates type of validation user info */
 
	if (!get_valid_user_struct(p->vuid))
		return NT_STATUS_NO_SUCH_USER;


	if ( (lp_server_schannel() == True) && (!p->netsec_auth_validated) ) {
		/* 'server schannel = yes' should enforce use of
		   schannel, the client did offer it in auth2, but
		   obviously did not use it. */
		return NT_STATUS_ACCESS_DENIED;
	}

	/* checks and updates credentials.  creates reply credentials */
	if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->sam_id.client.cred, &srv_cred)))
		return NT_STATUS_INVALID_HANDLE;

	memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred));
    
	r_u->buffer_creds = 1; /* yes, we have valid server credentials */
	memcpy(&r_u->srv_creds, &srv_cred, sizeof(r_u->srv_creds));

	/* find the username */
    
	switch (q_u->sam_id.logon_level) {
	case INTERACTIVE_LOGON_TYPE:
		uni_samlogon_user = &ctr->auth.id1.uni_user_name;
 		uni_samlogon_domain = &ctr->auth.id1.uni_domain_name;

                uni_samlogon_workstation = &ctr->auth.id1.uni_wksta_name;
            
		DEBUG(3,("SAM Logon (Interactive). Domain:[%s].  ", lp_workgroup()));
		break;
	case NET_LOGON_TYPE:
		uni_samlogon_user = &ctr->auth.id2.uni_user_name;
		uni_samlogon_domain = &ctr->auth.id2.uni_domain_name;
		uni_samlogon_workstation = &ctr->auth.id2.uni_wksta_name;
            
		DEBUG(3,("SAM Logon (Network). Domain:[%s].  ", lp_workgroup()));
		break;
	default:
		DEBUG(2,("SAM Logon: unsupported switch value\n"));
		return NT_STATUS_INVALID_INFO_CLASS;
	} /* end switch */

	rpcstr_pull(nt_username,uni_samlogon_user->buffer,sizeof(nt_username),uni_samlogon_user->uni_str_len*2,0);
	rpcstr_pull(nt_domain,uni_samlogon_domain->buffer,sizeof(nt_domain),uni_samlogon_domain->uni_str_len*2,0);
	rpcstr_pull(nt_workstation,uni_samlogon_workstation->buffer,sizeof(nt_workstation),uni_samlogon_workstation->uni_str_len*2,0);

	DEBUG(3,("User:[%s@%s] Requested Domain:[%s]\n", nt_username, 
                 nt_workstation, nt_domain));
   	
	fstrcpy(current_user_info.smb_name, nt_username);
	sub_set_smb_name(nt_username);
     
	DEBUG(5,("Attempting validation level %d for unmapped username %s.\n", q_u->sam_id.ctr->switch_value, nt_username));

	status = NT_STATUS_OK;
	
	switch (ctr->switch_value) {
	case NET_LOGON_TYPE:
	{
		const char *wksname = nt_workstation;
		
		if (!NT_STATUS_IS_OK(status = make_auth_context_fixed(&auth_context, ctr->auth.id2.lm_chal))) {
			return status;
		}

		/* For a network logon, the workstation name comes in with two
		 * backslashes in the front. Strip them if they are there. */

		if (*wksname == '\\') wksname++;
		if (*wksname == '\\') wksname++;

		/* Standard challenge/response authenticaion */
		if (!make_user_info_netlogon_network(&user_info, 
						     nt_username, nt_domain, 
						     wksname,
						     ctr->auth.id2.lm_chal_resp.buffer,
						     ctr->auth.id2.lm_chal_resp.str_str_len,
						     ctr->auth.id2.nt_chal_resp.buffer,
						     ctr->auth.id2.nt_chal_resp.str_str_len)) {
			status = NT_STATUS_NO_MEMORY;
		}	
		break;
	}
	case INTERACTIVE_LOGON_TYPE:
		/* 'Interactive' autheticaion, supplies the password in its
		   MD4 form, encrypted with the session key.  We will
		   convert this to chellange/responce for the auth
		   subsystem to chew on */
	{
		const uint8 *chal;
		
		if (!NT_STATUS_IS_OK(status = make_auth_context_subsystem(&auth_context))) {
			return status;
		}
		
		chal = auth_context->get_ntlm_challenge(auth_context);

		if (!make_user_info_netlogon_interactive(&user_info, 
							 nt_username, nt_domain, 
							 nt_workstation, chal,
							 ctr->auth.id1.lm_owf.data, 
							 ctr->auth.id1.nt_owf.data, 
							 p->dc.sess_key)) {
			status = NT_STATUS_NO_MEMORY;
		}
		break;
	}
	default:
		DEBUG(2,("SAM Logon: unsupported switch value\n"));
		return NT_STATUS_INVALID_INFO_CLASS;
	} /* end switch */
	
	if ( NT_STATUS_IS_OK(status) ) {
		status = auth_context->check_ntlm_password(auth_context, 
			user_info, &server_info);
	}

	(auth_context->free)(&auth_context);	
	free_user_info(&user_info);
	
	DEBUG(5, ("_net_sam_logon: check_password returned status %s\n", 
		  nt_errstr(status)));

	/* Check account and password */
    
	if (!NT_STATUS_IS_OK(status)) {
		free_server_info(&server_info);
		return status;
	}

	if (server_info->guest) {
		/* We don't like guest domain logons... */
		DEBUG(5,("_net_sam_logon: Attempted domain logon as GUEST denied.\n"));
		free_server_info(&server_info);
		return NT_STATUS_LOGON_FAILURE;
	}

	/* This is the point at which, if the login was successful, that
           the SAM Local Security Authority should record that the user is
           logged in to the domain.  */
    
	{
		DOM_GID *gids = NULL;
		const DOM_SID *user_sid = NULL;
		const DOM_SID *group_sid = NULL;
		DOM_SID domain_sid;
		uint32 user_rid, group_rid; 

		int num_gids = 0;
		pstring my_name;
		fstring user_sid_string;
		fstring group_sid_string;
		uchar user_session_key[16];
		uchar lm_session_key[16];
		uchar netlogon_sess_key[16];

		sampw = server_info->sam_account;

		/* set up pointer indicating user/password failed to be found */
		usr_info->ptr_user_info = 0;

		user_sid = pdb_get_user_sid(sampw);
		group_sid = pdb_get_group_sid(sampw);

		sid_copy(&domain_sid, user_sid);
		sid_split_rid(&domain_sid, &user_rid);

		if (!sid_peek_check_rid(&domain_sid, group_sid, &group_rid)) {
			DEBUG(1, ("_net_sam_logon: user %s\\%s has user sid %s\n but group sid %s.\nThe conflicting domain portions are not supported for NETLOGON calls\n", 	    
				  pdb_get_domain(sampw), pdb_get_username(sampw),
				  sid_to_string(user_sid_string, user_sid),
				  sid_to_string(group_sid_string, group_sid)));
			return NT_STATUS_UNSUCCESSFUL;
		}
		
		pstrcpy(my_name, global_myname());

		if (!NT_STATUS_IS_OK(status 
				     = nt_token_to_group_list(p->mem_ctx, 
							      &domain_sid, 
							      server_info->ptok, 
							      &num_gids, 
							      &gids))) {
			return status;
		}

		ZERO_STRUCT(netlogon_sess_key);
		memcpy(netlogon_sess_key, p->dc.sess_key, 8);
		if (server_info->user_session_key.length) {
			memcpy(user_session_key, server_info->user_session_key.data, 
			       MIN(sizeof(user_session_key), server_info->user_session_key.length));
			SamOEMhash(user_session_key, netlogon_sess_key, 16);
		}
		if (server_info->lm_session_key.length) {
			memcpy(lm_session_key, server_info->lm_session_key.data, 
			       MIN(sizeof(lm_session_key), server_info->lm_session_key.length));
			SamOEMhash(lm_session_key, netlogon_sess_key, 16);
		}
		ZERO_STRUCT(netlogon_sess_key);
		
		init_net_user_info3(p->mem_ctx, usr_info, 
				    user_rid,
				    group_rid,   
				    pdb_get_username(sampw),
				    pdb_get_fullname(sampw),
				    pdb_get_homedir(sampw),
				    pdb_get_dir_drive(sampw),
				    pdb_get_logon_script(sampw),
				    pdb_get_profile_path(sampw),
				    pdb_get_logon_time(sampw),
				    get_time_t_max(),
				    get_time_t_max(),
				    pdb_get_pass_last_set_time(sampw),
				    pdb_get_pass_can_change_time(sampw),
				    pdb_get_pass_must_change_time(sampw),
				    
				    0, /* logon_count */
				    0, /* bad_pw_count */
				    num_gids,    /* uint32 num_groups */
				    gids    , /* DOM_GID *gids */
				    0x20    , /* uint32 user_flgs (?) */
				    server_info->user_session_key.length ? user_session_key : NULL,
				    server_info->lm_session_key.length ? lm_session_key : NULL,
				    my_name     , /* char *logon_srv */
				    pdb_get_domain(sampw),
				    &domain_sid,     /* DOM_SID *dom_sid */  
				    /* Should be users domain sid, not servers - for trusted domains */
				  
				    NULL); /* char *other_sids */
		ZERO_STRUCT(user_session_key);
		ZERO_STRUCT(lm_session_key);
	}
	free_server_info(&server_info);
	return status;
}
Пример #11
0
BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
                             const char *old_password)
{
	pstring param;
	unsigned char data[532];
	char *p = param;
	unsigned char old_pw_hash[16];
	unsigned char new_pw_hash[16];
	unsigned int data_len;
	unsigned int param_len = 0;
	char *rparam = NULL;
	char *rdata = NULL;
	unsigned int rprcnt, rdrcnt;

	if (strlen(user) >= sizeof(fstring)-1) {
		DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
		return False;
	}

	SSVAL(p,0,214); /* SamOEMChangePassword command. */
	p += 2;
	pstrcpy_base(p, "zsT", param);
	p = skip_string(param,sizeof(param),p);
	pstrcpy_base(p, "B516B16", param);
	p = skip_string(param,sizeof(param),p);
	pstrcpy_base(p,user, param);
	p = skip_string(param,sizeof(param),p);
	SSVAL(p,0,532);
	p += 2;

	param_len = PTR_DIFF(p,param);

	/*
	 * Get the Lanman hash of the old password, we
	 * use this as the key to make_oem_passwd_hash().
	 */
	E_deshash(old_password, old_pw_hash);

	encode_pw_buffer(data, new_password, STR_ASCII);
  
#ifdef DEBUG_PASSWORD
	DEBUG(100,("make_oem_passwd_hash\n"));
	dump_data(100, (char *)data, 516);
#endif
	SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);

	/* 
	 * Now place the old password hash in the data.
	 */
	E_deshash(new_password, new_pw_hash);

	E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);

	data_len = 532;
    
	if (cli_send_trans(cli,SMBtrans,
                    PIPE_LANMAN,                          /* name */
                    0,0,                                  /* fid, flags */
                    NULL,0,0,                             /* setup, length, max */
                    param,param_len,2,                    /* param, length, max */
                    (char *)data,data_len,0                       /* data, length, max */
                   ) == False) {
		DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
			user ));
		return False;
	}

	if (!cli_receive_trans(cli,SMBtrans,
                       &rparam, &rprcnt,
                       &rdata, &rdrcnt)) {
		DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n",
			user ));
		return False;
	}
  
	if (rparam) {
		cli->rap_error = SVAL(rparam,0);
	}
  
	SAFE_FREE(rparam);
	SAFE_FREE(rdata);

	return (cli->rap_error == 0);
}
NTSTATUS serverinfo_to_SamInfo3(struct auth_serversupplied_info *server_info,
				uint8_t pipe_session_key[16],
				struct netr_SamInfo3 *sam3)
{
	struct samu *sampw;
	DOM_GID *gids = NULL;
	const DOM_SID *user_sid = NULL;
	const DOM_SID *group_sid = NULL;
	DOM_SID domain_sid;
	uint32 user_rid, group_rid;
	NTSTATUS status;

	int num_gids = 0;
	const char *my_name;

	struct netr_UserSessionKey user_session_key;
	struct netr_LMSessionKey lm_session_key;

	NTTIME last_logon, last_logoff, acct_expiry, last_password_change;
	NTTIME allow_password_change, force_password_change;
	struct samr_RidWithAttributeArray groups;
	int i;
	struct dom_sid2 *sid = NULL;

	ZERO_STRUCT(user_session_key);
	ZERO_STRUCT(lm_session_key);

	sampw = server_info->sam_account;

	user_sid = pdb_get_user_sid(sampw);
	group_sid = pdb_get_group_sid(sampw);

	if ((user_sid == NULL) || (group_sid == NULL)) {
		DEBUG(1, ("_netr_LogonSamLogon: User without group or user SID\n"));
		return NT_STATUS_UNSUCCESSFUL;
	}

	sid_copy(&domain_sid, user_sid);
	sid_split_rid(&domain_sid, &user_rid);

	sid = sid_dup_talloc(sam3, &domain_sid);
	if (!sid) {
		return NT_STATUS_NO_MEMORY;
	}

	if (!sid_peek_check_rid(&domain_sid, group_sid, &group_rid)) {
		DEBUG(1, ("_netr_LogonSamLogon: user %s\\%s has user sid "
			  "%s\n but group sid %s.\n"
			  "The conflicting domain portions are not "
			  "supported for NETLOGON calls\n",
			  pdb_get_domain(sampw),
			  pdb_get_username(sampw),
			  sid_string_dbg(user_sid),
			  sid_string_dbg(group_sid)));
		return NT_STATUS_UNSUCCESSFUL;
	}

	if(server_info->login_server) {
		my_name = server_info->login_server;
	} else {
		my_name = global_myname();
	}

	status = nt_token_to_group_list(sam3, &domain_sid,
					server_info->num_sids,
					server_info->sids,
					&num_gids, &gids);

	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	if (server_info->user_session_key.length) {
		memcpy(user_session_key.key,
		       server_info->user_session_key.data,
		       MIN(sizeof(user_session_key.key),
			   server_info->user_session_key.length));
		SamOEMhash(user_session_key.key, pipe_session_key, 16);
	}
	if (server_info->lm_session_key.length) {
		memcpy(lm_session_key.key,
		       server_info->lm_session_key.data,
		       MIN(sizeof(lm_session_key.key),
			   server_info->lm_session_key.length));
		SamOEMhash(lm_session_key.key, pipe_session_key, 8);
	}

	groups.count = num_gids;
	groups.rids = TALLOC_ARRAY(sam3, struct samr_RidWithAttribute, groups.count);
	if (!groups.rids) {
		return NT_STATUS_NO_MEMORY;
	}

	for (i=0; i < groups.count; i++) {
		groups.rids[i].rid = gids[i].g_rid;
		groups.rids[i].attributes = gids[i].attr;
	}

	unix_to_nt_time(&last_logon, pdb_get_logon_time(sampw));
	unix_to_nt_time(&last_logoff, get_time_t_max());
	unix_to_nt_time(&acct_expiry, get_time_t_max());
	unix_to_nt_time(&last_password_change, pdb_get_pass_last_set_time(sampw));
	unix_to_nt_time(&allow_password_change, pdb_get_pass_can_change_time(sampw));
	unix_to_nt_time(&force_password_change, pdb_get_pass_must_change_time(sampw));

	init_netr_SamInfo3(sam3,
			   last_logon,
			   last_logoff,
			   acct_expiry,
			   last_password_change,
			   allow_password_change,
			   force_password_change,
			   talloc_strdup(sam3, pdb_get_username(sampw)),
			   talloc_strdup(sam3, pdb_get_fullname(sampw)),
			   talloc_strdup(sam3, pdb_get_logon_script(sampw)),
			   talloc_strdup(sam3, pdb_get_profile_path(sampw)),
			   talloc_strdup(sam3, pdb_get_homedir(sampw)),
			   talloc_strdup(sam3, pdb_get_dir_drive(sampw)),
			   0, /* logon_count */
			   0, /* bad_password_count */
			   user_rid,
			   group_rid,
			   groups,
			   NETLOGON_EXTRA_SIDS,
			   user_session_key,
			   my_name,
			   talloc_strdup(sam3, pdb_get_domain(sampw)),
			   sid,
			   lm_session_key,
			   pdb_get_acct_ctrl(sampw),
			   0, /* sidcount */
			   NULL); /* struct netr_SidAttr *sids */
	ZERO_STRUCT(user_session_key);
	ZERO_STRUCT(lm_session_key);

	return NT_STATUS_OK;
}
Пример #13
0
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;

	/* 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;
	/* add start, water, 11/17/2008*/
	/*when security=share, the samba doesn't workable, 
	now set security=user, but does not check username & password*/
	FILE* fp = NULL;
	char TmpUsr[6] = "guest";/*If all shared folders are 'All - no password',
	                        then no need to login for "HTTP", "FTP" or samba.*/
	/* add end, water, 11/17/2008*/

	/* 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;
		}
	}
	/* add start, water, 11/17/2008*/
	/*when security=share, the samba doesn't workable, 
	now set security=user, but does not check username & password*/
	//DEBUG(0, ("[UsrDebug] %d, user=%s\n", __LINE__, user) );
	//if (strlen (user) > 0)
		//memcpy(user, TmpUsr, sizeof(TmpUsr) );
	//DEBUG(0, ("[UsrDebug] %d, user=%s\n", __LINE__, user) );
	/* add end, water, 11/17/2008*/
	
	/* add start, water, 06/08/2009*/
	/*If all shared folders are 'All - no password',
	 then no need to login for "HTTP", "FTP" or samba.*/
	fp = fopen("/tmp/all_no_password","r");
	if (fp != NULL)
	{
	    fclose(fp);
	    DEBUG(0, ("[UsrDebug] %d, user=%s\n", __LINE__, user) );
	    if (strlen (user) > 0)
	        memcpy(user, TmpUsr, sizeof(TmpUsr) );
	    DEBUG(0, ("[UsrDebug] %d, user=%s\n", __LINE__, user) );
	}
	/* add end, water, 06/08/2009*/

	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;
			}
		}
	}

	/*
	 * 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", 
				  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", 
				  session_key.length));
			ntlmssp_state->session_key = session_key;
		} else {
			dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
			SamOEMhash(encrypted_session_key.data, 
				   session_key.data, 
				   encrypted_session_key.length);
			ntlmssp_state->session_key = data_blob_talloc(ntlmssp_state->mem_ctx, 
								      encrypted_session_key.data, 
								      encrypted_session_key.length);
			dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, 
				     encrypted_session_key.length);
		}
	} else {
		ntlmssp_state->session_key = session_key;
	}

	if (!NT_STATUS_IS_OK(nt_status)) {
		ntlmssp_state->session_key = data_blob(NULL, 0);
	} else if (ntlmssp_state->session_key.length) {
		nt_status = ntlmssp_sign_init(ntlmssp_state);
	}

	data_blob_free(&encrypted_session_key);
	
	/* allow arbitarily many authentications */
	ntlmssp_state->expected_state = NTLMSSP_AUTH;

	return nt_status;
}
Пример #14
0
void init_id_info1(NET_ID_INFO_1 *id, char *domain_name,
				uint32 param_ctrl, uint32 log_id_low, uint32 log_id_high,
				char *user_name, char *wksta_name,
				char sess_key[16],
				unsigned char lm_cypher[16], unsigned char nt_cypher[16])
{
	int len_domain_name = strlen(domain_name);
	int len_user_name   = strlen(user_name  );
	int len_wksta_name  = strlen(wksta_name );

	unsigned char lm_owf[16];
	unsigned char nt_owf[16];

	DEBUG(5,("make_id_info1: %d\n", __LINE__));

	id->ptr_id_info1 = 1;

	init_uni_hdr(&id->hdr_domain_name, len_domain_name);

	id->param_ctrl = param_ctrl;
	init_logon_id(&id->logon_id, log_id_low, log_id_high);

	init_uni_hdr(&id->hdr_user_name, len_user_name);
	init_uni_hdr(&id->hdr_wksta_name, len_wksta_name);

	if (lm_cypher && nt_cypher) {
		unsigned char key[16];
#ifdef DEBUG_PASSWORD
		DEBUG(100,("lm cypher:"));
		dump_data(100, (char *)lm_cypher, 16);

		DEBUG(100,("nt cypher:"));
		dump_data(100, (char *)nt_cypher, 16);
#endif

		memset(key, 0, 16);
		memcpy(key, sess_key, 8);

		memcpy(lm_owf, lm_cypher, 16);
		SamOEMhash(lm_owf, key, False);
		memcpy(nt_owf, nt_cypher, 16);
		SamOEMhash(nt_owf, key, False);

#ifdef DEBUG_PASSWORD
		DEBUG(100,("encrypt of lm owf password:"******"encrypt of nt owf password:"));
		dump_data(100, (char *)nt_owf, 16);
#endif
		/* set up pointers to cypher blocks */
		lm_cypher = lm_owf;
		nt_cypher = nt_owf;
	}

	init_owf_info(&id->lm_owf, lm_cypher);
	init_owf_info(&id->nt_owf, nt_cypher);

	init_unistr2(&id->uni_domain_name, domain_name, len_domain_name);
	init_unistr2(&id->uni_user_name, user_name, len_user_name);
	init_unistr2(&id->uni_wksta_name, wksta_name, len_wksta_name);
}
Пример #15
0
BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags,
		   enum netsec_direction direction, 
		   RPC_AUTH_NETSEC_CHK * verf, char *data, size_t data_len)
{
	uchar digest_final[16];

	static const uchar netsec_seal_sig[8] = NETSEC_SEAL_SIGNATURE;
	static const uchar netsec_sign_sig[8] = NETSEC_SIGN_SIGNATURE;
	const uchar *netsec_sig = NULL;

	uchar seq_num[8];

	DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len));
	
	if (auth_flags & AUTH_PIPE_SEAL) {
		netsec_sig = netsec_seal_sig;
	} else if (auth_flags & AUTH_PIPE_SIGN) {
		netsec_sig = netsec_sign_sig;
	}

	/* Create the expected sequence number for comparison */
	RSIVAL(seq_num, 0, a->seq_num);

	switch (direction) {
	case SENDER_IS_INITIATOR:
		SIVAL(seq_num, 4, 0x80);
		break;
	case SENDER_IS_ACCEPTOR:
		SIVAL(seq_num, 4, 0x0);
		break;
	}

	DEBUG(10,("SCHANNEL: netsec_decode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len));
	dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key));

	dump_data_pw("seq_num:\n", seq_num, sizeof(seq_num));

	/* extract the sequence number (key based on supplied packet digest) */
	/* needs to be done before the sealing, as the original version 
	   is used in the sealing stuff... */
	netsec_deal_with_seq_num(a, verf);

	if (memcmp(verf->seq_num, seq_num, sizeof(seq_num))) {
		/* don't even bother with the below if the sequence number is out */
		/* The sequence number is MD5'ed with a key based on the whole-packet
		   digest, as supplied by the client.  We check that it's a valid 
		   checksum after the decode, below
		*/
		DEBUG(2, ("netsec_decode: FAILED: packet sequence number:\n"));
		dump_data(2, (const char*)verf->seq_num, sizeof(verf->seq_num));
		DEBUG(2, ("should be:\n"));
		dump_data(2, (const char*)seq_num, sizeof(seq_num));

		return False;
	}

	if (memcmp(verf->sig, netsec_sig, sizeof(verf->sig))) {
		/* Validate that the other end sent the expected header */
		DEBUG(2, ("netsec_decode: FAILED: packet header:\n"));
		dump_data(2, (const char*)verf->sig, sizeof(verf->sig));
		DEBUG(2, ("should be:\n"));
		dump_data(2, (const char*)netsec_sig, sizeof(netsec_sig));
		return False;
	}

	if (auth_flags & AUTH_PIPE_SEAL) {
		uchar sealing_key[16];
		
		/* get the key to extract the data with */
		netsec_get_sealing_key(a, verf, sealing_key);

		/* extract the verification data */
		dump_data_pw("verf->confounder:\n", verf->confounder, 
			     sizeof(verf->confounder));
		SamOEMhash(verf->confounder, sealing_key, 8);

		dump_data_pw("verf->confounder_dec:\n", verf->confounder, 
			     sizeof(verf->confounder));
		
		/* extract the packet payload */
		dump_data_pw("data   :\n", (const unsigned char *)data, data_len);
		SamOEMhash((unsigned char *)data, sealing_key, data_len);
		dump_data_pw("datadec:\n", (const unsigned char *)data, data_len);	
	}

	/* digest includes 'data' after unsealing */
	netsec_digest(a, auth_flags, verf, data, data_len, digest_final);

	dump_data_pw("Calculated digest:\n", digest_final, 
		     sizeof(digest_final));
	dump_data_pw("verf->packet_digest:\n", verf->packet_digest, 
		     sizeof(verf->packet_digest));
	
	/* compare - if the client got the same result as us, then
	   it must know the session key */
	return (memcmp(digest_final, verf->packet_digest, 
		       sizeof(verf->packet_digest)) == 0);
}
Пример #16
0
/*******************************************************************
 Encode a blob of data using the netsec (schannel) alogrithm, also produceing
 a checksum over the original data.  We currently only support
 signing and sealing togeather - the signing-only code is close, but not
 quite compatible with what MS does.
 ********************************************************************/
void netsec_encode(struct netsec_auth_struct *a, int auth_flags, 
		   enum netsec_direction direction,
		   RPC_AUTH_NETSEC_CHK * verf,
		   char *data, size_t data_len)
{
	uchar digest_final[16];
	uchar confounder[8];
	uchar seq_num[8];
	static const uchar nullbytes[8];

	static const uchar netsec_seal_sig[8] = NETSEC_SEAL_SIGNATURE;
	static const uchar netsec_sign_sig[8] = NETSEC_SIGN_SIGNATURE;
	const uchar *netsec_sig = NULL;

	DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len));
	
	if (auth_flags & AUTH_PIPE_SEAL) {
		netsec_sig = netsec_seal_sig;
	} else if (auth_flags & AUTH_PIPE_SIGN) {
		netsec_sig = netsec_sign_sig;
	}

	/* fill the 'confounder' with random data */
	generate_random_buffer(confounder, sizeof(confounder), False);

	dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key));

	RSIVAL(seq_num, 0, a->seq_num);

	switch (direction) {
	case SENDER_IS_INITIATOR:
		SIVAL(seq_num, 4, 0x80);
		break;
	case SENDER_IS_ACCEPTOR:
		SIVAL(seq_num, 4, 0x0);
		break;
	}

	dump_data_pw("verf->seq_num:\n", seq_num, sizeof(verf->seq_num));

	init_rpc_auth_netsec_chk(verf, netsec_sig, nullbytes,
				 seq_num, confounder);
				
	/* produce a digest of the packet to prove it's legit (before we seal it) */
	netsec_digest(a, auth_flags, verf, data, data_len, digest_final);
	memcpy(verf->packet_digest, digest_final, sizeof(verf->packet_digest));

	if (auth_flags & AUTH_PIPE_SEAL) {
		uchar sealing_key[16];

		/* get the key to encode the data with */
		netsec_get_sealing_key(a, verf, sealing_key);

		/* encode the verification data */
		dump_data_pw("verf->confounder:\n", verf->confounder, sizeof(verf->confounder));
		SamOEMhash(verf->confounder, sealing_key, 8);

		dump_data_pw("verf->confounder_enc:\n", verf->confounder, sizeof(verf->confounder));
		
		/* encode the packet payload */
		dump_data_pw("data:\n", (const unsigned char *)data, data_len);
		SamOEMhash((unsigned char *)data, sealing_key, data_len);
		dump_data_pw("data_enc:\n", (const unsigned char *)data, data_len);
	}

	/* encode the sequence number (key based on packet digest) */
	/* needs to be done after the sealing, as the original version 
	   is used in the sealing stuff... */
	netsec_deal_with_seq_num(a, verf);

	return;
}