s3:smb2_ioctl: Fix Coverity ID 701771 Uninitialized scalar variable
[samba.git] / source3 / smbd / signing.c
1 /*
2    Unix SMB/CIFS implementation.
3    SMB Signing Code
4    Copyright (C) Jeremy Allison 2003.
5    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
6    Copyright (C) Stefan Metzmacher 2009
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 "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_signing.h"
26
27 /***********************************************************
28  Called to validate an incoming packet from the client.
29 ************************************************************/
30
31 bool srv_check_sign_mac(struct smbd_server_connection *conn,
32                         const char *inbuf, uint32_t *seqnum,
33                         bool trusted_channel)
34 {
35         /* Check if it's a non-session message. */
36         if(CVAL(inbuf,0)) {
37                 return true;
38         }
39
40         if (trusted_channel) {
41                 NTSTATUS status;
42
43                 if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
44                         DEBUG(1,("smb_signing_check_pdu: Can't check signature "
45                                  "on short packet! smb_len = %u\n",
46                                  smb_len(inbuf)));
47                         return false;
48                 }
49
50                 status = NT_STATUS(IVAL(inbuf, smb_ss_field + 4));
51                 if (!NT_STATUS_IS_OK(status)) {
52                         DEBUG(1,("smb_signing_check_pdu: trusted channel passed %s\n",
53                                  nt_errstr(status)));
54                         return false;
55                 }
56
57                 *seqnum = IVAL(inbuf, smb_ss_field);
58                 return true;
59         }
60
61         *seqnum = smb_signing_next_seqnum(conn->smb1.signing_state, false);
62         return smb_signing_check_pdu(conn->smb1.signing_state,
63                                      (const uint8_t *)inbuf,
64                                      *seqnum);
65 }
66
67 /***********************************************************
68  Called to sign an outgoing packet to the client.
69 ************************************************************/
70
71 void srv_calculate_sign_mac(struct smbd_server_connection *conn,
72                             char *outbuf, uint32_t seqnum)
73 {
74         /* Check if it's a non-session message. */
75         if(CVAL(outbuf,0)) {
76                 return;
77         }
78
79         smb_signing_sign_pdu(conn->smb1.signing_state, (uint8_t *)outbuf, seqnum);
80 }
81
82
83 /***********************************************************
84  Called to indicate a oneway request
85 ************************************************************/
86 void srv_cancel_sign_response(struct smbd_server_connection *conn)
87 {
88         smb_signing_cancel_reply(conn->smb1.signing_state, true);
89 }
90
91 struct smbd_shm_signing {
92         size_t shm_size;
93         uint8_t *shm_pointer;
94
95         /* we know the signing engine will only allocate 2 chunks */
96         uint8_t *ptr1;
97         size_t len1;
98         uint8_t *ptr2;
99         size_t len2;
100 };
101
102 static int smbd_shm_signing_destructor(struct smbd_shm_signing *s)
103 {
104         anonymous_shared_free(s->shm_pointer);
105         return 0;
106 }
107
108 static void *smbd_shm_signing_alloc(TALLOC_CTX *mem_ctx, size_t len)
109 {
110         struct smbd_shm_signing *s = talloc_get_type_abort(mem_ctx,
111                                      struct smbd_shm_signing);
112
113         if (s->ptr1 == NULL) {
114                 s->len1 = len;
115                 if (len % 8) {
116                         s->len1 += (8 - (len % 8));
117                 }
118                 if (s->len1 > s->shm_size) {
119                         s->len1 = 0;
120                         errno = ENOMEM;
121                         return NULL;
122                 }
123                 s->ptr1 = s->shm_pointer;
124                 return s->ptr1;
125         }
126
127         if (s->ptr2 == NULL) {
128                 s->len2 = len;
129                 if (s->len2 > (s->shm_size - s->len1)) {
130                         s->len2 = 0;
131                         errno = ENOMEM;
132                         return NULL;
133                 }
134                 s->ptr2 = s->shm_pointer + s->len1;
135                 return s->ptr2;
136         }
137
138         errno = ENOMEM;
139         return NULL;
140 }
141
142 static void smbd_shm_signing_free(TALLOC_CTX *mem_ctx, void *ptr)
143 {
144         struct smbd_shm_signing *s = talloc_get_type_abort(mem_ctx,
145                                      struct smbd_shm_signing);
146
147         if (s->ptr2 == ptr) {
148                 s->ptr2 = NULL;
149                 s->len2 = 0;
150         }
151 }
152
153 /***********************************************************
154  Called by server negprot when signing has been negotiated.
155 ************************************************************/
156
157 bool srv_init_signing(struct smbd_server_connection *conn)
158 {
159         bool allowed = true;
160         bool desired;
161         bool mandatory = false;
162
163         switch (lp_server_signing()) {
164         case SMB_SIGNING_REQUIRED:
165                 mandatory = true;
166                 break;
167         case SMB_SIGNING_IF_REQUIRED:
168                 break;
169         case SMB_SIGNING_DEFAULT:
170         case SMB_SIGNING_OFF:
171                 allowed = false;
172                 break;
173         }
174
175         /*
176          * if the client and server allow signing,
177          * we desire to use it.
178          *
179          * This matches Windows behavior and is needed
180          * because not every client that requires signing
181          * sends FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED.
182          */
183         desired = allowed;
184
185         if (lp_async_smb_echo_handler()) {
186                 struct smbd_shm_signing *s;
187
188                 /* setup the signing state in shared memory */
189                 s = talloc_zero(server_event_context(), struct smbd_shm_signing);
190                 if (s == NULL) {
191                         return false;
192                 }
193                 s->shm_size = 4096;
194                 s->shm_pointer =
195                         (uint8_t *)anonymous_shared_allocate(s->shm_size);
196                 if (s->shm_pointer == NULL) {
197                         talloc_free(s);
198                         return false;
199                 }
200                 talloc_set_destructor(s, smbd_shm_signing_destructor);
201                 conn->smb1.signing_state = smb_signing_init_ex(s,
202                                                         allowed, desired, mandatory,
203                                                         smbd_shm_signing_alloc,
204                                                         smbd_shm_signing_free);
205                 if (!conn->smb1.signing_state) {
206                         return false;
207                 }
208                 return true;
209         }
210
211         conn->smb1.signing_state = smb_signing_init(server_event_context(),
212                                                     allowed, desired, mandatory);
213         if (!conn->smb1.signing_state) {
214                 return false;
215         }
216
217         return true;
218 }
219
220 void srv_set_signing_negotiated(struct smbd_server_connection *conn,
221                                 bool allowed, bool mandatory)
222 {
223         smb_signing_set_negotiated(conn->smb1.signing_state,
224                                    allowed, mandatory);
225 }
226
227 /***********************************************************
228  Returns whether signing is active. We can't use sendfile or raw
229  reads/writes if it is.
230 ************************************************************/
231
232 bool srv_is_signing_active(struct smbd_server_connection *conn)
233 {
234         return smb_signing_is_active(conn->smb1.signing_state);
235 }
236
237
238 /***********************************************************
239  Returns whether signing is negotiated. We can't use it unless it was
240  in the negprot.
241 ************************************************************/
242
243 bool srv_is_signing_negotiated(struct smbd_server_connection *conn)
244 {
245         return smb_signing_is_negotiated(conn->smb1.signing_state);
246 }
247
248 /***********************************************************
249  Turn on signing from this packet onwards.
250 ************************************************************/
251
252 void srv_set_signing(struct smbd_server_connection *conn,
253                      const DATA_BLOB user_session_key,
254                      const DATA_BLOB response)
255 {
256         bool negotiated;
257         bool mandatory;
258
259         if (!user_session_key.length)
260                 return;
261
262         negotiated = smb_signing_is_negotiated(conn->smb1.signing_state);
263         mandatory = smb_signing_is_mandatory(conn->smb1.signing_state);
264
265         if (!negotiated && !mandatory) {
266                 DEBUG(5,("srv_set_signing: signing negotiated = %u, "
267                          "mandatory_signing = %u. Not allowing smb signing.\n",
268                          negotiated, mandatory));
269                 return;
270         }
271
272         if (!smb_signing_activate(conn->smb1.signing_state,
273                                   user_session_key, response)) {
274                 return;
275         }
276
277         DEBUG(3,("srv_set_signing: turning on SMB signing: "
278                  "signing negotiated = %u, mandatory_signing = %u.\n",
279                  negotiated, mandatory));
280 }
281