2b6b3a820d4d5e5ad56795da104043de06d39e27
[amitay/samba.git] / source3 / smbd / smb2_sesssetup.c
1 /*
2    Unix SMB/CIFS implementation.
3    Core SMB2 server
4
5    Copyright (C) Stefan Metzmacher 2009
6    Copyright (C) Jeremy Allison 2010
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../auth/gensec/gensec.h"
27 #include "auth.h"
28 #include "../lib/tsocket/tsocket.h"
29 #include "../libcli/security/security.h"
30 #include "../lib/util/tevent_ntstatus.h"
31
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                         tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
846                         return tevent_req_post(req, ev);
847                 }
848
849                 if (!smb2req->xconn->client->server_multi_channel_enabled) {
850                         tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
851                         return tevent_req_post(req, ev);
852                 }
853
854                 if (in_session_id == 0) {
855                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
856                         return tevent_req_post(req, ev);
857                 }
858
859                 if (smb2req->session == NULL) {
860                         tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
861                         return tevent_req_post(req, ev);
862                 }
863
864                 if (!smb2req->do_signing) {
865                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
866                         return tevent_req_post(req, ev);
867                 }
868
869                 status = smbXsrv_session_find_channel(smb2req->session,
870                                                       smb2req->xconn,
871                                                       &c);
872                 if (NT_STATUS_IS_OK(status)) {
873                         if (!smb2_signing_key_valid(c->signing_key)) {
874                                 goto auth;
875                         }
876                         tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
877                         return tevent_req_post(req, ev);
878                 }
879
880                 /*
881                  * OLD: 3.00 NEW 3.02 => INVALID_PARAMETER
882                  * OLD: 3.02 NEW 3.00 => INVALID_PARAMETER
883                  * OLD: 2.10 NEW 3.02 => ACCESS_DENIED
884                  * OLD: 3.02 NEW 2.10 => ACCESS_DENIED
885                  */
886                 if (smb2req->session->global->connection_dialect
887                     < SMB2_DIALECT_REVISION_222)
888                 {
889                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
890                         return tevent_req_post(req, ev);
891                 }
892                 if (smb2req->xconn->smb2.server.dialect
893                     < SMB2_DIALECT_REVISION_222)
894                 {
895                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
896                         return tevent_req_post(req, ev);
897                 }
898                 if (smb2req->session->global->connection_dialect
899                     != smb2req->xconn->smb2.server.dialect)
900                 {
901                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
902                         return tevent_req_post(req, ev);
903                 }
904
905                 seclvl = security_session_user_level(
906                                 smb2req->session->global->auth_session_info,
907                                 NULL);
908                 if (seclvl < SECURITY_USER) {
909                         tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
910                         return tevent_req_post(req, ev);
911                 }
912
913                 status = smbXsrv_session_add_channel(smb2req->session,
914                                                      smb2req->xconn,
915                                                      now,
916                                                      &c);
917                 if (!NT_STATUS_IS_OK(status)) {
918                         tevent_req_nterror(req, status);
919                         return tevent_req_post(req, ev);
920                 }
921
922                 status = smbXsrv_session_update(smb2req->session);
923                 if (!NT_STATUS_IS_OK(status)) {
924                         tevent_req_nterror(req, status);
925                         return tevent_req_post(req, ev);
926                 }
927         }
928
929 auth:
930
931         if (state->in_session_id == 0) {
932                 /* create a new session */
933                 status = smbXsrv_session_create(state->smb2req->xconn,
934                                                 now, &state->session);
935                 if (tevent_req_nterror(req, status)) {
936                         return tevent_req_post(req, ev);
937                 }
938                 smb2req->session = state->session;
939         } else {
940                 if (smb2req->session == NULL) {
941                         tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
942                         return tevent_req_post(req, ev);
943                 }
944
945                 state->session = smb2req->session;
946                 status = state->session->status;
947                 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
948                         status = NT_STATUS_OK;
949                 }
950                 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
951                         status = NT_STATUS_OK;
952                 }
953                 if (tevent_req_nterror(req, status)) {
954                         return tevent_req_post(req, ev);
955                 }
956                 if (!(in_flags & SMB2_SESSION_FLAG_BINDING)) {
957                         state->session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
958                 }
959         }
960
961         status = smbXsrv_session_find_channel(smb2req->session,
962                                               smb2req->xconn, &c);
963         if (!NT_STATUS_IS_OK(status)) {
964                 tevent_req_nterror(req, status);
965                 return tevent_req_post(req, ev);
966         }
967
968         status = smbXsrv_session_find_auth(state->session, smb2req->xconn,
969                                            now, &state->auth);
970         if (!NT_STATUS_IS_OK(status)) {
971                 status = smbXsrv_session_create_auth(state->session,
972                                                      smb2req->xconn, now,
973                                                      in_flags, in_security_mode,
974                                                      &state->auth);
975                 if (tevent_req_nterror(req, status)) {
976                         return tevent_req_post(req, ev);
977                 }
978         }
979
980         if (state->auth->gensec == NULL) {
981                 status = auth_generic_prepare(state->auth,
982                                               state->smb2req->xconn->remote_address,
983                                               state->smb2req->xconn->local_address,
984                                               "SMB2",
985                                               &state->auth->gensec);
986                 if (tevent_req_nterror(req, status)) {
987                         return tevent_req_post(req, ev);
988                 }
989
990                 gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_SESSION_KEY);
991                 gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
992                 gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_SMB_TRANSPORT);
993
994                 status = gensec_start_mech_by_oid(state->auth->gensec,
995                                                   GENSEC_OID_SPNEGO);
996                 if (tevent_req_nterror(req, status)) {
997                         return tevent_req_post(req, ev);
998                 }
999         }
1000
1001         status = smbXsrv_session_update(state->session);
1002         if (tevent_req_nterror(req, status)) {
1003                 return tevent_req_post(req, ev);
1004         }
1005
1006         become_root();
1007         subreq = gensec_update_send(state, state->ev,
1008                                     state->auth->gensec,
1009                                     state->in_security_buffer);
1010         unbecome_root();
1011         if (tevent_req_nomem(subreq, req)) {
1012                 return tevent_req_post(req, ev);
1013         }
1014         tevent_req_set_callback(subreq, smbd_smb2_session_setup_gensec_done, req);
1015
1016         return req;
1017 }
1018
1019 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
1020 {
1021         struct tevent_req *req =
1022                 tevent_req_callback_data(subreq,
1023                 struct tevent_req);
1024         struct smbd_smb2_session_setup_state *state =
1025                 tevent_req_data(req,
1026                 struct smbd_smb2_session_setup_state);
1027         NTSTATUS status;
1028
1029         become_root();
1030         status = gensec_update_recv(subreq, state,
1031                                     &state->out_security_buffer);
1032         unbecome_root();
1033         TALLOC_FREE(subreq);
1034         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
1035             !NT_STATUS_IS_OK(status)) {
1036                 tevent_req_nterror(req, status);
1037                 return;
1038         }
1039
1040         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1041                 state->out_session_id = state->session->global->session_wire_id;
1042                 state->smb2req->preauth = state->auth->preauth;
1043                 tevent_req_nterror(req, status);
1044                 return;
1045         }
1046
1047         status = gensec_session_info(state->auth->gensec,
1048                                      state,
1049                                      &state->session_info);
1050         if (tevent_req_nterror(req, status)) {
1051                 return;
1052         }
1053
1054         if ((state->in_previous_session_id != 0) &&
1055              (state->session->global->session_wire_id !=
1056               state->in_previous_session_id))
1057         {
1058                 subreq = smb2srv_session_close_previous_send(state, state->ev,
1059                                                 state->smb2req->xconn,
1060                                                 state->session_info,
1061                                                 state->in_previous_session_id,
1062                                                 state->session->global->session_wire_id);
1063                 if (tevent_req_nomem(subreq, req)) {
1064                         return;
1065                 }
1066                 tevent_req_set_callback(subreq,
1067                                         smbd_smb2_session_setup_previous_done,
1068                                         req);
1069                 return;
1070         }
1071
1072         smbd_smb2_session_setup_auth_return(req);
1073 }
1074
1075 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq)
1076 {
1077         struct tevent_req *req =
1078                 tevent_req_callback_data(subreq,
1079                 struct tevent_req);
1080         NTSTATUS status;
1081
1082         status = smb2srv_session_close_previous_recv(subreq);
1083         TALLOC_FREE(subreq);
1084         if (tevent_req_nterror(req, status)) {
1085                 return;
1086         }
1087
1088         smbd_smb2_session_setup_auth_return(req);
1089 }
1090
1091 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req)
1092 {
1093         struct smbd_smb2_session_setup_state *state =
1094                 tevent_req_data(req,
1095                 struct smbd_smb2_session_setup_state);
1096         NTSTATUS status;
1097
1098         if (state->in_flags & SMB2_SESSION_FLAG_BINDING) {
1099                 status = smbd_smb2_bind_auth_return(state->session,
1100                                                     &state->auth,
1101                                                     state->smb2req,
1102                                                     state->session_info,
1103                                                     &state->out_session_flags,
1104                                                     &state->out_session_id);
1105                 if (tevent_req_nterror(req, status)) {
1106                         return;
1107                 }
1108                 tevent_req_done(req);
1109                 return;
1110         }
1111
1112         if (state->session->global->auth_session_info != NULL) {
1113                 status = smbd_smb2_reauth_generic_return(state->session,
1114                                                          &state->auth,
1115                                                          state->smb2req,
1116                                                          state->session_info,
1117                                                          &state->out_session_flags,
1118                                                          &state->out_session_id);
1119                 if (tevent_req_nterror(req, status)) {
1120                         return;
1121                 }
1122                 tevent_req_done(req);
1123                 return;
1124         }
1125
1126         status = smbd_smb2_auth_generic_return(state->session,
1127                                                &state->auth,
1128                                                state->smb2req,
1129                                                state->in_security_mode,
1130                                                state->session_info,
1131                                                &state->out_session_flags,
1132                                                &state->out_session_id);
1133         if (tevent_req_nterror(req, status)) {
1134                 return;
1135         }
1136
1137         tevent_req_done(req);
1138         return;
1139 }
1140
1141 static NTSTATUS smbd_smb2_session_setup_recv(struct tevent_req *req,
1142                                         uint16_t *out_session_flags,
1143                                         TALLOC_CTX *mem_ctx,
1144                                         DATA_BLOB *out_security_buffer,
1145                                         uint64_t *out_session_id)
1146 {
1147         struct smbd_smb2_session_setup_state *state =
1148                 tevent_req_data(req,
1149                 struct smbd_smb2_session_setup_state);
1150         NTSTATUS status;
1151
1152         if (tevent_req_is_nterror(req, &status)) {
1153                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1154                         tevent_req_received(req);
1155                         return nt_status_squash(status);
1156                 }
1157         } else {
1158                 status = NT_STATUS_OK;
1159         }
1160
1161         *out_session_flags = state->out_session_flags;
1162         *out_security_buffer = state->out_security_buffer;
1163         *out_session_id = state->out_session_id;
1164
1165         talloc_steal(mem_ctx, out_security_buffer->data);
1166         tevent_req_received(req);
1167         return status;
1168 }
1169
1170 struct smbd_smb2_session_setup_wrap_state {
1171         struct tevent_context *ev;
1172         struct smbd_smb2_request *smb2req;
1173         uint64_t in_session_id;
1174         uint8_t in_flags;
1175         uint8_t in_security_mode;
1176         uint64_t in_previous_session_id;
1177         DATA_BLOB in_security_buffer;
1178         uint16_t out_session_flags;
1179         DATA_BLOB out_security_buffer;
1180         uint64_t out_session_id;
1181         NTSTATUS error;
1182 };
1183
1184 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq);
1185 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq);
1186
1187 static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
1188                                         struct tevent_context *ev,
1189                                         struct smbd_smb2_request *smb2req,
1190                                         uint64_t in_session_id,
1191                                         uint8_t in_flags,
1192                                         uint8_t in_security_mode,
1193                                         uint64_t in_previous_session_id,
1194                                         DATA_BLOB in_security_buffer)
1195 {
1196         struct tevent_req *req;
1197         struct smbd_smb2_session_setup_wrap_state *state;
1198         struct tevent_req *subreq;
1199
1200         req = tevent_req_create(mem_ctx, &state,
1201                                 struct smbd_smb2_session_setup_wrap_state);
1202         if (req == NULL) {
1203                 return NULL;
1204         }
1205         state->ev = ev;
1206         state->smb2req = smb2req;
1207         state->in_session_id = in_session_id;
1208         state->in_flags = in_flags;
1209         state->in_security_mode = in_security_mode;
1210         state->in_previous_session_id = in_previous_session_id;
1211         state->in_security_buffer = in_security_buffer;
1212
1213         subreq = smbd_smb2_session_setup_send(state, state->ev,
1214                                               state->smb2req,
1215                                               state->in_session_id,
1216                                               state->in_flags,
1217                                               state->in_security_mode,
1218                                               state->in_previous_session_id,
1219                                               state->in_security_buffer);
1220         if (tevent_req_nomem(subreq, req)) {
1221                 return tevent_req_post(req, ev);
1222         }
1223         tevent_req_set_callback(subreq,
1224                                 smbd_smb2_session_setup_wrap_setup_done, req);
1225
1226         return req;
1227 }
1228
1229 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq)
1230 {
1231         struct tevent_req *req =
1232                 tevent_req_callback_data(subreq,
1233                 struct tevent_req);
1234         struct smbd_smb2_session_setup_wrap_state *state =
1235                 tevent_req_data(req,
1236                 struct smbd_smb2_session_setup_wrap_state);
1237         NTSTATUS status;
1238
1239         status = smbd_smb2_session_setup_recv(subreq,
1240                                               &state->out_session_flags,
1241                                               state,
1242                                               &state->out_security_buffer,
1243                                               &state->out_session_id);
1244         TALLOC_FREE(subreq);
1245         if (NT_STATUS_IS_OK(status)) {
1246                 tevent_req_done(req);
1247                 return;
1248         }
1249         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1250                 tevent_req_nterror(req, status);
1251                 return;
1252         }
1253
1254         if (state->smb2req->session == NULL) {
1255                 tevent_req_nterror(req, status);
1256                 return;
1257         }
1258
1259         state->error = status;
1260
1261         subreq = smb2srv_session_shutdown_send(state, state->ev,
1262                                                state->smb2req->session,
1263                                                state->smb2req);
1264         if (tevent_req_nomem(subreq, req)) {
1265                 return;
1266         }
1267         tevent_req_set_callback(subreq,
1268                                 smbd_smb2_session_setup_wrap_shutdown_done,
1269                                 req);
1270 }
1271
1272 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq)
1273 {
1274         struct tevent_req *req =
1275                 tevent_req_callback_data(subreq,
1276                 struct tevent_req);
1277         struct smbd_smb2_session_setup_wrap_state *state =
1278                 tevent_req_data(req,
1279                 struct smbd_smb2_session_setup_wrap_state);
1280         NTSTATUS status;
1281
1282         status = smb2srv_session_shutdown_recv(subreq);
1283         TALLOC_FREE(subreq);
1284         if (tevent_req_nterror(req, status)) {
1285                 return;
1286         }
1287
1288         /*
1289          * we may need to sign the response, so we need to keep
1290          * the session until the response is sent to the wire.
1291          */
1292         talloc_steal(state->smb2req, state->smb2req->session);
1293
1294         tevent_req_nterror(req, state->error);
1295 }
1296
1297 static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
1298                                         uint16_t *out_session_flags,
1299                                         TALLOC_CTX *mem_ctx,
1300                                         DATA_BLOB *out_security_buffer,
1301                                         uint64_t *out_session_id)
1302 {
1303         struct smbd_smb2_session_setup_wrap_state *state =
1304                 tevent_req_data(req,
1305                 struct smbd_smb2_session_setup_wrap_state);
1306         NTSTATUS status;
1307
1308         if (tevent_req_is_nterror(req, &status)) {
1309                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1310                         tevent_req_received(req);
1311                         return nt_status_squash(status);
1312                 }
1313         } else {
1314                 status = NT_STATUS_OK;
1315         }
1316
1317         *out_session_flags = state->out_session_flags;
1318         *out_security_buffer = state->out_security_buffer;
1319         *out_session_id = state->out_session_id;
1320
1321         talloc_steal(mem_ctx, out_security_buffer->data);
1322         tevent_req_received(req);
1323         return status;
1324 }
1325
1326 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
1327                                         struct tevent_context *ev,
1328                                         struct smbd_smb2_request *smb2req);
1329 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req);
1330 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq);
1331
1332 NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req)
1333 {
1334         NTSTATUS status;
1335         struct tevent_req *subreq = NULL;
1336
1337         status = smbd_smb2_request_verify_sizes(req, 0x04);
1338         if (!NT_STATUS_IS_OK(status)) {
1339                 return smbd_smb2_request_error(req, status);
1340         }
1341
1342         subreq = smbd_smb2_logoff_send(req, req->sconn->ev_ctx, req);
1343         if (subreq == NULL) {
1344                 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
1345         }
1346         tevent_req_set_callback(subreq, smbd_smb2_request_logoff_done, req);
1347
1348         /*
1349          * Avoid sending a STATUS_PENDING message, it's very likely
1350          * the client won't expect that.
1351          */
1352         return smbd_smb2_request_pending_queue(req, subreq, 0);
1353 }
1354
1355 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq)
1356 {
1357         struct smbd_smb2_request *smb2req =
1358                 tevent_req_callback_data(subreq,
1359                 struct smbd_smb2_request);
1360         DATA_BLOB outbody;
1361         NTSTATUS status;
1362         NTSTATUS error;
1363
1364         status = smbd_smb2_logoff_recv(subreq);
1365         TALLOC_FREE(subreq);
1366         if (!NT_STATUS_IS_OK(status)) {
1367                 error = smbd_smb2_request_error(smb2req, status);
1368                 if (!NT_STATUS_IS_OK(error)) {
1369                         smbd_server_connection_terminate(smb2req->xconn,
1370                                                         nt_errstr(error));
1371                         return;
1372                 }
1373                 return;
1374         }
1375
1376         outbody = smbd_smb2_generate_outbody(smb2req, 0x04);
1377         if (outbody.data == NULL) {
1378                 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
1379                 if (!NT_STATUS_IS_OK(error)) {
1380                         smbd_server_connection_terminate(smb2req->xconn,
1381                                                         nt_errstr(error));
1382                         return;
1383                 }
1384                 return;
1385         }
1386
1387         SSVAL(outbody.data, 0x00, 0x04);        /* struct size */
1388         SSVAL(outbody.data, 0x02, 0);           /* reserved */
1389
1390         error = smbd_smb2_request_done(smb2req, outbody, NULL);
1391         if (!NT_STATUS_IS_OK(error)) {
1392                 smbd_server_connection_terminate(smb2req->xconn,
1393                                                 nt_errstr(error));
1394                 return;
1395         }
1396 }
1397
1398 struct smbd_smb2_logoff_state {
1399         struct smbd_smb2_request *smb2req;
1400 };
1401
1402 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq);
1403
1404 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
1405                                         struct tevent_context *ev,
1406                                         struct smbd_smb2_request *smb2req)
1407 {
1408         struct tevent_req *req;
1409         struct smbd_smb2_logoff_state *state;
1410         struct tevent_req *subreq;
1411
1412         req = tevent_req_create(mem_ctx, &state,
1413                         struct smbd_smb2_logoff_state);
1414         if (req == NULL) {
1415                 return NULL;
1416         }
1417         state->smb2req = smb2req;
1418
1419         subreq = smb2srv_session_shutdown_send(state, ev,
1420                                                smb2req->session,
1421                                                smb2req);
1422         if (tevent_req_nomem(subreq, req)) {
1423                 return tevent_req_post(req, ev);
1424         }
1425         tevent_req_set_callback(subreq, smbd_smb2_logoff_shutdown_done, req);
1426
1427         return req;
1428 }
1429
1430 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq)
1431 {
1432         struct tevent_req *req = tevent_req_callback_data(
1433                 subreq, struct tevent_req);
1434         struct smbd_smb2_logoff_state *state = tevent_req_data(
1435                 req, struct smbd_smb2_logoff_state);
1436         NTSTATUS status;
1437         bool ok;
1438         const struct GUID *client_guid =
1439                 &state->smb2req->session->client->global->client_guid;
1440
1441         status = smb2srv_session_shutdown_recv(subreq);
1442         if (tevent_req_nterror(req, status)) {
1443                 return;
1444         }
1445         TALLOC_FREE(subreq);
1446
1447         if (!GUID_all_zero(client_guid)) {
1448                 ok = remote_arch_cache_delete(client_guid);
1449                 if (!ok) {
1450                         /* Most likely not an error, but not in cache */
1451                         DBG_DEBUG("Deletion from remote arch cache failed\n");
1452                 }
1453         }
1454
1455         /*
1456          * As we've been awoken, we may have changed
1457          * uid in the meantime. Ensure we're still
1458          * root (SMB2_OP_LOGOFF has .as_root = true).
1459          */
1460         change_to_root_user();
1461
1462         status = smbXsrv_session_logoff(state->smb2req->session);
1463         if (tevent_req_nterror(req, status)) {
1464                 return;
1465         }
1466
1467         /*
1468          * we may need to sign the response, so we need to keep
1469          * the session until the response is sent to the wire.
1470          */
1471         talloc_steal(state->smb2req, state->smb2req->session);
1472
1473         tevent_req_done(req);
1474 }
1475
1476 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req)
1477 {
1478         return tevent_req_simple_recv_ntstatus(req);
1479 }