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