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