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