s4:libcli/smb2: remove unused 'session_key' from struct smb2_session
[Samba.git] / source3 / smbd / sesssetup.c
blob987b626d6bcc2d7e96cfeab08f5a6b436f7b27c4
1 /*
2 Unix SMB/CIFS implementation.
3 handle SMBsessionsetup
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/>.
25 #include "includes.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "smbd/smbd.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/spnego.h"
30 #include "../auth/ntlmssp/ntlmssp.h"
31 #include "../librpc/gen_ndr/krb5pac.h"
32 #include "libads/kerberos_proto.h"
33 #include "../lib/util/asn1.h"
34 #include "auth.h"
35 #include "messages.h"
36 #include "smbprofile.h"
37 #include "../libcli/security/security.h"
38 #include "auth/gensec/gensec.h"
40 /****************************************************************************
41 Add the standard 'Samba' signature to the end of the session setup.
42 ****************************************************************************/
44 static int push_signature(uint8 **outbuf)
46 char *lanman;
47 int result, tmp;
49 result = 0;
51 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
53 if (tmp == -1) return -1;
54 result += tmp;
56 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
57 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
58 SAFE_FREE(lanman);
60 else {
61 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
64 if (tmp == -1) return -1;
65 result += tmp;
67 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
69 if (tmp == -1) return -1;
70 result += tmp;
72 return result;
75 /****************************************************************************
76 Do a 'guest' logon, getting back the
77 ****************************************************************************/
79 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
80 struct auth_serversupplied_info **server_info)
82 struct auth_context *auth_context;
83 struct auth_usersupplied_info *user_info = NULL;
85 NTSTATUS nt_status;
86 static unsigned char chal[8] = { 0, };
88 DEBUG(3,("Got anonymous request\n"));
90 nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
91 if (!NT_STATUS_IS_OK(nt_status)) {
92 return nt_status;
95 if (!make_user_info_guest(remote_address, &user_info)) {
96 TALLOC_FREE(auth_context);
97 return NT_STATUS_NO_MEMORY;
100 nt_status = auth_context->check_ntlm_password(auth_context,
101 user_info,
102 server_info);
103 TALLOC_FREE(auth_context);
104 free_user_info(&user_info);
105 return nt_status;
108 /****************************************************************************
109 Reply to a session setup command.
110 conn POINTER CAN BE NULL HERE !
111 ****************************************************************************/
113 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
115 const uint8 *p;
116 DATA_BLOB in_blob;
117 DATA_BLOB out_blob = data_blob_null;
118 size_t bufrem;
119 char *tmp;
120 const char *native_os;
121 const char *native_lanman;
122 const char *primary_domain;
123 const char *p2;
124 uint16 data_blob_len = SVAL(req->vwv+7, 0);
125 enum remote_arch_types ra_type = get_remote_arch();
126 int vuid = req->vuid;
127 user_struct *vuser = NULL;
128 NTSTATUS status = NT_STATUS_OK;
129 struct smbd_server_connection *sconn = req->sconn;
130 uint16_t action = 0;
132 DEBUG(3,("Doing spnego session setup\n"));
134 if (global_client_caps == 0) {
135 global_client_caps = IVAL(req->vwv+10, 0);
137 if (!(global_client_caps & CAP_STATUS32)) {
138 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
142 p = req->buf;
144 if (data_blob_len == 0) {
145 /* an invalid request */
146 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
147 return;
150 bufrem = smbreq_bufrem(req, p);
151 /* pull the spnego blob */
152 in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
154 #if 0
155 file_save("negotiate.dat", in_blob.data, in_blob.length);
156 #endif
158 p2 = (const char *)req->buf + in_blob.length;
160 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
161 STR_TERMINATE);
162 native_os = tmp ? tmp : "";
164 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
165 STR_TERMINATE);
166 native_lanman = tmp ? tmp : "";
168 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
169 STR_TERMINATE);
170 primary_domain = tmp ? tmp : "";
172 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
173 native_os, native_lanman, primary_domain));
175 if ( ra_type == RA_WIN2K ) {
176 /* Vista sets neither the OS or lanman strings */
178 if ( !strlen(native_os) && !strlen(native_lanman) )
179 set_remote_arch(RA_VISTA);
181 /* Windows 2003 doesn't set the native lanman string,
182 but does set primary domain which is a bug I think */
184 if ( !strlen(native_lanman) ) {
185 ra_lanman_string( primary_domain );
186 } else {
187 ra_lanman_string( native_lanman );
189 } else if ( ra_type == RA_VISTA ) {
190 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
191 set_remote_arch(RA_OSX);
195 vuser = get_valid_user_struct(sconn, vuid);
196 if (vuser != NULL) {
197 reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
198 return;
201 /* Do we have a valid vuid now ? */
202 if (!is_partial_auth_vuid(sconn, vuid)) {
203 /* No, start a new authentication setup. */
204 vuid = register_initial_vuid(sconn);
205 if (vuid == UID_FIELD_INVALID) {
206 reply_nterror(req, nt_status_squash(
207 NT_STATUS_INVALID_PARAMETER));
208 return;
212 vuser = get_partial_auth_user_struct(sconn, vuid);
213 /* This MUST be valid. */
214 if (!vuser) {
215 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
218 if (!vuser->gensec_security) {
219 status = auth_generic_prepare(vuser, sconn->remote_address,
220 &vuser->gensec_security);
221 if (!NT_STATUS_IS_OK(status)) {
222 /* Kill the intermediate vuid */
223 invalidate_vuid(sconn, vuid);
224 reply_nterror(req, nt_status_squash(status));
225 return;
228 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_SESSION_KEY);
229 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_UNIX_TOKEN);
231 status = gensec_start_mech_by_oid(vuser->gensec_security, GENSEC_OID_SPNEGO);
232 if (!NT_STATUS_IS_OK(status)) {
233 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
234 /* Kill the intermediate vuid */
235 invalidate_vuid(sconn, vuid);
236 reply_nterror(req, nt_status_squash(status));
237 return;
241 status = gensec_update(vuser->gensec_security,
242 talloc_tos(), NULL,
243 in_blob, &out_blob);
244 if (!NT_STATUS_IS_OK(status) &&
245 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
246 /* Kill the intermediate vuid */
247 invalidate_vuid(sconn, vuid);
248 reply_nterror(req, nt_status_squash(status));
249 return;
252 if (NT_STATUS_IS_OK(status)) {
253 struct auth_session_info *session_info = NULL;
254 int tmp_vuid;
256 status = gensec_session_info(vuser->gensec_security,
257 talloc_tos(),
258 &session_info);
259 if (!NT_STATUS_IS_OK(status)) {
260 DEBUG(1,("Failed to generate session_info "
261 "(user and group token) for session setup: %s\n",
262 nt_errstr(status)));
263 /* Kill the intermediate vuid */
264 data_blob_free(&out_blob);
265 invalidate_vuid(sconn, vuid);
266 reply_nterror(req, nt_status_squash(status));
267 return;
270 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
271 action = 1;
274 /* register_existing_vuid keeps the server info */
275 tmp_vuid = register_existing_vuid(sconn, vuid,
276 session_info,
277 data_blob_null);
278 if (tmp_vuid != vuid) {
279 data_blob_free(&out_blob);
280 invalidate_vuid(sconn, vuid);
281 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
282 return;
285 /* current_user_info is changed on new vuid */
286 reload_services(sconn, conn_snum_used, true);
289 reply_outbuf(req, 4, 0);
291 SSVAL(req->outbuf, smb_uid, vuid);
292 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
293 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
294 SSVAL(req->outbuf, smb_vwv2, action);
295 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
297 if (message_push_blob(&req->outbuf, out_blob) == -1) {
298 data_blob_free(&out_blob);
299 invalidate_vuid(sconn, vuid);
300 reply_nterror(req, NT_STATUS_NO_MEMORY);
301 return;
303 data_blob_free(&out_blob);
305 if (push_signature(&req->outbuf) == -1) {
306 invalidate_vuid(sconn, vuid);
307 reply_nterror(req, NT_STATUS_NO_MEMORY);
308 return;
312 /****************************************************************************
313 On new VC == 0, shutdown *all* old connections and users.
314 It seems that only NT4.x does this. At W2K and above (XP etc.).
315 a new session setup with VC==0 is ignored.
316 ****************************************************************************/
318 struct shutdown_state {
319 const char *ip;
320 struct messaging_context *msg_ctx;
323 static int shutdown_other_smbds(const struct connections_key *key,
324 const struct connections_data *crec,
325 void *private_data)
327 struct shutdown_state *state = (struct shutdown_state *)private_data;
329 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
330 server_id_str(talloc_tos(), &crec->pid), crec->addr));
332 if (!process_exists(crec->pid)) {
333 DEBUG(10, ("process does not exist\n"));
334 return 0;
337 if (procid_is_me(&crec->pid)) {
338 DEBUG(10, ("It's me\n"));
339 return 0;
342 if (strcmp(state->ip, crec->addr) != 0) {
343 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
344 return 0;
347 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
348 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
349 state->ip));
351 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
352 &data_blob_null);
353 return 0;
356 static void setup_new_vc_session(struct smbd_server_connection *sconn)
358 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
359 "compatible we would close all old resources.\n"));
360 #if 0
361 conn_close_all();
362 invalidate_all_vuids();
363 #endif
364 if (lp_reset_on_zero_vc()) {
365 char *addr;
366 struct shutdown_state state;
368 addr = tsocket_address_inet_addr_string(
369 sconn->remote_address, talloc_tos());
370 if (addr == NULL) {
371 return;
373 state.ip = addr;
374 state.msg_ctx = sconn->msg_ctx;
375 connections_forall_read(shutdown_other_smbds, &state);
376 TALLOC_FREE(addr);
380 /****************************************************************************
381 Reply to a session setup command.
382 ****************************************************************************/
384 void reply_sesssetup_and_X(struct smb_request *req)
386 int sess_vuid;
387 int smb_bufsize;
388 DATA_BLOB lm_resp;
389 DATA_BLOB nt_resp;
390 DATA_BLOB plaintext_password;
391 char *tmp;
392 const char *user;
393 fstring sub_user; /* Sanitised username for substituion */
394 const char *domain;
395 const char *native_os;
396 const char *native_lanman;
397 const char *primary_domain;
398 struct auth_usersupplied_info *user_info = NULL;
399 struct auth_serversupplied_info *server_info = NULL;
400 struct auth_session_info *session_info = NULL;
401 uint16 smb_flag2 = req->flags2;
403 NTSTATUS nt_status;
404 struct smbd_server_connection *sconn = req->sconn;
406 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
407 bool signing_allowed = false;
408 bool signing_mandatory = false;
410 START_PROFILE(SMBsesssetupX);
412 ZERO_STRUCT(lm_resp);
413 ZERO_STRUCT(nt_resp);
414 ZERO_STRUCT(plaintext_password);
416 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
418 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
419 signing_allowed = true;
421 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
422 signing_mandatory = true;
426 * We can call srv_set_signing_negotiated() each time.
427 * It finds out when it needs to turn into a noop
428 * itself.
430 srv_set_signing_negotiated(req->sconn,
431 signing_allowed,
432 signing_mandatory);
434 /* a SPNEGO session setup has 12 command words, whereas a normal
435 NT1 session setup has 13. See the cifs spec. */
436 if (req->wct == 12 &&
437 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
439 if (!sconn->smb1.negprot.spnego) {
440 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
441 "at SPNEGO session setup when it was not "
442 "negotiated.\n"));
443 reply_nterror(req, nt_status_squash(
444 NT_STATUS_LOGON_FAILURE));
445 END_PROFILE(SMBsesssetupX);
446 return;
449 if (SVAL(req->vwv+4, 0) == 0) {
450 setup_new_vc_session(req->sconn);
453 reply_sesssetup_and_X_spnego(req);
454 END_PROFILE(SMBsesssetupX);
455 return;
458 smb_bufsize = SVAL(req->vwv+2, 0);
460 if (get_Protocol() < PROTOCOL_NT1) {
461 uint16 passlen1 = SVAL(req->vwv+7, 0);
463 /* Never do NT status codes with protocols before NT1 as we
464 * don't get client caps. */
465 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
467 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
468 reply_nterror(req, nt_status_squash(
469 NT_STATUS_INVALID_PARAMETER));
470 END_PROFILE(SMBsesssetupX);
471 return;
474 if (doencrypt) {
475 lm_resp = data_blob(req->buf, passlen1);
476 } else {
477 plaintext_password = data_blob(req->buf, passlen1+1);
478 /* Ensure null termination */
479 plaintext_password.data[passlen1] = 0;
482 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
483 req->buf + passlen1, STR_TERMINATE);
484 user = tmp ? tmp : "";
486 domain = "";
488 } else {
489 uint16 passlen1 = SVAL(req->vwv+7, 0);
490 uint16 passlen2 = SVAL(req->vwv+8, 0);
491 enum remote_arch_types ra_type = get_remote_arch();
492 const uint8_t *p = req->buf;
493 const uint8_t *save_p = req->buf;
494 uint16 byte_count;
497 if(global_client_caps == 0) {
498 global_client_caps = IVAL(req->vwv+11, 0);
500 if (!(global_client_caps & CAP_STATUS32)) {
501 remove_from_common_flags2(
502 FLAGS2_32_BIT_ERROR_CODES);
505 /* client_caps is used as final determination if
506 * client is NT or Win95. This is needed to return
507 * the correct error codes in some circumstances.
510 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
511 ra_type == RA_WIN95) {
512 if(!(global_client_caps & (CAP_NT_SMBS|
513 CAP_STATUS32))) {
514 set_remote_arch( RA_WIN95);
519 if (!doencrypt) {
520 /* both Win95 and WinNT stuff up the password
521 * lengths for non-encrypting systems. Uggh.
523 if passlen1==24 its a win95 system, and its setting
524 the password length incorrectly. Luckily it still
525 works with the default code because Win95 will null
526 terminate the password anyway
528 if passlen1>0 and passlen2>0 then maybe its a NT box
529 and its setting passlen2 to some random value which
530 really stuffs things up. we need to fix that one. */
532 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
533 passlen2 != 1) {
534 passlen2 = 0;
538 /* check for nasty tricks */
539 if (passlen1 > MAX_PASS_LEN
540 || passlen1 > smbreq_bufrem(req, p)) {
541 reply_nterror(req, nt_status_squash(
542 NT_STATUS_INVALID_PARAMETER));
543 END_PROFILE(SMBsesssetupX);
544 return;
547 if (passlen2 > MAX_PASS_LEN
548 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
549 reply_nterror(req, nt_status_squash(
550 NT_STATUS_INVALID_PARAMETER));
551 END_PROFILE(SMBsesssetupX);
552 return;
555 /* Save the lanman2 password and the NT md4 password. */
557 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
558 doencrypt = False;
561 if (doencrypt) {
562 lm_resp = data_blob(p, passlen1);
563 nt_resp = data_blob(p+passlen1, passlen2);
564 } else if (lp_security() != SEC_SHARE) {
566 * In share level we should ignore any passwords, so
567 * only read them if we're not.
569 char *pass = NULL;
570 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
572 if (unic && (passlen2 == 0) && passlen1) {
573 /* Only a ascii plaintext password was sent. */
574 (void)srvstr_pull_talloc(talloc_tos(),
575 req->inbuf,
576 req->flags2,
577 &pass,
578 req->buf,
579 passlen1,
580 STR_TERMINATE|STR_ASCII);
581 } else {
582 (void)srvstr_pull_talloc(talloc_tos(),
583 req->inbuf,
584 req->flags2,
585 &pass,
586 req->buf,
587 unic ? passlen2 : passlen1,
588 STR_TERMINATE);
590 if (!pass) {
591 reply_nterror(req, nt_status_squash(
592 NT_STATUS_INVALID_PARAMETER));
593 END_PROFILE(SMBsesssetupX);
594 return;
596 plaintext_password = data_blob(pass, strlen(pass)+1);
599 p += passlen1 + passlen2;
601 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
602 STR_TERMINATE);
603 user = tmp ? tmp : "";
605 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
606 STR_TERMINATE);
607 domain = tmp ? tmp : "";
609 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
610 STR_TERMINATE);
611 native_os = tmp ? tmp : "";
613 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
614 STR_TERMINATE);
615 native_lanman = tmp ? tmp : "";
617 /* not documented or decoded by Ethereal but there is one more
618 * string in the extra bytes which is the same as the
619 * PrimaryDomain when using extended security. Windows NT 4
620 * and 2003 use this string to store the native lanman string.
621 * Windows 9x does not include a string here at all so we have
622 * to check if we have any extra bytes left */
624 byte_count = SVAL(req->vwv+13, 0);
625 if ( PTR_DIFF(p, save_p) < byte_count) {
626 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
627 STR_TERMINATE);
628 primary_domain = tmp ? tmp : "";
629 } else {
630 primary_domain = talloc_strdup(talloc_tos(), "null");
633 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
634 "PrimaryDomain=[%s]\n",
635 domain, native_os, native_lanman, primary_domain));
637 if ( ra_type == RA_WIN2K ) {
638 if ( strlen(native_lanman) == 0 )
639 ra_lanman_string( primary_domain );
640 else
641 ra_lanman_string( native_lanman );
646 if (SVAL(req->vwv+4, 0) == 0) {
647 setup_new_vc_session(req->sconn);
650 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
651 domain, user, get_remote_machine_name()));
653 if (*user) {
654 if (sconn->smb1.negprot.spnego) {
656 /* This has to be here, because this is a perfectly
657 * valid behaviour for guest logons :-( */
659 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
660 "at 'normal' session setup after "
661 "negotiating spnego.\n"));
662 reply_nterror(req, nt_status_squash(
663 NT_STATUS_LOGON_FAILURE));
664 END_PROFILE(SMBsesssetupX);
665 return;
667 fstrcpy(sub_user, user);
668 } else {
669 fstrcpy(sub_user, "");
672 sub_set_smb_name(sub_user);
674 reload_services(sconn, conn_snum_used, true);
676 if (lp_security() == SEC_SHARE) {
677 char *sub_user_mapped = NULL;
678 /* In share level we should ignore any passwords */
680 data_blob_free(&lm_resp);
681 data_blob_free(&nt_resp);
682 data_blob_clear_free(&plaintext_password);
684 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
685 if (!sub_user_mapped) {
686 reply_nterror(req, NT_STATUS_NO_MEMORY);
687 END_PROFILE(SMBsesssetupX);
688 return;
690 fstrcpy(sub_user, sub_user_mapped);
691 add_session_user(sconn, sub_user);
692 add_session_workgroup(sconn, domain);
693 /* Then force it to null for the benfit of the code below */
694 user = "";
697 if (!*user) {
699 nt_status = check_guest_password(sconn->remote_address, &server_info);
701 } else if (doencrypt) {
702 struct auth_context *negprot_auth_context = NULL;
703 negprot_auth_context = sconn->smb1.negprot.auth_context;
704 if (!negprot_auth_context) {
705 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
706 "session setup without negprot denied!\n"));
707 reply_nterror(req, nt_status_squash(
708 NT_STATUS_LOGON_FAILURE));
709 END_PROFILE(SMBsesssetupX);
710 return;
712 nt_status = make_user_info_for_reply_enc(&user_info, user,
713 domain,
714 sconn->remote_address,
715 lm_resp, nt_resp);
716 if (NT_STATUS_IS_OK(nt_status)) {
717 nt_status = negprot_auth_context->check_ntlm_password(
718 negprot_auth_context,
719 user_info,
720 &server_info);
722 } else {
723 struct auth_context *plaintext_auth_context = NULL;
725 nt_status = make_auth_context_subsystem(
726 talloc_tos(), &plaintext_auth_context);
728 if (NT_STATUS_IS_OK(nt_status)) {
729 uint8_t chal[8];
731 plaintext_auth_context->get_ntlm_challenge(
732 plaintext_auth_context, chal);
734 if (!make_user_info_for_reply(&user_info,
735 user, domain,
736 sconn->remote_address,
737 chal,
738 plaintext_password)) {
739 nt_status = NT_STATUS_NO_MEMORY;
742 if (NT_STATUS_IS_OK(nt_status)) {
743 nt_status = plaintext_auth_context->check_ntlm_password(
744 plaintext_auth_context,
745 user_info,
746 &server_info);
748 TALLOC_FREE(plaintext_auth_context);
753 free_user_info(&user_info);
755 if (!NT_STATUS_IS_OK(nt_status)) {
756 nt_status = do_map_to_guest_server_info(nt_status, &server_info,
757 user, domain);
760 if (!NT_STATUS_IS_OK(nt_status)) {
761 data_blob_free(&nt_resp);
762 data_blob_free(&lm_resp);
763 data_blob_clear_free(&plaintext_password);
764 reply_nterror(req, nt_status_squash(nt_status));
765 END_PROFILE(SMBsesssetupX);
766 return;
769 nt_status = create_local_token(req, server_info, NULL, sub_user, &session_info);
770 TALLOC_FREE(server_info);
772 if (!NT_STATUS_IS_OK(nt_status)) {
773 DEBUG(10, ("create_local_token failed: %s\n",
774 nt_errstr(nt_status)));
775 data_blob_free(&nt_resp);
776 data_blob_free(&lm_resp);
777 data_blob_clear_free(&plaintext_password);
778 reply_nterror(req, nt_status_squash(nt_status));
779 END_PROFILE(SMBsesssetupX);
780 return;
783 data_blob_clear_free(&plaintext_password);
785 /* it's ok - setup a reply */
786 reply_outbuf(req, 3, 0);
787 if (get_Protocol() >= PROTOCOL_NT1) {
788 push_signature(&req->outbuf);
789 /* perhaps grab OS version here?? */
792 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
793 SSVAL(req->outbuf,smb_vwv2,1);
796 /* register the name and uid as being validated, so further connections
797 to a uid can get through without a password, on the same VC */
799 if (lp_security() == SEC_SHARE) {
800 sess_vuid = UID_FIELD_INVALID;
801 TALLOC_FREE(session_info);
802 } else {
803 /* Ignore the initial vuid. */
804 sess_vuid = register_initial_vuid(sconn);
805 if (sess_vuid == UID_FIELD_INVALID) {
806 data_blob_free(&nt_resp);
807 data_blob_free(&lm_resp);
808 reply_nterror(req, nt_status_squash(
809 NT_STATUS_LOGON_FAILURE));
810 END_PROFILE(SMBsesssetupX);
811 return;
813 /* register_existing_vuid keeps the session_info */
814 sess_vuid = register_existing_vuid(sconn, sess_vuid,
815 session_info,
816 nt_resp.data ? nt_resp : lm_resp);
817 if (sess_vuid == UID_FIELD_INVALID) {
818 data_blob_free(&nt_resp);
819 data_blob_free(&lm_resp);
820 reply_nterror(req, nt_status_squash(
821 NT_STATUS_LOGON_FAILURE));
822 END_PROFILE(SMBsesssetupX);
823 return;
826 /* current_user_info is changed on new vuid */
827 reload_services(sconn, conn_snum_used, true);
830 data_blob_free(&nt_resp);
831 data_blob_free(&lm_resp);
833 SSVAL(req->outbuf,smb_uid,sess_vuid);
834 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
835 req->vuid = sess_vuid;
837 if (!sconn->smb1.sessions.done_sesssetup) {
838 sconn->smb1.sessions.max_send =
839 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
841 sconn->smb1.sessions.done_sesssetup = true;
843 END_PROFILE(SMBsesssetupX);
844 chain_reply(req);
845 return;