• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src/router/samba-3.5.8/source4/libcli/smb2/
1/*
2   Unix SMB/CIFS implementation.
3
4   SMB2 Signing Code
5
6   Copyright (C) Andrew Tridgell <tridge@samba.org> 2008
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "includes.h"
23#include "libcli/raw/libcliraw.h"
24#include "libcli/smb2/smb2.h"
25#include "libcli/smb2/smb2_calls.h"
26#include "../lib/crypto/crypto.h"
27
28/*
29  sign an outgoing message
30 */
31NTSTATUS smb2_sign_message(struct smb2_request_buffer *buf, DATA_BLOB session_key)
32{
33	struct HMACSHA256Context m;
34	uint8_t res[32];
35	uint64_t session_id;
36	size_t hdr_offset;
37
38	if (buf->size < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) {
39		/* can't sign non-SMB2 messages */
40		return NT_STATUS_OK;
41	}
42
43	hdr_offset = buf->hdr - buf->buffer;
44
45	session_id = BVAL(buf->hdr, SMB2_HDR_SESSION_ID);
46	if (session_id == 0) {
47		/* we don't sign messages with a zero session_id. See
48		   MS-SMB2 3.2.4.1.1 */
49		return NT_STATUS_OK;
50	}
51
52	if (session_key.length == 0) {
53		DEBUG(2,("Wrong session key length %u for SMB2 signing\n",
54			 (unsigned)session_key.length));
55		return NT_STATUS_ACCESS_DENIED;
56	}
57
58	memset(buf->hdr + SMB2_HDR_SIGNATURE, 0, 16);
59
60	SIVAL(buf->hdr, SMB2_HDR_FLAGS, IVAL(buf->hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
61
62	ZERO_STRUCT(m);
63	hmac_sha256_init(session_key.data, MIN(session_key.length, 16), &m);
64	hmac_sha256_update(buf->hdr, buf->size-hdr_offset, &m);
65	hmac_sha256_final(res, &m);
66	DEBUG(5,("signed SMB2 message of size %u\n", (unsigned)buf->size - NBT_HDR_SIZE));
67
68	memcpy(buf->hdr + SMB2_HDR_SIGNATURE, res, 16);
69
70	return NT_STATUS_OK;
71}
72
73/*
74  check an incoming signature
75 */
76NTSTATUS smb2_check_signature(struct smb2_request_buffer *buf, DATA_BLOB session_key)
77{
78	uint64_t session_id;
79	struct HMACSHA256Context m;
80	uint8_t res[SHA256_DIGEST_LENGTH];
81	uint8_t sig[16];
82	size_t hdr_offset;
83
84	if (buf->size < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) {
85		/* can't check non-SMB2 messages */
86		return NT_STATUS_OK;
87	}
88
89	hdr_offset = buf->hdr - buf->buffer;
90
91	session_id = BVAL(buf->hdr, SMB2_HDR_SESSION_ID);
92	if (session_id == 0) {
93		/* don't sign messages with a zero session_id. See
94		   MS-SMB2 3.2.4.1.1 */
95		return NT_STATUS_OK;
96	}
97
98	if (session_key.length == 0) {
99		/* we don't have the session key yet */
100		return NT_STATUS_OK;
101	}
102
103	memcpy(sig, buf->hdr+SMB2_HDR_SIGNATURE, 16);
104
105	memset(buf->hdr + SMB2_HDR_SIGNATURE, 0, 16);
106
107	ZERO_STRUCT(m);
108	hmac_sha256_init(session_key.data, MIN(session_key.length, 16), &m);
109	hmac_sha256_update(buf->hdr, buf->size-hdr_offset, &m);
110	hmac_sha256_final(res, &m);
111
112	memcpy(buf->hdr+SMB2_HDR_SIGNATURE, sig, 16);
113
114	if (memcmp(res, sig, 16) != 0) {
115		DEBUG(0,("Bad SMB2 signature for message of size %u\n",
116			 (unsigned)buf->size-NBT_HDR_SIZE));
117		dump_data(0, sig, 16);
118		dump_data(0, res, 16);
119		return NT_STATUS_ACCESS_DENIED;
120	}
121
122	return NT_STATUS_OK;
123}
124