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