2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher 2009
6 Copyright (C) Jeremy Allison 2010
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.
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.
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/>.
23 #include "smbd/globals.h"
24 #include "../libcli/smb/smb_common.h"
25 #include "../libcli/auth/spnego.h"
28 static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *smb2req,
29 uint64_t in_session_id,
30 uint8_t in_security_mode,
31 DATA_BLOB in_security_buffer,
32 uint16_t *out_session_flags,
33 DATA_BLOB *out_security_buffer,
34 uint64_t *out_session_id);
36 NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *smb2req)
39 const uint8_t *inbody;
40 int i = smb2req->current_idx;
44 size_t expected_body_size = 0x19;
46 uint64_t in_session_id;
47 uint8_t in_security_mode;
48 uint16_t in_security_offset;
49 uint16_t in_security_length;
50 DATA_BLOB in_security_buffer;
51 uint16_t out_session_flags;
52 uint64_t out_session_id;
53 uint16_t out_security_offset;
54 DATA_BLOB out_security_buffer;
57 inhdr = (const uint8_t *)smb2req->in.vector[i+0].iov_base;
59 if (smb2req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
60 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
63 inbody = (const uint8_t *)smb2req->in.vector[i+1].iov_base;
65 body_size = SVAL(inbody, 0x00);
66 if (body_size != expected_body_size) {
67 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
70 in_security_offset = SVAL(inbody, 0x0C);
71 in_security_length = SVAL(inbody, 0x0E);
73 if (in_security_offset != (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
74 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
77 if (in_security_length > smb2req->in.vector[i+2].iov_len) {
78 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
81 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
82 in_security_mode = CVAL(inbody, 0x03);
83 in_security_buffer.data = (uint8_t *)smb2req->in.vector[i+2].iov_base;
84 in_security_buffer.length = in_security_length;
86 status = smbd_smb2_session_setup(smb2req,
93 if (!NT_STATUS_IS_OK(status) &&
94 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
95 status = nt_status_squash(status);
96 return smbd_smb2_request_error(smb2req, status);
99 out_security_offset = SMB2_HDR_BODY + 0x08;
101 outhdr = (uint8_t *)smb2req->out.vector[i].iov_base;
103 outbody = data_blob_talloc(smb2req->out.vector, NULL, 0x08);
104 if (outbody.data == NULL) {
105 return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
108 SBVAL(outhdr, SMB2_HDR_SESSION_ID, out_session_id);
110 SSVAL(outbody.data, 0x00, 0x08 + 1); /* struct size */
111 SSVAL(outbody.data, 0x02,
112 out_session_flags); /* session flags */
113 SSVAL(outbody.data, 0x04,
114 out_security_offset); /* security buffer offset */
115 SSVAL(outbody.data, 0x06,
116 out_security_buffer.length); /* security buffer length */
118 outdyn = out_security_buffer;
120 return smbd_smb2_request_done_ex(smb2req, status, outbody, &outdyn,
124 static int smbd_smb2_session_destructor(struct smbd_smb2_session *session)
126 if (session->sconn == NULL) {
130 /* first free all tcons */
131 while (session->tcons.list) {
132 talloc_free(session->tcons.list);
135 idr_remove(session->sconn->smb2.sessions.idtree, session->vuid);
136 DLIST_REMOVE(session->sconn->smb2.sessions.list, session);
137 invalidate_vuid(session->sconn, session->vuid);
140 session->status = NT_STATUS_USER_SESSION_DELETED;
141 session->sconn = NULL;
146 static NTSTATUS smbd_smb2_session_setup_krb5(struct smbd_smb2_session *session,
147 struct smbd_smb2_request *smb2req,
148 uint8_t in_security_mode,
149 const DATA_BLOB *secblob,
151 uint16_t *out_session_flags,
152 DATA_BLOB *out_security_buffer,
153 uint64_t *out_session_id)
155 DATA_BLOB ap_rep = data_blob_null;
156 DATA_BLOB ap_rep_wrapped = data_blob_null;
157 DATA_BLOB ticket = data_blob_null;
158 DATA_BLOB session_key = data_blob_null;
159 DATA_BLOB secblob_out = data_blob_null;
161 struct PAC_LOGON_INFO *logon_info = NULL;
165 struct passwd *pw = NULL;
168 fstring real_username;
170 bool username_was_mapped = false;
171 bool map_domainuser_to_guest = false;
172 struct smbd_server_connection *sconn = smbd_server_conn;
174 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
175 status = NT_STATUS_LOGON_FAILURE;
179 status = ads_verify_ticket(smb2req, lp_realm(), 0, &ticket,
180 &client, &logon_info, &ap_rep,
183 if (!NT_STATUS_IS_OK(status)) {
184 DEBUG(1,("smb2: Failed to verify incoming ticket with error %s!\n",
186 if (!NT_STATUS_EQUAL(status, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
187 status = NT_STATUS_LOGON_FAILURE;
192 DEBUG(3,("smb2: Ticket name is [%s]\n", client));
194 p = strchr_m(client, '@');
196 DEBUG(3,("smb2: %s Doesn't look like a valid principal\n",
198 status = NT_STATUS_LOGON_FAILURE;
204 /* save the PAC data if we have it */
207 netsamlogon_cache_store(client, &logon_info->info3);
210 if (!strequal(p+1, lp_realm())) {
211 DEBUG(3,("smb2: Ticket for foreign realm %s@%s\n", client, p+1));
212 if (!lp_allow_trusted_domains()) {
213 status = NT_STATUS_LOGON_FAILURE;
218 /* this gives a fully qualified user name (ie. with full realm).
219 that leads to very long usernames, but what else can we do? */
223 if (logon_info && logon_info->info3.base.domain.string) {
224 domain = talloc_strdup(talloc_tos(),
225 logon_info->info3.base.domain.string);
227 status = NT_STATUS_NO_MEMORY;
230 DEBUG(10, ("smb2: Mapped to [%s] (using PAC)\n", domain));
233 /* If we have winbind running, we can (and must) shorten the
234 username by using the short netbios name. Otherwise we will
235 have inconsistent user names. With Kerberos, we get the
236 fully qualified realm, with ntlmssp we get the short
237 name. And even w2k3 does use ntlmssp if you for example
238 connect to an ip address. */
241 struct wbcDomainInfo *info = NULL;
243 DEBUG(10, ("smb2: Mapping [%s] to short name\n", domain));
245 wbc_status = wbcDomainInfo(domain, &info);
247 if (WBC_ERROR_IS_OK(wbc_status)) {
248 domain = talloc_strdup(talloc_tos(), info->short_name);
252 status = NT_STATUS_NO_MEMORY;
255 DEBUG(10, ("smb2: Mapped to [%s] (using Winbind)\n", domain));
257 DEBUG(3, ("smb2: Could not find short name: %s\n",
258 wbcErrorString(wbc_status)));
262 /* We have to use fstring for this - map_username requires it. */
263 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
265 /* lookup the passwd struct, create a new user if necessary */
267 username_was_mapped = map_username(sconn, user);
269 pw = smb_getpwnam(talloc_tos(), user, real_username, true );
271 /* if a real user check pam account restrictions */
272 /* only really perfomed if "obey pam restriction" is true */
273 /* do this before an eventual mapping to guest occurs */
274 status = smb_pam_accountcheck(pw->pw_name);
275 if (!NT_STATUS_IS_OK(status)) {
276 DEBUG(1,("smb2: PAM account restriction "
277 "prevents user login\n"));
284 /* this was originally the behavior of Samba 2.2, if a user
285 did not have a local uid but has been authenticated, then
286 map them to a guest account */
288 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
289 map_domainuser_to_guest = true;
290 fstrcpy(user,lp_guestaccount());
291 pw = smb_getpwnam(talloc_tos(), user, real_username, true );
294 /* extra sanity check that the guest account is valid */
297 DEBUG(1,("smb2: Username %s is invalid on this system\n",
299 status = NT_STATUS_LOGON_FAILURE;
304 /* setup the string used by %U */
306 sub_set_smb_name(real_username);
307 reload_services(true);
309 if (map_domainuser_to_guest) {
310 make_server_info_guest(session, &session->server_info);
311 } else if (logon_info) {
312 /* pass the unmapped username here since map_username()
313 will be called again from inside make_server_info_info3() */
315 status = make_server_info_info3(session,
318 &session->server_info,
320 if (!NT_STATUS_IS_OK(status) ) {
321 DEBUG(1,("smb2: make_server_info_info3 failed: %s!\n",
328 * We didn't get a PAC, we have to make up the user
329 * ourselves. Try to ask the pdb backend to provide
330 * SID consistency with ntlmssp session setup
332 struct samu *sampass;
333 /* The stupid make_server_info_XX functions here
334 don't take a talloc context. */
335 struct auth_serversupplied_info *tmp_server_info = NULL;
337 sampass = samu_new(talloc_tos());
338 if (sampass == NULL) {
339 status = NT_STATUS_NO_MEMORY;
343 if (pdb_getsampwnam(sampass, real_username)) {
344 DEBUG(10, ("smb2: found user %s in passdb, calling "
345 "make_server_info_sam\n", real_username));
346 status = make_server_info_sam(&tmp_server_info, sampass);
349 * User not in passdb, make it up artificially
351 TALLOC_FREE(sampass);
352 DEBUG(10, ("smb2: didn't find user %s in passdb, calling "
353 "make_server_info_pw\n", real_username));
354 status = make_server_info_pw(&tmp_server_info,
359 if (!NT_STATUS_IS_OK(status)) {
360 DEBUG(1,("smb2: make_server_info_[sam|pw] failed: %s!\n",
365 /* Steal tmp_server_info into the session->server_info
367 session->server_info = talloc_move(session, &tmp_server_info);
369 /* make_server_info_pw does not set the domain. Without this
370 * we end up with the local netbios name in substitutions for
373 if (session->server_info->sam_account != NULL) {
374 pdb_set_domain(session->server_info->sam_account,
380 session->server_info->nss_token |= username_was_mapped;
382 /* we need to build the token for the user. make_server_info_guest()
385 if (!session->server_info->ptok ) {
386 status = create_local_token(session->server_info);
387 if (!NT_STATUS_IS_OK(status)) {
388 DEBUG(10,("smb2: failed to create local token: %s\n",
394 if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
395 lp_server_signing() == Required) {
396 session->do_signing = true;
399 if (session->server_info->guest) {
400 /* we map anonymous to guest internally */
401 *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
402 *out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
403 /* force no signing */
404 session->do_signing = false;
407 data_blob_free(&session->server_info->user_session_key);
408 session->server_info->user_session_key =
410 session->server_info,
413 if (session_key.length > 0) {
414 if (session->server_info->user_session_key.data == NULL) {
415 status = NT_STATUS_NO_MEMORY;
419 session->session_key = session->server_info->user_session_key;
421 session->compat_vuser = talloc_zero(session, user_struct);
422 if (session->compat_vuser == NULL) {
423 status = NT_STATUS_NO_MEMORY;
426 session->compat_vuser->auth_ntlmssp_state = NULL;
427 session->compat_vuser->homes_snum = -1;
428 session->compat_vuser->server_info = session->server_info;
429 session->compat_vuser->session_keystr = NULL;
430 session->compat_vuser->vuid = session->vuid;
431 DLIST_ADD(session->sconn->smb1.sessions.validated_users, session->compat_vuser);
433 /* This is a potentially untrusted username */
438 session->server_info->sanitized_username = talloc_strdup(
439 session->server_info, tmp);
441 if (!session->server_info->guest) {
442 session->compat_vuser->homes_snum =
443 register_homes_share(session->server_info->unix_name);
446 if (!session_claim(session->compat_vuser)) {
447 DEBUG(1, ("smb2: Failed to claim session "
449 session->compat_vuser->vuid));
453 session->status = NT_STATUS_OK;
456 * we attach the session to the request
457 * so that the response can be signed
459 smb2req->session = session;
460 if (session->do_signing) {
461 smb2req->do_signing = true;
464 global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
465 status = NT_STATUS_OK;
467 /* wrap that up in a nice GSS-API wrapping */
468 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
471 secblob_out = spnego_gen_auth_response(
476 *out_security_buffer = data_blob_talloc(smb2req,
479 if (secblob_out.data && out_security_buffer->data == NULL) {
480 status = NT_STATUS_NO_MEMORY;
484 data_blob_free(&ap_rep);
485 data_blob_free(&ap_rep_wrapped);
486 data_blob_free(&ticket);
487 data_blob_free(&session_key);
488 data_blob_free(&secblob_out);
490 *out_session_id = session->vuid;
496 data_blob_free(&ap_rep);
497 data_blob_free(&ap_rep_wrapped);
498 data_blob_free(&ticket);
499 data_blob_free(&session_key);
500 data_blob_free(&secblob_out);
502 ap_rep_wrapped = data_blob_null;
503 secblob_out = spnego_gen_auth_response(
508 *out_security_buffer = data_blob_talloc(smb2req,
511 data_blob_free(&secblob_out);
515 static NTSTATUS smbd_smb2_spnego_negotiate(struct smbd_smb2_session *session,
516 struct smbd_smb2_request *smb2req,
517 uint8_t in_security_flags,
518 DATA_BLOB in_security_buffer,
519 uint16_t *out_session_flags,
520 DATA_BLOB *out_security_buffer,
521 uint64_t *out_session_id)
523 DATA_BLOB secblob_in = data_blob_null;
524 DATA_BLOB chal_out = data_blob_null;
525 DATA_BLOB secblob_out = data_blob_null;
526 char *kerb_mech = NULL;
529 /* Ensure we have no old NTLM state around. */
530 auth_ntlmssp_end(&session->auth_ntlmssp_state);
532 status = parse_spnego_mechanisms(in_security_buffer,
533 &secblob_in, &kerb_mech);
534 if (!NT_STATUS_IS_OK(status)) {
539 if (kerb_mech && ((lp_security()==SEC_ADS) ||
540 USE_KERBEROS_KEYTAB) ) {
541 status = smbd_smb2_session_setup_krb5(session,
554 /* Fall back to NTLMSSP. */
555 status = auth_ntlmssp_start(&session->auth_ntlmssp_state);
556 if (!NT_STATUS_IS_OK(status)) {
560 status = auth_ntlmssp_update(session->auth_ntlmssp_state,
564 if (!NT_STATUS_IS_OK(status) &&
565 !NT_STATUS_EQUAL(status,
566 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
570 secblob_out = spnego_gen_auth_response(&chal_out,
573 *out_security_buffer = data_blob_talloc(smb2req,
576 if (secblob_out.data && out_security_buffer->data == NULL) {
577 status = NT_STATUS_NO_MEMORY;
580 *out_session_id = session->vuid;
584 data_blob_free(&secblob_in);
585 data_blob_free(&secblob_out);
586 data_blob_free(&chal_out);
587 SAFE_FREE(kerb_mech);
588 if (!NT_STATUS_IS_OK(status) &&
589 !NT_STATUS_EQUAL(status,
590 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
591 auth_ntlmssp_end(&session->auth_ntlmssp_state);
592 TALLOC_FREE(session);
597 static NTSTATUS smbd_smb2_common_ntlmssp_auth_return(struct smbd_smb2_session *session,
598 struct smbd_smb2_request *smb2req,
599 uint8_t in_security_mode,
600 DATA_BLOB in_security_buffer,
601 uint16_t *out_session_flags,
602 uint64_t *out_session_id)
606 if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
607 lp_server_signing() == Required) {
608 session->do_signing = true;
611 if (session->auth_ntlmssp_state->server_info->guest) {
612 /* we map anonymous to guest internally */
613 *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
614 *out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
615 /* force no signing */
616 session->do_signing = false;
619 session->server_info = session->auth_ntlmssp_state->server_info;
620 data_blob_free(&session->server_info->user_session_key);
621 session->server_info->user_session_key =
623 session->server_info,
624 session->auth_ntlmssp_state->ntlmssp_state->session_key.data,
625 session->auth_ntlmssp_state->ntlmssp_state->session_key.length);
626 if (session->auth_ntlmssp_state->ntlmssp_state->session_key.length > 0) {
627 if (session->server_info->user_session_key.data == NULL) {
628 auth_ntlmssp_end(&session->auth_ntlmssp_state);
629 TALLOC_FREE(session);
630 return NT_STATUS_NO_MEMORY;
633 session->session_key = session->server_info->user_session_key;
635 session->compat_vuser = talloc_zero(session, user_struct);
636 if (session->compat_vuser == NULL) {
637 auth_ntlmssp_end(&session->auth_ntlmssp_state);
638 TALLOC_FREE(session);
639 return NT_STATUS_NO_MEMORY;
641 session->compat_vuser->auth_ntlmssp_state = session->auth_ntlmssp_state;
642 session->compat_vuser->homes_snum = -1;
643 session->compat_vuser->server_info = session->server_info;
644 session->compat_vuser->session_keystr = NULL;
645 session->compat_vuser->vuid = session->vuid;
646 DLIST_ADD(session->sconn->smb1.sessions.validated_users, session->compat_vuser);
648 /* This is a potentially untrusted username */
650 session->auth_ntlmssp_state->ntlmssp_state->user,
653 session->server_info->sanitized_username = talloc_strdup(
654 session->server_info, tmp);
656 if (!session->compat_vuser->server_info->guest) {
657 session->compat_vuser->homes_snum =
658 register_homes_share(session->server_info->unix_name);
661 if (!session_claim(session->compat_vuser)) {
662 DEBUG(1, ("smb2: Failed to claim session "
664 session->compat_vuser->vuid));
665 auth_ntlmssp_end(&session->auth_ntlmssp_state);
666 TALLOC_FREE(session);
667 return NT_STATUS_LOGON_FAILURE;
671 session->status = NT_STATUS_OK;
674 * we attach the session to the request
675 * so that the response can be signed
677 smb2req->session = session;
678 if (session->do_signing) {
679 smb2req->do_signing = true;
682 global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
684 *out_session_id = session->vuid;
689 static NTSTATUS smbd_smb2_spnego_auth(struct smbd_smb2_session *session,
690 struct smbd_smb2_request *smb2req,
691 uint8_t in_security_mode,
692 DATA_BLOB in_security_buffer,
693 uint16_t *out_session_flags,
694 DATA_BLOB *out_security_buffer,
695 uint64_t *out_session_id)
697 DATA_BLOB auth = data_blob_null;
698 DATA_BLOB auth_out = data_blob_null;
699 DATA_BLOB secblob_out = data_blob_null;
702 if (!spnego_parse_auth(in_security_buffer, &auth)) {
703 TALLOC_FREE(session);
704 return NT_STATUS_LOGON_FAILURE;
707 status = auth_ntlmssp_update(session->auth_ntlmssp_state,
710 if (!NT_STATUS_IS_OK(status)) {
711 auth_ntlmssp_end(&session->auth_ntlmssp_state);
712 data_blob_free(&auth);
713 TALLOC_FREE(session);
717 data_blob_free(&auth);
719 secblob_out = spnego_gen_auth_response(&auth_out,
722 *out_security_buffer = data_blob_talloc(smb2req,
725 if (secblob_out.data && out_security_buffer->data == NULL) {
726 auth_ntlmssp_end(&session->auth_ntlmssp_state);
727 TALLOC_FREE(session);
728 return NT_STATUS_NO_MEMORY;
731 *out_session_id = session->vuid;
733 return smbd_smb2_common_ntlmssp_auth_return(session,
741 static NTSTATUS smbd_smb2_raw_ntlmssp_auth(struct smbd_smb2_session *session,
742 struct smbd_smb2_request *smb2req,
743 uint8_t in_security_mode,
744 DATA_BLOB in_security_buffer,
745 uint16_t *out_session_flags,
746 DATA_BLOB *out_security_buffer,
747 uint64_t *out_session_id)
750 DATA_BLOB secblob_out = data_blob_null;
752 if (session->auth_ntlmssp_state == NULL) {
753 status = auth_ntlmssp_start(&session->auth_ntlmssp_state);
754 if (!NT_STATUS_IS_OK(status)) {
755 TALLOC_FREE(session);
761 status = auth_ntlmssp_update(session->auth_ntlmssp_state,
765 if (NT_STATUS_IS_OK(status) ||
766 NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
767 *out_security_buffer = data_blob_talloc(smb2req,
770 if (secblob_out.data && out_security_buffer->data == NULL) {
771 auth_ntlmssp_end(&session->auth_ntlmssp_state);
772 TALLOC_FREE(session);
773 return NT_STATUS_NO_MEMORY;
777 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
778 *out_session_id = session->vuid;
781 if (!NT_STATUS_IS_OK(status)) {
782 auth_ntlmssp_end(&session->auth_ntlmssp_state);
783 TALLOC_FREE(session);
786 *out_session_id = session->vuid;
788 return smbd_smb2_common_ntlmssp_auth_return(session,
796 static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *smb2req,
797 uint64_t in_session_id,
798 uint8_t in_security_mode,
799 DATA_BLOB in_security_buffer,
800 uint16_t *out_session_flags,
801 DATA_BLOB *out_security_buffer,
802 uint64_t *out_session_id)
804 struct smbd_smb2_session *session;
806 *out_session_flags = 0;
809 if (in_session_id == 0) {
812 /* create a new session */
813 session = talloc_zero(smb2req->sconn, struct smbd_smb2_session);
814 if (session == NULL) {
815 return NT_STATUS_NO_MEMORY;
817 session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
818 id = idr_get_new_random(smb2req->sconn->smb2.sessions.idtree,
820 smb2req->sconn->smb2.sessions.limit);
822 return NT_STATUS_INSUFFICIENT_RESOURCES;
826 session->tcons.idtree = idr_init(session);
827 if (session->tcons.idtree == NULL) {
828 return NT_STATUS_NO_MEMORY;
830 session->tcons.limit = 0x0000FFFE;
831 session->tcons.list = NULL;
833 DLIST_ADD_END(smb2req->sconn->smb2.sessions.list, session,
834 struct smbd_smb2_session *);
835 session->sconn = smb2req->sconn;
836 talloc_set_destructor(session, smbd_smb2_session_destructor);
840 /* lookup an existing session */
841 p = idr_find(smb2req->sconn->smb2.sessions.idtree, in_session_id);
843 return NT_STATUS_USER_SESSION_DELETED;
845 session = talloc_get_type_abort(p, struct smbd_smb2_session);
848 if (NT_STATUS_IS_OK(session->status)) {
849 return NT_STATUS_REQUEST_NOT_ACCEPTED;
852 if (in_security_buffer.data[0] == ASN1_APPLICATION(0)) {
853 return smbd_smb2_spnego_negotiate(session,
860 } else if (in_security_buffer.data[0] == ASN1_CONTEXT(1)) {
861 return smbd_smb2_spnego_auth(session,
868 } else if (strncmp((char *)(in_security_buffer.data), "NTLMSSP", 7) == 0) {
869 return smbd_smb2_raw_ntlmssp_auth(session,
878 /* Unknown packet type. */
879 DEBUG(1,("Unknown packet type %u in smb2 sessionsetup\n",
880 (unsigned int)in_security_buffer.data[0] ));
881 auth_ntlmssp_end(&session->auth_ntlmssp_state);
882 TALLOC_FREE(session);
883 return NT_STATUS_LOGON_FAILURE;
886 NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
888 const uint8_t *inhdr;
889 const uint8_t *outhdr;
890 int i = req->current_idx;
891 uint64_t in_session_id;
893 struct smbd_smb2_session *session;
894 bool chained_fixup = false;
896 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
898 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
900 if (in_session_id == (0xFFFFFFFFFFFFFFFFLL)) {
903 * async request - fill in session_id from
904 * already setup request out.vector[].iov_base.
906 outhdr = (const uint8_t *)req->out.vector[i].iov_base;
907 in_session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
910 * Chained request - fill in session_id from
911 * the previous request out.vector[].iov_base.
913 outhdr = (const uint8_t *)req->out.vector[i-3].iov_base;
914 in_session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
915 chained_fixup = true;
919 /* lookup an existing session */
920 p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
922 return NT_STATUS_USER_SESSION_DELETED;
924 session = talloc_get_type_abort(p, struct smbd_smb2_session);
926 if (!NT_STATUS_IS_OK(session->status)) {
927 return NT_STATUS_ACCESS_DENIED;
930 set_current_user_info(session->server_info->sanitized_username,
931 session->server_info->unix_name,
932 pdb_get_domain(session->server_info->sam_account));
934 req->session = session;
937 /* Fix up our own outhdr. */
938 outhdr = (const uint8_t *)req->out.vector[i].iov_base;
939 SBVAL(outhdr, SMB2_HDR_SESSION_ID, in_session_id);
944 NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req)
946 const uint8_t *inbody;
947 int i = req->current_idx;
949 size_t expected_body_size = 0x04;
952 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
953 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
956 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
958 body_size = SVAL(inbody, 0x00);
959 if (body_size != expected_body_size) {
960 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
964 * TODO: cancel all outstanding requests on the session
965 * and delete all tree connections.
967 smbd_smb2_session_destructor(req->session);
969 * we may need to sign the response, so we need to keep
970 * the session until the response is sent to the wire.
972 talloc_steal(req, req->session);
974 outbody = data_blob_talloc(req->out.vector, NULL, 0x04);
975 if (outbody.data == NULL) {
976 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
979 SSVAL(outbody.data, 0x00, 0x04); /* struct size */
980 SSVAL(outbody.data, 0x02, 0); /* reserved */
982 return smbd_smb2_request_done(req, outbody, NULL);