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;
147 static NTSTATUS smbd_smb2_session_setup_krb5(struct smbd_smb2_session *session,
148 struct smbd_smb2_request *smb2req,
149 uint8_t in_security_mode,
150 const DATA_BLOB *secblob,
152 uint16_t *out_session_flags,
153 DATA_BLOB *out_security_buffer,
154 uint64_t *out_session_id)
156 DATA_BLOB ap_rep = data_blob_null;
157 DATA_BLOB ap_rep_wrapped = data_blob_null;
158 DATA_BLOB ticket = data_blob_null;
159 DATA_BLOB session_key = data_blob_null;
160 DATA_BLOB secblob_out = data_blob_null;
162 struct PAC_LOGON_INFO *logon_info = NULL;
166 struct passwd *pw = NULL;
169 fstring real_username;
171 bool username_was_mapped = false;
172 bool map_domainuser_to_guest = false;
173 struct smbd_server_connection *sconn = smbd_server_conn;
175 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
176 status = NT_STATUS_LOGON_FAILURE;
180 status = ads_verify_ticket(smb2req, lp_realm(), 0, &ticket,
181 &client, &logon_info, &ap_rep,
184 if (!NT_STATUS_IS_OK(status)) {
185 DEBUG(1,("smb2: Failed to verify incoming ticket with error %s!\n",
187 if (!NT_STATUS_EQUAL(status, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
188 status = NT_STATUS_LOGON_FAILURE;
193 DEBUG(3,("smb2: Ticket name is [%s]\n", client));
195 p = strchr_m(client, '@');
197 DEBUG(3,("smb2: %s Doesn't look like a valid principal\n",
199 status = NT_STATUS_LOGON_FAILURE;
205 /* save the PAC data if we have it */
208 netsamlogon_cache_store(client, &logon_info->info3);
211 if (!strequal(p+1, lp_realm())) {
212 DEBUG(3,("smb2: Ticket for foreign realm %s@%s\n", client, p+1));
213 if (!lp_allow_trusted_domains()) {
214 status = NT_STATUS_LOGON_FAILURE;
219 /* this gives a fully qualified user name (ie. with full realm).
220 that leads to very long usernames, but what else can we do? */
224 if (logon_info && logon_info->info3.base.domain.string) {
225 domain = talloc_strdup(talloc_tos(),
226 logon_info->info3.base.domain.string);
228 status = NT_STATUS_NO_MEMORY;
231 DEBUG(10, ("smb2: Mapped to [%s] (using PAC)\n", domain));
234 /* If we have winbind running, we can (and must) shorten the
235 username by using the short netbios name. Otherwise we will
236 have inconsistent user names. With Kerberos, we get the
237 fully qualified realm, with ntlmssp we get the short
238 name. And even w2k3 does use ntlmssp if you for example
239 connect to an ip address. */
242 struct wbcDomainInfo *info = NULL;
244 DEBUG(10, ("smb2: Mapping [%s] to short name\n", domain));
246 wbc_status = wbcDomainInfo(domain, &info);
248 if (WBC_ERROR_IS_OK(wbc_status)) {
249 domain = talloc_strdup(talloc_tos(), info->short_name);
253 status = NT_STATUS_NO_MEMORY;
256 DEBUG(10, ("smb2: Mapped to [%s] (using Winbind)\n", domain));
258 DEBUG(3, ("smb2: Could not find short name: %s\n",
259 wbcErrorString(wbc_status)));
263 /* We have to use fstring for this - map_username requires it. */
264 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
266 /* lookup the passwd struct, create a new user if necessary */
268 username_was_mapped = map_username(sconn, user);
270 pw = smb_getpwnam(talloc_tos(), user, real_username, true );
272 /* if a real user check pam account restrictions */
273 /* only really perfomed if "obey pam restriction" is true */
274 /* do this before an eventual mapping to guest occurs */
275 status = smb_pam_accountcheck(pw->pw_name);
276 if (!NT_STATUS_IS_OK(status)) {
277 DEBUG(1,("smb2: PAM account restriction "
278 "prevents user login\n"));
285 /* this was originally the behavior of Samba 2.2, if a user
286 did not have a local uid but has been authenticated, then
287 map them to a guest account */
289 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
290 map_domainuser_to_guest = true;
291 fstrcpy(user,lp_guestaccount());
292 pw = smb_getpwnam(talloc_tos(), user, real_username, true );
295 /* extra sanity check that the guest account is valid */
298 DEBUG(1,("smb2: Username %s is invalid on this system\n",
300 status = NT_STATUS_LOGON_FAILURE;
305 /* setup the string used by %U */
307 sub_set_smb_name(real_username);
308 reload_services(true);
310 if (map_domainuser_to_guest) {
311 make_server_info_guest(session, &session->server_info);
312 } else if (logon_info) {
313 /* pass the unmapped username here since map_username()
314 will be called again from inside make_server_info_info3() */
316 status = make_server_info_info3(session,
319 &session->server_info,
321 if (!NT_STATUS_IS_OK(status) ) {
322 DEBUG(1,("smb2: make_server_info_info3 failed: %s!\n",
329 * We didn't get a PAC, we have to make up the user
330 * ourselves. Try to ask the pdb backend to provide
331 * SID consistency with ntlmssp session setup
333 struct samu *sampass;
334 /* The stupid make_server_info_XX functions here
335 don't take a talloc context. */
336 struct auth_serversupplied_info *tmp_server_info = NULL;
338 sampass = samu_new(talloc_tos());
339 if (sampass == NULL) {
340 status = NT_STATUS_NO_MEMORY;
344 if (pdb_getsampwnam(sampass, real_username)) {
345 DEBUG(10, ("smb2: found user %s in passdb, calling "
346 "make_server_info_sam\n", real_username));
347 status = make_server_info_sam(&tmp_server_info, sampass);
350 * User not in passdb, make it up artificially
352 TALLOC_FREE(sampass);
353 DEBUG(10, ("smb2: didn't find user %s in passdb, calling "
354 "make_server_info_pw\n", real_username));
355 status = make_server_info_pw(&tmp_server_info,
360 if (!NT_STATUS_IS_OK(status)) {
361 DEBUG(1,("smb2: make_server_info_[sam|pw] failed: %s!\n",
366 /* Steal tmp_server_info into the session->server_info
368 session->server_info = talloc_move(session, &tmp_server_info);
370 /* make_server_info_pw does not set the domain. Without this
371 * we end up with the local netbios name in substitutions for
374 if (session->server_info->sam_account != NULL) {
375 pdb_set_domain(session->server_info->sam_account,
381 session->server_info->nss_token |= username_was_mapped;
383 /* we need to build the token for the user. make_server_info_guest()
386 if (!session->server_info->ptok ) {
387 status = create_local_token(session->server_info);
388 if (!NT_STATUS_IS_OK(status)) {
389 DEBUG(10,("smb2: failed to create local token: %s\n",
395 if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
396 lp_server_signing() == Required) {
397 session->do_signing = true;
400 if (session->server_info->guest) {
401 /* we map anonymous to guest internally */
402 *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
403 *out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
404 /* force no signing */
405 session->do_signing = false;
408 data_blob_free(&session->server_info->user_session_key);
409 session->server_info->user_session_key =
411 session->server_info,
414 if (session_key.length > 0) {
415 if (session->server_info->user_session_key.data == NULL) {
416 status = NT_STATUS_NO_MEMORY;
420 session->session_key = session->server_info->user_session_key;
422 session->compat_vuser = talloc_zero(session, user_struct);
423 if (session->compat_vuser == NULL) {
424 status = NT_STATUS_NO_MEMORY;
427 session->compat_vuser->auth_ntlmssp_state = NULL;
428 session->compat_vuser->homes_snum = -1;
429 session->compat_vuser->server_info = session->server_info;
430 session->compat_vuser->session_keystr = NULL;
431 session->compat_vuser->vuid = session->vuid;
432 DLIST_ADD(session->sconn->smb1.sessions.validated_users, session->compat_vuser);
434 /* This is a potentially untrusted username */
439 session->server_info->sanitized_username = talloc_strdup(
440 session->server_info, tmp);
442 if (!session->server_info->guest) {
443 session->compat_vuser->homes_snum =
444 register_homes_share(session->server_info->unix_name);
447 if (!session_claim(session->compat_vuser)) {
448 DEBUG(1, ("smb2: Failed to claim session "
450 session->compat_vuser->vuid));
454 session->status = NT_STATUS_OK;
457 * we attach the session to the request
458 * so that the response can be signed
460 smb2req->session = session;
461 if (session->do_signing) {
462 smb2req->do_signing = true;
465 global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
466 status = NT_STATUS_OK;
468 /* wrap that up in a nice GSS-API wrapping */
469 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
472 secblob_out = spnego_gen_auth_response(
477 *out_security_buffer = data_blob_talloc(smb2req,
480 if (secblob_out.data && out_security_buffer->data == NULL) {
481 status = NT_STATUS_NO_MEMORY;
485 data_blob_free(&ap_rep);
486 data_blob_free(&ap_rep_wrapped);
487 data_blob_free(&ticket);
488 data_blob_free(&session_key);
489 data_blob_free(&secblob_out);
491 *out_session_id = session->vuid;
497 data_blob_free(&ap_rep);
498 data_blob_free(&ap_rep_wrapped);
499 data_blob_free(&ticket);
500 data_blob_free(&session_key);
501 data_blob_free(&secblob_out);
503 ap_rep_wrapped = data_blob_null;
504 secblob_out = spnego_gen_auth_response(
509 *out_security_buffer = data_blob_talloc(smb2req,
512 data_blob_free(&secblob_out);
517 static NTSTATUS smbd_smb2_spnego_negotiate(struct smbd_smb2_session *session,
518 struct smbd_smb2_request *smb2req,
519 uint8_t in_security_flags,
520 DATA_BLOB in_security_buffer,
521 uint16_t *out_session_flags,
522 DATA_BLOB *out_security_buffer,
523 uint64_t *out_session_id)
525 DATA_BLOB secblob_in = data_blob_null;
526 DATA_BLOB chal_out = data_blob_null;
527 DATA_BLOB secblob_out = data_blob_null;
528 char *kerb_mech = NULL;
531 /* Ensure we have no old NTLM state around. */
532 auth_ntlmssp_end(&session->auth_ntlmssp_state);
534 status = parse_spnego_mechanisms(in_security_buffer,
535 &secblob_in, &kerb_mech);
536 if (!NT_STATUS_IS_OK(status)) {
541 if (kerb_mech && ((lp_security()==SEC_ADS) ||
542 USE_KERBEROS_KEYTAB) ) {
543 status = smbd_smb2_session_setup_krb5(session,
556 /* Fall back to NTLMSSP. */
557 status = auth_ntlmssp_start(&session->auth_ntlmssp_state);
558 if (!NT_STATUS_IS_OK(status)) {
562 status = auth_ntlmssp_update(session->auth_ntlmssp_state,
566 if (!NT_STATUS_IS_OK(status) &&
567 !NT_STATUS_EQUAL(status,
568 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
572 secblob_out = spnego_gen_auth_response(&chal_out,
575 *out_security_buffer = data_blob_talloc(smb2req,
578 if (secblob_out.data && out_security_buffer->data == NULL) {
579 status = NT_STATUS_NO_MEMORY;
582 *out_session_id = session->vuid;
586 data_blob_free(&secblob_in);
587 data_blob_free(&secblob_out);
588 data_blob_free(&chal_out);
589 SAFE_FREE(kerb_mech);
590 if (!NT_STATUS_IS_OK(status) &&
591 !NT_STATUS_EQUAL(status,
592 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
593 auth_ntlmssp_end(&session->auth_ntlmssp_state);
594 TALLOC_FREE(session);
599 static NTSTATUS smbd_smb2_common_ntlmssp_auth_return(struct smbd_smb2_session *session,
600 struct smbd_smb2_request *smb2req,
601 uint8_t in_security_mode,
602 DATA_BLOB in_security_buffer,
603 uint16_t *out_session_flags,
604 uint64_t *out_session_id)
608 if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
609 lp_server_signing() == Required) {
610 session->do_signing = true;
613 if (session->auth_ntlmssp_state->server_info->guest) {
614 /* we map anonymous to guest internally */
615 *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
616 *out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
617 /* force no signing */
618 session->do_signing = false;
621 session->server_info = session->auth_ntlmssp_state->server_info;
622 data_blob_free(&session->server_info->user_session_key);
623 session->server_info->user_session_key =
625 session->server_info,
626 session->auth_ntlmssp_state->ntlmssp_state->session_key.data,
627 session->auth_ntlmssp_state->ntlmssp_state->session_key.length);
628 if (session->auth_ntlmssp_state->ntlmssp_state->session_key.length > 0) {
629 if (session->server_info->user_session_key.data == NULL) {
630 auth_ntlmssp_end(&session->auth_ntlmssp_state);
631 TALLOC_FREE(session);
632 return NT_STATUS_NO_MEMORY;
635 session->session_key = session->server_info->user_session_key;
637 session->compat_vuser = talloc_zero(session, user_struct);
638 if (session->compat_vuser == NULL) {
639 auth_ntlmssp_end(&session->auth_ntlmssp_state);
640 TALLOC_FREE(session);
641 return NT_STATUS_NO_MEMORY;
643 session->compat_vuser->auth_ntlmssp_state = session->auth_ntlmssp_state;
644 session->compat_vuser->homes_snum = -1;
645 session->compat_vuser->server_info = session->server_info;
646 session->compat_vuser->session_keystr = NULL;
647 session->compat_vuser->vuid = session->vuid;
648 DLIST_ADD(session->sconn->smb1.sessions.validated_users, session->compat_vuser);
650 /* This is a potentially untrusted username */
652 session->auth_ntlmssp_state->ntlmssp_state->user,
655 session->server_info->sanitized_username = talloc_strdup(
656 session->server_info, tmp);
658 if (!session->compat_vuser->server_info->guest) {
659 session->compat_vuser->homes_snum =
660 register_homes_share(session->server_info->unix_name);
663 if (!session_claim(session->compat_vuser)) {
664 DEBUG(1, ("smb2: Failed to claim session "
666 session->compat_vuser->vuid));
667 auth_ntlmssp_end(&session->auth_ntlmssp_state);
668 TALLOC_FREE(session);
669 return NT_STATUS_LOGON_FAILURE;
673 session->status = NT_STATUS_OK;
676 * we attach the session to the request
677 * so that the response can be signed
679 smb2req->session = session;
680 if (session->do_signing) {
681 smb2req->do_signing = true;
684 global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
686 *out_session_id = session->vuid;
691 static NTSTATUS smbd_smb2_spnego_auth(struct smbd_smb2_session *session,
692 struct smbd_smb2_request *smb2req,
693 uint8_t in_security_mode,
694 DATA_BLOB in_security_buffer,
695 uint16_t *out_session_flags,
696 DATA_BLOB *out_security_buffer,
697 uint64_t *out_session_id)
699 DATA_BLOB auth = data_blob_null;
700 DATA_BLOB auth_out = data_blob_null;
701 DATA_BLOB secblob_out = data_blob_null;
704 if (!spnego_parse_auth(in_security_buffer, &auth)) {
705 TALLOC_FREE(session);
706 return NT_STATUS_LOGON_FAILURE;
709 status = auth_ntlmssp_update(session->auth_ntlmssp_state,
712 if (!NT_STATUS_IS_OK(status)) {
713 auth_ntlmssp_end(&session->auth_ntlmssp_state);
714 data_blob_free(&auth);
715 TALLOC_FREE(session);
719 data_blob_free(&auth);
721 secblob_out = spnego_gen_auth_response(&auth_out,
724 *out_security_buffer = data_blob_talloc(smb2req,
727 if (secblob_out.data && out_security_buffer->data == NULL) {
728 auth_ntlmssp_end(&session->auth_ntlmssp_state);
729 TALLOC_FREE(session);
730 return NT_STATUS_NO_MEMORY;
733 *out_session_id = session->vuid;
735 return smbd_smb2_common_ntlmssp_auth_return(session,
743 static NTSTATUS smbd_smb2_raw_ntlmssp_auth(struct smbd_smb2_session *session,
744 struct smbd_smb2_request *smb2req,
745 uint8_t in_security_mode,
746 DATA_BLOB in_security_buffer,
747 uint16_t *out_session_flags,
748 DATA_BLOB *out_security_buffer,
749 uint64_t *out_session_id)
752 DATA_BLOB secblob_out = data_blob_null;
754 if (session->auth_ntlmssp_state == NULL) {
755 status = auth_ntlmssp_start(&session->auth_ntlmssp_state);
756 if (!NT_STATUS_IS_OK(status)) {
757 TALLOC_FREE(session);
763 status = auth_ntlmssp_update(session->auth_ntlmssp_state,
767 if (NT_STATUS_IS_OK(status) ||
768 NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
769 *out_security_buffer = data_blob_talloc(smb2req,
772 if (secblob_out.data && out_security_buffer->data == NULL) {
773 auth_ntlmssp_end(&session->auth_ntlmssp_state);
774 TALLOC_FREE(session);
775 return NT_STATUS_NO_MEMORY;
779 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
780 *out_session_id = session->vuid;
783 if (!NT_STATUS_IS_OK(status)) {
784 auth_ntlmssp_end(&session->auth_ntlmssp_state);
785 TALLOC_FREE(session);
788 *out_session_id = session->vuid;
790 return smbd_smb2_common_ntlmssp_auth_return(session,
798 static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *smb2req,
799 uint64_t in_session_id,
800 uint8_t in_security_mode,
801 DATA_BLOB in_security_buffer,
802 uint16_t *out_session_flags,
803 DATA_BLOB *out_security_buffer,
804 uint64_t *out_session_id)
806 struct smbd_smb2_session *session;
808 *out_session_flags = 0;
811 if (in_session_id == 0) {
814 /* create a new session */
815 session = talloc_zero(smb2req->sconn, struct smbd_smb2_session);
816 if (session == NULL) {
817 return NT_STATUS_NO_MEMORY;
819 session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
820 id = idr_get_new_random(smb2req->sconn->smb2.sessions.idtree,
822 smb2req->sconn->smb2.sessions.limit);
824 return NT_STATUS_INSUFFICIENT_RESOURCES;
828 session->tcons.idtree = idr_init(session);
829 if (session->tcons.idtree == NULL) {
830 return NT_STATUS_NO_MEMORY;
832 session->tcons.limit = 0x0000FFFE;
833 session->tcons.list = NULL;
835 DLIST_ADD_END(smb2req->sconn->smb2.sessions.list, session,
836 struct smbd_smb2_session *);
837 session->sconn = smb2req->sconn;
838 talloc_set_destructor(session, smbd_smb2_session_destructor);
842 /* lookup an existing session */
843 p = idr_find(smb2req->sconn->smb2.sessions.idtree, in_session_id);
845 return NT_STATUS_USER_SESSION_DELETED;
847 session = talloc_get_type_abort(p, struct smbd_smb2_session);
850 if (NT_STATUS_IS_OK(session->status)) {
851 return NT_STATUS_REQUEST_NOT_ACCEPTED;
854 if (in_security_buffer.data[0] == ASN1_APPLICATION(0)) {
855 return smbd_smb2_spnego_negotiate(session,
862 } else if (in_security_buffer.data[0] == ASN1_CONTEXT(1)) {
863 return smbd_smb2_spnego_auth(session,
870 } else if (strncmp((char *)(in_security_buffer.data), "NTLMSSP", 7) == 0) {
871 return smbd_smb2_raw_ntlmssp_auth(session,
880 /* Unknown packet type. */
881 DEBUG(1,("Unknown packet type %u in smb2 sessionsetup\n",
882 (unsigned int)in_security_buffer.data[0] ));
883 auth_ntlmssp_end(&session->auth_ntlmssp_state);
884 TALLOC_FREE(session);
885 return NT_STATUS_LOGON_FAILURE;
888 NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
890 const uint8_t *inhdr;
891 const uint8_t *outhdr;
892 int i = req->current_idx;
893 uint64_t in_session_id;
895 struct smbd_smb2_session *session;
896 bool chained_fixup = false;
898 inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
900 in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
902 if (in_session_id == (0xFFFFFFFFFFFFFFFFLL)) {
905 * async request - fill in session_id from
906 * already setup request out.vector[].iov_base.
908 outhdr = (const uint8_t *)req->out.vector[i].iov_base;
909 in_session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
912 * Chained request - fill in session_id from
913 * the previous request out.vector[].iov_base.
915 outhdr = (const uint8_t *)req->out.vector[i-3].iov_base;
916 in_session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
917 chained_fixup = true;
921 /* lookup an existing session */
922 p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
924 return NT_STATUS_USER_SESSION_DELETED;
926 session = talloc_get_type_abort(p, struct smbd_smb2_session);
928 if (!NT_STATUS_IS_OK(session->status)) {
929 return NT_STATUS_ACCESS_DENIED;
932 set_current_user_info(session->server_info->sanitized_username,
933 session->server_info->unix_name,
934 pdb_get_domain(session->server_info->sam_account));
936 req->session = session;
939 /* Fix up our own outhdr. */
940 outhdr = (const uint8_t *)req->out.vector[i].iov_base;
941 SBVAL(outhdr, SMB2_HDR_SESSION_ID, in_session_id);
946 NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req)
948 const uint8_t *inbody;
949 int i = req->current_idx;
951 size_t expected_body_size = 0x04;
954 if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
955 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
958 inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
960 body_size = SVAL(inbody, 0x00);
961 if (body_size != expected_body_size) {
962 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
966 * TODO: cancel all outstanding requests on the session
967 * and delete all tree connections.
969 smbd_smb2_session_destructor(req->session);
971 * we may need to sign the response, so we need to keep
972 * the session until the response is sent to the wire.
974 talloc_steal(req, req->session);
976 outbody = data_blob_talloc(req->out.vector, NULL, 0x04);
977 if (outbody.data == NULL) {
978 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
981 SSVAL(outbody.data, 0x00, 0x04); /* struct size */
982 SSVAL(outbody.data, 0x02, 0); /* reserved */
984 return smbd_smb2_request_done(req, outbody, NULL);