smbd: Fix clients connecting unencrypted with PROTOCOL_SMB2_24 or higher.
[samba.git] / source3 / smbd / smb2_sesssetup.c
1 /*
2    Unix SMB/CIFS implementation.
3    Core SMB2 server
4
5    Copyright (C) Stefan Metzmacher 2009
6    Copyright (C) Jeremy Allison 2010
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_common.h"
26 #include "../auth/gensec/gensec.h"
27 #include "auth.h"
28 #include "../lib/tsocket/tsocket.h"
29 #include "../libcli/security/security.h"
30 #include "../lib/util/tevent_ntstatus.h"
31 #include "lib/crypto/sha512.h"
32 #include "lib/crypto/aes.h"
33 #include "lib/crypto/aes_ccm_128.h"
34 #include "lib/crypto/aes_gcm_128.h"
35
36 static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
37                                         struct tevent_context *ev,
38                                         struct smbd_smb2_request *smb2req,
39                                         uint64_t in_session_id,
40                                         uint8_t in_flags,
41                                         uint8_t in_security_mode,
42                                         uint64_t in_previous_session_id,
43                                         DATA_BLOB in_security_buffer);
44 static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
45                                         uint16_t *out_session_flags,
46                                         TALLOC_CTX *mem_ctx,
47                                         DATA_BLOB *out_security_buffer,
48                                         uint64_t *out_session_id);
49
50 static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq);
51
52 NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *smb2req)
53 {
54         const uint8_t *inhdr;
55         const uint8_t *inbody;
56         uint64_t in_session_id;
57         uint8_t in_flags;
58         uint8_t in_security_mode;
59         uint64_t in_previous_session_id;
60         uint16_t in_security_offset;
61         uint16_t in_security_length;
62         DATA_BLOB in_security_buffer;
63         NTSTATUS status;
64         struct tevent_req *subreq;
65
66         status = smbd_smb2_request_verify_sizes(smb2req, 0x19);
67         if (!NT_STATUS_IS_OK(status)) {
68                 return smbd_smb2_request_error(smb2req, status);
69         }
70         inhdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
71         inbody = SMBD_SMB2_IN_BODY_PTR(smb2req);
72
73         in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
74
75         in_flags = CVAL(inbody, 0x02);
76         in_security_mode = CVAL(inbody, 0x03);
77         /* Capabilities = IVAL(inbody, 0x04) */
78         /* Channel = IVAL(inbody, 0x08) */
79         in_security_offset = SVAL(inbody, 0x0C);
80         in_security_length = SVAL(inbody, 0x0E);
81         in_previous_session_id = BVAL(inbody, 0x10);
82
83         if (in_security_offset != (SMB2_HDR_BODY + SMBD_SMB2_IN_BODY_LEN(smb2req))) {
84                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
85         }
86
87         if (in_security_length > SMBD_SMB2_IN_DYN_LEN(smb2req)) {
88                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
89         }
90
91         in_security_buffer.data = SMBD_SMB2_IN_DYN_PTR(smb2req);
92         in_security_buffer.length = in_security_length;
93
94         subreq = smbd_smb2_session_setup_wrap_send(smb2req,
95                                                    smb2req->sconn->ev_ctx,
96                                                    smb2req,
97                                                    in_session_id,
98                                                    in_flags,
99                                                    in_security_mode,
100                                                    in_previous_session_id,
101                                                    in_security_buffer);
102         if (subreq == NULL) {
103                 return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
104         }
105         tevent_req_set_callback(subreq, smbd_smb2_request_sesssetup_done, smb2req);
106
107         return smbd_smb2_request_pending_queue(smb2req, subreq, 500);
108 }
109
110 static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq)
111 {
112         struct smbd_smb2_request *smb2req =
113                 tevent_req_callback_data(subreq,
114                 struct smbd_smb2_request);
115         uint8_t *outhdr;
116         DATA_BLOB outbody;
117         DATA_BLOB outdyn;
118         uint16_t out_session_flags = 0;
119         uint64_t out_session_id = 0;
120         uint16_t out_security_offset;
121         DATA_BLOB out_security_buffer = data_blob_null;
122         NTSTATUS status;
123         NTSTATUS error; /* transport error */
124
125         status = smbd_smb2_session_setup_wrap_recv(subreq,
126                                                    &out_session_flags,
127                                                    smb2req,
128                                                    &out_security_buffer,
129                                                    &out_session_id);
130         TALLOC_FREE(subreq);
131         if (!NT_STATUS_IS_OK(status) &&
132             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
133                 status = nt_status_squash(status);
134                 error = smbd_smb2_request_error(smb2req, status);
135                 if (!NT_STATUS_IS_OK(error)) {
136                         smbd_server_connection_terminate(smb2req->xconn,
137                                                          nt_errstr(error));
138                         return;
139                 }
140                 return;
141         }
142
143         out_security_offset = SMB2_HDR_BODY + 0x08;
144
145         outhdr = SMBD_SMB2_OUT_HDR_PTR(smb2req);
146
147         outbody = smbd_smb2_generate_outbody(smb2req, 0x08);
148         if (outbody.data == NULL) {
149                 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
150                 if (!NT_STATUS_IS_OK(error)) {
151                         smbd_server_connection_terminate(smb2req->xconn,
152                                                          nt_errstr(error));
153                         return;
154                 }
155                 return;
156         }
157
158         SBVAL(outhdr, SMB2_HDR_SESSION_ID, out_session_id);
159
160         SSVAL(outbody.data, 0x00, 0x08 + 1);    /* struct size */
161         SSVAL(outbody.data, 0x02,
162               out_session_flags);               /* session flags */
163         SSVAL(outbody.data, 0x04,
164               out_security_offset);             /* security buffer offset */
165         SSVAL(outbody.data, 0x06,
166               out_security_buffer.length);      /* security buffer length */
167
168         outdyn = out_security_buffer;
169
170         error = smbd_smb2_request_done_ex(smb2req, status, outbody, &outdyn,
171                                            __location__);
172         if (!NT_STATUS_IS_OK(error)) {
173                 smbd_server_connection_terminate(smb2req->xconn,
174                                                  nt_errstr(error));
175                 return;
176         }
177 }
178
179 static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
180                                         struct smbd_smb2_request *smb2req,
181                                         uint8_t in_security_mode,
182                                         struct auth_session_info *session_info,
183                                         uint16_t *out_session_flags,
184                                         uint64_t *out_session_id)
185 {
186         NTSTATUS status;
187         bool guest = false;
188         uint8_t session_key[16];
189         struct smbXsrv_session *x = session;
190         struct smbXsrv_connection *xconn = smb2req->xconn;
191         struct _derivation {
192                 DATA_BLOB label;
193                 DATA_BLOB context;
194         };
195         struct {
196                 struct _derivation signing;
197                 struct _derivation encryption;
198                 struct _derivation decryption;
199                 struct _derivation application;
200         } derivation = { };
201
202         if (xconn->protocol >= PROTOCOL_SMB3_10) {
203                 struct smbXsrv_preauth *preauth;
204                 struct _derivation *d;
205                 DATA_BLOB p;
206                 struct hc_sha512state sctx;
207                 size_t i;
208
209                 preauth = talloc_move(smb2req, &session->preauth);
210
211                 samba_SHA512_Init(&sctx);
212                 samba_SHA512_Update(&sctx, preauth->sha512_value,
213                                     sizeof(preauth->sha512_value));
214                 for (i = 1; i < smb2req->in.vector_count; i++) {
215                         samba_SHA512_Update(&sctx,
216                                             smb2req->in.vector[i].iov_base,
217                                             smb2req->in.vector[i].iov_len);
218                 }
219                 samba_SHA512_Final(preauth->sha512_value, &sctx);
220
221                 p = data_blob_const(preauth->sha512_value,
222                                     sizeof(preauth->sha512_value));
223
224                 d = &derivation.signing;
225                 d->label = data_blob_string_const_null("SMBSigningKey");
226                 d->context = p;
227
228                 d = &derivation.decryption;
229                 d->label = data_blob_string_const_null("SMBC2SCipherKey");
230                 d->context = p;
231
232                 d = &derivation.encryption;
233                 d->label = data_blob_string_const_null("SMBS2CCipherKey");
234                 d->context = p;
235
236                 d = &derivation.application;
237                 d->label = data_blob_string_const_null("SMBAppKey");
238                 d->context = p;
239
240         } else if (xconn->protocol >= PROTOCOL_SMB2_24) {
241                 struct _derivation *d;
242
243                 d = &derivation.signing;
244                 d->label = data_blob_string_const_null("SMB2AESCMAC");
245                 d->context = data_blob_string_const_null("SmbSign");
246
247                 d = &derivation.decryption;
248                 d->label = data_blob_string_const_null("SMB2AESCCM");
249                 d->context = data_blob_string_const_null("ServerIn ");
250
251                 d = &derivation.encryption;
252                 d->label = data_blob_string_const_null("SMB2AESCCM");
253                 d->context = data_blob_string_const_null("ServerOut");
254
255                 d = &derivation.application;
256                 d->label = data_blob_string_const_null("SMB2APP");
257                 d->context = data_blob_string_const_null("SmbRpc");
258         }
259
260         if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
261             lp_server_signing() == SMB_SIGNING_REQUIRED) {
262                 x->global->signing_required = true;
263         }
264
265         if ((lp_smb_encrypt(-1) > SMB_SIGNING_OFF) &&
266             (xconn->smb2.client.capabilities & SMB2_CAP_ENCRYPTION)) {
267                 x->global->encryption_required = true;
268         }
269
270         if (lp_smb_encrypt(-1) == SMB_SIGNING_REQUIRED) {
271                 x->global->encryption_required = true;
272         }
273
274         if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
275                 /* we map anonymous to guest internally */
276                 *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
277                 *out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
278                 /* force no signing */
279                 x->global->signing_required = false;
280                 guest = true;
281         }
282
283         if (guest && x->global->encryption_required) {
284                 DEBUG(1,("reject guest session as encryption is required\n"));
285                 return NT_STATUS_ACCESS_DENIED;
286         }
287
288         if (xconn->smb2.server.cipher == 0) {
289                 if (x->global->encryption_required) {
290                         DEBUG(1,("reject session with dialect[0x%04X] "
291                                  "as encryption is required\n",
292                                  xconn->smb2.server.dialect));
293                         return NT_STATUS_ACCESS_DENIED;
294                 }
295         }
296
297         if (x->global->encryption_required) {
298                 *out_session_flags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
299         }
300
301         ZERO_STRUCT(session_key);
302         memcpy(session_key, session_info->session_key.data,
303                MIN(session_info->session_key.length, sizeof(session_key)));
304
305         x->global->signing_key = data_blob_talloc(x->global,
306                                                   session_key,
307                                                   sizeof(session_key));
308         if (x->global->signing_key.data == NULL) {
309                 ZERO_STRUCT(session_key);
310                 return NT_STATUS_NO_MEMORY;
311         }
312
313         if (xconn->protocol >= PROTOCOL_SMB2_24) {
314                 struct _derivation *d = &derivation.signing;
315
316                 smb2_key_derivation(session_key, sizeof(session_key),
317                                     d->label.data, d->label.length,
318                                     d->context.data, d->context.length,
319                                     x->global->signing_key.data);
320         }
321
322         if (xconn->protocol >= PROTOCOL_SMB2_24) {
323                 struct _derivation *d = &derivation.decryption;
324
325                 x->global->decryption_key = data_blob_talloc(x->global,
326                                                              session_key,
327                                                              sizeof(session_key));
328                 if (x->global->decryption_key.data == NULL) {
329                         ZERO_STRUCT(session_key);
330                         return NT_STATUS_NO_MEMORY;
331                 }
332
333                 smb2_key_derivation(session_key, sizeof(session_key),
334                                     d->label.data, d->label.length,
335                                     d->context.data, d->context.length,
336                                     x->global->decryption_key.data);
337         }
338
339         if (xconn->protocol >= PROTOCOL_SMB2_24) {
340                 struct _derivation *d = &derivation.encryption;
341                 size_t nonce_size;
342
343                 x->global->encryption_key = data_blob_talloc(x->global,
344                                                              session_key,
345                                                              sizeof(session_key));
346                 if (x->global->encryption_key.data == NULL) {
347                         ZERO_STRUCT(session_key);
348                         return NT_STATUS_NO_MEMORY;
349                 }
350
351                 smb2_key_derivation(session_key, sizeof(session_key),
352                                     d->label.data, d->label.length,
353                                     d->context.data, d->context.length,
354                                     x->global->encryption_key.data);
355
356                 /*
357                  * CCM and GCM algorithms must never have their
358                  * nonce wrap, or the security of the whole
359                  * communication and the keys is destroyed.
360                  * We must drop the connection once we have
361                  * transfered too much data.
362                  *
363                  * NOTE: We assume nonces greater than 8 bytes.
364                  */
365                 generate_random_buffer((uint8_t *)&x->nonce_high_random,
366                                        sizeof(x->nonce_high_random));
367                 switch (xconn->smb2.server.cipher) {
368                 case SMB2_ENCRYPTION_AES128_CCM:
369                         nonce_size = AES_CCM_128_NONCE_SIZE;
370                         break;
371                 case SMB2_ENCRYPTION_AES128_GCM:
372                         nonce_size = AES_GCM_128_IV_SIZE;
373                         break;
374                 default:
375                         nonce_size = 0;
376                         break;
377                 }
378                 x->nonce_high_max = SMB2_NONCE_HIGH_MAX(nonce_size);
379                 x->nonce_high = 0;
380                 x->nonce_low = 0;
381         }
382
383         x->global->application_key = data_blob_dup_talloc(x->global,
384                                                 x->global->signing_key);
385         if (x->global->application_key.data == NULL) {
386                 ZERO_STRUCT(session_key);
387                 return NT_STATUS_NO_MEMORY;
388         }
389
390         if (xconn->protocol >= PROTOCOL_SMB2_24) {
391                 struct _derivation *d = &derivation.application;
392
393                 smb2_key_derivation(session_key, sizeof(session_key),
394                                     d->label.data, d->label.length,
395                                     d->context.data, d->context.length,
396                                     x->global->application_key.data);
397         }
398         ZERO_STRUCT(session_key);
399
400         x->global->channels[0].signing_key = data_blob_dup_talloc(x->global->channels,
401                                                 x->global->signing_key);
402         if (x->global->channels[0].signing_key.data == NULL) {
403                 return NT_STATUS_NO_MEMORY;
404         }
405
406         data_blob_clear_free(&session_info->session_key);
407         session_info->session_key = data_blob_dup_talloc(session_info,
408                                                 x->global->application_key);
409         if (session_info->session_key.data == NULL) {
410                 return NT_STATUS_NO_MEMORY;
411         }
412
413         session->compat = talloc_zero(session, struct user_struct);
414         if (session->compat == NULL) {
415                 return NT_STATUS_NO_MEMORY;
416         }
417         session->compat->session = session;
418         session->compat->homes_snum = -1;
419         session->compat->session_info = session_info;
420         session->compat->session_keystr = NULL;
421         session->compat->vuid = session->global->session_wire_id;
422         DLIST_ADD(smb2req->sconn->users, session->compat);
423         smb2req->sconn->num_users++;
424
425         if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
426                 session->compat->homes_snum =
427                         register_homes_share(session_info->unix_info->unix_name);
428         }
429
430         set_current_user_info(session_info->unix_info->sanitized_username,
431                               session_info->unix_info->unix_name,
432                               session_info->info->domain_name);
433
434         reload_services(smb2req->sconn, conn_snum_used, true);
435
436         session->status = NT_STATUS_OK;
437         session->global->auth_session_info = session_info;
438         session->global->auth_session_info_seqnum += 1;
439         session->global->channels[0].auth_session_info_seqnum =
440                 session->global->auth_session_info_seqnum;
441         session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
442         session->global->expiration_time = gensec_expire_time(session->gensec);
443
444         if (!session_claim(session)) {
445                 DEBUG(1, ("smb2: Failed to claim session "
446                         "for vuid=%llu\n",
447                         (unsigned long long)session->compat->vuid));
448                 return NT_STATUS_LOGON_FAILURE;
449         }
450
451         status = smbXsrv_session_update(session);
452         if (!NT_STATUS_IS_OK(status)) {
453                 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
454                           (unsigned long long)session->compat->vuid,
455                           nt_errstr(status)));
456                 return NT_STATUS_LOGON_FAILURE;
457         }
458
459         /*
460          * we attach the session to the request
461          * so that the response can be signed
462          */
463         if (!guest) {
464                 smb2req->do_signing = true;
465         }
466
467         global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
468
469         *out_session_id = session->global->session_wire_id;
470
471         return NT_STATUS_OK;
472 }
473
474 static NTSTATUS smbd_smb2_reauth_generic_return(struct smbXsrv_session *session,
475                                         struct smbd_smb2_request *smb2req,
476                                         struct auth_session_info *session_info,
477                                         uint16_t *out_session_flags,
478                                         uint64_t *out_session_id)
479 {
480         NTSTATUS status;
481         struct smbXsrv_session *x = session;
482
483         data_blob_clear_free(&session_info->session_key);
484         session_info->session_key = data_blob_dup_talloc(session_info,
485                                                 x->global->application_key);
486         if (session_info->session_key.data == NULL) {
487                 return NT_STATUS_NO_MEMORY;
488         }
489
490         session->compat->session_info = session_info;
491         session->compat->vuid = session->global->session_wire_id;
492
493         session->compat->homes_snum =
494                         register_homes_share(session_info->unix_info->unix_name);
495
496         set_current_user_info(session_info->unix_info->sanitized_username,
497                               session_info->unix_info->unix_name,
498                               session_info->info->domain_name);
499
500         reload_services(smb2req->sconn, conn_snum_used, true);
501
502         session->status = NT_STATUS_OK;
503         TALLOC_FREE(session->global->auth_session_info);
504         session->global->auth_session_info = session_info;
505         session->global->auth_session_info_seqnum += 1;
506         session->global->channels[0].auth_session_info_seqnum =
507                 session->global->auth_session_info_seqnum;
508         session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
509         session->global->expiration_time = gensec_expire_time(session->gensec);
510
511         status = smbXsrv_session_update(session);
512         if (!NT_STATUS_IS_OK(status)) {
513                 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
514                           (unsigned long long)session->compat->vuid,
515                           nt_errstr(status)));
516                 return NT_STATUS_LOGON_FAILURE;
517         }
518
519         conn_clear_vuid_caches(smb2req->sconn, session->compat->vuid);
520
521         if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
522                 smb2req->do_signing = true;
523         }
524
525         *out_session_id = session->global->session_wire_id;
526
527         return NT_STATUS_OK;
528 }
529
530 struct smbd_smb2_session_setup_state {
531         struct tevent_context *ev;
532         struct smbd_smb2_request *smb2req;
533         uint64_t in_session_id;
534         uint8_t in_flags;
535         uint8_t in_security_mode;
536         uint64_t in_previous_session_id;
537         DATA_BLOB in_security_buffer;
538         struct smbXsrv_session *session;
539         struct auth_session_info *session_info;
540         uint16_t out_session_flags;
541         DATA_BLOB out_security_buffer;
542         uint64_t out_session_id;
543 };
544
545 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq);
546 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq);
547 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req);
548
549 static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
550                                         struct tevent_context *ev,
551                                         struct smbd_smb2_request *smb2req,
552                                         uint64_t in_session_id,
553                                         uint8_t in_flags,
554                                         uint8_t in_security_mode,
555                                         uint64_t in_previous_session_id,
556                                         DATA_BLOB in_security_buffer)
557 {
558         struct tevent_req *req;
559         struct smbd_smb2_session_setup_state *state;
560         NTSTATUS status;
561         NTTIME now = timeval_to_nttime(&smb2req->request_time);
562         struct tevent_req *subreq;
563
564         req = tevent_req_create(mem_ctx, &state,
565                                 struct smbd_smb2_session_setup_state);
566         if (req == NULL) {
567                 return NULL;
568         }
569         state->ev = ev;
570         state->smb2req = smb2req;
571         state->in_session_id = in_session_id;
572         state->in_flags = in_flags;
573         state->in_security_mode = in_security_mode;
574         state->in_previous_session_id = in_previous_session_id;
575         state->in_security_buffer = in_security_buffer;
576
577         if (in_flags & SMB2_SESSION_FLAG_BINDING) {
578                 if (smb2req->xconn->protocol < PROTOCOL_SMB2_22) {
579                         tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
580                         return tevent_req_post(req, ev);
581                 }
582
583                 /*
584                  * We do not support multi channel.
585                  */
586                 tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
587                 return tevent_req_post(req, ev);
588         }
589
590         if (state->in_session_id == 0) {
591                 /* create a new session */
592                 status = smbXsrv_session_create(state->smb2req->xconn,
593                                                 now, &state->session);
594                 if (tevent_req_nterror(req, status)) {
595                         return tevent_req_post(req, ev);
596                 }
597                 smb2req->session = state->session;
598         } else {
599                 if (smb2req->session == NULL) {
600                         tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
601                         return tevent_req_post(req, ev);
602                 }
603
604                 state->session = smb2req->session;
605                 status = state->session->status;
606                 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
607                         status = NT_STATUS_OK;
608                 }
609                 if (NT_STATUS_IS_OK(status)) {
610                         state->session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
611                         status = NT_STATUS_MORE_PROCESSING_REQUIRED;
612                         TALLOC_FREE(state->session->gensec);
613                 }
614                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
615                         tevent_req_nterror(req, status);
616                         return tevent_req_post(req, ev);
617                 }
618         }
619
620         if (state->session->gensec == NULL) {
621                 status = auth_generic_prepare(state->session,
622                                               state->smb2req->xconn->remote_address,
623                                               &state->session->gensec);
624                 if (tevent_req_nterror(req, status)) {
625                         return tevent_req_post(req, ev);
626                 }
627
628                 gensec_want_feature(state->session->gensec, GENSEC_FEATURE_SESSION_KEY);
629                 gensec_want_feature(state->session->gensec, GENSEC_FEATURE_UNIX_TOKEN);
630
631                 status = gensec_start_mech_by_oid(state->session->gensec,
632                                                   GENSEC_OID_SPNEGO);
633                 if (tevent_req_nterror(req, status)) {
634                         return tevent_req_post(req, ev);
635                 }
636         }
637
638         become_root();
639         subreq = gensec_update_send(state, state->ev,
640                                     state->session->gensec,
641                                     state->in_security_buffer);
642         unbecome_root();
643         if (tevent_req_nomem(subreq, req)) {
644                 return tevent_req_post(req, ev);
645         }
646         tevent_req_set_callback(subreq, smbd_smb2_session_setup_gensec_done, req);
647
648         return req;
649 }
650
651 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
652 {
653         struct tevent_req *req =
654                 tevent_req_callback_data(subreq,
655                 struct tevent_req);
656         struct smbd_smb2_session_setup_state *state =
657                 tevent_req_data(req,
658                 struct smbd_smb2_session_setup_state);
659         NTSTATUS status;
660
661         become_root();
662         status = gensec_update_recv(subreq, state,
663                                     &state->out_security_buffer);
664         unbecome_root();
665         TALLOC_FREE(subreq);
666         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
667             !NT_STATUS_IS_OK(status)) {
668                 tevent_req_nterror(req, status);
669                 return;
670         }
671
672         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
673                 state->out_session_id = state->session->global->session_wire_id;
674                 state->smb2req->preauth = state->session->preauth;
675                 tevent_req_nterror(req, status);
676                 return;
677         }
678
679         status = gensec_session_info(state->session->gensec,
680                                      state->session->global,
681                                      &state->session_info);
682         if (tevent_req_nterror(req, status)) {
683                 return;
684         }
685
686         if ((state->in_previous_session_id != 0) &&
687              (state->session->global->session_wire_id !=
688               state->in_previous_session_id))
689         {
690                 subreq = smb2srv_session_close_previous_send(state, state->ev,
691                                                 state->smb2req->xconn,
692                                                 state->session_info,
693                                                 state->in_previous_session_id,
694                                                 state->session->global->session_wire_id);
695                 if (tevent_req_nomem(subreq, req)) {
696                         return;
697                 }
698                 tevent_req_set_callback(subreq,
699                                         smbd_smb2_session_setup_previous_done,
700                                         req);
701                 return;
702         }
703
704         smbd_smb2_session_setup_auth_return(req);
705 }
706
707 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq)
708 {
709         struct tevent_req *req =
710                 tevent_req_callback_data(subreq,
711                 struct tevent_req);
712         NTSTATUS status;
713
714         status = smb2srv_session_close_previous_recv(subreq);
715         TALLOC_FREE(subreq);
716         if (tevent_req_nterror(req, status)) {
717                 return;
718         }
719
720         smbd_smb2_session_setup_auth_return(req);
721 }
722
723 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req)
724 {
725         struct smbd_smb2_session_setup_state *state =
726                 tevent_req_data(req,
727                 struct smbd_smb2_session_setup_state);
728         NTSTATUS status;
729
730         if (state->session->global->auth_session_info != NULL) {
731                 status = smbd_smb2_reauth_generic_return(state->session,
732                                                          state->smb2req,
733                                                          state->session_info,
734                                                          &state->out_session_flags,
735                                                          &state->out_session_id);
736                 if (tevent_req_nterror(req, status)) {
737                         return;
738                 }
739                 tevent_req_done(req);
740                 return;
741         }
742
743         status = smbd_smb2_auth_generic_return(state->session,
744                                                state->smb2req,
745                                                state->in_security_mode,
746                                                state->session_info,
747                                                &state->out_session_flags,
748                                                &state->out_session_id);
749         if (tevent_req_nterror(req, status)) {
750                 return;
751         }
752
753         tevent_req_done(req);
754         return;
755 }
756
757 static NTSTATUS smbd_smb2_session_setup_recv(struct tevent_req *req,
758                                         uint16_t *out_session_flags,
759                                         TALLOC_CTX *mem_ctx,
760                                         DATA_BLOB *out_security_buffer,
761                                         uint64_t *out_session_id)
762 {
763         struct smbd_smb2_session_setup_state *state =
764                 tevent_req_data(req,
765                 struct smbd_smb2_session_setup_state);
766         NTSTATUS status;
767
768         if (tevent_req_is_nterror(req, &status)) {
769                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
770                         tevent_req_received(req);
771                         return nt_status_squash(status);
772                 }
773         } else {
774                 status = NT_STATUS_OK;
775         }
776
777         *out_session_flags = state->out_session_flags;
778         *out_security_buffer = state->out_security_buffer;
779         *out_session_id = state->out_session_id;
780
781         talloc_steal(mem_ctx, out_security_buffer->data);
782         tevent_req_received(req);
783         return status;
784 }
785
786 struct smbd_smb2_session_setup_wrap_state {
787         struct tevent_context *ev;
788         struct smbd_smb2_request *smb2req;
789         uint64_t in_session_id;
790         uint8_t in_flags;
791         uint8_t in_security_mode;
792         uint64_t in_previous_session_id;
793         DATA_BLOB in_security_buffer;
794         uint16_t out_session_flags;
795         DATA_BLOB out_security_buffer;
796         uint64_t out_session_id;
797         NTSTATUS error;
798 };
799
800 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq);
801 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq);
802
803 static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
804                                         struct tevent_context *ev,
805                                         struct smbd_smb2_request *smb2req,
806                                         uint64_t in_session_id,
807                                         uint8_t in_flags,
808                                         uint8_t in_security_mode,
809                                         uint64_t in_previous_session_id,
810                                         DATA_BLOB in_security_buffer)
811 {
812         struct tevent_req *req;
813         struct smbd_smb2_session_setup_wrap_state *state;
814         struct tevent_req *subreq;
815
816         req = tevent_req_create(mem_ctx, &state,
817                                 struct smbd_smb2_session_setup_wrap_state);
818         if (req == NULL) {
819                 return NULL;
820         }
821         state->ev = ev;
822         state->smb2req = smb2req;
823         state->in_session_id = in_session_id;
824         state->in_flags = in_flags;
825         state->in_security_mode = in_security_mode;
826         state->in_previous_session_id = in_previous_session_id;
827         state->in_security_buffer = in_security_buffer;
828
829         subreq = smbd_smb2_session_setup_send(state, state->ev,
830                                               state->smb2req,
831                                               state->in_session_id,
832                                               state->in_flags,
833                                               state->in_security_mode,
834                                               state->in_previous_session_id,
835                                               state->in_security_buffer);
836         if (tevent_req_nomem(subreq, req)) {
837                 return tevent_req_post(req, ev);
838         }
839         tevent_req_set_callback(subreq,
840                                 smbd_smb2_session_setup_wrap_setup_done, req);
841
842         return req;
843 }
844
845 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq)
846 {
847         struct tevent_req *req =
848                 tevent_req_callback_data(subreq,
849                 struct tevent_req);
850         struct smbd_smb2_session_setup_wrap_state *state =
851                 tevent_req_data(req,
852                 struct smbd_smb2_session_setup_wrap_state);
853         NTSTATUS status;
854
855         status = smbd_smb2_session_setup_recv(subreq,
856                                               &state->out_session_flags,
857                                               state,
858                                               &state->out_security_buffer,
859                                               &state->out_session_id);
860         TALLOC_FREE(subreq);
861         if (NT_STATUS_IS_OK(status)) {
862                 tevent_req_done(req);
863                 return;
864         }
865         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
866                 tevent_req_nterror(req, status);
867                 return;
868         }
869
870         if (state->smb2req->session == NULL) {
871                 tevent_req_nterror(req, status);
872                 return;
873         }
874
875         state->error = status;
876
877         subreq = smb2srv_session_shutdown_send(state, state->ev,
878                                                state->smb2req->session,
879                                                state->smb2req);
880         if (tevent_req_nomem(subreq, req)) {
881                 return;
882         }
883         tevent_req_set_callback(subreq,
884                                 smbd_smb2_session_setup_wrap_shutdown_done,
885                                 req);
886 }
887
888 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq)
889 {
890         struct tevent_req *req =
891                 tevent_req_callback_data(subreq,
892                 struct tevent_req);
893         struct smbd_smb2_session_setup_wrap_state *state =
894                 tevent_req_data(req,
895                 struct smbd_smb2_session_setup_wrap_state);
896         NTSTATUS status;
897
898         status = smb2srv_session_shutdown_recv(subreq);
899         TALLOC_FREE(subreq);
900         if (tevent_req_nterror(req, status)) {
901                 return;
902         }
903
904         /*
905          * we may need to sign the response, so we need to keep
906          * the session until the response is sent to the wire.
907          */
908         talloc_steal(state->smb2req, state->smb2req->session);
909
910         tevent_req_nterror(req, state->error);
911 }
912
913 static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
914                                         uint16_t *out_session_flags,
915                                         TALLOC_CTX *mem_ctx,
916                                         DATA_BLOB *out_security_buffer,
917                                         uint64_t *out_session_id)
918 {
919         struct smbd_smb2_session_setup_wrap_state *state =
920                 tevent_req_data(req,
921                 struct smbd_smb2_session_setup_wrap_state);
922         NTSTATUS status;
923
924         if (tevent_req_is_nterror(req, &status)) {
925                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
926                         tevent_req_received(req);
927                         return nt_status_squash(status);
928                 }
929         } else {
930                 status = NT_STATUS_OK;
931         }
932
933         *out_session_flags = state->out_session_flags;
934         *out_security_buffer = state->out_security_buffer;
935         *out_session_id = state->out_session_id;
936
937         talloc_steal(mem_ctx, out_security_buffer->data);
938         tevent_req_received(req);
939         return status;
940 }
941
942 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
943                                         struct tevent_context *ev,
944                                         struct smbd_smb2_request *smb2req);
945 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req);
946 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq);
947
948 NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req)
949 {
950         NTSTATUS status;
951         struct tevent_req *subreq = NULL;
952
953         status = smbd_smb2_request_verify_sizes(req, 0x04);
954         if (!NT_STATUS_IS_OK(status)) {
955                 return smbd_smb2_request_error(req, status);
956         }
957
958         subreq = smbd_smb2_logoff_send(req, req->sconn->ev_ctx, req);
959         if (subreq == NULL) {
960                 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
961         }
962         tevent_req_set_callback(subreq, smbd_smb2_request_logoff_done, req);
963
964         /*
965          * Wait a long time before going async on this to allow
966          * requests we're waiting on to finish. Set timeout to 10 secs.
967          */
968         return smbd_smb2_request_pending_queue(req, subreq, 10000000);
969 }
970
971 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq)
972 {
973         struct smbd_smb2_request *smb2req =
974                 tevent_req_callback_data(subreq,
975                 struct smbd_smb2_request);
976         DATA_BLOB outbody;
977         NTSTATUS status;
978         NTSTATUS error;
979
980         status = smbd_smb2_logoff_recv(subreq);
981         TALLOC_FREE(subreq);
982         if (!NT_STATUS_IS_OK(status)) {
983                 error = smbd_smb2_request_error(smb2req, status);
984                 if (!NT_STATUS_IS_OK(error)) {
985                         smbd_server_connection_terminate(smb2req->xconn,
986                                                         nt_errstr(error));
987                         return;
988                 }
989                 return;
990         }
991
992         outbody = smbd_smb2_generate_outbody(smb2req, 0x04);
993         if (outbody.data == NULL) {
994                 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
995                 if (!NT_STATUS_IS_OK(error)) {
996                         smbd_server_connection_terminate(smb2req->xconn,
997                                                         nt_errstr(error));
998                         return;
999                 }
1000                 return;
1001         }
1002
1003         SSVAL(outbody.data, 0x00, 0x04);        /* struct size */
1004         SSVAL(outbody.data, 0x02, 0);           /* reserved */
1005
1006         error = smbd_smb2_request_done(smb2req, outbody, NULL);
1007         if (!NT_STATUS_IS_OK(error)) {
1008                 smbd_server_connection_terminate(smb2req->xconn,
1009                                                 nt_errstr(error));
1010                 return;
1011         }
1012 }
1013
1014 struct smbd_smb2_logoff_state {
1015         struct smbd_smb2_request *smb2req;
1016 };
1017
1018 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq);
1019
1020 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
1021                                         struct tevent_context *ev,
1022                                         struct smbd_smb2_request *smb2req)
1023 {
1024         struct tevent_req *req;
1025         struct smbd_smb2_logoff_state *state;
1026         struct tevent_req *subreq;
1027
1028         req = tevent_req_create(mem_ctx, &state,
1029                         struct smbd_smb2_logoff_state);
1030         if (req == NULL) {
1031                 return NULL;
1032         }
1033         state->smb2req = smb2req;
1034
1035         subreq = smb2srv_session_shutdown_send(state, ev,
1036                                                smb2req->session,
1037                                                smb2req);
1038         if (tevent_req_nomem(subreq, req)) {
1039                 return tevent_req_post(req, ev);
1040         }
1041         tevent_req_set_callback(subreq, smbd_smb2_logoff_shutdown_done, req);
1042
1043         return req;
1044 }
1045
1046 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq)
1047 {
1048         struct tevent_req *req = tevent_req_callback_data(
1049                 subreq, struct tevent_req);
1050         struct smbd_smb2_logoff_state *state = tevent_req_data(
1051                 req, struct smbd_smb2_logoff_state);
1052         NTSTATUS status;
1053
1054         status = smb2srv_session_shutdown_recv(subreq);
1055         if (tevent_req_nterror(req, status)) {
1056                 return;
1057         }
1058         TALLOC_FREE(subreq);
1059
1060         /*
1061          * As we've been awoken, we may have changed
1062          * uid in the meantime. Ensure we're still
1063          * root (SMB2_OP_LOGOFF has .as_root = true).
1064          */
1065         change_to_root_user();
1066
1067         status = smbXsrv_session_logoff(state->smb2req->session);
1068         if (tevent_req_nterror(req, status)) {
1069                 return;
1070         }
1071
1072         /*
1073          * we may need to sign the response, so we need to keep
1074          * the session until the response is sent to the wire.
1075          */
1076         talloc_steal(state->smb2req, state->smb2req->session);
1077
1078         tevent_req_done(req);
1079 }
1080
1081 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req)
1082 {
1083         return tevent_req_simple_recv_ntstatus(req);
1084 }