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