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