s3/smbd: update some more DEBUG macros in smbd_smb2_create_send
[nivanova/samba-autobuild/.git] / source3 / smbd / smb2_sesssetup.c
1 /*
2    Unix SMB/CIFS implementation.
3    Core SMB2 server
4
5    Copyright (C) Stefan Metzmacher 2009
6    Copyright (C) Jeremy Allison 2010
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../auth/gensec/gensec.h"
27 #include "auth.h"
28 #include "../lib/tsocket/tsocket.h"
29 #include "../libcli/security/security.h"
30 #include "../lib/util/tevent_ntstatus.h"
31 #include "lib/crypto/sha512.h"
32 #include "lib/crypto/aes.h"
33 #include "lib/crypto/aes_ccm_128.h"
34 #include "lib/crypto/aes_gcm_128.h"
35
36 static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
37                                         struct tevent_context *ev,
38                                         struct smbd_smb2_request *smb2req,
39                                         uint64_t in_session_id,
40                                         uint8_t in_flags,
41                                         uint8_t in_security_mode,
42                                         uint64_t in_previous_session_id,
43                                         DATA_BLOB in_security_buffer);
44 static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
45                                         uint16_t *out_session_flags,
46                                         TALLOC_CTX *mem_ctx,
47                                         DATA_BLOB *out_security_buffer,
48                                         uint64_t *out_session_id);
49
50 static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq);
51
52 NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *smb2req)
53 {
54         const uint8_t *inhdr;
55         const uint8_t *inbody;
56         uint64_t in_session_id;
57         uint8_t in_flags;
58         uint8_t in_security_mode;
59         uint64_t in_previous_session_id;
60         uint16_t in_security_offset;
61         uint16_t in_security_length;
62         DATA_BLOB in_security_buffer;
63         NTSTATUS status;
64         struct tevent_req *subreq;
65
66         status = smbd_smb2_request_verify_sizes(smb2req, 0x19);
67         if (!NT_STATUS_IS_OK(status)) {
68                 return smbd_smb2_request_error(smb2req, status);
69         }
70         inhdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
71         inbody = SMBD_SMB2_IN_BODY_PTR(smb2req);
72
73         in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
74
75         in_flags = CVAL(inbody, 0x02);
76         in_security_mode = CVAL(inbody, 0x03);
77         /* Capabilities = IVAL(inbody, 0x04) */
78         /* Channel = IVAL(inbody, 0x08) */
79         in_security_offset = SVAL(inbody, 0x0C);
80         in_security_length = SVAL(inbody, 0x0E);
81         in_previous_session_id = BVAL(inbody, 0x10);
82
83         if (in_security_offset != (SMB2_HDR_BODY + SMBD_SMB2_IN_BODY_LEN(smb2req))) {
84                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
85         }
86
87         if (in_security_length > SMBD_SMB2_IN_DYN_LEN(smb2req)) {
88                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
89         }
90
91         in_security_buffer.data = SMBD_SMB2_IN_DYN_PTR(smb2req);
92         in_security_buffer.length = in_security_length;
93
94         subreq = smbd_smb2_session_setup_wrap_send(smb2req,
95                                                    smb2req->sconn->ev_ctx,
96                                                    smb2req,
97                                                    in_session_id,
98                                                    in_flags,
99                                                    in_security_mode,
100                                                    in_previous_session_id,
101                                                    in_security_buffer);
102         if (subreq == NULL) {
103                 return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
104         }
105         tevent_req_set_callback(subreq, smbd_smb2_request_sesssetup_done, smb2req);
106
107         return smbd_smb2_request_pending_queue(smb2req, subreq, 500);
108 }
109
110 static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq)
111 {
112         struct smbd_smb2_request *smb2req =
113                 tevent_req_callback_data(subreq,
114                 struct smbd_smb2_request);
115         uint8_t *outhdr;
116         DATA_BLOB outbody;
117         DATA_BLOB outdyn;
118         uint16_t out_session_flags = 0;
119         uint64_t out_session_id = 0;
120         uint16_t out_security_offset;
121         DATA_BLOB out_security_buffer = data_blob_null;
122         NTSTATUS status;
123         NTSTATUS error; /* transport error */
124
125         status = smbd_smb2_session_setup_wrap_recv(subreq,
126                                                    &out_session_flags,
127                                                    smb2req,
128                                                    &out_security_buffer,
129                                                    &out_session_id);
130         TALLOC_FREE(subreq);
131         if (!NT_STATUS_IS_OK(status) &&
132             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
133                 status = nt_status_squash(status);
134                 error = smbd_smb2_request_error(smb2req, status);
135                 if (!NT_STATUS_IS_OK(error)) {
136                         smbd_server_connection_terminate(smb2req->xconn,
137                                                          nt_errstr(error));
138                         return;
139                 }
140                 return;
141         }
142
143         out_security_offset = SMB2_HDR_BODY + 0x08;
144
145         outhdr = SMBD_SMB2_OUT_HDR_PTR(smb2req);
146
147         outbody = smbd_smb2_generate_outbody(smb2req, 0x08);
148         if (outbody.data == NULL) {
149                 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
150                 if (!NT_STATUS_IS_OK(error)) {
151                         smbd_server_connection_terminate(smb2req->xconn,
152                                                          nt_errstr(error));
153                         return;
154                 }
155                 return;
156         }
157
158         SBVAL(outhdr, SMB2_HDR_SESSION_ID, out_session_id);
159
160         SSVAL(outbody.data, 0x00, 0x08 + 1);    /* struct size */
161         SSVAL(outbody.data, 0x02,
162               out_session_flags);               /* session flags */
163         SSVAL(outbody.data, 0x04,
164               out_security_offset);             /* security buffer offset */
165         SSVAL(outbody.data, 0x06,
166               out_security_buffer.length);      /* security buffer length */
167
168         outdyn = out_security_buffer;
169
170         error = smbd_smb2_request_done_ex(smb2req, status, outbody, &outdyn,
171                                            __location__);
172         if (!NT_STATUS_IS_OK(error)) {
173                 smbd_server_connection_terminate(smb2req->xconn,
174                                                  nt_errstr(error));
175                 return;
176         }
177 }
178
179 static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
180                                         struct smbXsrv_session_auth0 **_auth,
181                                         struct smbd_smb2_request *smb2req,
182                                         uint8_t in_security_mode,
183                                         struct auth_session_info *session_info,
184                                         uint16_t *out_session_flags,
185                                         uint64_t *out_session_id)
186 {
187         NTSTATUS status;
188         bool guest = false;
189         uint8_t session_key[16];
190         struct smbXsrv_session *x = session;
191         struct smbXsrv_session_auth0 *auth = *_auth;
192         struct smbXsrv_connection *xconn = smb2req->xconn;
193         size_t i;
194         struct _derivation {
195                 DATA_BLOB label;
196                 DATA_BLOB context;
197         };
198         struct {
199                 struct _derivation signing;
200                 struct _derivation encryption;
201                 struct _derivation decryption;
202                 struct _derivation application;
203         } derivation = { };
204
205         *_auth = NULL;
206
207         if (xconn->protocol >= PROTOCOL_SMB3_10) {
208                 struct smbXsrv_preauth *preauth;
209                 struct _derivation *d;
210                 DATA_BLOB p;
211                 struct hc_sha512state sctx;
212
213                 preauth = talloc_move(smb2req, &auth->preauth);
214
215                 samba_SHA512_Init(&sctx);
216                 samba_SHA512_Update(&sctx, preauth->sha512_value,
217                                     sizeof(preauth->sha512_value));
218                 for (i = 1; i < smb2req->in.vector_count; i++) {
219                         samba_SHA512_Update(&sctx,
220                                             smb2req->in.vector[i].iov_base,
221                                             smb2req->in.vector[i].iov_len);
222                 }
223                 samba_SHA512_Final(preauth->sha512_value, &sctx);
224
225                 p = data_blob_const(preauth->sha512_value,
226                                     sizeof(preauth->sha512_value));
227
228                 d = &derivation.signing;
229                 d->label = data_blob_string_const_null("SMBSigningKey");
230                 d->context = p;
231
232                 d = &derivation.decryption;
233                 d->label = data_blob_string_const_null("SMBC2SCipherKey");
234                 d->context = p;
235
236                 d = &derivation.encryption;
237                 d->label = data_blob_string_const_null("SMBS2CCipherKey");
238                 d->context = p;
239
240                 d = &derivation.application;
241                 d->label = data_blob_string_const_null("SMBAppKey");
242                 d->context = p;
243
244         } else if (xconn->protocol >= PROTOCOL_SMB2_24) {
245                 struct _derivation *d;
246
247                 d = &derivation.signing;
248                 d->label = data_blob_string_const_null("SMB2AESCMAC");
249                 d->context = data_blob_string_const_null("SmbSign");
250
251                 d = &derivation.decryption;
252                 d->label = data_blob_string_const_null("SMB2AESCCM");
253                 d->context = data_blob_string_const_null("ServerIn ");
254
255                 d = &derivation.encryption;
256                 d->label = data_blob_string_const_null("SMB2AESCCM");
257                 d->context = data_blob_string_const_null("ServerOut");
258
259                 d = &derivation.application;
260                 d->label = data_blob_string_const_null("SMB2APP");
261                 d->context = data_blob_string_const_null("SmbRpc");
262         }
263
264         if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
265             (xconn->smb2.server.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
266         {
267                 x->global->signing_flags = SMBXSRV_SIGNING_REQUIRED;
268         }
269
270         if ((lp_smb_encrypt(-1) >= SMB_SIGNING_DESIRED) &&
271             (xconn->smb2.client.capabilities & SMB2_CAP_ENCRYPTION)) {
272                 x->global->encryption_flags = SMBXSRV_ENCRYPTION_DESIRED;
273         }
274
275         if (lp_smb_encrypt(-1) == SMB_SIGNING_REQUIRED) {
276                 x->global->encryption_flags = SMBXSRV_ENCRYPTION_REQUIRED |
277                         SMBXSRV_ENCRYPTION_DESIRED;
278         }
279
280         if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
281                 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
282                         *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
283                 }
284                 /* force no signing */
285                 x->global->signing_flags &= ~SMBXSRV_SIGNING_REQUIRED;
286                 /* we map anonymous to guest internally */
287                 guest = true;
288         }
289
290         if (guest && (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED)) {
291                 DEBUG(1,("reject guest session as encryption is required\n"));
292                 return NT_STATUS_ACCESS_DENIED;
293         }
294
295         if (xconn->smb2.server.cipher == 0) {
296                 if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
297                         DEBUG(1,("reject session with dialect[0x%04X] "
298                                  "as encryption is required\n",
299                                  xconn->smb2.server.dialect));
300                         return NT_STATUS_ACCESS_DENIED;
301                 }
302         } else {
303                 x->global->channels[0].encryption_cipher = xconn->smb2.server.cipher;
304         }
305
306         if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
307                 *out_session_flags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
308         }
309
310         ZERO_STRUCT(session_key);
311         memcpy(session_key, session_info->session_key.data,
312                MIN(session_info->session_key.length, sizeof(session_key)));
313
314         x->global->signing_key = data_blob_talloc(x->global,
315                                                   session_key,
316                                                   sizeof(session_key));
317         if (x->global->signing_key.data == NULL) {
318                 ZERO_STRUCT(session_key);
319                 return NT_STATUS_NO_MEMORY;
320         }
321
322         if (xconn->protocol >= PROTOCOL_SMB2_24) {
323                 struct _derivation *d = &derivation.signing;
324
325                 smb2_key_derivation(session_key, sizeof(session_key),
326                                     d->label.data, d->label.length,
327                                     d->context.data, d->context.length,
328                                     x->global->signing_key.data);
329         }
330
331         if (xconn->protocol >= PROTOCOL_SMB2_24) {
332                 struct _derivation *d = &derivation.decryption;
333
334                 x->global->decryption_key = data_blob_talloc(x->global,
335                                                              session_key,
336                                                              sizeof(session_key));
337                 if (x->global->decryption_key.data == NULL) {
338                         ZERO_STRUCT(session_key);
339                         return NT_STATUS_NO_MEMORY;
340                 }
341
342                 smb2_key_derivation(session_key, sizeof(session_key),
343                                     d->label.data, d->label.length,
344                                     d->context.data, d->context.length,
345                                     x->global->decryption_key.data);
346         }
347
348         if (xconn->protocol >= PROTOCOL_SMB2_24) {
349                 struct _derivation *d = &derivation.encryption;
350                 size_t nonce_size;
351
352                 x->global->encryption_key = data_blob_talloc(x->global,
353                                                              session_key,
354                                                              sizeof(session_key));
355                 if (x->global->encryption_key.data == NULL) {
356                         ZERO_STRUCT(session_key);
357                         return NT_STATUS_NO_MEMORY;
358                 }
359
360                 smb2_key_derivation(session_key, sizeof(session_key),
361                                     d->label.data, d->label.length,
362                                     d->context.data, d->context.length,
363                                     x->global->encryption_key.data);
364
365                 /*
366                  * CCM and GCM algorithms must never have their
367                  * nonce wrap, or the security of the whole
368                  * communication and the keys is destroyed.
369                  * We must drop the connection once we have
370                  * transfered too much data.
371                  *
372                  * NOTE: We assume nonces greater than 8 bytes.
373                  */
374                 generate_random_buffer((uint8_t *)&x->nonce_high_random,
375                                        sizeof(x->nonce_high_random));
376                 switch (xconn->smb2.server.cipher) {
377                 case SMB2_ENCRYPTION_AES128_CCM:
378                         nonce_size = AES_CCM_128_NONCE_SIZE;
379                         break;
380                 case SMB2_ENCRYPTION_AES128_GCM:
381                         nonce_size = AES_GCM_128_IV_SIZE;
382                         break;
383                 default:
384                         nonce_size = 0;
385                         break;
386                 }
387                 x->nonce_high_max = SMB2_NONCE_HIGH_MAX(nonce_size);
388                 x->nonce_high = 0;
389                 x->nonce_low = 0;
390         }
391
392         x->global->application_key = data_blob_dup_talloc(x->global,
393                                                 x->global->signing_key);
394         if (x->global->application_key.data == NULL) {
395                 ZERO_STRUCT(session_key);
396                 return NT_STATUS_NO_MEMORY;
397         }
398
399         if (xconn->protocol >= PROTOCOL_SMB2_24) {
400                 struct _derivation *d = &derivation.application;
401
402                 smb2_key_derivation(session_key, sizeof(session_key),
403                                     d->label.data, d->label.length,
404                                     d->context.data, d->context.length,
405                                     x->global->application_key.data);
406         }
407         ZERO_STRUCT(session_key);
408
409         x->global->channels[0].signing_key = data_blob_dup_talloc(x->global->channels,
410                                                 x->global->signing_key);
411         if (x->global->channels[0].signing_key.data == NULL) {
412                 return NT_STATUS_NO_MEMORY;
413         }
414
415         data_blob_clear_free(&session_info->session_key);
416         session_info->session_key = data_blob_dup_talloc(session_info,
417                                                 x->global->application_key);
418         if (session_info->session_key.data == NULL) {
419                 return NT_STATUS_NO_MEMORY;
420         }
421
422         session->compat = talloc_zero(session, struct user_struct);
423         if (session->compat == NULL) {
424                 return NT_STATUS_NO_MEMORY;
425         }
426         session->compat->session = session;
427         session->compat->homes_snum = -1;
428         session->compat->session_info = session_info;
429         session->compat->session_keystr = NULL;
430         session->compat->vuid = session->global->session_wire_id;
431         DLIST_ADD(smb2req->sconn->users, session->compat);
432         smb2req->sconn->num_users++;
433
434         if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
435                 session->compat->homes_snum =
436                         register_homes_share(session_info->unix_info->unix_name);
437         }
438
439         set_current_user_info(session_info->unix_info->sanitized_username,
440                               session_info->unix_info->unix_name,
441                               session_info->info->domain_name);
442
443         reload_services(smb2req->sconn, conn_snum_used, true);
444
445         session->status = NT_STATUS_OK;
446         session->global->auth_session_info = talloc_move(session->global,
447                                                          &session_info);
448         session->global->auth_session_info_seqnum += 1;
449         for (i=0; i < session->global->num_channels; i++) {
450                 struct smbXsrv_channel_global0 *_c =
451                         &session->global->channels[i];
452
453                 _c->auth_session_info_seqnum =
454                         session->global->auth_session_info_seqnum;
455         }
456         session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
457         session->global->expiration_time = gensec_expire_time(auth->gensec);
458
459         if (!session_claim(session)) {
460                 DEBUG(1, ("smb2: Failed to claim session "
461                         "for vuid=%llu\n",
462                         (unsigned long long)session->compat->vuid));
463                 return NT_STATUS_LOGON_FAILURE;
464         }
465
466         TALLOC_FREE(auth);
467         status = smbXsrv_session_update(session);
468         if (!NT_STATUS_IS_OK(status)) {
469                 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
470                           (unsigned long long)session->compat->vuid,
471                           nt_errstr(status)));
472                 return NT_STATUS_LOGON_FAILURE;
473         }
474
475         /*
476          * we attach the session to the request
477          * so that the response can be signed
478          */
479         if (!guest) {
480                 smb2req->do_signing = true;
481         }
482
483         global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
484
485         *out_session_id = session->global->session_wire_id;
486         smb2req->last_session_id = session->global->session_wire_id;
487
488         return NT_STATUS_OK;
489 }
490
491 static NTSTATUS smbd_smb2_reauth_generic_return(struct smbXsrv_session *session,
492                                         struct smbXsrv_session_auth0 **_auth,
493                                         struct smbd_smb2_request *smb2req,
494                                         struct auth_session_info *session_info,
495                                         uint16_t *out_session_flags,
496                                         uint64_t *out_session_id)
497 {
498         NTSTATUS status;
499         struct smbXsrv_session *x = session;
500         struct smbXsrv_session_auth0 *auth = *_auth;
501         struct smbXsrv_connection *xconn = smb2req->xconn;
502         size_t i;
503
504         *_auth = NULL;
505
506         data_blob_clear_free(&session_info->session_key);
507         session_info->session_key = data_blob_dup_talloc(session_info,
508                                                 x->global->application_key);
509         if (session_info->session_key.data == NULL) {
510                 return NT_STATUS_NO_MEMORY;
511         }
512
513         session->compat->session_info = session_info;
514         session->compat->vuid = session->global->session_wire_id;
515
516         session->compat->homes_snum =
517                         register_homes_share(session_info->unix_info->unix_name);
518
519         set_current_user_info(session_info->unix_info->sanitized_username,
520                               session_info->unix_info->unix_name,
521                               session_info->info->domain_name);
522
523         reload_services(smb2req->sconn, conn_snum_used, true);
524
525         session->status = NT_STATUS_OK;
526         TALLOC_FREE(session->global->auth_session_info);
527         session->global->auth_session_info = talloc_move(session->global,
528                                                          &session_info);
529         session->global->auth_session_info_seqnum += 1;
530         for (i=0; i < session->global->num_channels; i++) {
531                 struct smbXsrv_channel_global0 *_c =
532                         &session->global->channels[i];
533
534                 _c->auth_session_info_seqnum =
535                         session->global->auth_session_info_seqnum;
536         }
537         session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
538         session->global->expiration_time = gensec_expire_time(auth->gensec);
539
540         TALLOC_FREE(auth);
541         status = smbXsrv_session_update(session);
542         if (!NT_STATUS_IS_OK(status)) {
543                 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
544                           (unsigned long long)session->compat->vuid,
545                           nt_errstr(status)));
546                 return NT_STATUS_LOGON_FAILURE;
547         }
548
549         conn_clear_vuid_caches(xconn->client->sconn, session->compat->vuid);
550
551         if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
552                 smb2req->do_signing = true;
553         }
554
555         *out_session_id = session->global->session_wire_id;
556
557         return NT_STATUS_OK;
558 }
559
560 static NTSTATUS smbd_smb2_bind_auth_return(struct smbXsrv_session *session,
561                                            struct smbXsrv_session_auth0 **_auth,
562                                            struct smbd_smb2_request *smb2req,
563                                            struct auth_session_info *session_info,
564                                            uint16_t *out_session_flags,
565                                            uint64_t *out_session_id)
566 {
567         NTSTATUS status;
568         struct smbXsrv_session *x = session;
569         struct smbXsrv_session_auth0 *auth = *_auth;
570         struct smbXsrv_connection *xconn = smb2req->xconn;
571         struct smbXsrv_channel_global0 *c = NULL;
572         uint8_t session_key[16];
573         size_t i;
574         struct _derivation {
575                 DATA_BLOB label;
576                 DATA_BLOB context;
577         };
578         struct {
579                 struct _derivation signing;
580         } derivation = { };
581         bool ok;
582
583         *_auth = NULL;
584
585         if (xconn->protocol >= PROTOCOL_SMB3_10) {
586                 struct smbXsrv_preauth *preauth;
587                 struct _derivation *d;
588                 DATA_BLOB p;
589                 struct hc_sha512state sctx;
590
591                 preauth = talloc_move(smb2req, &auth->preauth);
592
593                 samba_SHA512_Init(&sctx);
594                 samba_SHA512_Update(&sctx, preauth->sha512_value,
595                                     sizeof(preauth->sha512_value));
596                 for (i = 1; i < smb2req->in.vector_count; i++) {
597                         samba_SHA512_Update(&sctx,
598                                             smb2req->in.vector[i].iov_base,
599                                             smb2req->in.vector[i].iov_len);
600                 }
601                 samba_SHA512_Final(preauth->sha512_value, &sctx);
602
603                 p = data_blob_const(preauth->sha512_value,
604                                     sizeof(preauth->sha512_value));
605
606                 d = &derivation.signing;
607                 d->label = data_blob_string_const_null("SMBSigningKey");
608                 d->context = p;
609
610         } else if (xconn->protocol >= PROTOCOL_SMB2_24) {
611                 struct _derivation *d;
612
613                 d = &derivation.signing;
614                 d->label = data_blob_string_const_null("SMB2AESCMAC");
615                 d->context = data_blob_string_const_null("SmbSign");
616         }
617
618         status = smbXsrv_session_find_channel(session, xconn, &c);
619         if (!NT_STATUS_IS_OK(status)) {
620                 return status;
621         }
622
623         ok = security_token_is_sid(session_info->security_token,
624                         &x->global->auth_session_info->security_token->sids[0]);
625         if (!ok) {
626                 return NT_STATUS_NOT_SUPPORTED;
627         }
628
629         if (session_info->session_key.length == 0) {
630                 /* See [MS-SMB2] 3.3.5.2.4 for the return code. */
631                 return NT_STATUS_NOT_SUPPORTED;
632         }
633
634         ZERO_STRUCT(session_key);
635         memcpy(session_key, session_info->session_key.data,
636                MIN(session_info->session_key.length, sizeof(session_key)));
637
638         c->signing_key = data_blob_talloc(x->global,
639                                           session_key,
640                                           sizeof(session_key));
641         if (c->signing_key.data == NULL) {
642                 ZERO_STRUCT(session_key);
643                 return NT_STATUS_NO_MEMORY;
644         }
645
646         if (xconn->protocol >= PROTOCOL_SMB2_24) {
647                 struct _derivation *d = &derivation.signing;
648
649                 smb2_key_derivation(session_key, sizeof(session_key),
650                                     d->label.data, d->label.length,
651                                     d->context.data, d->context.length,
652                                     c->signing_key.data);
653         }
654         ZERO_STRUCT(session_key);
655
656         TALLOC_FREE(auth);
657         status = smbXsrv_session_update(session);
658         if (!NT_STATUS_IS_OK(status)) {
659                 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
660                           (unsigned long long)session->compat->vuid,
661                           nt_errstr(status)));
662                 return NT_STATUS_LOGON_FAILURE;
663         }
664
665         *out_session_id = session->global->session_wire_id;
666
667         return NT_STATUS_OK;
668 }
669
670 struct smbd_smb2_session_setup_state {
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         struct smbXsrv_session *session;
679         struct smbXsrv_session_auth0 *auth;
680         struct auth_session_info *session_info;
681         uint16_t out_session_flags;
682         DATA_BLOB out_security_buffer;
683         uint64_t out_session_id;
684 };
685
686 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq);
687 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq);
688 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req);
689
690 static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
691                                         struct tevent_context *ev,
692                                         struct smbd_smb2_request *smb2req,
693                                         uint64_t in_session_id,
694                                         uint8_t in_flags,
695                                         uint8_t in_security_mode,
696                                         uint64_t in_previous_session_id,
697                                         DATA_BLOB in_security_buffer)
698 {
699         struct tevent_req *req;
700         struct smbd_smb2_session_setup_state *state;
701         NTSTATUS status;
702         NTTIME now = timeval_to_nttime(&smb2req->request_time);
703         struct tevent_req *subreq;
704         struct smbXsrv_channel_global0 *c = NULL;
705         enum security_user_level seclvl;
706
707         req = tevent_req_create(mem_ctx, &state,
708                                 struct smbd_smb2_session_setup_state);
709         if (req == NULL) {
710                 return NULL;
711         }
712         state->ev = ev;
713         state->smb2req = smb2req;
714         state->in_session_id = in_session_id;
715         state->in_flags = in_flags;
716         state->in_security_mode = in_security_mode;
717         state->in_previous_session_id = in_previous_session_id;
718         state->in_security_buffer = in_security_buffer;
719
720         if (in_flags & SMB2_SESSION_FLAG_BINDING) {
721                 if (smb2req->xconn->protocol < PROTOCOL_SMB2_22) {
722                         tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
723                         return tevent_req_post(req, ev);
724                 }
725
726                 if (!smb2req->xconn->client->server_multi_channel_enabled) {
727                         tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
728                         return tevent_req_post(req, ev);
729                 }
730
731                 if (in_session_id == 0) {
732                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
733                         return tevent_req_post(req, ev);
734                 }
735
736                 if (smb2req->session == NULL) {
737                         tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
738                         return tevent_req_post(req, ev);
739                 }
740
741                 if (!smb2req->do_signing) {
742                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
743                         return tevent_req_post(req, ev);
744                 }
745
746                 status = smbXsrv_session_find_channel(smb2req->session,
747                                                       smb2req->xconn,
748                                                       &c);
749                 if (NT_STATUS_IS_OK(status)) {
750                         if (c->signing_key.length == 0) {
751                                 goto auth;
752                         }
753                         tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
754                         return tevent_req_post(req, ev);
755                 }
756
757                 /*
758                  * OLD: 3.00 NEW 3.02 => INVALID_PARAMETER
759                  * OLD: 3.02 NEW 3.00 => INVALID_PARAMETER
760                  * OLD: 2.10 NEW 3.02 => ACCESS_DENIED
761                  * OLD: 3.02 NEW 2.10 => ACCESS_DENIED
762                  */
763                 if (smb2req->session->global->connection_dialect
764                     < SMB2_DIALECT_REVISION_222)
765                 {
766                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
767                         return tevent_req_post(req, ev);
768                 }
769                 if (smb2req->xconn->smb2.server.dialect
770                     < SMB2_DIALECT_REVISION_222)
771                 {
772                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
773                         return tevent_req_post(req, ev);
774                 }
775                 if (smb2req->session->global->connection_dialect
776                     != smb2req->xconn->smb2.server.dialect)
777                 {
778                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
779                         return tevent_req_post(req, ev);
780                 }
781
782                 seclvl = security_session_user_level(
783                                 smb2req->session->global->auth_session_info,
784                                 NULL);
785                 if (seclvl < SECURITY_USER) {
786                         tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
787                         return tevent_req_post(req, ev);
788                 }
789
790                 status = smbXsrv_session_add_channel(smb2req->session,
791                                                      smb2req->xconn,
792                                                      &c);
793                 if (!NT_STATUS_IS_OK(status)) {
794                         tevent_req_nterror(req, status);
795                         return tevent_req_post(req, ev);
796                 }
797
798                 status = smbXsrv_session_update(smb2req->session);
799                 if (!NT_STATUS_IS_OK(status)) {
800                         tevent_req_nterror(req, status);
801                         return tevent_req_post(req, ev);
802                 }
803         }
804
805 auth:
806
807         if (state->in_session_id == 0) {
808                 /* create a new session */
809                 status = smbXsrv_session_create(state->smb2req->xconn,
810                                                 now, &state->session);
811                 if (tevent_req_nterror(req, status)) {
812                         return tevent_req_post(req, ev);
813                 }
814                 smb2req->session = state->session;
815         } else {
816                 if (smb2req->session == NULL) {
817                         tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
818                         return tevent_req_post(req, ev);
819                 }
820
821                 state->session = smb2req->session;
822                 status = state->session->status;
823                 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
824                         status = NT_STATUS_OK;
825                 }
826                 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
827                         status = NT_STATUS_OK;
828                 }
829                 if (tevent_req_nterror(req, status)) {
830                         return tevent_req_post(req, ev);
831                 }
832                 if (!(in_flags & SMB2_SESSION_FLAG_BINDING)) {
833                         state->session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
834                 }
835         }
836
837         status = smbXsrv_session_find_channel(smb2req->session,
838                                               smb2req->xconn, &c);
839         if (!NT_STATUS_IS_OK(status)) {
840                 tevent_req_nterror(req, status);
841                 return tevent_req_post(req, ev);
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         subreq = smb2srv_session_shutdown_send(state, state->ev,
1138                                                state->smb2req->session,
1139                                                state->smb2req);
1140         if (tevent_req_nomem(subreq, req)) {
1141                 return;
1142         }
1143         tevent_req_set_callback(subreq,
1144                                 smbd_smb2_session_setup_wrap_shutdown_done,
1145                                 req);
1146 }
1147
1148 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq)
1149 {
1150         struct tevent_req *req =
1151                 tevent_req_callback_data(subreq,
1152                 struct tevent_req);
1153         struct smbd_smb2_session_setup_wrap_state *state =
1154                 tevent_req_data(req,
1155                 struct smbd_smb2_session_setup_wrap_state);
1156         NTSTATUS status;
1157
1158         status = smb2srv_session_shutdown_recv(subreq);
1159         TALLOC_FREE(subreq);
1160         if (tevent_req_nterror(req, status)) {
1161                 return;
1162         }
1163
1164         /*
1165          * we may need to sign the response, so we need to keep
1166          * the session until the response is sent to the wire.
1167          */
1168         talloc_steal(state->smb2req, state->smb2req->session);
1169
1170         tevent_req_nterror(req, state->error);
1171 }
1172
1173 static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
1174                                         uint16_t *out_session_flags,
1175                                         TALLOC_CTX *mem_ctx,
1176                                         DATA_BLOB *out_security_buffer,
1177                                         uint64_t *out_session_id)
1178 {
1179         struct smbd_smb2_session_setup_wrap_state *state =
1180                 tevent_req_data(req,
1181                 struct smbd_smb2_session_setup_wrap_state);
1182         NTSTATUS status;
1183
1184         if (tevent_req_is_nterror(req, &status)) {
1185                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1186                         tevent_req_received(req);
1187                         return nt_status_squash(status);
1188                 }
1189         } else {
1190                 status = NT_STATUS_OK;
1191         }
1192
1193         *out_session_flags = state->out_session_flags;
1194         *out_security_buffer = state->out_security_buffer;
1195         *out_session_id = state->out_session_id;
1196
1197         talloc_steal(mem_ctx, out_security_buffer->data);
1198         tevent_req_received(req);
1199         return status;
1200 }
1201
1202 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
1203                                         struct tevent_context *ev,
1204                                         struct smbd_smb2_request *smb2req);
1205 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req);
1206 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq);
1207
1208 NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req)
1209 {
1210         NTSTATUS status;
1211         struct tevent_req *subreq = NULL;
1212
1213         status = smbd_smb2_request_verify_sizes(req, 0x04);
1214         if (!NT_STATUS_IS_OK(status)) {
1215                 return smbd_smb2_request_error(req, status);
1216         }
1217
1218         subreq = smbd_smb2_logoff_send(req, req->sconn->ev_ctx, req);
1219         if (subreq == NULL) {
1220                 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
1221         }
1222         tevent_req_set_callback(subreq, smbd_smb2_request_logoff_done, req);
1223
1224         /*
1225          * Wait a long time before going async on this to allow
1226          * requests we're waiting on to finish. Set timeout to 10 secs.
1227          */
1228         return smbd_smb2_request_pending_queue(req, subreq, 10000000);
1229 }
1230
1231 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq)
1232 {
1233         struct smbd_smb2_request *smb2req =
1234                 tevent_req_callback_data(subreq,
1235                 struct smbd_smb2_request);
1236         DATA_BLOB outbody;
1237         NTSTATUS status;
1238         NTSTATUS error;
1239
1240         status = smbd_smb2_logoff_recv(subreq);
1241         TALLOC_FREE(subreq);
1242         if (!NT_STATUS_IS_OK(status)) {
1243                 error = smbd_smb2_request_error(smb2req, status);
1244                 if (!NT_STATUS_IS_OK(error)) {
1245                         smbd_server_connection_terminate(smb2req->xconn,
1246                                                         nt_errstr(error));
1247                         return;
1248                 }
1249                 return;
1250         }
1251
1252         outbody = smbd_smb2_generate_outbody(smb2req, 0x04);
1253         if (outbody.data == NULL) {
1254                 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
1255                 if (!NT_STATUS_IS_OK(error)) {
1256                         smbd_server_connection_terminate(smb2req->xconn,
1257                                                         nt_errstr(error));
1258                         return;
1259                 }
1260                 return;
1261         }
1262
1263         SSVAL(outbody.data, 0x00, 0x04);        /* struct size */
1264         SSVAL(outbody.data, 0x02, 0);           /* reserved */
1265
1266         error = smbd_smb2_request_done(smb2req, outbody, NULL);
1267         if (!NT_STATUS_IS_OK(error)) {
1268                 smbd_server_connection_terminate(smb2req->xconn,
1269                                                 nt_errstr(error));
1270                 return;
1271         }
1272 }
1273
1274 struct smbd_smb2_logoff_state {
1275         struct smbd_smb2_request *smb2req;
1276 };
1277
1278 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq);
1279
1280 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
1281                                         struct tevent_context *ev,
1282                                         struct smbd_smb2_request *smb2req)
1283 {
1284         struct tevent_req *req;
1285         struct smbd_smb2_logoff_state *state;
1286         struct tevent_req *subreq;
1287
1288         req = tevent_req_create(mem_ctx, &state,
1289                         struct smbd_smb2_logoff_state);
1290         if (req == NULL) {
1291                 return NULL;
1292         }
1293         state->smb2req = smb2req;
1294
1295         subreq = smb2srv_session_shutdown_send(state, ev,
1296                                                smb2req->session,
1297                                                smb2req);
1298         if (tevent_req_nomem(subreq, req)) {
1299                 return tevent_req_post(req, ev);
1300         }
1301         tevent_req_set_callback(subreq, smbd_smb2_logoff_shutdown_done, req);
1302
1303         return req;
1304 }
1305
1306 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq)
1307 {
1308         struct tevent_req *req = tevent_req_callback_data(
1309                 subreq, struct tevent_req);
1310         struct smbd_smb2_logoff_state *state = tevent_req_data(
1311                 req, struct smbd_smb2_logoff_state);
1312         NTSTATUS status;
1313         bool ok;
1314         const struct GUID *client_guid =
1315                 &state->smb2req->session->client->connections->smb2.client.guid;
1316
1317         status = smb2srv_session_shutdown_recv(subreq);
1318         if (tevent_req_nterror(req, status)) {
1319                 return;
1320         }
1321         TALLOC_FREE(subreq);
1322
1323         if (!GUID_all_zero(client_guid)) {
1324                 ok = remote_arch_cache_delete(client_guid);
1325                 if (!ok) {
1326                         /* Most likely not an error, but not in cache */
1327                         DBG_DEBUG("Deletion from remote arch cache failed\n");
1328                 }
1329         }
1330
1331         /*
1332          * As we've been awoken, we may have changed
1333          * uid in the meantime. Ensure we're still
1334          * root (SMB2_OP_LOGOFF has .as_root = true).
1335          */
1336         change_to_root_user();
1337
1338         status = smbXsrv_session_logoff(state->smb2req->session);
1339         if (tevent_req_nterror(req, status)) {
1340                 return;
1341         }
1342
1343         /*
1344          * we may need to sign the response, so we need to keep
1345          * the session until the response is sent to the wire.
1346          */
1347         talloc_steal(state->smb2req, state->smb2req->session);
1348
1349         tevent_req_done(req);
1350 }
1351
1352 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req)
1353 {
1354         return tevent_req_simple_recv_ntstatus(req);
1355 }