auth: Log the transport connection for the authorization
[vlendec/samba-autobuild/.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 smbXsrv_session_auth0 **_auth,
181                                         struct smbd_smb2_request *smb2req,
182                                         uint8_t in_security_mode,
183                                         struct auth_session_info *session_info,
184                                         uint16_t *out_session_flags,
185                                         uint64_t *out_session_id)
186 {
187         NTSTATUS status;
188         bool guest = false;
189         uint8_t session_key[16];
190         struct smbXsrv_session *x = session;
191         struct smbXsrv_session_auth0 *auth = *_auth;
192         struct smbXsrv_connection *xconn = smb2req->xconn;
193         size_t i;
194         struct _derivation {
195                 DATA_BLOB label;
196                 DATA_BLOB context;
197         };
198         struct {
199                 struct _derivation signing;
200                 struct _derivation encryption;
201                 struct _derivation decryption;
202                 struct _derivation application;
203         } derivation = { };
204
205         *_auth = NULL;
206
207         if (xconn->protocol >= PROTOCOL_SMB3_10) {
208                 struct smbXsrv_preauth *preauth;
209                 struct _derivation *d;
210                 DATA_BLOB p;
211                 struct hc_sha512state sctx;
212
213                 preauth = talloc_move(smb2req, &auth->preauth);
214
215                 samba_SHA512_Init(&sctx);
216                 samba_SHA512_Update(&sctx, preauth->sha512_value,
217                                     sizeof(preauth->sha512_value));
218                 for (i = 1; i < smb2req->in.vector_count; i++) {
219                         samba_SHA512_Update(&sctx,
220                                             smb2req->in.vector[i].iov_base,
221                                             smb2req->in.vector[i].iov_len);
222                 }
223                 samba_SHA512_Final(preauth->sha512_value, &sctx);
224
225                 p = data_blob_const(preauth->sha512_value,
226                                     sizeof(preauth->sha512_value));
227
228                 d = &derivation.signing;
229                 d->label = data_blob_string_const_null("SMBSigningKey");
230                 d->context = p;
231
232                 d = &derivation.decryption;
233                 d->label = data_blob_string_const_null("SMBC2SCipherKey");
234                 d->context = p;
235
236                 d = &derivation.encryption;
237                 d->label = data_blob_string_const_null("SMBS2CCipherKey");
238                 d->context = p;
239
240                 d = &derivation.application;
241                 d->label = data_blob_string_const_null("SMBAppKey");
242                 d->context = p;
243
244         } else if (xconn->protocol >= PROTOCOL_SMB2_24) {
245                 struct _derivation *d;
246
247                 d = &derivation.signing;
248                 d->label = data_blob_string_const_null("SMB2AESCMAC");
249                 d->context = data_blob_string_const_null("SmbSign");
250
251                 d = &derivation.decryption;
252                 d->label = data_blob_string_const_null("SMB2AESCCM");
253                 d->context = data_blob_string_const_null("ServerIn ");
254
255                 d = &derivation.encryption;
256                 d->label = data_blob_string_const_null("SMB2AESCCM");
257                 d->context = data_blob_string_const_null("ServerOut");
258
259                 d = &derivation.application;
260                 d->label = data_blob_string_const_null("SMB2APP");
261                 d->context = data_blob_string_const_null("SmbRpc");
262         }
263
264         if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
265             (xconn->smb2.server.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
266         {
267                 x->global->signing_flags = SMBXSRV_SIGNING_REQUIRED;
268         }
269
270         if ((lp_smb_encrypt(-1) >= SMB_SIGNING_DESIRED) &&
271             (xconn->smb2.client.capabilities & SMB2_CAP_ENCRYPTION)) {
272                 x->global->encryption_flags = SMBXSRV_ENCRYPTION_DESIRED;
273         }
274
275         if (lp_smb_encrypt(-1) == SMB_SIGNING_REQUIRED) {
276                 x->global->encryption_flags = SMBXSRV_ENCRYPTION_REQUIRED |
277                         SMBXSRV_ENCRYPTION_DESIRED;
278         }
279
280         if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
281                 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
282                         *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
283                 }
284                 /* force no signing */
285                 x->global->signing_flags &= ~SMBXSRV_SIGNING_REQUIRED;
286                 /* we map anonymous to guest internally */
287                 guest = true;
288         }
289
290         if (guest && (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED)) {
291                 DEBUG(1,("reject guest session as encryption is required\n"));
292                 return NT_STATUS_ACCESS_DENIED;
293         }
294
295         if (xconn->smb2.server.cipher == 0) {
296                 if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
297                         DEBUG(1,("reject session with dialect[0x%04X] "
298                                  "as encryption is required\n",
299                                  xconn->smb2.server.dialect));
300                         return NT_STATUS_ACCESS_DENIED;
301                 }
302         } else {
303                 x->global->channels[0].encryption_cipher = xconn->smb2.server.cipher;
304         }
305
306         if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
307                 *out_session_flags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
308         }
309
310         ZERO_STRUCT(session_key);
311         memcpy(session_key, session_info->session_key.data,
312                MIN(session_info->session_key.length, sizeof(session_key)));
313
314         x->global->signing_key = data_blob_talloc(x->global,
315                                                   session_key,
316                                                   sizeof(session_key));
317         if (x->global->signing_key.data == NULL) {
318                 ZERO_STRUCT(session_key);
319                 return NT_STATUS_NO_MEMORY;
320         }
321
322         if (xconn->protocol >= PROTOCOL_SMB2_24) {
323                 struct _derivation *d = &derivation.signing;
324
325                 smb2_key_derivation(session_key, sizeof(session_key),
326                                     d->label.data, d->label.length,
327                                     d->context.data, d->context.length,
328                                     x->global->signing_key.data);
329         }
330
331         if (xconn->protocol >= PROTOCOL_SMB2_24) {
332                 struct _derivation *d = &derivation.decryption;
333
334                 x->global->decryption_key = data_blob_talloc(x->global,
335                                                              session_key,
336                                                              sizeof(session_key));
337                 if (x->global->decryption_key.data == NULL) {
338                         ZERO_STRUCT(session_key);
339                         return NT_STATUS_NO_MEMORY;
340                 }
341
342                 smb2_key_derivation(session_key, sizeof(session_key),
343                                     d->label.data, d->label.length,
344                                     d->context.data, d->context.length,
345                                     x->global->decryption_key.data);
346         }
347
348         if (xconn->protocol >= PROTOCOL_SMB2_24) {
349                 struct _derivation *d = &derivation.encryption;
350                 size_t nonce_size;
351
352                 x->global->encryption_key = data_blob_talloc(x->global,
353                                                              session_key,
354                                                              sizeof(session_key));
355                 if (x->global->encryption_key.data == NULL) {
356                         ZERO_STRUCT(session_key);
357                         return NT_STATUS_NO_MEMORY;
358                 }
359
360                 smb2_key_derivation(session_key, sizeof(session_key),
361                                     d->label.data, d->label.length,
362                                     d->context.data, d->context.length,
363                                     x->global->encryption_key.data);
364
365                 /*
366                  * CCM and GCM algorithms must never have their
367                  * nonce wrap, or the security of the whole
368                  * communication and the keys is destroyed.
369                  * We must drop the connection once we have
370                  * transfered too much data.
371                  *
372                  * NOTE: We assume nonces greater than 8 bytes.
373                  */
374                 generate_random_buffer((uint8_t *)&x->nonce_high_random,
375                                        sizeof(x->nonce_high_random));
376                 switch (xconn->smb2.server.cipher) {
377                 case SMB2_ENCRYPTION_AES128_CCM:
378                         nonce_size = AES_CCM_128_NONCE_SIZE;
379                         break;
380                 case SMB2_ENCRYPTION_AES128_GCM:
381                         nonce_size = AES_GCM_128_IV_SIZE;
382                         break;
383                 default:
384                         nonce_size = 0;
385                         break;
386                 }
387                 x->nonce_high_max = SMB2_NONCE_HIGH_MAX(nonce_size);
388                 x->nonce_high = 0;
389                 x->nonce_low = 0;
390         }
391
392         x->global->application_key = data_blob_dup_talloc(x->global,
393                                                 x->global->signing_key);
394         if (x->global->application_key.data == NULL) {
395                 ZERO_STRUCT(session_key);
396                 return NT_STATUS_NO_MEMORY;
397         }
398
399         if (xconn->protocol >= PROTOCOL_SMB2_24) {
400                 struct _derivation *d = &derivation.application;
401
402                 smb2_key_derivation(session_key, sizeof(session_key),
403                                     d->label.data, d->label.length,
404                                     d->context.data, d->context.length,
405                                     x->global->application_key.data);
406         }
407         ZERO_STRUCT(session_key);
408
409         x->global->channels[0].signing_key = data_blob_dup_talloc(x->global->channels,
410                                                 x->global->signing_key);
411         if (x->global->channels[0].signing_key.data == NULL) {
412                 return NT_STATUS_NO_MEMORY;
413         }
414
415         data_blob_clear_free(&session_info->session_key);
416         session_info->session_key = data_blob_dup_talloc(session_info,
417                                                 x->global->application_key);
418         if (session_info->session_key.data == NULL) {
419                 return NT_STATUS_NO_MEMORY;
420         }
421
422         session->compat = talloc_zero(session, struct user_struct);
423         if (session->compat == NULL) {
424                 return NT_STATUS_NO_MEMORY;
425         }
426         session->compat->session = session;
427         session->compat->homes_snum = -1;
428         session->compat->session_info = session_info;
429         session->compat->session_keystr = NULL;
430         session->compat->vuid = session->global->session_wire_id;
431         DLIST_ADD(smb2req->sconn->users, session->compat);
432         smb2req->sconn->num_users++;
433
434         if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
435                 session->compat->homes_snum =
436                         register_homes_share(session_info->unix_info->unix_name);
437         }
438
439         set_current_user_info(session_info->unix_info->sanitized_username,
440                               session_info->unix_info->unix_name,
441                               session_info->info->domain_name);
442
443         reload_services(smb2req->sconn, conn_snum_used, true);
444
445         session->status = NT_STATUS_OK;
446         session->global->auth_session_info = talloc_move(session->global,
447                                                          &session_info);
448         session->global->auth_session_info_seqnum += 1;
449         for (i=0; i < session->global->num_channels; i++) {
450                 struct smbXsrv_channel_global0 *_c =
451                         &session->global->channels[i];
452
453                 _c->auth_session_info_seqnum =
454                         session->global->auth_session_info_seqnum;
455         }
456         session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
457         session->global->expiration_time = gensec_expire_time(auth->gensec);
458
459         if (!session_claim(session)) {
460                 DEBUG(1, ("smb2: Failed to claim session "
461                         "for vuid=%llu\n",
462                         (unsigned long long)session->compat->vuid));
463                 return NT_STATUS_LOGON_FAILURE;
464         }
465
466         TALLOC_FREE(auth);
467         status = smbXsrv_session_update(session);
468         if (!NT_STATUS_IS_OK(status)) {
469                 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
470                           (unsigned long long)session->compat->vuid,
471                           nt_errstr(status)));
472                 return NT_STATUS_LOGON_FAILURE;
473         }
474
475         /*
476          * we attach the session to the request
477          * so that the response can be signed
478          */
479         if (!guest) {
480                 smb2req->do_signing = true;
481         }
482
483         global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
484
485         *out_session_id = session->global->session_wire_id;
486
487         return NT_STATUS_OK;
488 }
489
490 static NTSTATUS smbd_smb2_reauth_generic_return(struct smbXsrv_session *session,
491                                         struct smbXsrv_session_auth0 **_auth,
492                                         struct smbd_smb2_request *smb2req,
493                                         struct auth_session_info *session_info,
494                                         uint16_t *out_session_flags,
495                                         uint64_t *out_session_id)
496 {
497         NTSTATUS status;
498         struct smbXsrv_session *x = session;
499         struct smbXsrv_session_auth0 *auth = *_auth;
500         struct smbXsrv_connection *xconn = smb2req->xconn;
501         size_t i;
502
503         *_auth = NULL;
504
505         data_blob_clear_free(&session_info->session_key);
506         session_info->session_key = data_blob_dup_talloc(session_info,
507                                                 x->global->application_key);
508         if (session_info->session_key.data == NULL) {
509                 return NT_STATUS_NO_MEMORY;
510         }
511
512         session->compat->session_info = session_info;
513         session->compat->vuid = session->global->session_wire_id;
514
515         session->compat->homes_snum =
516                         register_homes_share(session_info->unix_info->unix_name);
517
518         set_current_user_info(session_info->unix_info->sanitized_username,
519                               session_info->unix_info->unix_name,
520                               session_info->info->domain_name);
521
522         reload_services(smb2req->sconn, conn_snum_used, true);
523
524         session->status = NT_STATUS_OK;
525         TALLOC_FREE(session->global->auth_session_info);
526         session->global->auth_session_info = talloc_move(session->global,
527                                                          &session_info);
528         session->global->auth_session_info_seqnum += 1;
529         for (i=0; i < session->global->num_channels; i++) {
530                 struct smbXsrv_channel_global0 *_c =
531                         &session->global->channels[i];
532
533                 _c->auth_session_info_seqnum =
534                         session->global->auth_session_info_seqnum;
535         }
536         session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
537         session->global->expiration_time = gensec_expire_time(auth->gensec);
538
539         TALLOC_FREE(auth);
540         status = smbXsrv_session_update(session);
541         if (!NT_STATUS_IS_OK(status)) {
542                 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
543                           (unsigned long long)session->compat->vuid,
544                           nt_errstr(status)));
545                 return NT_STATUS_LOGON_FAILURE;
546         }
547
548         conn_clear_vuid_caches(xconn->client->sconn, session->compat->vuid);
549
550         if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
551                 smb2req->do_signing = true;
552         }
553
554         *out_session_id = session->global->session_wire_id;
555
556         return NT_STATUS_OK;
557 }
558
559 static NTSTATUS smbd_smb2_bind_auth_return(struct smbXsrv_session *session,
560                                            struct smbXsrv_session_auth0 **_auth,
561                                            struct smbd_smb2_request *smb2req,
562                                            struct auth_session_info *session_info,
563                                            uint16_t *out_session_flags,
564                                            uint64_t *out_session_id)
565 {
566         NTSTATUS status;
567         struct smbXsrv_session *x = session;
568         struct smbXsrv_session_auth0 *auth = *_auth;
569         struct smbXsrv_connection *xconn = smb2req->xconn;
570         struct smbXsrv_channel_global0 *c = NULL;
571         uint8_t session_key[16];
572         size_t i;
573         struct _derivation {
574                 DATA_BLOB label;
575                 DATA_BLOB context;
576         };
577         struct {
578                 struct _derivation signing;
579         } derivation = { };
580         bool ok;
581
582         *_auth = NULL;
583
584         if (xconn->protocol >= PROTOCOL_SMB3_10) {
585                 struct smbXsrv_preauth *preauth;
586                 struct _derivation *d;
587                 DATA_BLOB p;
588                 struct hc_sha512state sctx;
589
590                 preauth = talloc_move(smb2req, &auth->preauth);
591
592                 samba_SHA512_Init(&sctx);
593                 samba_SHA512_Update(&sctx, preauth->sha512_value,
594                                     sizeof(preauth->sha512_value));
595                 for (i = 1; i < smb2req->in.vector_count; i++) {
596                         samba_SHA512_Update(&sctx,
597                                             smb2req->in.vector[i].iov_base,
598                                             smb2req->in.vector[i].iov_len);
599                 }
600                 samba_SHA512_Final(preauth->sha512_value, &sctx);
601
602                 p = data_blob_const(preauth->sha512_value,
603                                     sizeof(preauth->sha512_value));
604
605                 d = &derivation.signing;
606                 d->label = data_blob_string_const_null("SMBSigningKey");
607                 d->context = p;
608
609         } else if (xconn->protocol >= PROTOCOL_SMB2_24) {
610                 struct _derivation *d;
611
612                 d = &derivation.signing;
613                 d->label = data_blob_string_const_null("SMB2AESCMAC");
614                 d->context = data_blob_string_const_null("SmbSign");
615         }
616
617         status = smbXsrv_session_find_channel(session, xconn, &c);
618         if (!NT_STATUS_IS_OK(status)) {
619                 return status;
620         }
621
622         ok = security_token_is_sid(session_info->security_token,
623                         &x->global->auth_session_info->security_token->sids[0]);
624         if (!ok) {
625                 return NT_STATUS_NOT_SUPPORTED;
626         }
627
628         if (session_info->session_key.length == 0) {
629                 /* See [MS-SMB2] 3.3.5.2.4 for the return code. */
630                 return NT_STATUS_NOT_SUPPORTED;
631         }
632
633         ZERO_STRUCT(session_key);
634         memcpy(session_key, session_info->session_key.data,
635                MIN(session_info->session_key.length, sizeof(session_key)));
636
637         c->signing_key = data_blob_talloc(x->global,
638                                           session_key,
639                                           sizeof(session_key));
640         if (c->signing_key.data == NULL) {
641                 ZERO_STRUCT(session_key);
642                 return NT_STATUS_NO_MEMORY;
643         }
644
645         if (xconn->protocol >= PROTOCOL_SMB2_24) {
646                 struct _derivation *d = &derivation.signing;
647
648                 smb2_key_derivation(session_key, sizeof(session_key),
649                                     d->label.data, d->label.length,
650                                     d->context.data, d->context.length,
651                                     c->signing_key.data);
652         }
653         ZERO_STRUCT(session_key);
654
655         TALLOC_FREE(auth);
656         status = smbXsrv_session_update(session);
657         if (!NT_STATUS_IS_OK(status)) {
658                 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
659                           (unsigned long long)session->compat->vuid,
660                           nt_errstr(status)));
661                 return NT_STATUS_LOGON_FAILURE;
662         }
663
664         *out_session_id = session->global->session_wire_id;
665
666         return NT_STATUS_OK;
667 }
668
669 struct smbd_smb2_session_setup_state {
670         struct tevent_context *ev;
671         struct smbd_smb2_request *smb2req;
672         uint64_t in_session_id;
673         uint8_t in_flags;
674         uint8_t in_security_mode;
675         uint64_t in_previous_session_id;
676         DATA_BLOB in_security_buffer;
677         struct smbXsrv_session *session;
678         struct smbXsrv_session_auth0 *auth;
679         struct auth_session_info *session_info;
680         uint16_t out_session_flags;
681         DATA_BLOB out_security_buffer;
682         uint64_t out_session_id;
683 };
684
685 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq);
686 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq);
687 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req);
688
689 static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
690                                         struct tevent_context *ev,
691                                         struct smbd_smb2_request *smb2req,
692                                         uint64_t in_session_id,
693                                         uint8_t in_flags,
694                                         uint8_t in_security_mode,
695                                         uint64_t in_previous_session_id,
696                                         DATA_BLOB in_security_buffer)
697 {
698         struct tevent_req *req;
699         struct smbd_smb2_session_setup_state *state;
700         NTSTATUS status;
701         NTTIME now = timeval_to_nttime(&smb2req->request_time);
702         struct tevent_req *subreq;
703         struct smbXsrv_channel_global0 *c = NULL;
704         enum security_user_level seclvl;
705
706         req = tevent_req_create(mem_ctx, &state,
707                                 struct smbd_smb2_session_setup_state);
708         if (req == NULL) {
709                 return NULL;
710         }
711         state->ev = ev;
712         state->smb2req = smb2req;
713         state->in_session_id = in_session_id;
714         state->in_flags = in_flags;
715         state->in_security_mode = in_security_mode;
716         state->in_previous_session_id = in_previous_session_id;
717         state->in_security_buffer = in_security_buffer;
718
719         if (in_flags & SMB2_SESSION_FLAG_BINDING) {
720                 if (smb2req->xconn->protocol < PROTOCOL_SMB2_22) {
721                         tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
722                         return tevent_req_post(req, ev);
723                 }
724
725                 if (!smb2req->xconn->client->server_multi_channel_enabled) {
726                         tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
727                         return tevent_req_post(req, ev);
728                 }
729
730                 if (in_session_id == 0) {
731                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
732                         return tevent_req_post(req, ev);
733                 }
734
735                 if (smb2req->session == NULL) {
736                         tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
737                         return tevent_req_post(req, ev);
738                 }
739
740                 if (!smb2req->do_signing) {
741                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
742                         return tevent_req_post(req, ev);
743                 }
744
745                 status = smbXsrv_session_find_channel(smb2req->session,
746                                                       smb2req->xconn,
747                                                       &c);
748                 if (NT_STATUS_IS_OK(status)) {
749                         if (c->signing_key.length == 0) {
750                                 goto auth;
751                         }
752                         tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
753                         return tevent_req_post(req, ev);
754                 }
755
756                 /*
757                  * OLD: 3.00 NEW 3.02 => INVALID_PARAMETER
758                  * OLD: 3.02 NEW 3.00 => INVALID_PARAMETER
759                  * OLD: 2.10 NEW 3.02 => ACCESS_DENIED
760                  * OLD: 3.02 NEW 2.10 => ACCESS_DENIED
761                  */
762                 if (smb2req->session->global->connection_dialect
763                     < SMB2_DIALECT_REVISION_222)
764                 {
765                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
766                         return tevent_req_post(req, ev);
767                 }
768                 if (smb2req->xconn->smb2.server.dialect
769                     < SMB2_DIALECT_REVISION_222)
770                 {
771                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
772                         return tevent_req_post(req, ev);
773                 }
774                 if (smb2req->session->global->connection_dialect
775                     != smb2req->xconn->smb2.server.dialect)
776                 {
777                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
778                         return tevent_req_post(req, ev);
779                 }
780
781                 seclvl = security_session_user_level(
782                                 smb2req->session->global->auth_session_info,
783                                 NULL);
784                 if (seclvl < SECURITY_USER) {
785                         tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
786                         return tevent_req_post(req, ev);
787                 }
788
789                 status = smbXsrv_session_add_channel(smb2req->session,
790                                                      smb2req->xconn,
791                                                      &c);
792                 if (!NT_STATUS_IS_OK(status)) {
793                         tevent_req_nterror(req, status);
794                         return tevent_req_post(req, ev);
795                 }
796
797                 status = smbXsrv_session_update(smb2req->session);
798                 if (!NT_STATUS_IS_OK(status)) {
799                         tevent_req_nterror(req, status);
800                         return tevent_req_post(req, ev);
801                 }
802         }
803
804 auth:
805
806         if (state->in_session_id == 0) {
807                 /* create a new session */
808                 status = smbXsrv_session_create(state->smb2req->xconn,
809                                                 now, &state->session);
810                 if (tevent_req_nterror(req, status)) {
811                         return tevent_req_post(req, ev);
812                 }
813                 smb2req->session = state->session;
814         } else {
815                 if (smb2req->session == NULL) {
816                         tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
817                         return tevent_req_post(req, ev);
818                 }
819
820                 state->session = smb2req->session;
821                 status = state->session->status;
822                 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
823                         status = NT_STATUS_OK;
824                 }
825                 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
826                         status = NT_STATUS_OK;
827                 }
828                 if (tevent_req_nterror(req, status)) {
829                         return tevent_req_post(req, ev);
830                 }
831                 if (!(in_flags & SMB2_SESSION_FLAG_BINDING)) {
832                         state->session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
833                 }
834         }
835
836         status = smbXsrv_session_find_channel(smb2req->session,
837                                               smb2req->xconn, &c);
838         if (!NT_STATUS_IS_OK(status)) {
839                 tevent_req_nterror(req, status);
840                 return tevent_req_post(req, ev);
841         }
842
843         status = smbXsrv_session_find_auth(state->session, smb2req->xconn,
844                                            now, &state->auth);
845         if (!NT_STATUS_IS_OK(status)) {
846                 status = smbXsrv_session_create_auth(state->session,
847                                                      smb2req->xconn, now,
848                                                      in_flags, in_security_mode,
849                                                      &state->auth);
850                 if (tevent_req_nterror(req, status)) {
851                         return tevent_req_post(req, ev);
852                 }
853         }
854
855         if (state->auth->gensec == NULL) {
856                 status = auth_generic_prepare(state->auth,
857                                               state->smb2req->xconn->remote_address,
858                                               state->smb2req->xconn->local_address,
859                                               "SMB2",
860                                               &state->auth->gensec);
861                 if (tevent_req_nterror(req, status)) {
862                         return tevent_req_post(req, ev);
863                 }
864
865                 gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_SESSION_KEY);
866                 gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
867                 gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_SMB_TRANSPORT);
868
869                 status = gensec_start_mech_by_oid(state->auth->gensec,
870                                                   GENSEC_OID_SPNEGO);
871                 if (tevent_req_nterror(req, status)) {
872                         return tevent_req_post(req, ev);
873                 }
874         }
875
876         status = smbXsrv_session_update(state->session);
877         if (tevent_req_nterror(req, status)) {
878                 return tevent_req_post(req, ev);
879         }
880
881         become_root();
882         subreq = gensec_update_send(state, state->ev,
883                                     state->auth->gensec,
884                                     state->in_security_buffer);
885         unbecome_root();
886         if (tevent_req_nomem(subreq, req)) {
887                 return tevent_req_post(req, ev);
888         }
889         tevent_req_set_callback(subreq, smbd_smb2_session_setup_gensec_done, req);
890
891         return req;
892 }
893
894 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
895 {
896         struct tevent_req *req =
897                 tevent_req_callback_data(subreq,
898                 struct tevent_req);
899         struct smbd_smb2_session_setup_state *state =
900                 tevent_req_data(req,
901                 struct smbd_smb2_session_setup_state);
902         NTSTATUS status;
903
904         become_root();
905         status = gensec_update_recv(subreq, state,
906                                     &state->out_security_buffer);
907         unbecome_root();
908         TALLOC_FREE(subreq);
909         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
910             !NT_STATUS_IS_OK(status)) {
911                 tevent_req_nterror(req, status);
912                 return;
913         }
914
915         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
916                 state->out_session_id = state->session->global->session_wire_id;
917                 state->smb2req->preauth = state->auth->preauth;
918                 tevent_req_nterror(req, status);
919                 return;
920         }
921
922         status = gensec_session_info(state->auth->gensec,
923                                      state,
924                                      &state->session_info);
925         if (tevent_req_nterror(req, status)) {
926                 return;
927         }
928
929         if ((state->in_previous_session_id != 0) &&
930              (state->session->global->session_wire_id !=
931               state->in_previous_session_id))
932         {
933                 subreq = smb2srv_session_close_previous_send(state, state->ev,
934                                                 state->smb2req->xconn,
935                                                 state->session_info,
936                                                 state->in_previous_session_id,
937                                                 state->session->global->session_wire_id);
938                 if (tevent_req_nomem(subreq, req)) {
939                         return;
940                 }
941                 tevent_req_set_callback(subreq,
942                                         smbd_smb2_session_setup_previous_done,
943                                         req);
944                 return;
945         }
946
947         smbd_smb2_session_setup_auth_return(req);
948 }
949
950 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq)
951 {
952         struct tevent_req *req =
953                 tevent_req_callback_data(subreq,
954                 struct tevent_req);
955         NTSTATUS status;
956
957         status = smb2srv_session_close_previous_recv(subreq);
958         TALLOC_FREE(subreq);
959         if (tevent_req_nterror(req, status)) {
960                 return;
961         }
962
963         smbd_smb2_session_setup_auth_return(req);
964 }
965
966 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req)
967 {
968         struct smbd_smb2_session_setup_state *state =
969                 tevent_req_data(req,
970                 struct smbd_smb2_session_setup_state);
971         NTSTATUS status;
972
973         if (state->in_flags & SMB2_SESSION_FLAG_BINDING) {
974                 status = smbd_smb2_bind_auth_return(state->session,
975                                                     &state->auth,
976                                                     state->smb2req,
977                                                     state->session_info,
978                                                     &state->out_session_flags,
979                                                     &state->out_session_id);
980                 if (tevent_req_nterror(req, status)) {
981                         return;
982                 }
983                 tevent_req_done(req);
984                 return;
985         }
986
987         if (state->session->global->auth_session_info != NULL) {
988                 status = smbd_smb2_reauth_generic_return(state->session,
989                                                          &state->auth,
990                                                          state->smb2req,
991                                                          state->session_info,
992                                                          &state->out_session_flags,
993                                                          &state->out_session_id);
994                 if (tevent_req_nterror(req, status)) {
995                         return;
996                 }
997                 tevent_req_done(req);
998                 return;
999         }
1000
1001         status = smbd_smb2_auth_generic_return(state->session,
1002                                                &state->auth,
1003                                                state->smb2req,
1004                                                state->in_security_mode,
1005                                                state->session_info,
1006                                                &state->out_session_flags,
1007                                                &state->out_session_id);
1008         if (tevent_req_nterror(req, status)) {
1009                 return;
1010         }
1011
1012         tevent_req_done(req);
1013         return;
1014 }
1015
1016 static NTSTATUS smbd_smb2_session_setup_recv(struct tevent_req *req,
1017                                         uint16_t *out_session_flags,
1018                                         TALLOC_CTX *mem_ctx,
1019                                         DATA_BLOB *out_security_buffer,
1020                                         uint64_t *out_session_id)
1021 {
1022         struct smbd_smb2_session_setup_state *state =
1023                 tevent_req_data(req,
1024                 struct smbd_smb2_session_setup_state);
1025         NTSTATUS status;
1026
1027         if (tevent_req_is_nterror(req, &status)) {
1028                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1029                         tevent_req_received(req);
1030                         return nt_status_squash(status);
1031                 }
1032         } else {
1033                 status = NT_STATUS_OK;
1034         }
1035
1036         *out_session_flags = state->out_session_flags;
1037         *out_security_buffer = state->out_security_buffer;
1038         *out_session_id = state->out_session_id;
1039
1040         talloc_steal(mem_ctx, out_security_buffer->data);
1041         tevent_req_received(req);
1042         return status;
1043 }
1044
1045 struct smbd_smb2_session_setup_wrap_state {
1046         struct tevent_context *ev;
1047         struct smbd_smb2_request *smb2req;
1048         uint64_t in_session_id;
1049         uint8_t in_flags;
1050         uint8_t in_security_mode;
1051         uint64_t in_previous_session_id;
1052         DATA_BLOB in_security_buffer;
1053         uint16_t out_session_flags;
1054         DATA_BLOB out_security_buffer;
1055         uint64_t out_session_id;
1056         NTSTATUS error;
1057 };
1058
1059 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq);
1060 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq);
1061
1062 static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
1063                                         struct tevent_context *ev,
1064                                         struct smbd_smb2_request *smb2req,
1065                                         uint64_t in_session_id,
1066                                         uint8_t in_flags,
1067                                         uint8_t in_security_mode,
1068                                         uint64_t in_previous_session_id,
1069                                         DATA_BLOB in_security_buffer)
1070 {
1071         struct tevent_req *req;
1072         struct smbd_smb2_session_setup_wrap_state *state;
1073         struct tevent_req *subreq;
1074
1075         req = tevent_req_create(mem_ctx, &state,
1076                                 struct smbd_smb2_session_setup_wrap_state);
1077         if (req == NULL) {
1078                 return NULL;
1079         }
1080         state->ev = ev;
1081         state->smb2req = smb2req;
1082         state->in_session_id = in_session_id;
1083         state->in_flags = in_flags;
1084         state->in_security_mode = in_security_mode;
1085         state->in_previous_session_id = in_previous_session_id;
1086         state->in_security_buffer = in_security_buffer;
1087
1088         subreq = smbd_smb2_session_setup_send(state, state->ev,
1089                                               state->smb2req,
1090                                               state->in_session_id,
1091                                               state->in_flags,
1092                                               state->in_security_mode,
1093                                               state->in_previous_session_id,
1094                                               state->in_security_buffer);
1095         if (tevent_req_nomem(subreq, req)) {
1096                 return tevent_req_post(req, ev);
1097         }
1098         tevent_req_set_callback(subreq,
1099                                 smbd_smb2_session_setup_wrap_setup_done, req);
1100
1101         return req;
1102 }
1103
1104 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq)
1105 {
1106         struct tevent_req *req =
1107                 tevent_req_callback_data(subreq,
1108                 struct tevent_req);
1109         struct smbd_smb2_session_setup_wrap_state *state =
1110                 tevent_req_data(req,
1111                 struct smbd_smb2_session_setup_wrap_state);
1112         NTSTATUS status;
1113
1114         status = smbd_smb2_session_setup_recv(subreq,
1115                                               &state->out_session_flags,
1116                                               state,
1117                                               &state->out_security_buffer,
1118                                               &state->out_session_id);
1119         TALLOC_FREE(subreq);
1120         if (NT_STATUS_IS_OK(status)) {
1121                 tevent_req_done(req);
1122                 return;
1123         }
1124         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1125                 tevent_req_nterror(req, status);
1126                 return;
1127         }
1128
1129         if (state->smb2req->session == NULL) {
1130                 tevent_req_nterror(req, status);
1131                 return;
1132         }
1133
1134         state->error = status;
1135
1136         subreq = smb2srv_session_shutdown_send(state, state->ev,
1137                                                state->smb2req->session,
1138                                                state->smb2req);
1139         if (tevent_req_nomem(subreq, req)) {
1140                 return;
1141         }
1142         tevent_req_set_callback(subreq,
1143                                 smbd_smb2_session_setup_wrap_shutdown_done,
1144                                 req);
1145 }
1146
1147 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq)
1148 {
1149         struct tevent_req *req =
1150                 tevent_req_callback_data(subreq,
1151                 struct tevent_req);
1152         struct smbd_smb2_session_setup_wrap_state *state =
1153                 tevent_req_data(req,
1154                 struct smbd_smb2_session_setup_wrap_state);
1155         NTSTATUS status;
1156
1157         status = smb2srv_session_shutdown_recv(subreq);
1158         TALLOC_FREE(subreq);
1159         if (tevent_req_nterror(req, status)) {
1160                 return;
1161         }
1162
1163         /*
1164          * we may need to sign the response, so we need to keep
1165          * the session until the response is sent to the wire.
1166          */
1167         talloc_steal(state->smb2req, state->smb2req->session);
1168
1169         tevent_req_nterror(req, state->error);
1170 }
1171
1172 static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
1173                                         uint16_t *out_session_flags,
1174                                         TALLOC_CTX *mem_ctx,
1175                                         DATA_BLOB *out_security_buffer,
1176                                         uint64_t *out_session_id)
1177 {
1178         struct smbd_smb2_session_setup_wrap_state *state =
1179                 tevent_req_data(req,
1180                 struct smbd_smb2_session_setup_wrap_state);
1181         NTSTATUS status;
1182
1183         if (tevent_req_is_nterror(req, &status)) {
1184                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1185                         tevent_req_received(req);
1186                         return nt_status_squash(status);
1187                 }
1188         } else {
1189                 status = NT_STATUS_OK;
1190         }
1191
1192         *out_session_flags = state->out_session_flags;
1193         *out_security_buffer = state->out_security_buffer;
1194         *out_session_id = state->out_session_id;
1195
1196         talloc_steal(mem_ctx, out_security_buffer->data);
1197         tevent_req_received(req);
1198         return status;
1199 }
1200
1201 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
1202                                         struct tevent_context *ev,
1203                                         struct smbd_smb2_request *smb2req);
1204 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req);
1205 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq);
1206
1207 NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req)
1208 {
1209         NTSTATUS status;
1210         struct tevent_req *subreq = NULL;
1211
1212         status = smbd_smb2_request_verify_sizes(req, 0x04);
1213         if (!NT_STATUS_IS_OK(status)) {
1214                 return smbd_smb2_request_error(req, status);
1215         }
1216
1217         subreq = smbd_smb2_logoff_send(req, req->sconn->ev_ctx, req);
1218         if (subreq == NULL) {
1219                 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
1220         }
1221         tevent_req_set_callback(subreq, smbd_smb2_request_logoff_done, req);
1222
1223         /*
1224          * Wait a long time before going async on this to allow
1225          * requests we're waiting on to finish. Set timeout to 10 secs.
1226          */
1227         return smbd_smb2_request_pending_queue(req, subreq, 10000000);
1228 }
1229
1230 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq)
1231 {
1232         struct smbd_smb2_request *smb2req =
1233                 tevent_req_callback_data(subreq,
1234                 struct smbd_smb2_request);
1235         DATA_BLOB outbody;
1236         NTSTATUS status;
1237         NTSTATUS error;
1238
1239         status = smbd_smb2_logoff_recv(subreq);
1240         TALLOC_FREE(subreq);
1241         if (!NT_STATUS_IS_OK(status)) {
1242                 error = smbd_smb2_request_error(smb2req, status);
1243                 if (!NT_STATUS_IS_OK(error)) {
1244                         smbd_server_connection_terminate(smb2req->xconn,
1245                                                         nt_errstr(error));
1246                         return;
1247                 }
1248                 return;
1249         }
1250
1251         outbody = smbd_smb2_generate_outbody(smb2req, 0x04);
1252         if (outbody.data == NULL) {
1253                 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
1254                 if (!NT_STATUS_IS_OK(error)) {
1255                         smbd_server_connection_terminate(smb2req->xconn,
1256                                                         nt_errstr(error));
1257                         return;
1258                 }
1259                 return;
1260         }
1261
1262         SSVAL(outbody.data, 0x00, 0x04);        /* struct size */
1263         SSVAL(outbody.data, 0x02, 0);           /* reserved */
1264
1265         error = smbd_smb2_request_done(smb2req, outbody, NULL);
1266         if (!NT_STATUS_IS_OK(error)) {
1267                 smbd_server_connection_terminate(smb2req->xconn,
1268                                                 nt_errstr(error));
1269                 return;
1270         }
1271 }
1272
1273 struct smbd_smb2_logoff_state {
1274         struct smbd_smb2_request *smb2req;
1275 };
1276
1277 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq);
1278
1279 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
1280                                         struct tevent_context *ev,
1281                                         struct smbd_smb2_request *smb2req)
1282 {
1283         struct tevent_req *req;
1284         struct smbd_smb2_logoff_state *state;
1285         struct tevent_req *subreq;
1286
1287         req = tevent_req_create(mem_ctx, &state,
1288                         struct smbd_smb2_logoff_state);
1289         if (req == NULL) {
1290                 return NULL;
1291         }
1292         state->smb2req = smb2req;
1293
1294         subreq = smb2srv_session_shutdown_send(state, ev,
1295                                                smb2req->session,
1296                                                smb2req);
1297         if (tevent_req_nomem(subreq, req)) {
1298                 return tevent_req_post(req, ev);
1299         }
1300         tevent_req_set_callback(subreq, smbd_smb2_logoff_shutdown_done, req);
1301
1302         return req;
1303 }
1304
1305 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq)
1306 {
1307         struct tevent_req *req = tevent_req_callback_data(
1308                 subreq, struct tevent_req);
1309         struct smbd_smb2_logoff_state *state = tevent_req_data(
1310                 req, struct smbd_smb2_logoff_state);
1311         NTSTATUS status;
1312         bool ok;
1313         const struct GUID *client_guid =
1314                 &state->smb2req->session->client->connections->smb2.client.guid;
1315
1316         status = smb2srv_session_shutdown_recv(subreq);
1317         if (tevent_req_nterror(req, status)) {
1318                 return;
1319         }
1320         TALLOC_FREE(subreq);
1321
1322         if (!GUID_all_zero(client_guid)) {
1323                 ok = remote_arch_cache_delete(client_guid);
1324                 if (!ok) {
1325                         /* Most likely not an error, but not in cache */
1326                         DBG_DEBUG("Deletion from remote arch cache failed\n");
1327                 }
1328         }
1329
1330         /*
1331          * As we've been awoken, we may have changed
1332          * uid in the meantime. Ensure we're still
1333          * root (SMB2_OP_LOGOFF has .as_root = true).
1334          */
1335         change_to_root_user();
1336
1337         status = smbXsrv_session_logoff(state->smb2req->session);
1338         if (tevent_req_nterror(req, status)) {
1339                 return;
1340         }
1341
1342         /*
1343          * we may need to sign the response, so we need to keep
1344          * the session until the response is sent to the wire.
1345          */
1346         talloc_steal(state->smb2req, state->smb2req->session);
1347
1348         tevent_req_done(req);
1349 }
1350
1351 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req)
1352 {
1353         return tevent_req_simple_recv_ntstatus(req);
1354 }