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