s3:smb2_server: store encryption cipher in the channel
[gd/samba-autobuild/.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->global->encryption_flags = SMBXSRV_ENCRYPTION_DESIRED;
272         }
273
274         if (lp_smb_encrypt(-1) == SMB_SIGNING_REQUIRED) {
275                 x->global->encryption_flags = SMBXSRV_ENCRYPTION_REQUIRED |
276                         SMBXSRV_ENCRYPTION_DESIRED;
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_flags & SMBXSRV_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_flags & SMBXSRV_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         } else {
301                 x->global->channels[0].encryption_cipher = xconn->smb2.server.cipher;
302         }
303
304         if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
305                 *out_session_flags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
306         }
307
308         ZERO_STRUCT(session_key);
309         memcpy(session_key, session_info->session_key.data,
310                MIN(session_info->session_key.length, sizeof(session_key)));
311
312         x->global->signing_key = data_blob_talloc(x->global,
313                                                   session_key,
314                                                   sizeof(session_key));
315         if (x->global->signing_key.data == NULL) {
316                 ZERO_STRUCT(session_key);
317                 return NT_STATUS_NO_MEMORY;
318         }
319
320         if (xconn->protocol >= PROTOCOL_SMB2_24) {
321                 struct _derivation *d = &derivation.signing;
322
323                 smb2_key_derivation(session_key, sizeof(session_key),
324                                     d->label.data, d->label.length,
325                                     d->context.data, d->context.length,
326                                     x->global->signing_key.data);
327         }
328
329         if (xconn->protocol >= PROTOCOL_SMB2_24) {
330                 struct _derivation *d = &derivation.decryption;
331
332                 x->global->decryption_key = data_blob_talloc(x->global,
333                                                              session_key,
334                                                              sizeof(session_key));
335                 if (x->global->decryption_key.data == NULL) {
336                         ZERO_STRUCT(session_key);
337                         return NT_STATUS_NO_MEMORY;
338                 }
339
340                 smb2_key_derivation(session_key, sizeof(session_key),
341                                     d->label.data, d->label.length,
342                                     d->context.data, d->context.length,
343                                     x->global->decryption_key.data);
344         }
345
346         if (xconn->protocol >= PROTOCOL_SMB2_24) {
347                 struct _derivation *d = &derivation.encryption;
348                 size_t nonce_size;
349
350                 x->global->encryption_key = data_blob_talloc(x->global,
351                                                              session_key,
352                                                              sizeof(session_key));
353                 if (x->global->encryption_key.data == NULL) {
354                         ZERO_STRUCT(session_key);
355                         return NT_STATUS_NO_MEMORY;
356                 }
357
358                 smb2_key_derivation(session_key, sizeof(session_key),
359                                     d->label.data, d->label.length,
360                                     d->context.data, d->context.length,
361                                     x->global->encryption_key.data);
362
363                 /*
364                  * CCM and GCM algorithms must never have their
365                  * nonce wrap, or the security of the whole
366                  * communication and the keys is destroyed.
367                  * We must drop the connection once we have
368                  * transfered too much data.
369                  *
370                  * NOTE: We assume nonces greater than 8 bytes.
371                  */
372                 generate_random_buffer((uint8_t *)&x->nonce_high_random,
373                                        sizeof(x->nonce_high_random));
374                 switch (xconn->smb2.server.cipher) {
375                 case SMB2_ENCRYPTION_AES128_CCM:
376                         nonce_size = AES_CCM_128_NONCE_SIZE;
377                         break;
378                 case SMB2_ENCRYPTION_AES128_GCM:
379                         nonce_size = AES_GCM_128_IV_SIZE;
380                         break;
381                 default:
382                         nonce_size = 0;
383                         break;
384                 }
385                 x->nonce_high_max = SMB2_NONCE_HIGH_MAX(nonce_size);
386                 x->nonce_high = 0;
387                 x->nonce_low = 0;
388         }
389
390         x->global->application_key = data_blob_dup_talloc(x->global,
391                                                 x->global->signing_key);
392         if (x->global->application_key.data == NULL) {
393                 ZERO_STRUCT(session_key);
394                 return NT_STATUS_NO_MEMORY;
395         }
396
397         if (xconn->protocol >= PROTOCOL_SMB2_24) {
398                 struct _derivation *d = &derivation.application;
399
400                 smb2_key_derivation(session_key, sizeof(session_key),
401                                     d->label.data, d->label.length,
402                                     d->context.data, d->context.length,
403                                     x->global->application_key.data);
404         }
405         ZERO_STRUCT(session_key);
406
407         x->global->channels[0].signing_key = data_blob_dup_talloc(x->global->channels,
408                                                 x->global->signing_key);
409         if (x->global->channels[0].signing_key.data == NULL) {
410                 return NT_STATUS_NO_MEMORY;
411         }
412
413         data_blob_clear_free(&session_info->session_key);
414         session_info->session_key = data_blob_dup_talloc(session_info,
415                                                 x->global->application_key);
416         if (session_info->session_key.data == NULL) {
417                 return NT_STATUS_NO_MEMORY;
418         }
419
420         session->compat = talloc_zero(session, struct user_struct);
421         if (session->compat == NULL) {
422                 return NT_STATUS_NO_MEMORY;
423         }
424         session->compat->session = session;
425         session->compat->homes_snum = -1;
426         session->compat->session_info = session_info;
427         session->compat->session_keystr = NULL;
428         session->compat->vuid = session->global->session_wire_id;
429         DLIST_ADD(smb2req->sconn->users, session->compat);
430         smb2req->sconn->num_users++;
431
432         if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
433                 session->compat->homes_snum =
434                         register_homes_share(session_info->unix_info->unix_name);
435         }
436
437         set_current_user_info(session_info->unix_info->sanitized_username,
438                               session_info->unix_info->unix_name,
439                               session_info->info->domain_name);
440
441         reload_services(smb2req->sconn, conn_snum_used, true);
442
443         session->status = NT_STATUS_OK;
444         session->global->auth_session_info = talloc_move(session->global,
445                                                          &session_info);
446         session->global->auth_session_info_seqnum += 1;
447         for (i=0; i < session->global->num_channels; i++) {
448                 struct smbXsrv_channel_global0 *_c =
449                         &session->global->channels[i];
450
451                 _c->auth_session_info_seqnum =
452                         session->global->auth_session_info_seqnum;
453         }
454         session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
455         session->global->expiration_time = gensec_expire_time(auth->gensec);
456
457         if (!session_claim(session)) {
458                 DEBUG(1, ("smb2: Failed to claim session "
459                         "for vuid=%llu\n",
460                         (unsigned long long)session->compat->vuid));
461                 return NT_STATUS_LOGON_FAILURE;
462         }
463
464         TALLOC_FREE(auth);
465         status = smbXsrv_session_update(session);
466         if (!NT_STATUS_IS_OK(status)) {
467                 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
468                           (unsigned long long)session->compat->vuid,
469                           nt_errstr(status)));
470                 return NT_STATUS_LOGON_FAILURE;
471         }
472
473         /*
474          * we attach the session to the request
475          * so that the response can be signed
476          */
477         if (!guest) {
478                 smb2req->do_signing = true;
479         }
480
481         global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
482
483         *out_session_id = session->global->session_wire_id;
484
485         return NT_STATUS_OK;
486 }
487
488 static NTSTATUS smbd_smb2_reauth_generic_return(struct smbXsrv_session *session,
489                                         struct smbXsrv_session_auth0 **_auth,
490                                         struct smbd_smb2_request *smb2req,
491                                         struct auth_session_info *session_info,
492                                         uint16_t *out_session_flags,
493                                         uint64_t *out_session_id)
494 {
495         NTSTATUS status;
496         struct smbXsrv_session *x = session;
497         struct smbXsrv_session_auth0 *auth = *_auth;
498         struct smbXsrv_connection *xconn = smb2req->xconn;
499         size_t i;
500
501         *_auth = NULL;
502
503         data_blob_clear_free(&session_info->session_key);
504         session_info->session_key = data_blob_dup_talloc(session_info,
505                                                 x->global->application_key);
506         if (session_info->session_key.data == NULL) {
507                 return NT_STATUS_NO_MEMORY;
508         }
509
510         session->compat->session_info = session_info;
511         session->compat->vuid = session->global->session_wire_id;
512
513         session->compat->homes_snum =
514                         register_homes_share(session_info->unix_info->unix_name);
515
516         set_current_user_info(session_info->unix_info->sanitized_username,
517                               session_info->unix_info->unix_name,
518                               session_info->info->domain_name);
519
520         reload_services(smb2req->sconn, conn_snum_used, true);
521
522         session->status = NT_STATUS_OK;
523         TALLOC_FREE(session->global->auth_session_info);
524         session->global->auth_session_info = talloc_move(session->global,
525                                                          &session_info);
526         session->global->auth_session_info_seqnum += 1;
527         for (i=0; i < session->global->num_channels; i++) {
528                 struct smbXsrv_channel_global0 *_c =
529                         &session->global->channels[i];
530
531                 _c->auth_session_info_seqnum =
532                         session->global->auth_session_info_seqnum;
533         }
534         session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
535         session->global->expiration_time = gensec_expire_time(auth->gensec);
536
537         TALLOC_FREE(auth);
538         status = smbXsrv_session_update(session);
539         if (!NT_STATUS_IS_OK(status)) {
540                 DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
541                           (unsigned long long)session->compat->vuid,
542                           nt_errstr(status)));
543                 return NT_STATUS_LOGON_FAILURE;
544         }
545
546         conn_clear_vuid_caches(xconn->client->sconn, session->compat->vuid);
547
548         if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
549                 smb2req->do_signing = true;
550         }
551
552         *out_session_id = session->global->session_wire_id;
553
554         return NT_STATUS_OK;
555 }
556
557 struct smbd_smb2_session_setup_state {
558         struct tevent_context *ev;
559         struct smbd_smb2_request *smb2req;
560         uint64_t in_session_id;
561         uint8_t in_flags;
562         uint8_t in_security_mode;
563         uint64_t in_previous_session_id;
564         DATA_BLOB in_security_buffer;
565         struct smbXsrv_session *session;
566         struct smbXsrv_session_auth0 *auth;
567         struct auth_session_info *session_info;
568         uint16_t out_session_flags;
569         DATA_BLOB out_security_buffer;
570         uint64_t out_session_id;
571 };
572
573 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq);
574 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq);
575 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req);
576
577 static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
578                                         struct tevent_context *ev,
579                                         struct smbd_smb2_request *smb2req,
580                                         uint64_t in_session_id,
581                                         uint8_t in_flags,
582                                         uint8_t in_security_mode,
583                                         uint64_t in_previous_session_id,
584                                         DATA_BLOB in_security_buffer)
585 {
586         struct tevent_req *req;
587         struct smbd_smb2_session_setup_state *state;
588         NTSTATUS status;
589         NTTIME now = timeval_to_nttime(&smb2req->request_time);
590         struct tevent_req *subreq;
591         struct smbXsrv_channel_global0 *c = NULL;
592
593         req = tevent_req_create(mem_ctx, &state,
594                                 struct smbd_smb2_session_setup_state);
595         if (req == NULL) {
596                 return NULL;
597         }
598         state->ev = ev;
599         state->smb2req = smb2req;
600         state->in_session_id = in_session_id;
601         state->in_flags = in_flags;
602         state->in_security_mode = in_security_mode;
603         state->in_previous_session_id = in_previous_session_id;
604         state->in_security_buffer = in_security_buffer;
605
606         if (in_flags & SMB2_SESSION_FLAG_BINDING) {
607                 if (smb2req->xconn->protocol < PROTOCOL_SMB2_22) {
608                         tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
609                         return tevent_req_post(req, ev);
610                 }
611
612                 /*
613                  * We do not support multi channel.
614                  */
615                 tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
616                 return tevent_req_post(req, ev);
617         }
618
619         if (state->in_session_id == 0) {
620                 /* create a new session */
621                 status = smbXsrv_session_create(state->smb2req->xconn,
622                                                 now, &state->session);
623                 if (tevent_req_nterror(req, status)) {
624                         return tevent_req_post(req, ev);
625                 }
626                 smb2req->session = state->session;
627         } else {
628                 if (smb2req->session == NULL) {
629                         tevent_req_nterror(req, NT_STATUS_USER_SESSION_DELETED);
630                         return tevent_req_post(req, ev);
631                 }
632
633                 state->session = smb2req->session;
634                 status = state->session->status;
635                 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
636                         status = NT_STATUS_OK;
637                 }
638                 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
639                         status = NT_STATUS_OK;
640                 }
641                 if (tevent_req_nterror(req, status)) {
642                         return tevent_req_post(req, ev);
643                 }
644                 if (!(in_flags & SMB2_SESSION_FLAG_BINDING)) {
645                         state->session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
646                 }
647         }
648
649         status = smbXsrv_session_find_channel(smb2req->session,
650                                               smb2req->xconn, &c);
651         if (!NT_STATUS_IS_OK(status)) {
652                 tevent_req_nterror(req, status);
653                 return tevent_req_post(req, ev);
654         }
655
656         status = smbXsrv_session_find_auth(state->session, smb2req->xconn,
657                                            now, &state->auth);
658         if (!NT_STATUS_IS_OK(status)) {
659                 status = smbXsrv_session_create_auth(state->session,
660                                                      smb2req->xconn, now,
661                                                      in_flags, in_security_mode,
662                                                      &state->auth);
663                 if (tevent_req_nterror(req, status)) {
664                         return tevent_req_post(req, ev);
665                 }
666         }
667
668         if (state->auth->gensec == NULL) {
669                 status = auth_generic_prepare(state->auth,
670                                               state->smb2req->xconn->remote_address,
671                                               &state->auth->gensec);
672                 if (tevent_req_nterror(req, status)) {
673                         return tevent_req_post(req, ev);
674                 }
675
676                 gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_SESSION_KEY);
677                 gensec_want_feature(state->auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
678
679                 status = gensec_start_mech_by_oid(state->auth->gensec,
680                                                   GENSEC_OID_SPNEGO);
681                 if (tevent_req_nterror(req, status)) {
682                         return tevent_req_post(req, ev);
683                 }
684         }
685
686         status = smbXsrv_session_update(state->session);
687         if (tevent_req_nterror(req, status)) {
688                 return tevent_req_post(req, ev);
689         }
690
691         become_root();
692         subreq = gensec_update_send(state, state->ev,
693                                     state->auth->gensec,
694                                     state->in_security_buffer);
695         unbecome_root();
696         if (tevent_req_nomem(subreq, req)) {
697                 return tevent_req_post(req, ev);
698         }
699         tevent_req_set_callback(subreq, smbd_smb2_session_setup_gensec_done, req);
700
701         return req;
702 }
703
704 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
705 {
706         struct tevent_req *req =
707                 tevent_req_callback_data(subreq,
708                 struct tevent_req);
709         struct smbd_smb2_session_setup_state *state =
710                 tevent_req_data(req,
711                 struct smbd_smb2_session_setup_state);
712         NTSTATUS status;
713
714         become_root();
715         status = gensec_update_recv(subreq, state,
716                                     &state->out_security_buffer);
717         unbecome_root();
718         TALLOC_FREE(subreq);
719         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
720             !NT_STATUS_IS_OK(status)) {
721                 tevent_req_nterror(req, status);
722                 return;
723         }
724
725         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
726                 state->out_session_id = state->session->global->session_wire_id;
727                 state->smb2req->preauth = state->auth->preauth;
728                 tevent_req_nterror(req, status);
729                 return;
730         }
731
732         status = gensec_session_info(state->auth->gensec,
733                                      state,
734                                      &state->session_info);
735         if (tevent_req_nterror(req, status)) {
736                 return;
737         }
738
739         if ((state->in_previous_session_id != 0) &&
740              (state->session->global->session_wire_id !=
741               state->in_previous_session_id))
742         {
743                 subreq = smb2srv_session_close_previous_send(state, state->ev,
744                                                 state->smb2req->xconn,
745                                                 state->session_info,
746                                                 state->in_previous_session_id,
747                                                 state->session->global->session_wire_id);
748                 if (tevent_req_nomem(subreq, req)) {
749                         return;
750                 }
751                 tevent_req_set_callback(subreq,
752                                         smbd_smb2_session_setup_previous_done,
753                                         req);
754                 return;
755         }
756
757         smbd_smb2_session_setup_auth_return(req);
758 }
759
760 static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq)
761 {
762         struct tevent_req *req =
763                 tevent_req_callback_data(subreq,
764                 struct tevent_req);
765         NTSTATUS status;
766
767         status = smb2srv_session_close_previous_recv(subreq);
768         TALLOC_FREE(subreq);
769         if (tevent_req_nterror(req, status)) {
770                 return;
771         }
772
773         smbd_smb2_session_setup_auth_return(req);
774 }
775
776 static void smbd_smb2_session_setup_auth_return(struct tevent_req *req)
777 {
778         struct smbd_smb2_session_setup_state *state =
779                 tevent_req_data(req,
780                 struct smbd_smb2_session_setup_state);
781         NTSTATUS status;
782
783         if (state->session->global->auth_session_info != NULL) {
784                 status = smbd_smb2_reauth_generic_return(state->session,
785                                                          &state->auth,
786                                                          state->smb2req,
787                                                          state->session_info,
788                                                          &state->out_session_flags,
789                                                          &state->out_session_id);
790                 if (tevent_req_nterror(req, status)) {
791                         return;
792                 }
793                 tevent_req_done(req);
794                 return;
795         }
796
797         status = smbd_smb2_auth_generic_return(state->session,
798                                                &state->auth,
799                                                state->smb2req,
800                                                state->in_security_mode,
801                                                state->session_info,
802                                                &state->out_session_flags,
803                                                &state->out_session_id);
804         if (tevent_req_nterror(req, status)) {
805                 return;
806         }
807
808         tevent_req_done(req);
809         return;
810 }
811
812 static NTSTATUS smbd_smb2_session_setup_recv(struct tevent_req *req,
813                                         uint16_t *out_session_flags,
814                                         TALLOC_CTX *mem_ctx,
815                                         DATA_BLOB *out_security_buffer,
816                                         uint64_t *out_session_id)
817 {
818         struct smbd_smb2_session_setup_state *state =
819                 tevent_req_data(req,
820                 struct smbd_smb2_session_setup_state);
821         NTSTATUS status;
822
823         if (tevent_req_is_nterror(req, &status)) {
824                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
825                         tevent_req_received(req);
826                         return nt_status_squash(status);
827                 }
828         } else {
829                 status = NT_STATUS_OK;
830         }
831
832         *out_session_flags = state->out_session_flags;
833         *out_security_buffer = state->out_security_buffer;
834         *out_session_id = state->out_session_id;
835
836         talloc_steal(mem_ctx, out_security_buffer->data);
837         tevent_req_received(req);
838         return status;
839 }
840
841 struct smbd_smb2_session_setup_wrap_state {
842         struct tevent_context *ev;
843         struct smbd_smb2_request *smb2req;
844         uint64_t in_session_id;
845         uint8_t in_flags;
846         uint8_t in_security_mode;
847         uint64_t in_previous_session_id;
848         DATA_BLOB in_security_buffer;
849         uint16_t out_session_flags;
850         DATA_BLOB out_security_buffer;
851         uint64_t out_session_id;
852         NTSTATUS error;
853 };
854
855 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq);
856 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq);
857
858 static struct tevent_req *smbd_smb2_session_setup_wrap_send(TALLOC_CTX *mem_ctx,
859                                         struct tevent_context *ev,
860                                         struct smbd_smb2_request *smb2req,
861                                         uint64_t in_session_id,
862                                         uint8_t in_flags,
863                                         uint8_t in_security_mode,
864                                         uint64_t in_previous_session_id,
865                                         DATA_BLOB in_security_buffer)
866 {
867         struct tevent_req *req;
868         struct smbd_smb2_session_setup_wrap_state *state;
869         struct tevent_req *subreq;
870
871         req = tevent_req_create(mem_ctx, &state,
872                                 struct smbd_smb2_session_setup_wrap_state);
873         if (req == NULL) {
874                 return NULL;
875         }
876         state->ev = ev;
877         state->smb2req = smb2req;
878         state->in_session_id = in_session_id;
879         state->in_flags = in_flags;
880         state->in_security_mode = in_security_mode;
881         state->in_previous_session_id = in_previous_session_id;
882         state->in_security_buffer = in_security_buffer;
883
884         subreq = smbd_smb2_session_setup_send(state, state->ev,
885                                               state->smb2req,
886                                               state->in_session_id,
887                                               state->in_flags,
888                                               state->in_security_mode,
889                                               state->in_previous_session_id,
890                                               state->in_security_buffer);
891         if (tevent_req_nomem(subreq, req)) {
892                 return tevent_req_post(req, ev);
893         }
894         tevent_req_set_callback(subreq,
895                                 smbd_smb2_session_setup_wrap_setup_done, req);
896
897         return req;
898 }
899
900 static void smbd_smb2_session_setup_wrap_setup_done(struct tevent_req *subreq)
901 {
902         struct tevent_req *req =
903                 tevent_req_callback_data(subreq,
904                 struct tevent_req);
905         struct smbd_smb2_session_setup_wrap_state *state =
906                 tevent_req_data(req,
907                 struct smbd_smb2_session_setup_wrap_state);
908         NTSTATUS status;
909
910         status = smbd_smb2_session_setup_recv(subreq,
911                                               &state->out_session_flags,
912                                               state,
913                                               &state->out_security_buffer,
914                                               &state->out_session_id);
915         TALLOC_FREE(subreq);
916         if (NT_STATUS_IS_OK(status)) {
917                 tevent_req_done(req);
918                 return;
919         }
920         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
921                 tevent_req_nterror(req, status);
922                 return;
923         }
924
925         if (state->smb2req->session == NULL) {
926                 tevent_req_nterror(req, status);
927                 return;
928         }
929
930         state->error = status;
931
932         subreq = smb2srv_session_shutdown_send(state, state->ev,
933                                                state->smb2req->session,
934                                                state->smb2req);
935         if (tevent_req_nomem(subreq, req)) {
936                 return;
937         }
938         tevent_req_set_callback(subreq,
939                                 smbd_smb2_session_setup_wrap_shutdown_done,
940                                 req);
941 }
942
943 static void smbd_smb2_session_setup_wrap_shutdown_done(struct tevent_req *subreq)
944 {
945         struct tevent_req *req =
946                 tevent_req_callback_data(subreq,
947                 struct tevent_req);
948         struct smbd_smb2_session_setup_wrap_state *state =
949                 tevent_req_data(req,
950                 struct smbd_smb2_session_setup_wrap_state);
951         NTSTATUS status;
952
953         status = smb2srv_session_shutdown_recv(subreq);
954         TALLOC_FREE(subreq);
955         if (tevent_req_nterror(req, status)) {
956                 return;
957         }
958
959         /*
960          * we may need to sign the response, so we need to keep
961          * the session until the response is sent to the wire.
962          */
963         talloc_steal(state->smb2req, state->smb2req->session);
964
965         tevent_req_nterror(req, state->error);
966 }
967
968 static NTSTATUS smbd_smb2_session_setup_wrap_recv(struct tevent_req *req,
969                                         uint16_t *out_session_flags,
970                                         TALLOC_CTX *mem_ctx,
971                                         DATA_BLOB *out_security_buffer,
972                                         uint64_t *out_session_id)
973 {
974         struct smbd_smb2_session_setup_wrap_state *state =
975                 tevent_req_data(req,
976                 struct smbd_smb2_session_setup_wrap_state);
977         NTSTATUS status;
978
979         if (tevent_req_is_nterror(req, &status)) {
980                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
981                         tevent_req_received(req);
982                         return nt_status_squash(status);
983                 }
984         } else {
985                 status = NT_STATUS_OK;
986         }
987
988         *out_session_flags = state->out_session_flags;
989         *out_security_buffer = state->out_security_buffer;
990         *out_session_id = state->out_session_id;
991
992         talloc_steal(mem_ctx, out_security_buffer->data);
993         tevent_req_received(req);
994         return status;
995 }
996
997 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
998                                         struct tevent_context *ev,
999                                         struct smbd_smb2_request *smb2req);
1000 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req);
1001 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq);
1002
1003 NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req)
1004 {
1005         NTSTATUS status;
1006         struct tevent_req *subreq = NULL;
1007
1008         status = smbd_smb2_request_verify_sizes(req, 0x04);
1009         if (!NT_STATUS_IS_OK(status)) {
1010                 return smbd_smb2_request_error(req, status);
1011         }
1012
1013         subreq = smbd_smb2_logoff_send(req, req->sconn->ev_ctx, req);
1014         if (subreq == NULL) {
1015                 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
1016         }
1017         tevent_req_set_callback(subreq, smbd_smb2_request_logoff_done, req);
1018
1019         /*
1020          * Wait a long time before going async on this to allow
1021          * requests we're waiting on to finish. Set timeout to 10 secs.
1022          */
1023         return smbd_smb2_request_pending_queue(req, subreq, 10000000);
1024 }
1025
1026 static void smbd_smb2_request_logoff_done(struct tevent_req *subreq)
1027 {
1028         struct smbd_smb2_request *smb2req =
1029                 tevent_req_callback_data(subreq,
1030                 struct smbd_smb2_request);
1031         DATA_BLOB outbody;
1032         NTSTATUS status;
1033         NTSTATUS error;
1034
1035         status = smbd_smb2_logoff_recv(subreq);
1036         TALLOC_FREE(subreq);
1037         if (!NT_STATUS_IS_OK(status)) {
1038                 error = smbd_smb2_request_error(smb2req, status);
1039                 if (!NT_STATUS_IS_OK(error)) {
1040                         smbd_server_connection_terminate(smb2req->xconn,
1041                                                         nt_errstr(error));
1042                         return;
1043                 }
1044                 return;
1045         }
1046
1047         outbody = smbd_smb2_generate_outbody(smb2req, 0x04);
1048         if (outbody.data == NULL) {
1049                 error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
1050                 if (!NT_STATUS_IS_OK(error)) {
1051                         smbd_server_connection_terminate(smb2req->xconn,
1052                                                         nt_errstr(error));
1053                         return;
1054                 }
1055                 return;
1056         }
1057
1058         SSVAL(outbody.data, 0x00, 0x04);        /* struct size */
1059         SSVAL(outbody.data, 0x02, 0);           /* reserved */
1060
1061         error = smbd_smb2_request_done(smb2req, outbody, NULL);
1062         if (!NT_STATUS_IS_OK(error)) {
1063                 smbd_server_connection_terminate(smb2req->xconn,
1064                                                 nt_errstr(error));
1065                 return;
1066         }
1067 }
1068
1069 struct smbd_smb2_logoff_state {
1070         struct smbd_smb2_request *smb2req;
1071 };
1072
1073 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq);
1074
1075 static struct tevent_req *smbd_smb2_logoff_send(TALLOC_CTX *mem_ctx,
1076                                         struct tevent_context *ev,
1077                                         struct smbd_smb2_request *smb2req)
1078 {
1079         struct tevent_req *req;
1080         struct smbd_smb2_logoff_state *state;
1081         struct tevent_req *subreq;
1082
1083         req = tevent_req_create(mem_ctx, &state,
1084                         struct smbd_smb2_logoff_state);
1085         if (req == NULL) {
1086                 return NULL;
1087         }
1088         state->smb2req = smb2req;
1089
1090         subreq = smb2srv_session_shutdown_send(state, ev,
1091                                                smb2req->session,
1092                                                smb2req);
1093         if (tevent_req_nomem(subreq, req)) {
1094                 return tevent_req_post(req, ev);
1095         }
1096         tevent_req_set_callback(subreq, smbd_smb2_logoff_shutdown_done, req);
1097
1098         return req;
1099 }
1100
1101 static void smbd_smb2_logoff_shutdown_done(struct tevent_req *subreq)
1102 {
1103         struct tevent_req *req = tevent_req_callback_data(
1104                 subreq, struct tevent_req);
1105         struct smbd_smb2_logoff_state *state = tevent_req_data(
1106                 req, struct smbd_smb2_logoff_state);
1107         NTSTATUS status;
1108
1109         status = smb2srv_session_shutdown_recv(subreq);
1110         if (tevent_req_nterror(req, status)) {
1111                 return;
1112         }
1113         TALLOC_FREE(subreq);
1114
1115         /*
1116          * As we've been awoken, we may have changed
1117          * uid in the meantime. Ensure we're still
1118          * root (SMB2_OP_LOGOFF has .as_root = true).
1119          */
1120         change_to_root_user();
1121
1122         status = smbXsrv_session_logoff(state->smb2req->session);
1123         if (tevent_req_nterror(req, status)) {
1124                 return;
1125         }
1126
1127         /*
1128          * we may need to sign the response, so we need to keep
1129          * the session until the response is sent to the wire.
1130          */
1131         talloc_steal(state->smb2req, state->smb2req->session);
1132
1133         tevent_req_done(req);
1134 }
1135
1136 static NTSTATUS smbd_smb2_logoff_recv(struct tevent_req *req)
1137 {
1138         return tevent_req_simple_recv_ntstatus(req);
1139 }