selftest: mark samba3.smb2.durable-open reopen tests knownfail
[Samba.git] / source3 / smbd / sesssetup.c
blobda306b97bc732cabe4dfdb6ac4ec769b60671511
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 {
565 char *pass = NULL;
566 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
568 if (unic && (passlen2 == 0) && passlen1) {
569 /* Only a ascii plaintext password was sent. */
570 (void)srvstr_pull_talloc(talloc_tos(),
571 req->inbuf,
572 req->flags2,
573 &pass,
574 req->buf,
575 passlen1,
576 STR_TERMINATE|STR_ASCII);
577 } else {
578 (void)srvstr_pull_talloc(talloc_tos(),
579 req->inbuf,
580 req->flags2,
581 &pass,
582 req->buf,
583 unic ? passlen2 : passlen1,
584 STR_TERMINATE);
586 if (!pass) {
587 reply_nterror(req, nt_status_squash(
588 NT_STATUS_INVALID_PARAMETER));
589 END_PROFILE(SMBsesssetupX);
590 return;
592 plaintext_password = data_blob(pass, strlen(pass)+1);
595 p += passlen1 + passlen2;
597 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
598 STR_TERMINATE);
599 user = tmp ? tmp : "";
601 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
602 STR_TERMINATE);
603 domain = tmp ? tmp : "";
605 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
606 STR_TERMINATE);
607 native_os = tmp ? tmp : "";
609 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
610 STR_TERMINATE);
611 native_lanman = tmp ? tmp : "";
613 /* not documented or decoded by Ethereal but there is one more
614 * string in the extra bytes which is the same as the
615 * PrimaryDomain when using extended security. Windows NT 4
616 * and 2003 use this string to store the native lanman string.
617 * Windows 9x does not include a string here at all so we have
618 * to check if we have any extra bytes left */
620 byte_count = SVAL(req->vwv+13, 0);
621 if ( PTR_DIFF(p, save_p) < byte_count) {
622 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
623 STR_TERMINATE);
624 primary_domain = tmp ? tmp : "";
625 } else {
626 primary_domain = talloc_strdup(talloc_tos(), "null");
629 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
630 "PrimaryDomain=[%s]\n",
631 domain, native_os, native_lanman, primary_domain));
633 if ( ra_type == RA_WIN2K ) {
634 if ( strlen(native_lanman) == 0 )
635 ra_lanman_string( primary_domain );
636 else
637 ra_lanman_string( native_lanman );
642 if (SVAL(req->vwv+4, 0) == 0) {
643 setup_new_vc_session(req->sconn);
646 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
647 domain, user, get_remote_machine_name()));
649 if (*user) {
650 if (sconn->smb1.negprot.spnego) {
652 /* This has to be here, because this is a perfectly
653 * valid behaviour for guest logons :-( */
655 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
656 "at 'normal' session setup after "
657 "negotiating spnego.\n"));
658 reply_nterror(req, nt_status_squash(
659 NT_STATUS_LOGON_FAILURE));
660 END_PROFILE(SMBsesssetupX);
661 return;
663 fstrcpy(sub_user, user);
664 } else {
665 fstrcpy(sub_user, "");
668 sub_set_smb_name(sub_user);
670 reload_services(sconn, conn_snum_used, true);
672 if (!*user) {
674 nt_status = check_guest_password(sconn->remote_address, &server_info);
676 } else if (doencrypt) {
677 struct auth_context *negprot_auth_context = NULL;
678 negprot_auth_context = sconn->smb1.negprot.auth_context;
679 if (!negprot_auth_context) {
680 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
681 "session setup without negprot denied!\n"));
682 reply_nterror(req, nt_status_squash(
683 NT_STATUS_LOGON_FAILURE));
684 END_PROFILE(SMBsesssetupX);
685 return;
687 nt_status = make_user_info_for_reply_enc(&user_info, user,
688 domain,
689 sconn->remote_address,
690 lm_resp, nt_resp);
691 if (NT_STATUS_IS_OK(nt_status)) {
692 nt_status = negprot_auth_context->check_ntlm_password(
693 negprot_auth_context,
694 user_info,
695 &server_info);
697 } else {
698 struct auth_context *plaintext_auth_context = NULL;
700 nt_status = make_auth_context_subsystem(
701 talloc_tos(), &plaintext_auth_context);
703 if (NT_STATUS_IS_OK(nt_status)) {
704 uint8_t chal[8];
706 plaintext_auth_context->get_ntlm_challenge(
707 plaintext_auth_context, chal);
709 if (!make_user_info_for_reply(&user_info,
710 user, domain,
711 sconn->remote_address,
712 chal,
713 plaintext_password)) {
714 nt_status = NT_STATUS_NO_MEMORY;
717 if (NT_STATUS_IS_OK(nt_status)) {
718 nt_status = plaintext_auth_context->check_ntlm_password(
719 plaintext_auth_context,
720 user_info,
721 &server_info);
723 TALLOC_FREE(plaintext_auth_context);
728 free_user_info(&user_info);
730 if (!NT_STATUS_IS_OK(nt_status)) {
731 nt_status = do_map_to_guest_server_info(nt_status, &server_info,
732 user, domain);
735 if (!NT_STATUS_IS_OK(nt_status)) {
736 data_blob_free(&nt_resp);
737 data_blob_free(&lm_resp);
738 data_blob_clear_free(&plaintext_password);
739 reply_nterror(req, nt_status_squash(nt_status));
740 END_PROFILE(SMBsesssetupX);
741 return;
744 nt_status = create_local_token(req, server_info, NULL, sub_user, &session_info);
745 TALLOC_FREE(server_info);
747 if (!NT_STATUS_IS_OK(nt_status)) {
748 DEBUG(10, ("create_local_token failed: %s\n",
749 nt_errstr(nt_status)));
750 data_blob_free(&nt_resp);
751 data_blob_free(&lm_resp);
752 data_blob_clear_free(&plaintext_password);
753 reply_nterror(req, nt_status_squash(nt_status));
754 END_PROFILE(SMBsesssetupX);
755 return;
758 data_blob_clear_free(&plaintext_password);
760 /* it's ok - setup a reply */
761 reply_outbuf(req, 3, 0);
762 if (get_Protocol() >= PROTOCOL_NT1) {
763 push_signature(&req->outbuf);
764 /* perhaps grab OS version here?? */
767 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
768 SSVAL(req->outbuf,smb_vwv2,1);
771 /* register the name and uid as being validated, so further connections
772 to a uid can get through without a password, on the same VC */
774 /* Ignore the initial vuid. */
775 sess_vuid = register_initial_vuid(sconn);
776 if (sess_vuid == UID_FIELD_INVALID) {
777 data_blob_free(&nt_resp);
778 data_blob_free(&lm_resp);
779 reply_nterror(req, nt_status_squash(
780 NT_STATUS_LOGON_FAILURE));
781 END_PROFILE(SMBsesssetupX);
782 return;
784 /* register_existing_vuid keeps the session_info */
785 sess_vuid = register_existing_vuid(sconn, sess_vuid,
786 session_info,
787 nt_resp.data ? nt_resp : lm_resp);
788 if (sess_vuid == UID_FIELD_INVALID) {
789 data_blob_free(&nt_resp);
790 data_blob_free(&lm_resp);
791 reply_nterror(req, nt_status_squash(
792 NT_STATUS_LOGON_FAILURE));
793 END_PROFILE(SMBsesssetupX);
794 return;
797 /* current_user_info is changed on new vuid */
798 reload_services(sconn, conn_snum_used, true);
800 data_blob_free(&nt_resp);
801 data_blob_free(&lm_resp);
803 SSVAL(req->outbuf,smb_uid,sess_vuid);
804 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
805 req->vuid = sess_vuid;
807 if (!sconn->smb1.sessions.done_sesssetup) {
808 sconn->smb1.sessions.max_send =
809 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
811 sconn->smb1.sessions.done_sesssetup = true;
813 END_PROFILE(SMBsesssetupX);
814 chain_reply(req);
815 return;