14249dfa7f341f8ef8af000346e75c8fafe5ac0d
[obnox/samba/samba-obnox.git] / source3 / smbd / smb2_sesssetup.c
1 /*
2    Unix SMB/CIFS implementation.
3    Core SMB2 server
4
5    Copyright (C) Stefan Metzmacher 2009
6    Copyright (C) Jeremy Allison 2010
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "../libcli/smb/smb_common.h"
26 #include "../auth/gensec/gensec.h"
27 #include "auth.h"
28 #include "../lib/tsocket/tsocket.h"
29 #include "../libcli/security/security.h"
30 #include "../lib/util/tevent_ntstatus.h"
31 #include "lib/crypto/sha512.h"
32 #include "lib/crypto/aes.h"
33 #include "lib/crypto/aes_ccm_128.h"
34 #include "lib/crypto/aes_gcm_128.h"
35
36 static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
37                                         struct tevent_context *ev,
38                                         struct smbd_smb2_request *smb2req,
39                                         uint64_t in_session_id,
40                                         uint8_t in_flags,
41                                         uint8_t in_security_mode,
42                                         uint64_t in_previous_session_id,
43                                         DATA_BLOB in_security_buffer);
44 static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
45                                         uint16_t *out_session_flags,
46                                         TALLOC_CTX *mem_ctx,
47                                         DATA_BLOB *out_security_buffer,
48                                         uint64_t *out_session_id);
49
50 static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq);
51
52 NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *smb2req)
53 {
54         const uint8_t *inhdr;
55         const uint8_t *inbody;
56         uint64_t in_session_id;
57         uint8_t in_flags;
58         uint8_t in_security_mode;
59         uint64_t in_previous_session_id;
60         uint16_t in_security_offset;
61         uint16_t in_security_length;
62         DATA_BLOB in_security_buffer;
63         NTSTATUS status;
64         struct tevent_req *subreq;
65
66         status = smbd_smb2_request_verify_sizes(smb2req, 0x19);
67         if (!NT_STATUS_IS_OK(status)) {
68                 return smbd_smb2_request_error(smb2req, status);
69         }
70         inhdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
71         inbody = SMBD_SMB2_IN_BODY_PTR(smb2req);
72
73         in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
74
75         in_flags = CVAL(inbody, 0x02);
76         in_security_mode = CVAL(inbody, 0x03);
77         /* Capabilities = IVAL(inbody, 0x04) */
78         /* Channel = IVAL(inbody, 0x08) */
79         in_security_offset = SVAL(inbody, 0x0C);
80         in_security_length = SVAL(inbody, 0x0E);
81         in_previous_session_id = BVAL(inbody, 0x10);
82
83         if (in_security_offset != (SMB2_HDR_BODY + SMBD_SMB2_IN_BODY_LEN(smb2req))) {
84                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
85         }
86
87         if (in_security_length > SMBD_SMB2_IN_DYN_LEN(smb2req)) {
88                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
89         }
90
91         in_security_buffer.data = SMBD_SMB2_IN_DYN_PTR(smb2req);
92         in_security_buffer.length = in_security_length;
93
94         subreq = smbd_smb2_session_setup_wrap_send(smb2req,
95                                                    smb2req->sconn->ev_ctx,
96                                                    smb2req,
97                                                    in_session_id,
98                                                    in_flags,
99                                                    in_security_mode,
100                                                    in_previous_session_id,
101                                                    in_security_buffer);
102         if (subreq == NULL) {
103                 return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
104         }
105         tevent_req_set_callback(subreq, smbd_smb2_request_sesssetup_done, smb2req);
106
107         return smbd_smb2_request_pending_queue(smb2req, subreq, 500);
108 }
109
110 static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq)
111 {
112         struct smbd_smb2_request *smb2req =
113                 tevent_req_callback_data(subreq,
114                 struct smbd_smb2_request);
115         uint8_t *outhdr;
116         DATA_BLOB outbody;
117         DATA_BLOB outdyn;
118         uint16_t out_session_flags = 0;
119         uint64_t out_session_id = 0;
120         uint16_t out_security_offset;
121         DATA_BLOB out_security_buffer = data_blob_null;
122         NTSTATUS status;
123         NTSTATUS error; /* transport error */
124
125         status = smbd_smb2_session_setup_wrap_recv(subreq,
126                                                    &out_session_flags,
127                                                    smb2req,
128                                                    &out_security_buffer,
129                                                    &out_session_id);
130         TALLOC_FREE(subreq);
131         if (!NT_STATUS_IS_OK(status) &&
132             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
133                 status = nt_status_squash(status);
134                 error = smbd_smb2_request_error(smb2req, status);
135                 if (!NT_STATUS_IS_OK(error)) {
136                         smbd_server_connection_terminate(smb2req->xconn,
137                                                          nt_errstr(error));
138                         return;
139                 }
140                 return;
141         }
142
143         out_security_offset = SMB2_HDR_BODY + 0x08;
144
145         outhdr = SMBD_SMB2_OUT_HDR_PTR(smb2req);
146
147         outbody = smbd_smb2_generate_outbody(smb2req, 0x08);
148         if (outbody.data == NULL) {
149                 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
150                 if (!NT_STATUS_IS_OK(error)) {
151                         smbd_server_connection_terminate(smb2req->xconn,
152                                                          nt_errstr(error));
153                         return;
154                 }
155                 return;
156         }
157
158         SBVAL(outhdr, SMB2_HDR_SESSION_ID, out_session_id);
159
160         SSVAL(outbody.data, 0x00, 0x08 + 1);    /* struct size */
161         SSVAL(outbody.data, 0x02,
162               out_session_flags);               /* session flags */
163         SSVAL(outbody.data, 0x04,
164               out_security_offset);             /* security buffer offset */
165         SSVAL(outbody.data, 0x06,
166               out_security_buffer.length);      /* security buffer length */
167
168         outdyn = out_security_buffer;
169
170         error = smbd_smb2_request_done_ex(smb2req, status, outbody, &outdyn,
171                                            __location__);
172         if (!NT_STATUS_IS_OK(error)) {
173                 smbd_server_connection_terminate(smb2req->xconn,
174                                                  nt_errstr(error));
175                 return;
176         }
177 }
178
179 static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
180                                         struct smbXsrv_session_auth0 **_auth,
181                                         struct smbd_smb2_request *smb2req,
182                                         uint8_t in_security_mode,
183                                         struct auth_session_info *session_info,
184                                         uint16_t *out_session_flags,
185                                         uint64_t *out_session_id)
186 {
187         NTSTATUS status;
188         bool guest = false;
189         uint8_t session_key[16];
190         struct smbXsrv_session *x = session;
191         struct smbXsrv_session_auth0 *auth = *_auth;
192         struct smbXsrv_connection *xconn = smb2req->xconn;
193         size_t i;
194         struct _derivation {
195                 DATA_BLOB label;
196                 DATA_BLOB context;
197         };
198         struct {
199                 struct _derivation signing;
200                 struct _derivation encryption;
201                 struct _derivation decryption;
202                 struct _derivation application;
203         } derivation = { };
204
205         *_auth = NULL;
206
207         if (xconn->protocol >= PROTOCOL_SMB3_10) {
208                 struct smbXsrv_preauth *preauth;
209                 struct _derivation *d;
210                 DATA_BLOB p;
211                 struct hc_sha512state sctx;
212
213                 preauth = talloc_move(smb2req, &auth->preauth);
214
215                 samba_SHA512_Init(&sctx);
216                 samba_SHA512_Update(&sctx, preauth->sha512_value,
217                                     sizeof(preauth->sha512_value));
218                 for (i = 1; i < smb2req->in.vector_count; i++) {
219                         samba_SHA512_Update(&sctx,
220                                             smb2req->in.vector[i].iov_base,
221                                             smb2req->in.vector[i].iov_len);
222                 }
223                 samba_SHA512_Final(preauth->sha512_value, &sctx);
224
225                 p = data_blob_const(preauth->sha512_value,
226                                     sizeof(preauth->sha512_value));
227
228                 d = &derivation.signing;
229                 d->label = data_blob_string_const_null("SMBSigningKey");
230                 d->context = p;
231
232                 d = &derivation.decryption;
233                 d->label = data_blob_string_const_null("SMBC2SCipherKey");
234                 d->context = p;
235
236                 d = &derivation.encryption;
237                 d->label = data_blob_string_const_null("SMBS2CCipherKey");
238                 d->context = p;
239
240                 d = &derivation.application;
241                 d->label = data_blob_string_const_null("SMBAppKey");
242                 d->context = p;
243
244         } else if (xconn->protocol >= PROTOCOL_SMB2_24) {
245                 struct _derivation *d;
246
247                 d = &derivation.signing;
248                 d->label = data_blob_string_const_null("SMB2AESCMAC");
249                 d->context = data_blob_string_const_null("SmbSign");
250
251                 d = &derivation.decryption;
252                 d->label = data_blob_string_const_null("SMB2AESCCM");
253                 d->context = data_blob_string_const_null("ServerIn ");
254
255                 d = &derivation.encryption;
256                 d->label = data_blob_string_const_null("SMB2AESCCM");
257                 d->context = data_blob_string_const_null("ServerOut");
258
259                 d = &derivation.application;
260                 d->label = data_blob_string_const_null("SMB2APP");
261                 d->context = data_blob_string_const_null("SmbRpc");
262         }
263
264         if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
265             lp_server_signing() == SMB_SIGNING_REQUIRED) {
266                 x->global->signing_required = true;
267         }
268
269         if ((lp_smb_encrypt(-1) >= SMB_SIGNING_DESIRED) &&
270             (xconn->smb2.client.capabilities & SMB2_CAP_ENCRYPTION)) {
271                 x->encryption_desired = true;
272         }
273
274         if (lp_smb_encrypt(-1) == SMB_SIGNING_REQUIRED) {
275                 x->encryption_desired = true;
276                 x->global->encryption_required = true;
277         }
278
279         if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
280                 /* we map anonymous to guest internally */
281                 *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
282                 *out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
283                 /* force no signing */
284                 x->global->signing_required = false;
285                 guest = true;
286         }
287
288         if (guest && x->global->encryption_required) {
289                 DEBUG(1,("reject guest session as encryption is required\n"));
290                 return NT_STATUS_ACCESS_DENIED;
291         }
292
293         if (xconn->smb2.server.cipher == 0) {
294                 if (x->global->encryption_required) {
295                         DEBUG(1,("reject session with dialect[0x%04X] "
296                                  "as encryption is required\n",
297                                  xconn->smb2.server.dialect));
298                         return NT_STATUS_ACCESS_DENIED;
299                 }
300         }
301
302         if (x->encryption_desired) {
303                 *out_session_flags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
304         }
305
306         ZERO_STRUCT(session_key);
307         memcpy(session_key, session_info->session_key.data,
308                MIN(session_info->session_key.length, sizeof(session_key)));
309
310         x->global->signing_key = data_blob_talloc(x->global,
311                                                   session_key,
312                                                   sizeof(session_key));
313         if (x->global->signing_key.data == NULL) {
314                 ZERO_STRUCT(session_key);
315                 return NT_STATUS_NO_MEMORY;
316         }
317
318         if (xconn->protocol >= PROTOCOL_SMB2_24) {
319                 struct _derivation *d = &derivation.signing;
320
321                 smb2_key_derivation(session_key, sizeof(session_key),
322                                     d->label.data, d->label.length,
323                                     d->context.data, d->context.length,
324                                     x->global->signing_key.data);
325         }
326
327         if (xconn->protocol >= PROTOCOL_SMB2_24) {
328                 struct _derivation *d = &derivation.decryption;
329
330                 x->global->decryption_key = data_blob_talloc(x->global,
331                                                              session_key,
332                                                              sizeof(session_key));
333                 if (x->global->decryption_key.data == NULL) {
334                         ZERO_STRUCT(session_key);
335                         return NT_STATUS_NO_MEMORY;
336                 }
337
338                 smb2_key_derivation(session_key, sizeof(session_key),
339                                     d->label.data, d->label.length,
340                                     d->context.data, d->context.length,
341                                     x->global->decryption_key.data);
342         }
343
344         if (xconn->protocol >= PROTOCOL_SMB2_24) {
345                 struct _derivation *d = &derivation.encryption;
346                 size_t nonce_size;
347
348                 x->global->encryption_key = data_blob_talloc(x->global,
349                                                              session_key,
350                                                              sizeof(session_key));
351                 if (x->global->encryption_key.data == NULL) {
352                         ZERO_STRUCT(session_key);
353                         return NT_STATUS_NO_MEMORY;
354                 }
355
356                 smb2_key_derivation(session_key, sizeof(session_key),
357                                     d->label.data, d->label.length,
358                                     d->context.data, d->context.length,
359                                     x->global->encryption_key.data);
360
361                 /*
362                  * CCM and GCM algorithms must never have their
363                  * nonce wrap, or the security of the whole
364                  * communication and the keys is destroyed.
365                  * We must drop the connection once we have
366                  * transfered too much data.
367                  *
368                  * NOTE: We assume nonces greater than 8 bytes.
369                  */
370                 generate_random_buffer((uint8_t *)&x->nonce_high_random,
371                                        sizeof(x->nonce_high_random));
372                 switch (xconn->smb2.server.cipher) {
373                 case SMB2_ENCRYPTION_AES128_CCM:
374                         nonce_size = AES_CCM_128_NONCE_SIZE;
375                         break;
376                 case SMB2_ENCRYPTION_AES128_GCM:
377                         nonce_size = AES_GCM_128_IV_SIZE;
378                         break;
379                 default:
380                         nonce_size = 0;
381                         break;
382                 }
383                 x->nonce_high_max = SMB2_NONCE_HIGH_MAX(nonce_size);
384                 x->nonce_high = 0;
385                 x->nonce_low = 0;
386         }
387
388         x->global->application_key = data_blob_dup_talloc(x->global,
389                                                 x->global->signing_key);
390         if (x->global->application_key.data == NULL) {
391                 ZERO_STRUCT(session_key);
392                 return NT_STATUS_NO_MEMORY;
393         }
394
395         if (xconn->protocol >= PROTOCOL_SMB2_24) {
396                 struct _derivation *d = &derivation.application;
397
398                 smb2_key_derivation(session_key, sizeof(session_key),
399                                     d->label.data, d->label.length,
400                                     d->context.data, d->context.length,
401                                     x->global->application_key.data);
402         }
403         ZERO_STRUCT(session_key);
404
405         x->global->channels[0].signing_key = data_blob_dup_talloc(x->global->channels,
406                                                 x->global->signing_key);
407         if (x->global->channels[0].signing_key.data == NULL) {
408                 return NT_STATUS_NO_MEMORY;
409         }
410
411         data_blob_clear_free(&session_info->session_key);
412         session_info->session_key = data_blob_dup_talloc(session_info,
413                                                 x->global->application_key);
414         if (session_info->session_key.data == NULL) {
415                 return NT_STATUS_NO_MEMORY;
416         }
417
418         session->compat = talloc_zero(session, struct user_struct);
419         if (session->compat == NULL) {
420                 return NT_STATUS_NO_MEMORY;
421         }
422         session->compat->session = session;
423         session->compat->homes_snum = -1;
424         session->compat->session_info = session_info;
425         session->compat->session_keystr = NULL;
426         session->compat->vuid = session->global->session_wire_id;
427         DLIST_ADD(smb2req->sconn->users, session->compat);
428         smb2req->sconn->num_users++;
429
430         if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
431                 session->compat->homes_snum =
432                         register_homes_share(session_info->unix_info->unix_name);
433         }
434
435         set_current_user_info(session_info->unix_info->sanitized_username,
436                               session_info->unix_info->unix_name,
437                               session_info->info->domain_name);
438
439         reload_services(smb2req->sconn, conn_snum_used, true);
440
441         session->status = NT_STATUS_OK;
442         session->global->auth_session_info = talloc_move(session->global,
443                                                          &session_info);
444         session->global->auth_session_info_seqnum += 1;
445         for (i=0; i < session->global->num_channels; i++) {
446                 struct smbXsrv_channel_global0 *_c =
447                         &session->global->channels[i];
448
449                 _c->auth_session_info_seqnum =
450                         session->global->auth_session_info_seqnum;
451         }
452         session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
453         session->global->expiration_time = gensec_expire_time(auth->gensec);
454
455         if (!session_claim(session)) {
456                 DEBUG(1, ("smb2: Failed to claim session "
457                         "for vuid=%llu\n",
458                         (unsigned long long)session->compat->vuid));
459                 return NT_STATUS_LOGON_FAILURE;
460         }
461
462         TALLOC_FREE(auth);
463         status = smbXsrv_session_update(session);
464         if (!NT_STATUS_IS_OK(status)) {
465                 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
466                           (unsigned long long)session->compat->vuid,
467                           nt_errstr(status)));
468                 return NT_STATUS_LOGON_FAILURE;
469         }
470
471         /*
472          * we attach the session to the request
473          * so that the response can be signed
474          */
475         if (!guest) {
476                 smb2req->do_signing = true;
477         }
478
479         global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
480
481         *out_session_id = session->global->session_wire_id;
482
483         return NT_STATUS_OK;
484 }
485
486 static NTSTATUS smbd_smb2_reauth_generic_return(struct smbXsrv_session *session,
487                                         struct smbXsrv_session_auth0 **_auth,
488                                         struct smbd_smb2_request *smb2req,
489                                         struct auth_session_info *session_info,
490                                         uint16_t *out_session_flags,
491                                         uint64_t *out_session_id)
492 {
493         NTSTATUS status;
494         struct smbXsrv_session *x = session;
495         struct smbXsrv_session_auth0 *auth = *_auth;
496         size_t i;
497
498         *_auth = NULL;
499
500         data_blob_clear_free(&session_info->session_key);
501         session_info->session_key = data_blob_dup_talloc(session_info,
502                                                 x->global->application_key);
503         if (session_info->session_key.data == NULL) {
504                 return NT_STATUS_NO_MEMORY;
505         }
506
507         session->compat->session_info = session_info;
508         session->compat->vuid = session->global->session_wire_id;
509
510         session->compat->homes_snum =
511                         register_homes_share(session_info->unix_info->unix_name);
512
513         set_current_user_info(session_info->unix_info->sanitized_username,
514                               session_info->unix_info->unix_name,
515                               session_info->info->domain_name);
516
517         reload_services(smb2req->sconn, conn_snum_used, true);
518
519         session->status = NT_STATUS_OK;
520         TALLOC_FREE(session->global->auth_session_info);
521         session->global->auth_session_info = talloc_move(session->global,
522                                                          &session_info);
523         session->global->auth_session_info_seqnum += 1;
524         for (i=0; i < session->global->num_channels; i++) {
525                 struct smbXsrv_channel_global0 *_c =
526                         &session->global->channels[i];
527
528                 _c->auth_session_info_seqnum =
529                         session->global->auth_session_info_seqnum;
530         }
531         session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
532         session->global->expiration_time = gensec_expire_time(auth->gensec);
533
534         TALLOC_FREE(auth);
535         status = smbXsrv_session_update(session);
536         if (!NT_STATUS_IS_OK(status)) {
537                 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
538                           (unsigned long long)session->compat->vuid,
539                           nt_errstr(status)));
540                 return NT_STATUS_LOGON_FAILURE;
541         }
542
543         conn_clear_vuid_caches(smb2req->sconn, session->compat->vuid);
544
545         if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
546                 smb2req->do_signing = true;
547         }
548
549         *out_session_id = session->global->session_wire_id;
550
551         return NT_STATUS_OK;
552 }
553
554 struct smbd_smb2_session_setup_state {
555         struct tevent_context *ev;
556         struct smbd_smb2_request *smb2req;
557         uint64_t in_session_id;
558         uint8_t in_flags;
559         uint8_t in_security_mode;
560         uint64_t in_previous_session_id;
561         DATA_BLOB in_security_buffer;
562         struct smbXsrv_session *session;
563         struct smbXsrv_session_auth0 *auth;
564         struct auth_session_info *session_info;
565         uint16_t out_session_flags;
566         DATA_BLOB out_security_buffer;
567         uint64_t out_session_id;
568 };
569
570 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq);
571 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq);
572 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req);
573
574 static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
575                                         struct tevent_context *ev,
576                                         struct smbd_smb2_request *smb2req,
577                                         uint64_t in_session_id,
578                                         uint8_t in_flags,
579                                         uint8_t in_security_mode,
580                                         uint64_t in_previous_session_id,
581                                         DATA_BLOB in_security_buffer)
582 {
583         struct tevent_req *req;
584         struct smbd_smb2_session_setup_state *state;
585         NTSTATUS status;
586         NTTIME now = timeval_to_nttime(&smb2req->request_time);
587         struct tevent_req *subreq;
588         struct smbXsrv_channel_global0 *c = NULL;
589
590         req = tevent_req_create(mem_ctx, &state,
591                                 struct smbd_smb2_session_setup_state);
592         if (req == NULL) {
593                 return NULL;
594         }
595         state->ev = ev;
596         state->smb2req = smb2req;
597         state->in_session_id = in_session_id;
598         state->in_flags = in_flags;
599         state->in_security_mode = in_security_mode;
600         state->in_previous_session_id = in_previous_session_id;
601         state->in_security_buffer = in_security_buffer;
602
603         if (in_flags & SMB2_SESSION_FLAG_BINDING) {
604                 if (smb2req->xconn->protocol < PROTOCOL_SMB2_22) {
605                         tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
606                         return tevent_req_post(req, ev);
607                 }
608
609                 /*
610                  * We do not support multi channel.
611                  */
612                 tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
613                 return tevent_req_post(req, ev);
614         }
615
616         if (state->in_session_id == 0) {
617                 /* create a new session */
618                 status = smbXsrv_session_create(state->smb2req->xconn,
619                                                 now, &state->session);
620                 if (tevent_req_nterror(req, status)) {
621                         return tevent_req_post(req, ev);
622                 }
623                 smb2req->session = state->session;
624         } else {
625                 if (smb2req->session == NULL) {
626                         tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
627                         return tevent_req_post(req, ev);
628                 }
629
630                 state->session = smb2req->session;
631                 status = state->session->status;
632                 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
633                         status = NT_STATUS_OK;
634                 }
635                 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
636                         status = NT_STATUS_OK;
637                 }
638                 if (tevent_req_nterror(req, status)) {
639                         return tevent_req_post(req, ev);
640                 }
641                 if (!(in_flags & SMB2_SESSION_FLAG_BINDING)) {
642                         state->session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
643                 }
644         }
645
646         status = smbXsrv_session_find_channel(smb2req->session,
647                                               smb2req->xconn, &c);
648         if (!NT_STATUS_IS_OK(status)) {
649                 tevent_req_nterror(req, status);
650                 return tevent_req_post(req, ev);
651         }
652
653         status = smbXsrv_session_find_auth(state->session, smb2req->xconn,
654                                            now, &state->auth);
655         if (!NT_STATUS_IS_OK(status)) {
656                 status = smbXsrv_session_create_auth(state->session,
657                                                      smb2req->xconn, now,
658                                                      in_flags, in_security_mode,
659                                                      &state->auth);
660                 if (tevent_req_nterror(req, status)) {
661                         return tevent_req_post(req, ev);
662                 }
663         }
664
665         if (state->auth->gensec == NULL) {
666                 status = auth_generic_prepare(state->auth,
667                                               state->smb2req->xconn->remote_address,
668                                               &state->auth->gensec);
669                 if (tevent_req_nterror(req, status)) {
670                         return tevent_req_post(req, ev);
671                 }
672
673                 gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_SESSION_KEY);
674                 gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
675
676                 status = gensec_start_mech_by_oid(state->auth->gensec,
677                                                   GENSEC_OID_SPNEGO);
678                 if (tevent_req_nterror(req, status)) {
679                         return tevent_req_post(req, ev);
680                 }
681         }
682
683         status = smbXsrv_session_update(state->session);
684         if (tevent_req_nterror(req, status)) {
685                 return tevent_req_post(req, ev);
686         }
687
688         become_root();
689         subreq = gensec_update_send(state, state->ev,
690                                     state->auth->gensec,
691                                     state->in_security_buffer);
692         unbecome_root();
693         if (tevent_req_nomem(subreq, req)) {
694                 return tevent_req_post(req, ev);
695         }
696         tevent_req_set_callback(subreq, smbd_smb2_session_setup_gensec_done, req);
697
698         return req;
699 }
700
701 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
702 {
703         struct tevent_req *req =
704                 tevent_req_callback_data(subreq,
705                 struct tevent_req);
706         struct smbd_smb2_session_setup_state *state =
707                 tevent_req_data(req,
708                 struct smbd_smb2_session_setup_state);
709         NTSTATUS status;
710
711         become_root();
712         status = gensec_update_recv(subreq, state,
713                                     &state->out_security_buffer);
714         unbecome_root();
715         TALLOC_FREE(subreq);
716         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
717             !NT_STATUS_IS_OK(status)) {
718                 tevent_req_nterror(req, status);
719                 return;
720         }
721
722         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
723                 state->out_session_id = state->session->global->session_wire_id;
724                 state->smb2req->preauth = state->auth->preauth;
725                 tevent_req_nterror(req, status);
726                 return;
727         }
728
729         status = gensec_session_info(state->auth->gensec,
730                                      state,
731                                      &state->session_info);
732         if (tevent_req_nterror(req, status)) {
733                 return;
734         }
735
736         if ((state->in_previous_session_id != 0) &&
737              (state->session->global->session_wire_id !=
738               state->in_previous_session_id))
739         {
740                 subreq = smb2srv_session_close_previous_send(state, state->ev,
741                                                 state->smb2req->xconn,
742                                                 state->session_info,
743                                                 state->in_previous_session_id,
744                                                 state->session->global->session_wire_id);
745                 if (tevent_req_nomem(subreq, req)) {
746                         return;
747                 }
748                 tevent_req_set_callback(subreq,
749                                         smbd_smb2_session_setup_previous_done,
750                                         req);
751                 return;
752         }
753
754         smbd_smb2_session_setup_auth_return(req);
755 }
756
757 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq)
758 {
759         struct tevent_req *req =
760                 tevent_req_callback_data(subreq,
761                 struct tevent_req);
762         NTSTATUS status;
763
764         status = smb2srv_session_close_previous_recv(subreq);
765         TALLOC_FREE(subreq);
766         if (tevent_req_nterror(req, status)) {
767                 return;
768         }
769
770         smbd_smb2_session_setup_auth_return(req);
771 }
772
773 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req)
774 {
775         struct smbd_smb2_session_setup_state *state =
776                 tevent_req_data(req,
777                 struct smbd_smb2_session_setup_state);
778         NTSTATUS status;
779
780         if (state->session->global->auth_session_info != NULL) {
781                 status = smbd_smb2_reauth_generic_return(state->session,
782                                                          &state->auth,
783                                                          state->smb2req,
784                                                          state->session_info,
785                                                          &state->out_session_flags,
786                                                          &state->out_session_id);
787                 if (tevent_req_nterror(req, status)) {
788                         return;
789                 }
790                 tevent_req_done(req);
791                 return;
792         }
793
794         status = smbd_smb2_auth_generic_return(state->session,
795                                                &state->auth,
796                                                state->smb2req,
797                                                state->in_security_mode,
798                                                state->session_info,
799                                                &state->out_session_flags,
800                                                &state->out_session_id);
801         if (tevent_req_nterror(req, status)) {
802                 return;
803         }
804
805         tevent_req_done(req);
806         return;
807 }
808
809 static NTSTATUS smbd_smb2_session_setup_recv(struct tevent_req *req,
810                                         uint16_t *out_session_flags,
811                                         TALLOC_CTX *mem_ctx,
812                                         DATA_BLOB *out_security_buffer,
813                                         uint64_t *out_session_id)
814 {
815         struct smbd_smb2_session_setup_state *state =
816                 tevent_req_data(req,
817                 struct smbd_smb2_session_setup_state);
818         NTSTATUS status;
819
820         if (tevent_req_is_nterror(req, &status)) {
821                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
822                         tevent_req_received(req);
823                         return nt_status_squash(status);
824                 }
825         } else {
826                 status = NT_STATUS_OK;
827         }
828
829         *out_session_flags = state->out_session_flags;
830         *out_security_buffer = state->out_security_buffer;
831         *out_session_id = state->out_session_id;
832
833         talloc_steal(mem_ctx, out_security_buffer->data);
834         tevent_req_received(req);
835         return status;
836 }
837
838 struct smbd_smb2_session_setup_wrap_state {
839         struct tevent_context *ev;
840         struct smbd_smb2_request *smb2req;
841         uint64_t in_session_id;
842         uint8_t in_flags;
843         uint8_t in_security_mode;
844         uint64_t in_previous_session_id;
845         DATA_BLOB in_security_buffer;
846         uint16_t out_session_flags;
847         DATA_BLOB out_security_buffer;
848         uint64_t out_session_id;
849         NTSTATUS error;
850 };
851
852 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq);
853 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq);
854
855 static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
856                                         struct tevent_context *ev,
857                                         struct smbd_smb2_request *smb2req,
858                                         uint64_t in_session_id,
859                                         uint8_t in_flags,
860                                         uint8_t in_security_mode,
861                                         uint64_t in_previous_session_id,
862                                         DATA_BLOB in_security_buffer)
863 {
864         struct tevent_req *req;
865         struct smbd_smb2_session_setup_wrap_state *state;
866         struct tevent_req *subreq;
867
868         req = tevent_req_create(mem_ctx, &state,
869                                 struct smbd_smb2_session_setup_wrap_state);
870         if (req == NULL) {
871                 return NULL;
872         }
873         state->ev = ev;
874         state->smb2req = smb2req;
875         state->in_session_id = in_session_id;
876         state->in_flags = in_flags;
877         state->in_security_mode = in_security_mode;
878         state->in_previous_session_id = in_previous_session_id;
879         state->in_security_buffer = in_security_buffer;
880
881         subreq = smbd_smb2_session_setup_send(state, state->ev,
882                                               state->smb2req,
883                                               state->in_session_id,
884                                               state->in_flags,
885                                               state->in_security_mode,
886                                               state->in_previous_session_id,
887                                               state->in_security_buffer);
888         if (tevent_req_nomem(subreq, req)) {
889                 return tevent_req_post(req, ev);
890         }
891         tevent_req_set_callback(subreq,
892                                 smbd_smb2_session_setup_wrap_setup_done, req);
893
894         return req;
895 }
896
897 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq)
898 {
899         struct tevent_req *req =
900                 tevent_req_callback_data(subreq,
901                 struct tevent_req);
902         struct smbd_smb2_session_setup_wrap_state *state =
903                 tevent_req_data(req,
904                 struct smbd_smb2_session_setup_wrap_state);
905         NTSTATUS status;
906
907         status = smbd_smb2_session_setup_recv(subreq,
908                                               &state->out_session_flags,
909                                               state,
910                                               &state->out_security_buffer,
911                                               &state->out_session_id);
912         TALLOC_FREE(subreq);
913         if (NT_STATUS_IS_OK(status)) {
914                 tevent_req_done(req);
915                 return;
916         }
917         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
918                 tevent_req_nterror(req, status);
919                 return;
920         }
921
922         if (state->smb2req->session == NULL) {
923                 tevent_req_nterror(req, status);
924                 return;
925         }
926
927         state->error = status;
928
929         subreq = smb2srv_session_shutdown_send(state, state->ev,
930                                                state->smb2req->session,
931                                                state->smb2req);
932         if (tevent_req_nomem(subreq, req)) {
933                 return;
934         }
935         tevent_req_set_callback(subreq,
936                                 smbd_smb2_session_setup_wrap_shutdown_done,
937                                 req);
938 }
939
940 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq)
941 {
942         struct tevent_req *req =
943                 tevent_req_callback_data(subreq,
944                 struct tevent_req);
945         struct smbd_smb2_session_setup_wrap_state *state =
946                 tevent_req_data(req,
947                 struct smbd_smb2_session_setup_wrap_state);
948         NTSTATUS status;
949
950         status = smb2srv_session_shutdown_recv(subreq);
951         TALLOC_FREE(subreq);
952         if (tevent_req_nterror(req, status)) {
953                 return;
954         }
955
956         /*
957          * we may need to sign the response, so we need to keep
958          * the session until the response is sent to the wire.
959          */
960         talloc_steal(state->smb2req, state->smb2req->session);
961
962         tevent_req_nterror(req, state->error);
963 }
964
965 static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
966                                         uint16_t *out_session_flags,
967                                         TALLOC_CTX *mem_ctx,
968                                         DATA_BLOB *out_security_buffer,
969                                         uint64_t *out_session_id)
970 {
971         struct smbd_smb2_session_setup_wrap_state *state =
972                 tevent_req_data(req,
973                 struct smbd_smb2_session_setup_wrap_state);
974         NTSTATUS status;
975
976         if (tevent_req_is_nterror(req, &status)) {
977                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
978                         tevent_req_received(req);
979                         return nt_status_squash(status);
980                 }
981         } else {
982                 status = NT_STATUS_OK;
983         }
984
985         *out_session_flags = state->out_session_flags;
986         *out_security_buffer = state->out_security_buffer;
987         *out_session_id = state->out_session_id;
988
989         talloc_steal(mem_ctx, out_security_buffer->data);
990         tevent_req_received(req);
991         return status;
992 }
993
994 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
995                                         struct tevent_context *ev,
996                                         struct smbd_smb2_request *smb2req);
997 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req);
998 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq);
999
1000 NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req)
1001 {
1002         NTSTATUS status;
1003         struct tevent_req *subreq = NULL;
1004
1005         status = smbd_smb2_request_verify_sizes(req, 0x04);
1006         if (!NT_STATUS_IS_OK(status)) {
1007                 return smbd_smb2_request_error(req, status);
1008         }
1009
1010         subreq = smbd_smb2_logoff_send(req, req->sconn->ev_ctx, req);
1011         if (subreq == NULL) {
1012                 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
1013         }
1014         tevent_req_set_callback(subreq, smbd_smb2_request_logoff_done, req);
1015
1016         /*
1017          * Wait a long time before going async on this to allow
1018          * requests we're waiting on to finish. Set timeout to 10 secs.
1019          */
1020         return smbd_smb2_request_pending_queue(req, subreq, 10000000);
1021 }
1022
1023 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq)
1024 {
1025         struct smbd_smb2_request *smb2req =
1026                 tevent_req_callback_data(subreq,
1027                 struct smbd_smb2_request);
1028         DATA_BLOB outbody;
1029         NTSTATUS status;
1030         NTSTATUS error;
1031
1032         status = smbd_smb2_logoff_recv(subreq);
1033         TALLOC_FREE(subreq);
1034         if (!NT_STATUS_IS_OK(status)) {
1035                 error = smbd_smb2_request_error(smb2req, status);
1036                 if (!NT_STATUS_IS_OK(error)) {
1037                         smbd_server_connection_terminate(smb2req->xconn,
1038                                                         nt_errstr(error));
1039                         return;
1040                 }
1041                 return;
1042         }
1043
1044         outbody = smbd_smb2_generate_outbody(smb2req, 0x04);
1045         if (outbody.data == NULL) {
1046                 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
1047                 if (!NT_STATUS_IS_OK(error)) {
1048                         smbd_server_connection_terminate(smb2req->xconn,
1049                                                         nt_errstr(error));
1050                         return;
1051                 }
1052                 return;
1053         }
1054
1055         SSVAL(outbody.data, 0x00, 0x04);        /* struct size */
1056         SSVAL(outbody.data, 0x02, 0);           /* reserved */
1057
1058         error = smbd_smb2_request_done(smb2req, outbody, NULL);
1059         if (!NT_STATUS_IS_OK(error)) {
1060                 smbd_server_connection_terminate(smb2req->xconn,
1061                                                 nt_errstr(error));
1062                 return;
1063         }
1064 }
1065
1066 struct smbd_smb2_logoff_state {
1067         struct smbd_smb2_request *smb2req;
1068 };
1069
1070 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq);
1071
1072 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
1073                                         struct tevent_context *ev,
1074                                         struct smbd_smb2_request *smb2req)
1075 {
1076         struct tevent_req *req;
1077         struct smbd_smb2_logoff_state *state;
1078         struct tevent_req *subreq;
1079
1080         req = tevent_req_create(mem_ctx, &state,
1081                         struct smbd_smb2_logoff_state);
1082         if (req == NULL) {
1083                 return NULL;
1084         }
1085         state->smb2req = smb2req;
1086
1087         subreq = smb2srv_session_shutdown_send(state, ev,
1088                                                smb2req->session,
1089                                                smb2req);
1090         if (tevent_req_nomem(subreq, req)) {
1091                 return tevent_req_post(req, ev);
1092         }
1093         tevent_req_set_callback(subreq, smbd_smb2_logoff_shutdown_done, req);
1094
1095         return req;
1096 }
1097
1098 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq)
1099 {
1100         struct tevent_req *req = tevent_req_callback_data(
1101                 subreq, struct tevent_req);
1102         struct smbd_smb2_logoff_state *state = tevent_req_data(
1103                 req, struct smbd_smb2_logoff_state);
1104         NTSTATUS status;
1105
1106         status = smb2srv_session_shutdown_recv(subreq);
1107         if (tevent_req_nterror(req, status)) {
1108                 return;
1109         }
1110         TALLOC_FREE(subreq);
1111
1112         /*
1113          * As we've been awoken, we may have changed
1114          * uid in the meantime. Ensure we're still
1115          * root (SMB2_OP_LOGOFF has .as_root = true).
1116          */
1117         change_to_root_user();
1118
1119         status = smbXsrv_session_logoff(state->smb2req->session);
1120         if (tevent_req_nterror(req, status)) {
1121                 return;
1122         }
1123
1124         /*
1125          * we may need to sign the response, so we need to keep
1126          * the session until the response is sent to the wire.
1127          */
1128         talloc_steal(state->smb2req, state->smb2req->session);
1129
1130         tevent_req_done(req);
1131 }
1132
1133 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req)
1134 {
1135         return tevent_req_simple_recv_ntstatus(req);
1136 }