2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1998-2001
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
7 Copyright (C) Luke Howard 2003
8 Copyright (C) Volker Lendecke 2007
9 Copyright (C) Jeremy Allison 2007
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "../lib/tsocket/tsocket.h"
27 #include "lib/util/server_id.h"
28 #include "smbd/smbd.h"
29 #include "smbd/globals.h"
32 #include "smbprofile.h"
33 #include "../libcli/security/security.h"
34 #include "auth/gensec/gensec.h"
35 #include "lib/conn_tdb.h"
36 #include "../libcli/smb/smb_signing.h"
38 /****************************************************************************
39 Add the standard 'Samba' signature to the end of the session setup.
40 ****************************************************************************/
42 static int push_signature(uint8_t **outbuf)
50 fstr_sprintf(native_os, "Windows %d.%d", SAMBA_MAJOR_NBT_ANNOUNCE_VERSION,
51 SAMBA_MINOR_NBT_ANNOUNCE_VERSION);
53 tmp = message_push_string(outbuf, native_os, STR_TERMINATE);
55 if (tmp == -1) return -1;
58 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
59 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
63 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
66 if (tmp == -1) return -1;
69 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
71 if (tmp == -1) return -1;
77 /****************************************************************************
78 Do a 'guest' logon, getting back the
79 ****************************************************************************/
81 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
83 struct auth_session_info **session_info)
85 struct auth4_context *auth_context;
86 struct auth_usersupplied_info *user_info = NULL;
90 DEBUG(3,("Got anonymous request\n"));
92 nt_status = make_auth4_context(talloc_tos(), &auth_context);
93 if (!NT_STATUS_IS_OK(nt_status)) {
97 auth_context->get_ntlm_challenge(auth_context,
100 if (!make_user_info_guest(talloc_tos(), remote_address, &user_info)) {
101 TALLOC_FREE(auth_context);
102 return NT_STATUS_NO_MEMORY;
105 nt_status = auth_check_password_session_info(auth_context,
106 mem_ctx, user_info, session_info);
107 TALLOC_FREE(user_info);
108 TALLOC_FREE(auth_context);
112 /****************************************************************************
113 Reply to a session setup command.
114 conn POINTER CAN BE NULL HERE !
115 ****************************************************************************/
117 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
121 DATA_BLOB out_blob = data_blob_null;
124 const char *native_os;
125 const char *native_lanman;
126 const char *primary_domain;
127 uint16_t data_blob_len = SVAL(req->vwv+7, 0);
128 enum remote_arch_types ra_type = get_remote_arch();
129 uint64_t vuid = req->vuid;
130 NTSTATUS status = NT_STATUS_OK;
131 struct smbXsrv_connection *xconn = req->xconn;
132 struct smbd_server_connection *sconn = req->sconn;
134 bool is_authenticated = false;
135 NTTIME now = timeval_to_nttime(&req->request_time);
136 struct smbXsrv_session *session = NULL;
137 uint16_t smb_bufsize = SVAL(req->vwv+2, 0);
138 uint32_t client_caps = IVAL(req->vwv+10, 0);
139 struct smbXsrv_session_auth0 *auth;
141 DEBUG(3,("Doing spnego session setup\n"));
143 if (!xconn->smb1.sessions.done_sesssetup) {
144 global_client_caps = client_caps;
146 if (!(global_client_caps & CAP_STATUS32)) {
147 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
153 if (data_blob_len == 0) {
154 /* an invalid request */
155 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
159 bufrem = smbreq_bufrem(req, p);
160 /* pull the spnego blob */
161 in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
164 file_save("negotiate.dat", in_blob.data, in_blob.length);
167 p = req->buf + in_blob.length;
169 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
171 native_os = tmp ? tmp : "";
173 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
175 native_lanman = tmp ? tmp : "";
177 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
179 primary_domain = tmp ? tmp : "";
181 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
182 native_os, native_lanman, primary_domain));
184 if ( ra_type == RA_WIN2K ) {
185 /* Vista sets neither the OS or lanman strings */
187 if ( !strlen(native_os) && !strlen(native_lanman) )
188 set_remote_arch(RA_VISTA);
190 /* Windows 2003 doesn't set the native lanman string,
191 but does set primary domain which is a bug I think */
193 if ( !strlen(native_lanman) ) {
194 ra_lanman_string( primary_domain );
196 ra_lanman_string( native_lanman );
198 } else if ( ra_type == RA_VISTA ) {
199 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
200 set_remote_arch(RA_OSX);
205 status = smb1srv_session_lookup(xconn,
208 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
209 reply_force_doserror(req, ERRSRV, ERRbaduid);
212 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
213 status = NT_STATUS_OK;
215 if (NT_STATUS_IS_OK(status)) {
216 session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
217 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
218 TALLOC_FREE(session->pending_auth);
220 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
221 reply_nterror(req, nt_status_squash(status));
226 if (session == NULL) {
227 /* create a new session */
228 status = smbXsrv_session_create(xconn,
230 if (!NT_STATUS_IS_OK(status)) {
231 reply_nterror(req, nt_status_squash(status));
236 status = smbXsrv_session_find_auth(session, xconn, now, &auth);
237 if (!NT_STATUS_IS_OK(status)) {
238 status = smbXsrv_session_create_auth(session, xconn, now,
242 if (!NT_STATUS_IS_OK(status)) {
243 reply_nterror(req, nt_status_squash(status));
248 if (auth->gensec == NULL) {
249 status = auth_generic_prepare(session, xconn->remote_address,
251 if (!NT_STATUS_IS_OK(status)) {
252 TALLOC_FREE(session);
253 reply_nterror(req, nt_status_squash(status));
257 gensec_want_feature(auth->gensec, GENSEC_FEATURE_SESSION_KEY);
258 gensec_want_feature(auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
260 status = gensec_start_mech_by_oid(auth->gensec,
262 if (!NT_STATUS_IS_OK(status)) {
263 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
264 TALLOC_FREE(session);;
265 reply_nterror(req, nt_status_squash(status));
271 status = gensec_update(auth->gensec,
275 if (!NT_STATUS_IS_OK(status) &&
276 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
277 TALLOC_FREE(session);
278 reply_nterror(req, nt_status_squash(status));
282 if (NT_STATUS_IS_OK(status) && session->global->auth_session_info == NULL) {
283 struct auth_session_info *session_info = NULL;
285 status = gensec_session_info(auth->gensec,
288 if (!NT_STATUS_IS_OK(status)) {
289 DEBUG(1,("Failed to generate session_info "
290 "(user and group token) for session setup: %s\n",
292 data_blob_free(&out_blob);
293 TALLOC_FREE(session);
294 reply_nterror(req, nt_status_squash(status));
298 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
299 action |= SMB_SETUP_GUEST;
302 if (session_info->session_key.length > 0) {
303 struct smbXsrv_session *x = session;
306 * Note: the SMB1 signing key is not truncated to 16 byte!
308 x->global->signing_key =
309 data_blob_dup_talloc(x->global,
310 session_info->session_key);
311 if (x->global->signing_key.data == NULL) {
312 data_blob_free(&out_blob);
313 TALLOC_FREE(session);
314 reply_nterror(req, NT_STATUS_NO_MEMORY);
319 * clear the session key
320 * the first tcon will add setup the application key
322 data_blob_clear_free(&session_info->session_key);
325 session->compat = talloc_zero(session, struct user_struct);
326 if (session->compat == NULL) {
327 data_blob_free(&out_blob);
328 TALLOC_FREE(session);
329 reply_nterror(req, NT_STATUS_NO_MEMORY);
332 session->compat->session = session;
333 session->compat->homes_snum = -1;
334 session->compat->session_info = session_info;
335 session->compat->session_keystr = NULL;
336 session->compat->vuid = session->global->session_wire_id;
337 DLIST_ADD(sconn->users, session->compat);
340 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
341 is_authenticated = true;
342 session->compat->homes_snum =
343 register_homes_share(session_info->unix_info->unix_name);
346 if (srv_is_signing_negotiated(xconn) &&
348 session->global->signing_key.length > 0)
351 * Try and turn on server signing on the first non-guest
354 srv_set_signing(xconn,
355 session->global->signing_key,
359 set_current_user_info(session_info->unix_info->sanitized_username,
360 session_info->unix_info->unix_name,
361 session_info->info->domain_name);
363 session->status = NT_STATUS_OK;
364 session->global->auth_session_info = talloc_move(session->global,
366 session->global->auth_session_info_seqnum += 1;
367 session->global->channels[0].auth_session_info_seqnum =
368 session->global->auth_session_info_seqnum;
369 session->global->auth_time = now;
370 if (client_caps & CAP_DYNAMIC_REAUTH) {
371 session->global->expiration_time =
372 gensec_expire_time(auth->gensec);
374 session->global->expiration_time =
375 GENSEC_EXPIRE_TIME_INFINITY;
378 if (!session_claim(session)) {
379 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
380 (unsigned long long)session->compat->vuid));
381 data_blob_free(&out_blob);
382 TALLOC_FREE(session);
383 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
387 status = smbXsrv_session_update(session);
388 if (!NT_STATUS_IS_OK(status)) {
389 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
390 (unsigned long long)session->compat->vuid,
392 data_blob_free(&out_blob);
393 TALLOC_FREE(session);
394 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
398 if (!xconn->smb1.sessions.done_sesssetup) {
399 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
400 reply_force_doserror(req, ERRSRV, ERRerror);
403 xconn->smb1.sessions.max_send = smb_bufsize;
404 xconn->smb1.sessions.done_sesssetup = true;
407 /* current_user_info is changed on new vuid */
408 reload_services(sconn, conn_snum_used, true);
409 } else if (NT_STATUS_IS_OK(status)) {
410 struct auth_session_info *session_info = NULL;
412 status = gensec_session_info(auth->gensec,
415 if (!NT_STATUS_IS_OK(status)) {
416 DEBUG(1,("Failed to generate session_info "
417 "(user and group token) for session setup: %s\n",
419 data_blob_free(&out_blob);
420 TALLOC_FREE(session);
421 reply_nterror(req, nt_status_squash(status));
425 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
426 action |= SMB_SETUP_GUEST;
430 * Keep the application key
432 data_blob_clear_free(&session_info->session_key);
433 session_info->session_key =
434 session->global->auth_session_info->session_key;
435 talloc_steal(session_info, session_info->session_key.data);
436 TALLOC_FREE(session->global->auth_session_info);
438 session->compat->session_info = session_info;
440 session->compat->vuid = session->global->session_wire_id;
442 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
443 session->compat->homes_snum =
444 register_homes_share(session_info->unix_info->unix_name);
447 set_current_user_info(session_info->unix_info->sanitized_username,
448 session_info->unix_info->unix_name,
449 session_info->info->domain_name);
451 session->status = NT_STATUS_OK;
452 session->global->auth_session_info = talloc_move(session->global,
454 session->global->auth_session_info_seqnum += 1;
455 session->global->channels[0].auth_session_info_seqnum =
456 session->global->auth_session_info_seqnum;
457 session->global->auth_time = now;
458 if (client_caps & CAP_DYNAMIC_REAUTH) {
459 session->global->expiration_time =
460 gensec_expire_time(auth->gensec);
462 session->global->expiration_time =
463 GENSEC_EXPIRE_TIME_INFINITY;
466 status = smbXsrv_session_update(session);
467 if (!NT_STATUS_IS_OK(status)) {
468 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
469 (unsigned long long)session->compat->vuid,
471 data_blob_free(&out_blob);
472 TALLOC_FREE(session);
473 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
477 conn_clear_vuid_caches(sconn, session->compat->vuid);
479 /* current_user_info is changed on new vuid */
480 reload_services(sconn, conn_snum_used, true);
483 vuid = session->global->session_wire_id;
485 reply_outbuf(req, 4, 0);
487 SSVAL(req->outbuf, smb_uid, vuid);
488 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
489 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
490 SSVAL(req->outbuf, smb_vwv2, action);
491 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
493 if (message_push_blob(&req->outbuf, out_blob) == -1) {
494 data_blob_free(&out_blob);
495 TALLOC_FREE(session);
496 reply_nterror(req, NT_STATUS_NO_MEMORY);
499 data_blob_free(&out_blob);
501 if (push_signature(&req->outbuf) == -1) {
502 TALLOC_FREE(session);
503 reply_nterror(req, NT_STATUS_NO_MEMORY);
508 /****************************************************************************
509 On new VC == 0, shutdown *all* old connections and users.
510 It seems that only NT4.x does this. At W2K and above (XP etc.).
511 a new session setup with VC==0 is ignored.
512 ****************************************************************************/
514 struct shutdown_state {
516 struct messaging_context *msg_ctx;
519 static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
522 struct shutdown_state *state = (struct shutdown_state *)private_data;
523 struct server_id self_pid = messaging_server_id(state->msg_ctx);
524 struct server_id pid = session->channels[0].server_id;
525 const char *addr = session->channels[0].remote_address;
526 struct server_id_buf tmp;
528 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
529 server_id_str_buf(pid, &tmp), addr));
531 if (!process_exists(pid)) {
532 DEBUG(10, ("process does not exist\n"));
536 if (serverid_equal(&pid, &self_pid)) {
537 DEBUG(10, ("It's me\n"));
542 * here we use strstr() because 'addr'
543 * (session->channels[0].remote_address)
544 * contains a string like:
545 * 'ipv4:127.0.0.1:48163'
547 if (strstr(addr, state->ip) == NULL) {
548 DEBUG(10, ("%s does not match %s\n", state->ip, addr));
552 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
553 "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
556 messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
561 static void setup_new_vc_session(struct smbd_server_connection *sconn)
563 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
564 "compatible we would close all old resources.\n"));
567 invalidate_all_vuids();
569 if (lp_reset_on_zero_vc()) {
571 struct shutdown_state state;
573 addr = tsocket_address_inet_addr_string(
574 sconn->remote_address, talloc_tos());
579 state.msg_ctx = sconn->msg_ctx;
580 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
585 /****************************************************************************
586 Reply to a session setup command.
587 ****************************************************************************/
589 void reply_sesssetup_and_X(struct smb_request *req)
592 uint16_t smb_bufsize;
595 DATA_BLOB plaintext_password;
598 fstring sub_user; /* Sanitised username for substituion */
600 const char *native_os;
601 const char *native_lanman;
602 const char *primary_domain;
603 struct auth_usersupplied_info *user_info = NULL;
604 struct auth_session_info *session_info = NULL;
605 uint16_t smb_flag2 = req->flags2;
607 bool is_authenticated = false;
608 NTTIME now = timeval_to_nttime(&req->request_time);
609 struct smbXsrv_session *session = NULL;
611 struct smbXsrv_connection *xconn = req->xconn;
612 struct smbd_server_connection *sconn = req->sconn;
613 bool doencrypt = xconn->smb1.negprot.encrypted_passwords;
614 bool signing_allowed = false;
615 bool signing_mandatory = smb_signing_is_mandatory(
616 xconn->smb1.signing_state);
618 START_PROFILE(SMBsesssetupX);
620 ZERO_STRUCT(lm_resp);
621 ZERO_STRUCT(nt_resp);
622 ZERO_STRUCT(plaintext_password);
624 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
626 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
627 signing_allowed = true;
629 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
630 signing_mandatory = true;
634 * We can call srv_set_signing_negotiated() each time.
635 * It finds out when it needs to turn into a noop
638 srv_set_signing_negotiated(xconn,
642 /* a SPNEGO session setup has 12 command words, whereas a normal
643 NT1 session setup has 13. See the cifs spec. */
644 if (req->wct == 12 &&
645 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
647 if (!xconn->smb1.negprot.spnego) {
648 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
649 "at SPNEGO session setup when it was not "
651 reply_nterror(req, nt_status_squash(
652 NT_STATUS_LOGON_FAILURE));
653 END_PROFILE(SMBsesssetupX);
657 if (SVAL(req->vwv+4, 0) == 0) {
658 setup_new_vc_session(req->sconn);
661 reply_sesssetup_and_X_spnego(req);
662 END_PROFILE(SMBsesssetupX);
666 smb_bufsize = SVAL(req->vwv+2, 0);
668 if (get_Protocol() < PROTOCOL_NT1) {
669 uint16_t passlen1 = SVAL(req->vwv+7, 0);
671 /* Never do NT status codes with protocols before NT1 as we
672 * don't get client caps. */
673 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
675 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
676 reply_nterror(req, nt_status_squash(
677 NT_STATUS_INVALID_PARAMETER));
678 END_PROFILE(SMBsesssetupX);
683 lm_resp = data_blob(req->buf, passlen1);
685 plaintext_password = data_blob(req->buf, passlen1+1);
686 /* Ensure null termination */
687 plaintext_password.data[passlen1] = 0;
690 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
691 req->buf + passlen1, STR_TERMINATE);
692 user = tmp ? tmp : "";
697 uint16_t passlen1 = SVAL(req->vwv+7, 0);
698 uint16_t passlen2 = SVAL(req->vwv+8, 0);
699 enum remote_arch_types ra_type = get_remote_arch();
700 const uint8_t *p = req->buf;
701 const uint8_t *save_p = req->buf;
704 if (!xconn->smb1.sessions.done_sesssetup) {
705 global_client_caps = IVAL(req->vwv+11, 0);
707 if (!(global_client_caps & CAP_STATUS32)) {
708 remove_from_common_flags2(
709 FLAGS2_32_BIT_ERROR_CODES);
712 /* client_caps is used as final determination if
713 * client is NT or Win95. This is needed to return
714 * the correct error codes in some circumstances.
717 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
718 ra_type == RA_WIN95) {
719 if(!(global_client_caps & (CAP_NT_SMBS|
721 set_remote_arch( RA_WIN95);
727 /* both Win95 and WinNT stuff up the password
728 * lengths for non-encrypting systems. Uggh.
730 if passlen1==24 its a win95 system, and its setting
731 the password length incorrectly. Luckily it still
732 works with the default code because Win95 will null
733 terminate the password anyway
735 if passlen1>0 and passlen2>0 then maybe its a NT box
736 and its setting passlen2 to some random value which
737 really stuffs things up. we need to fix that one. */
739 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
745 /* check for nasty tricks */
746 if (passlen1 > MAX_PASS_LEN
747 || passlen1 > smbreq_bufrem(req, p)) {
748 reply_nterror(req, nt_status_squash(
749 NT_STATUS_INVALID_PARAMETER));
750 END_PROFILE(SMBsesssetupX);
754 if (passlen2 > MAX_PASS_LEN
755 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
756 reply_nterror(req, nt_status_squash(
757 NT_STATUS_INVALID_PARAMETER));
758 END_PROFILE(SMBsesssetupX);
762 /* Save the lanman2 password and the NT md4 password. */
764 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
769 lm_resp = data_blob(p, passlen1);
770 nt_resp = data_blob(p+passlen1, passlen2);
773 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
775 if (unic && (passlen2 == 0) && passlen1) {
776 /* Only a ascii plaintext password was sent. */
777 (void)srvstr_pull_talloc(talloc_tos(),
783 STR_TERMINATE|STR_ASCII);
785 (void)srvstr_pull_talloc(talloc_tos(),
790 unic ? passlen2 : passlen1,
794 reply_nterror(req, nt_status_squash(
795 NT_STATUS_INVALID_PARAMETER));
796 END_PROFILE(SMBsesssetupX);
799 plaintext_password = data_blob(pass, strlen(pass)+1);
802 p += passlen1 + passlen2;
804 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
806 user = tmp ? tmp : "";
808 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
810 domain = tmp ? tmp : "";
812 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
814 native_os = tmp ? tmp : "";
816 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
818 native_lanman = tmp ? tmp : "";
820 /* not documented or decoded by Ethereal but there is one more
821 * string in the extra bytes which is the same as the
822 * PrimaryDomain when using extended security. Windows NT 4
823 * and 2003 use this string to store the native lanman string.
824 * Windows 9x does not include a string here at all so we have
825 * to check if we have any extra bytes left */
827 byte_count = SVAL(req->vwv+13, 0);
828 if ( PTR_DIFF(p, save_p) < byte_count) {
829 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
831 primary_domain = tmp ? tmp : "";
833 primary_domain = talloc_strdup(talloc_tos(), "null");
836 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
837 "PrimaryDomain=[%s]\n",
838 domain, native_os, native_lanman, primary_domain));
840 if ( ra_type == RA_WIN2K ) {
841 if ( strlen(native_lanman) == 0 )
842 ra_lanman_string( primary_domain );
844 ra_lanman_string( native_lanman );
849 if (SVAL(req->vwv+4, 0) == 0) {
850 setup_new_vc_session(req->sconn);
853 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
854 domain, user, get_remote_machine_name()));
857 if (xconn->smb1.negprot.spnego) {
859 /* This has to be here, because this is a perfectly
860 * valid behaviour for guest logons :-( */
862 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
863 "at 'normal' session setup after "
864 "negotiating spnego.\n"));
865 reply_nterror(req, nt_status_squash(
866 NT_STATUS_LOGON_FAILURE));
867 END_PROFILE(SMBsesssetupX);
870 fstrcpy(sub_user, user);
872 fstrcpy(sub_user, "");
875 sub_set_smb_name(sub_user);
877 reload_services(sconn, conn_snum_used, true);
881 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
883 } else if (doencrypt) {
884 struct auth4_context *negprot_auth_context = NULL;
885 negprot_auth_context = xconn->smb1.negprot.auth_context;
886 if (!negprot_auth_context) {
887 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
888 "session setup without negprot denied!\n"));
889 reply_nterror(req, nt_status_squash(
890 NT_STATUS_LOGON_FAILURE));
891 END_PROFILE(SMBsesssetupX);
894 nt_status = make_user_info_for_reply_enc(talloc_tos(),
897 sconn->remote_address,
899 if (NT_STATUS_IS_OK(nt_status)) {
900 nt_status = auth_check_password_session_info(negprot_auth_context,
901 req, user_info, &session_info);
904 struct auth4_context *plaintext_auth_context = NULL;
906 nt_status = make_auth4_context(
907 talloc_tos(), &plaintext_auth_context);
909 if (NT_STATUS_IS_OK(nt_status)) {
912 plaintext_auth_context->get_ntlm_challenge(
913 plaintext_auth_context, chal);
915 if (!make_user_info_for_reply(talloc_tos(),
918 sconn->remote_address,
920 plaintext_password)) {
921 nt_status = NT_STATUS_NO_MEMORY;
924 if (NT_STATUS_IS_OK(nt_status)) {
925 nt_status = auth_check_password_session_info(plaintext_auth_context,
926 req, user_info, &session_info);
928 TALLOC_FREE(plaintext_auth_context);
932 TALLOC_FREE(user_info);
934 if (!NT_STATUS_IS_OK(nt_status)) {
935 data_blob_free(&nt_resp);
936 data_blob_free(&lm_resp);
937 data_blob_clear_free(&plaintext_password);
938 reply_nterror(req, nt_status_squash(nt_status));
939 END_PROFILE(SMBsesssetupX);
943 data_blob_clear_free(&plaintext_password);
945 /* it's ok - setup a reply */
946 reply_outbuf(req, 3, 0);
947 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
948 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
950 if (get_Protocol() >= PROTOCOL_NT1) {
951 push_signature(&req->outbuf);
952 /* perhaps grab OS version here?? */
955 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
956 action |= SMB_SETUP_GUEST;
959 /* register the name and uid as being validated, so further connections
960 to a uid can get through without a password, on the same VC */
962 nt_status = smbXsrv_session_create(xconn,
964 if (!NT_STATUS_IS_OK(nt_status)) {
965 data_blob_free(&nt_resp);
966 data_blob_free(&lm_resp);
967 reply_nterror(req, nt_status_squash(nt_status));
968 END_PROFILE(SMBsesssetupX);
972 if (session_info->session_key.length > 0) {
973 uint8_t session_key[16];
976 * Note: the SMB1 signing key is not truncated to 16 byte!
978 session->global->signing_key =
979 data_blob_dup_talloc(session->global,
980 session_info->session_key);
981 if (session->global->signing_key.data == NULL) {
982 data_blob_free(&nt_resp);
983 data_blob_free(&lm_resp);
984 TALLOC_FREE(session);
985 reply_nterror(req, NT_STATUS_NO_MEMORY);
986 END_PROFILE(SMBsesssetupX);
991 * The application key is truncated/padded to 16 bytes
993 ZERO_STRUCT(session_key);
994 memcpy(session_key, session->global->signing_key.data,
995 MIN(session->global->signing_key.length,
996 sizeof(session_key)));
997 session->global->application_key =
998 data_blob_talloc(session->global,
1000 sizeof(session_key));
1001 ZERO_STRUCT(session_key);
1002 if (session->global->application_key.data == NULL) {
1003 data_blob_free(&nt_resp);
1004 data_blob_free(&lm_resp);
1005 TALLOC_FREE(session);
1006 reply_nterror(req, NT_STATUS_NO_MEMORY);
1007 END_PROFILE(SMBsesssetupX);
1012 * Place the application key into the session_info
1014 data_blob_clear_free(&session_info->session_key);
1015 session_info->session_key = data_blob_dup_talloc(session_info,
1016 session->global->application_key);
1017 if (session_info->session_key.data == NULL) {
1018 data_blob_free(&nt_resp);
1019 data_blob_free(&lm_resp);
1020 TALLOC_FREE(session);
1021 reply_nterror(req, NT_STATUS_NO_MEMORY);
1022 END_PROFILE(SMBsesssetupX);
1027 session->compat = talloc_zero(session, struct user_struct);
1028 if (session->compat == NULL) {
1029 data_blob_free(&nt_resp);
1030 data_blob_free(&lm_resp);
1031 TALLOC_FREE(session);
1032 reply_nterror(req, NT_STATUS_NO_MEMORY);
1033 END_PROFILE(SMBsesssetupX);
1036 session->compat->session = session;
1037 session->compat->homes_snum = -1;
1038 session->compat->session_info = session_info;
1039 session->compat->session_keystr = NULL;
1040 session->compat->vuid = session->global->session_wire_id;
1041 DLIST_ADD(sconn->users, session->compat);
1044 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1045 is_authenticated = true;
1046 session->compat->homes_snum =
1047 register_homes_share(session_info->unix_info->unix_name);
1050 if (srv_is_signing_negotiated(xconn) &&
1052 session->global->signing_key.length > 0)
1055 * Try and turn on server signing on the first non-guest
1058 srv_set_signing(xconn,
1059 session->global->signing_key,
1060 nt_resp.data ? nt_resp : lm_resp);
1063 set_current_user_info(session_info->unix_info->sanitized_username,
1064 session_info->unix_info->unix_name,
1065 session_info->info->domain_name);
1067 session->status = NT_STATUS_OK;
1068 session->global->auth_session_info = talloc_move(session->global,
1070 session->global->auth_session_info_seqnum += 1;
1071 session->global->channels[0].auth_session_info_seqnum =
1072 session->global->auth_session_info_seqnum;
1073 session->global->auth_time = now;
1074 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1076 nt_status = smbXsrv_session_update(session);
1077 if (!NT_STATUS_IS_OK(nt_status)) {
1078 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1079 (unsigned long long)session->compat->vuid,
1080 nt_errstr(nt_status)));
1081 data_blob_free(&nt_resp);
1082 data_blob_free(&lm_resp);
1083 TALLOC_FREE(session);
1084 reply_nterror(req, nt_status_squash(nt_status));
1085 END_PROFILE(SMBsesssetupX);
1089 if (!session_claim(session)) {
1090 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1091 (unsigned long long)session->compat->vuid));
1092 data_blob_free(&nt_resp);
1093 data_blob_free(&lm_resp);
1094 TALLOC_FREE(session);
1095 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1096 END_PROFILE(SMBsesssetupX);
1100 /* current_user_info is changed on new vuid */
1101 reload_services(sconn, conn_snum_used, true);
1103 sess_vuid = session->global->session_wire_id;
1105 data_blob_free(&nt_resp);
1106 data_blob_free(&lm_resp);
1108 SSVAL(req->outbuf,smb_vwv2,action);
1109 SSVAL(req->outbuf,smb_uid,sess_vuid);
1110 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1111 req->vuid = sess_vuid;
1113 if (!xconn->smb1.sessions.done_sesssetup) {
1114 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
1115 reply_force_doserror(req, ERRSRV, ERRerror);
1116 END_PROFILE(SMBsesssetupX);
1119 xconn->smb1.sessions.max_send = smb_bufsize;
1120 xconn->smb1.sessions.done_sesssetup = true;
1123 END_PROFILE(SMBsesssetupX);