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