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