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