Line data Source code
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 :
27 : #include <gnutls/gnutls.h>
28 : #include <gnutls/crypto.h>
29 : #include "lib/crypto/gnutls_helpers.h"
30 :
31 : /*
32 : sign an outgoing message
33 : */
34 411669 : NTSTATUS smb2_sign_message(struct smb2_request_buffer *buf, DATA_BLOB session_key)
35 411669 : {
36 411669 : uint8_t digest[gnutls_hmac_get_len(GNUTLS_MAC_SHA256)];
37 0 : uint64_t session_id;
38 0 : size_t hdr_offset;
39 0 : int rc;
40 :
41 411669 : if (buf->size < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) {
42 : /* can't sign non-SMB2 messages */
43 0 : return NT_STATUS_OK;
44 : }
45 :
46 411669 : hdr_offset = buf->hdr - buf->buffer;
47 :
48 411669 : session_id = BVAL(buf->hdr, SMB2_HDR_SESSION_ID);
49 411669 : if (session_id == 0) {
50 : /* we don't sign messages with a zero session_id. See
51 : MS-SMB2 3.2.4.1.1 */
52 0 : return NT_STATUS_OK;
53 : }
54 :
55 411669 : if (session_key.length == 0) {
56 0 : DEBUG(2,("Wrong session key length %u for SMB2 signing\n",
57 : (unsigned)session_key.length));
58 0 : return NT_STATUS_ACCESS_DENIED;
59 : }
60 :
61 411669 : memset(buf->hdr + SMB2_HDR_SIGNATURE, 0, 16);
62 :
63 411669 : SIVAL(buf->hdr, SMB2_HDR_FLAGS, IVAL(buf->hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
64 :
65 411669 : rc = gnutls_hmac_fast(GNUTLS_MAC_SHA256,
66 411669 : session_key.data,
67 411669 : MIN(session_key.length, 16),
68 411669 : buf->hdr,
69 411669 : buf->size - hdr_offset,
70 : digest);
71 411669 : if (rc < 0) {
72 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
73 : }
74 :
75 411669 : DEBUG(5,("signed SMB2 message of size %u\n", (unsigned)buf->size - NBT_HDR_SIZE));
76 :
77 411669 : memcpy(buf->hdr + SMB2_HDR_SIGNATURE, digest, 16);
78 :
79 411669 : return NT_STATUS_OK;
80 : }
81 :
82 : /*
83 : check an incoming signature
84 : */
85 410115 : NTSTATUS smb2_check_signature(struct smb2_request_buffer *buf, DATA_BLOB session_key)
86 410115 : {
87 0 : uint64_t session_id;
88 820230 : uint8_t digest[gnutls_hmac_get_len(GNUTLS_MAC_SHA256)];
89 0 : uint8_t sig[16];
90 0 : size_t hdr_offset;
91 0 : int rc;
92 :
93 410115 : if (buf->size < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) {
94 : /* can't check non-SMB2 messages */
95 0 : return NT_STATUS_OK;
96 : }
97 :
98 410115 : hdr_offset = buf->hdr - buf->buffer;
99 :
100 410115 : session_id = BVAL(buf->hdr, SMB2_HDR_SESSION_ID);
101 410115 : if (session_id == 0) {
102 : /* don't sign messages with a zero session_id. See
103 : MS-SMB2 3.2.4.1.1 */
104 0 : return NT_STATUS_OK;
105 : }
106 :
107 410115 : if (session_key.length == 0) {
108 : /* we don't have the session key yet */
109 0 : return NT_STATUS_OK;
110 : }
111 :
112 410115 : memcpy(sig, buf->hdr+SMB2_HDR_SIGNATURE, 16);
113 :
114 410115 : memset(buf->hdr + SMB2_HDR_SIGNATURE, 0, 16);
115 :
116 410115 : rc = gnutls_hmac_fast(GNUTLS_MAC_SHA256,
117 410115 : session_key.data,
118 410115 : MIN(session_key.length, 16),
119 410115 : buf->hdr,
120 410115 : buf->size - hdr_offset,
121 : digest);
122 410115 : if (rc < 0) {
123 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
124 : }
125 :
126 410115 : memcpy(buf->hdr + SMB2_HDR_SIGNATURE, digest, 16);
127 :
128 410115 : if (!mem_equal_const_time(digest, sig, 16)) {
129 0 : DEBUG(0,("Bad SMB2 signature for message of size %u\n",
130 : (unsigned)buf->size-NBT_HDR_SIZE));
131 0 : dump_data(0, sig, 16);
132 0 : dump_data(0, digest, 16);
133 0 : ZERO_ARRAY(digest);
134 0 : return NT_STATUS_ACCESS_DENIED;
135 : }
136 410115 : ZERO_ARRAY(digest);
137 :
138 410115 : return NT_STATUS_OK;
139 : }
|