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

📄 ntlmssp_sign.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  *  Unix SMB/CIFS implementation. *  Version 3.0 *  NTLMSSP Signing routines *  Copyright (C) Luke Kenneth Casson Leighton 1996-2001 *  Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2005 *   *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 3 of the License, or *  (at your option) any later version. *   *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. *   *  You should have received a copy of the GNU General Public License *  along with this program; if not, see <http://www.gnu.org/licenses/>. */#include "includes.h"#include "auth/auth.h"#include "auth/ntlmssp/ntlmssp.h"#include "auth/ntlmssp/msrpc_parse.h"#include "lib/crypto/crypto.h"#include "auth/credentials/credentials.h"#include "auth/gensec/gensec.h"#include "param/param.h"#define CLI_SIGN "session key to client-to-server signing key magic constant"#define CLI_SEAL "session key to client-to-server sealing key magic constant"#define SRV_SIGN "session key to server-to-client signing key magic constant"#define SRV_SEAL "session key to server-to-client sealing key magic constant"/** * Some notes on the NTLM2 code: * * NTLM2 is a AEAD system.  This means that the data encrypted is not * all the data that is signed.  In DCE-RPC case, the headers of the * DCE-RPC packets are also signed.  This prevents some of the * fun-and-games one might have by changing them. * */static void calc_ntlmv2_key(TALLOC_CTX *mem_ctx, 			    DATA_BLOB *subkey,			    DATA_BLOB session_key, 			    const char *constant){	struct MD5Context ctx3;	*subkey = data_blob_talloc(mem_ctx, NULL, 16);	MD5Init(&ctx3);	MD5Update(&ctx3, session_key.data, session_key.length);	MD5Update(&ctx3, (const uint8_t *)constant, strlen(constant)+1);	MD5Final(subkey->data, &ctx3);}enum ntlmssp_direction {	NTLMSSP_SEND,	NTLMSSP_RECEIVE};static NTSTATUS ntlmssp_make_packet_signature(struct gensec_ntlmssp_state *gensec_ntlmssp_state,					      TALLOC_CTX *sig_mem_ctx, 					      const uint8_t *data, size_t length, 					      const uint8_t *whole_pdu, size_t pdu_length, 					      enum ntlmssp_direction direction,					      DATA_BLOB *sig, bool encrypt_sig){	if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {		HMACMD5Context ctx;		uint8_t digest[16];		uint8_t seq_num[4];		*sig = data_blob_talloc(sig_mem_ctx, NULL, NTLMSSP_SIG_SIZE);		if (!sig->data) {			return NT_STATUS_NO_MEMORY;		}					switch (direction) {		case NTLMSSP_SEND:			SIVAL(seq_num, 0, gensec_ntlmssp_state->crypt.ntlm2.send_seq_num);			gensec_ntlmssp_state->crypt.ntlm2.send_seq_num++;			hmac_md5_init_limK_to_64(gensec_ntlmssp_state->crypt.ntlm2.send_sign_key.data, 						 gensec_ntlmssp_state->crypt.ntlm2.send_sign_key.length, &ctx);			break;		case NTLMSSP_RECEIVE:			SIVAL(seq_num, 0, gensec_ntlmssp_state->crypt.ntlm2.recv_seq_num);			gensec_ntlmssp_state->crypt.ntlm2.recv_seq_num++;			hmac_md5_init_limK_to_64(gensec_ntlmssp_state->crypt.ntlm2.recv_sign_key.data, 						 gensec_ntlmssp_state->crypt.ntlm2.recv_sign_key.length, &ctx);			break;		}		hmac_md5_update(seq_num, sizeof(seq_num), &ctx);		hmac_md5_update(whole_pdu, pdu_length, &ctx);		hmac_md5_final(digest, &ctx);		if (encrypt_sig && gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {			switch (direction) {			case NTLMSSP_SEND:				arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state, digest, 8);				break;			case NTLMSSP_RECEIVE:				arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state, digest, 8);				break;			}		}		SIVAL(sig->data, 0, NTLMSSP_SIGN_VERSION);		memcpy(sig->data + 4, digest, 8);		memcpy(sig->data + 12, seq_num, 4);		DEBUG(10, ("NTLM2: created signature over %llu bytes of input:\n", (unsigned long long)pdu_length));		dump_data(11, sig->data, sig->length);				} else {		uint32_t crc;		crc = crc32_calc_buffer(data, length);		if (!msrpc_gen(sig_mem_ctx, 			       lp_iconv_convenience(gensec_ntlmssp_state->gensec_security->lp_ctx),			       sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, gensec_ntlmssp_state->crypt.ntlm.seq_num)) {			return NT_STATUS_NO_MEMORY;		}		gensec_ntlmssp_state->crypt.ntlm.seq_num++;		arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm.arcfour_state, sig->data+4, sig->length-4);		DEBUG(10, ("NTLM1: created signature over %llu bytes of input:\n", (unsigned long long)length));		dump_data(11, sig->data, sig->length);	}	return NT_STATUS_OK;}/* TODO: make this non-public */NTSTATUS gensec_ntlmssp_sign_packet(struct gensec_security *gensec_security, 				    TALLOC_CTX *sig_mem_ctx, 				    const uint8_t *data, size_t length, 				    const uint8_t *whole_pdu, size_t pdu_length, 				    DATA_BLOB *sig){	struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data;	return ntlmssp_make_packet_signature(gensec_ntlmssp_state, sig_mem_ctx, 					     data, length, 					     whole_pdu, pdu_length, 					     NTLMSSP_SEND, sig, true);}/** * Check the signature of an incoming packet  * */NTSTATUS gensec_ntlmssp_check_packet(struct gensec_security *gensec_security, 				     TALLOC_CTX *sig_mem_ctx, 				     const uint8_t *data, size_t length, 				     const uint8_t *whole_pdu, size_t pdu_length, 				     const DATA_BLOB *sig){	struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data;	DATA_BLOB local_sig;	NTSTATUS nt_status;	if (!gensec_ntlmssp_state->session_key.length) {		DEBUG(3, ("NO session key, cannot check packet signature\n"));		return NT_STATUS_NO_USER_SESSION_KEY;	}	nt_status = ntlmssp_make_packet_signature(gensec_ntlmssp_state, sig_mem_ctx, 						  data, length, 						  whole_pdu, pdu_length, 						  NTLMSSP_RECEIVE, &local_sig, true);		if (!NT_STATUS_IS_OK(nt_status)) {		DEBUG(0, ("NTLMSSP packet check failed with %s\n", nt_errstr(nt_status)));		return nt_status;	}	if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {		if (local_sig.length != sig->length ||		    memcmp(local_sig.data, 			   sig->data, sig->length) != 0) {			DEBUG(5, ("BAD SIG NTLM2: wanted signature over %llu bytes of input:\n", (unsigned long long)pdu_length));			dump_data(5, local_sig.data, local_sig.length);						DEBUG(5, ("BAD SIG: got signature over %llu bytes of input:\n", (unsigned long long)pdu_length));			dump_data(5, sig->data, sig->length);						DEBUG(1, ("NTLMSSP NTLM2 packet check failed due to invalid signature on %llu bytes of input!\n", (unsigned long long)pdu_length));			return NT_STATUS_ACCESS_DENIED;		}	} else {		if (local_sig.length != sig->length ||		    memcmp(local_sig.data + 8, 			   sig->data + 8, sig->length - 8) != 0) {			DEBUG(5, ("BAD SIG NTLM1: wanted signature of %llu bytes of input:\n", (unsigned long long)length));			dump_data(5, local_sig.data, local_sig.length);						DEBUG(5, ("BAD SIG: got signature of %llu bytes of input:\n", (unsigned long long)length));			dump_data(5, sig->data, sig->length);						DEBUG(1, ("NTLMSSP NTLM1 packet check failed due to invalid signature on %llu bytes of input:\n", (unsigned long long)length));			return NT_STATUS_ACCESS_DENIED;		}	}	dump_data_pw("checked ntlmssp signature\n", sig->data, sig->length);	return NT_STATUS_OK;}/** * Seal data with the NTLMSSP algorithm * */NTSTATUS gensec_ntlmssp_seal_packet(struct gensec_security *gensec_security, 				    TALLOC_CTX *sig_mem_ctx, 				    uint8_t *data, size_t length, 				    const uint8_t *whole_pdu, size_t pdu_length, 				    DATA_BLOB *sig){	struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data;	NTSTATUS nt_status;	if (!gensec_ntlmssp_state->session_key.length) {		DEBUG(3, ("NO session key, cannot seal packet\n"));		return NT_STATUS_NO_USER_SESSION_KEY;	}	DEBUG(10,("ntlmssp_seal_data: seal\n"));	dump_data_pw("ntlmssp clear data\n", data, length);	if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {		/* The order of these two operations matters - we must first seal the packet,		   then seal the sequence number - this is becouse the send_seal_hash is not		   constant, but is is rather updated with each iteration */		nt_status = ntlmssp_make_packet_signature(gensec_ntlmssp_state, sig_mem_ctx, 							  data, length, 							  whole_pdu, pdu_length, 							  NTLMSSP_SEND, sig, false);		arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state, data, length);		if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {			arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state, sig->data+4, 8);		}	} else {		uint32_t crc;		crc = crc32_calc_buffer(data, length);		if (!msrpc_gen(sig_mem_ctx, 		               lp_iconv_convenience(gensec_security->lp_ctx),			       sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, gensec_ntlmssp_state->crypt.ntlm.seq_num)) {			return NT_STATUS_NO_MEMORY;		}		/* The order of these two operations matters - we must		   first seal the packet, then seal the sequence		   number - this is becouse the ntlmssp_hash is not		   constant, but is is rather updated with each		   iteration */		arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm.arcfour_state, data, length);		arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm.arcfour_state, sig->data+4, sig->length-4);		/* increment counter on send */		gensec_ntlmssp_state->crypt.ntlm.seq_num++;		nt_status = NT_STATUS_OK;	}	dump_data_pw("ntlmssp signature\n", sig->data, sig->length);	dump_data_pw("ntlmssp sealed data\n", data, length);	return nt_status;}/**

⌨️ 快捷键说明

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