ntlmssp: Add ntlmssp_blob_matches_magic()
[amitay/samba.git] / source3 / smbd / smb2_signing.c
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/smbd.h"
23 #include "smbd/globals.h"
24 #include "../libcli/smb/smb_common.h"
25 #include "../lib/crypto/crypto.h"
26
27 NTSTATUS smb2_signing_sign_pdu(DATA_BLOB session_key,
28                                struct iovec *vector,
29                                int count)
30 {
31         uint8_t *hdr;
32         uint64_t session_id;
33         struct HMACSHA256Context m;
34         uint8_t res[SHA256_DIGEST_LENGTH];
35         int i;
36
37         if (count < 2) {
38                 return NT_STATUS_INVALID_PARAMETER;
39         }
40
41         if (vector[0].iov_len != SMB2_HDR_BODY) {
42                 return NT_STATUS_INVALID_PARAMETER;
43         }
44
45         hdr = (uint8_t *)vector[0].iov_base;
46
47         session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
48         if (session_id == 0) {
49                 /*
50                  * do not sign messages with a zero session_id.
51                  * See MS-SMB2 3.2.4.1.1
52                  */
53                 return NT_STATUS_OK;
54         }
55
56         if (session_key.length == 0) {
57                 DEBUG(2,("Wrong session key length %u for SMB2 signing\n",
58                          (unsigned)session_key.length));
59                 return NT_STATUS_ACCESS_DENIED;
60         }
61
62         memset(hdr + SMB2_HDR_SIGNATURE, 0, 16);
63
64         SIVAL(hdr, SMB2_HDR_FLAGS, IVAL(hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
65
66         ZERO_STRUCT(m);
67         hmac_sha256_init(session_key.data, MIN(session_key.length, 16), &m);
68         for (i=0; i < count; i++) {
69                 hmac_sha256_update((const uint8_t *)vector[i].iov_base,
70                                    vector[i].iov_len, &m);
71         }
72         hmac_sha256_final(res, &m);
73         DEBUG(5,("signed SMB2 message\n"));
74
75         memcpy(hdr + SMB2_HDR_SIGNATURE, res, 16);
76
77         return NT_STATUS_OK;
78 }
79
80 NTSTATUS smb2_signing_check_pdu(DATA_BLOB session_key,
81                                 const struct iovec *vector,
82                                 int count)
83 {
84         const uint8_t *hdr;
85         const uint8_t *sig;
86         uint64_t session_id;
87         struct HMACSHA256Context m;
88         uint8_t res[SHA256_DIGEST_LENGTH];
89         static const uint8_t zero_sig[16] = { 0, };
90         int i;
91
92         if (count < 2) {
93                 return NT_STATUS_INVALID_PARAMETER;
94         }
95
96         if (vector[0].iov_len != SMB2_HDR_BODY) {
97                 return NT_STATUS_INVALID_PARAMETER;
98         }
99
100         hdr = (const uint8_t *)vector[0].iov_base;
101
102         session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
103         if (session_id == 0) {
104                 /*
105                  * do not sign messages with a zero session_id.
106                  * See MS-SMB2 3.2.4.1.1
107                  */
108                 return NT_STATUS_OK;
109         }
110
111         if (session_key.length == 0) {
112                 /* we don't have the session key yet */
113                 return NT_STATUS_OK;
114         }
115
116         sig = hdr+SMB2_HDR_SIGNATURE;
117
118         ZERO_STRUCT(m);
119         hmac_sha256_init(session_key.data, MIN(session_key.length, 16), &m);
120         hmac_sha256_update(hdr, SMB2_HDR_SIGNATURE, &m);
121         hmac_sha256_update(zero_sig, 16, &m);
122         for (i=1; i < count; i++) {
123                 hmac_sha256_update((const uint8_t *)vector[i].iov_base,
124                                    vector[i].iov_len, &m);
125         }
126         hmac_sha256_final(res, &m);
127
128         if (memcmp(res, sig, 16) != 0) {
129                 DEBUG(0,("Bad SMB2 signature for message\n"));
130                 dump_data(0, sig, 16);
131                 dump_data(0, res, 16);
132                 return NT_STATUS_ACCESS_DENIED;
133         }
134
135         return NT_STATUS_OK;
136 }