2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1998-2001
5 Copyright (C) Andrew Bartlett 2001
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 uint32 global_client_caps = 0;
25 static struct auth_context *ntlmssp_auth_context = NULL;
28 on a logon error possibly map the error to success if "map to guest"
31 static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info,
32 const char *user, const char *domain)
34 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
35 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
36 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
37 DEBUG(3,("No such user %s [%s] - using guest account\n",
39 make_server_info_guest(server_info);
40 status = NT_STATUS_OK;
44 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
45 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
46 DEBUG(3,("Registered username %s for guest access\n",user));
47 make_server_info_guest(server_info);
48 status = NT_STATUS_OK;
56 /****************************************************************************
57 Add the standard 'Samba' signature to the end of the session setup.
58 ****************************************************************************/
59 static void add_signature(char *outbuf)
63 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
64 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
65 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
66 set_message_end(outbuf,p);
69 /****************************************************************************
70 Do a 'guest' logon, getting back the
71 ****************************************************************************/
72 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
74 struct auth_context *auth_context;
75 auth_usersupplied_info *user_info = NULL;
78 unsigned char chal[8];
82 DEBUG(3,("Got anonymous request\n"));
84 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
88 if (!make_user_info_guest(&user_info)) {
89 (auth_context->free)(&auth_context);
90 return NT_STATUS_NO_MEMORY;
93 nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
94 (auth_context->free)(&auth_context);
95 free_user_info(&user_info);
101 /****************************************************************************
102 reply to a session setup spnego negotiate packet for kerberos
103 ****************************************************************************/
104 static int reply_spnego_kerberos(connection_struct *conn,
105 char *inbuf, char *outbuf,
106 int length, int bufsize,
111 const struct passwd *pw;
116 auth_serversupplied_info *server_info = NULL;
119 if (!spnego_parse_krb5_wrap(*secblob, &ticket)) {
120 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
123 ads = ads_init_simple();
126 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
129 ads->auth.realm = strdup(lp_realm());
131 ret = ads_verify_ticket(ads, &ticket, &client, &auth_data);
132 if (!NT_STATUS_IS_OK(ret)) {
133 DEBUG(1,("Failed to verify incoming ticket!\n"));
135 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
138 DEBUG(3,("Ticket name is [%s]\n", client));
140 p = strchr_m(client, '@');
142 DEBUG(3,("Doesn't look like a valid principal\n"));
144 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
148 if (strcasecmp(p+1, ads->auth.realm) != 0) {
149 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
150 if (!lp_allow_trusted_domains()) {
151 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
153 /* this gives a fully qualified user name (ie. with full realm).
154 that leads to very long usernames, but what else can we do? */
155 asprintf(&user, "%s%s%s", p+1, lp_winbind_separator(), client);
157 user = strdup(client);
161 /* the password is good - let them in */
162 pw = smb_getpwnam(user,False);
163 if (!pw && !strstr(user, lp_winbind_separator())) {
165 /* try it with a winbind domain prefix */
166 asprintf(&user2, "%s%s%s", lp_workgroup(), lp_winbind_separator(), user);
167 pw = smb_getpwnam(user2,False);
175 DEBUG(1,("Username %s is invalid on this system\n",user));
176 return ERROR_NT(NT_STATUS_NO_SUCH_USER);
179 if (!make_server_info_pw(&server_info,pw)) {
180 DEBUG(1,("make_server_info_from_pw failed!\n"));
181 return ERROR_NT(NT_STATUS_NO_MEMORY);
184 sess_vuid = register_vuid(server_info, user);
187 free_server_info(&server_info);
189 if (sess_vuid == -1) {
190 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
193 set_message(outbuf,4,0,True);
194 SSVAL(outbuf, smb_vwv3, 0);
195 add_signature(outbuf);
197 SSVAL(outbuf,smb_uid,sess_vuid);
198 SSVAL(inbuf,smb_uid,sess_vuid);
200 return chain_reply(inbuf,outbuf,length,bufsize);
205 /****************************************************************************
206 send a security blob via a session setup reply
207 ****************************************************************************/
208 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
213 set_message(outbuf,4,0,True);
215 /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end
216 that we aren't finished yet */
218 SIVAL(outbuf, smb_rcls, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED));
219 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
220 SSVAL(outbuf, smb_vwv3, blob.length);
222 memcpy(p, blob.data, blob.length);
224 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
225 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
226 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
227 set_message_end(outbuf,p);
229 return send_smb(smbd_server_fd(),outbuf);
232 /****************************************************************************
233 reply to a session setup spnego negotiate packet
234 ****************************************************************************/
235 static int reply_spnego_negotiate(connection_struct *conn,
238 int length, int bufsize,
241 char *OIDs[ASN1_MAX_OIDS];
244 uint32 ntlmssp_command, neg_flags, chal_flags;
245 DATA_BLOB chal, spnego_chal, extra_data;
246 const uint8 *cryptkey;
247 BOOL got_kerberos = False;
249 extern pstring global_myname;
251 /* parse out the OIDs and the first sec blob */
252 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
253 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
256 for (i=0;OIDs[i];i++) {
257 DEBUG(3,("Got OID %s\n", OIDs[i]));
258 if (strcmp(OID_KERBEROS5, OIDs[i]) == 0 ||
259 strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) {
264 DEBUG(3,("Got secblob of size %d\n", secblob.length));
268 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
269 length, bufsize, &secblob);
270 data_blob_free(&secblob);
275 /* parse the NTLMSSP packet */
277 file_save("secblob.dat", secblob.data, secblob.length);
280 if (!msrpc_parse(&secblob, "CddB",
285 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
288 DEBUG(5, ("Extra data: \n"));
289 dump_data(5, extra_data.data, extra_data.length);
291 data_blob_free(&secblob);
292 data_blob_free(&extra_data);
294 if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
295 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
298 DEBUG(3,("Got neg_flags=0x%08x\n", neg_flags));
300 debug_ntlmssp_flags(neg_flags);
302 if (ntlmssp_auth_context) {
303 (ntlmssp_auth_context->free)(&ntlmssp_auth_context);
306 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&ntlmssp_auth_context))) {
307 return ERROR_NT(nt_status);
310 cryptkey = ntlmssp_auth_context->get_ntlm_challenge(ntlmssp_auth_context);
312 /* Give them the challenge. For now, ignore neg_flags and just
313 return the flags we want. Obviously this is not correct */
315 chal_flags = NTLMSSP_NEGOTIATE_UNICODE |
316 NTLMSSP_NEGOTIATE_LM_KEY |
317 NTLMSSP_NEGOTIATE_NTLM |
318 NTLMSSP_CHAL_TARGET_INFO;
321 DATA_BLOB domain_blob, netbios_blob, realm_blob;
323 msrpc_gen(&domain_blob,
327 msrpc_gen(&netbios_blob,
331 msrpc_gen(&realm_blob,
336 msrpc_gen(&chal, "CddddbBBBB",
343 domain_blob.data, domain_blob.length,
344 domain_blob.data, domain_blob.length,
345 netbios_blob.data, netbios_blob.length,
346 realm_blob.data, realm_blob.length);
348 data_blob_free(&domain_blob);
349 data_blob_free(&netbios_blob);
350 data_blob_free(&realm_blob);
353 if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) {
354 DEBUG(3,("Failed to generate challenge\n"));
355 data_blob_free(&chal);
356 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
359 /* now tell the client to send the auth packet */
360 reply_sesssetup_blob(conn, outbuf, spnego_chal);
362 data_blob_free(&chal);
363 data_blob_free(&spnego_chal);
365 /* and tell smbd that we have already replied to this packet */
370 /****************************************************************************
371 reply to a session setup spnego auth packet
372 ****************************************************************************/
373 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
374 int length, int bufsize,
378 char *workgroup = NULL, *user = NULL, *machine = NULL;
379 DATA_BLOB lmhash, nthash, sess_key;
380 DATA_BLOB plaintext_password = data_blob(NULL, 0);
381 uint32 ntlmssp_command, neg_flags;
385 uint32 auth_flags = AUTH_FLAG_NONE;
386 auth_usersupplied_info *user_info = NULL;
387 auth_serversupplied_info *server_info = NULL;
389 /* we must have setup the auth context by now */
390 if (!ntlmssp_auth_context) {
391 DEBUG(2,("ntlmssp_auth_context is NULL in reply_spnego_auth\n"));
392 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
395 if (!spnego_parse_auth(blob1, &auth)) {
397 file_save("auth.dat", blob1.data, blob1.length);
399 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
402 /* now the NTLMSSP encoded auth hashes */
403 if (!msrpc_parse(&auth, "CdBBUUUBd",
413 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
416 data_blob_free(&auth);
417 data_blob_free(&sess_key);
419 DEBUG(3,("Got user=[%s] workgroup=[%s] machine=[%s] len1=%d len2=%d\n",
420 user, workgroup, machine, lmhash.length, nthash.length));
422 /* the client has given us its machine name (which we otherwise would not get on port 445).
423 we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
425 set_remote_machine_name(machine);
427 reload_services(True);
430 file_save("nthash1.dat", nthash.data, nthash.length);
431 file_save("lmhash1.dat", lmhash.data, lmhash.length);
435 auth_flags |= AUTH_FLAG_LM_RESP;
438 if (nthash.length == 24) {
439 auth_flags |= AUTH_FLAG_NTLM_RESP;
440 } else if (nthash.length > 24) {
441 auth_flags |= AUTH_FLAG_NTLMv2_RESP;
444 if (!make_user_info_map(&user_info,
450 return ERROR_NT(NT_STATUS_NO_MEMORY);
453 nt_status = ntlmssp_auth_context->check_ntlm_password(ntlmssp_auth_context, user_info, &server_info);
455 if (!NT_STATUS_IS_OK(nt_status)) {
456 nt_status = do_map_to_guest(nt_status, &server_info, user, workgroup);
459 SAFE_FREE(workgroup);
462 (ntlmssp_auth_context->free)(&ntlmssp_auth_context);
464 free_user_info(&user_info);
466 data_blob_free(&lmhash);
468 data_blob_free(&nthash);
470 if (!NT_STATUS_IS_OK(nt_status)) {
472 return ERROR_NT(nt_status_squash(nt_status));
475 as_guest = server_info->guest;
477 sess_vuid = register_vuid(server_info, user);
478 free_server_info(&server_info);
482 if (sess_vuid == -1) {
483 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
486 set_message(outbuf,4,0,True);
487 SSVAL(outbuf, smb_vwv3, 0);
490 SSVAL(outbuf,smb_vwv2,1);
493 add_signature(outbuf);
495 SSVAL(outbuf,smb_uid,sess_vuid);
496 SSVAL(inbuf,smb_uid,sess_vuid);
498 return chain_reply(inbuf,outbuf,length,bufsize);
502 /****************************************************************************
503 reply to a session setup spnego anonymous packet
504 ****************************************************************************/
505 static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf,
506 int length, int bufsize)
509 auth_serversupplied_info *server_info = NULL;
512 nt_status = check_guest_password(&server_info);
514 if (!NT_STATUS_IS_OK(nt_status)) {
515 return ERROR_NT(nt_status_squash(nt_status));
518 sess_vuid = register_vuid(server_info, lp_guestaccount());
520 free_server_info(&server_info);
522 if (sess_vuid == -1) {
523 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
526 set_message(outbuf,4,0,True);
527 SSVAL(outbuf, smb_vwv3, 0);
528 add_signature(outbuf);
530 SSVAL(outbuf,smb_uid,sess_vuid);
531 SSVAL(inbuf,smb_uid,sess_vuid);
533 return chain_reply(inbuf,outbuf,length,bufsize);
537 /****************************************************************************
538 reply to a session setup command
539 ****************************************************************************/
540 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,char *outbuf,
541 int length,int bufsize)
547 DEBUG(3,("Doing spnego session setup\n"));
549 if (global_client_caps == 0) {
550 global_client_caps = IVAL(inbuf,smb_vwv10);
553 p = (uint8 *)smb_buf(inbuf);
555 if (SVAL(inbuf, smb_vwv7) == 0) {
556 /* an anonymous request */
557 return reply_spnego_anonymous(conn, inbuf, outbuf, length, bufsize);
560 /* pull the spnego blob */
561 blob1 = data_blob(p, SVAL(inbuf, smb_vwv7));
564 file_save("negotiate.dat", blob1.data, blob1.length);
567 if (blob1.data[0] == ASN1_APPLICATION(0)) {
568 /* its a negTokenTarg packet */
569 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
570 data_blob_free(&blob1);
574 if (blob1.data[0] == ASN1_CONTEXT(1)) {
575 /* its a auth packet */
576 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
577 data_blob_free(&blob1);
581 /* what sort of packet is this? */
582 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
584 data_blob_free(&blob1);
586 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
590 /****************************************************************************
591 reply to a session setup command
592 ****************************************************************************/
593 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
594 int length,int bufsize)
600 DATA_BLOB plaintext_password;
602 pstring sub_user; /* Sainitised username for substituion */
605 fstring native_lanman;
606 static BOOL done_sesssetup = False;
607 extern BOOL global_encrypted_passwords_negotiated;
608 extern BOOL global_spnego_negotiated;
610 extern userdom_struct current_user_info;
613 auth_usersupplied_info *user_info = NULL;
614 extern struct auth_context *negprot_global_auth_context;
615 auth_serversupplied_info *server_info = NULL;
619 BOOL doencrypt = global_encrypted_passwords_negotiated;
621 START_PROFILE(SMBsesssetupX);
623 ZERO_STRUCT(lm_resp);
624 ZERO_STRUCT(nt_resp);
625 ZERO_STRUCT(plaintext_password);
627 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
629 /* a SPNEGO session setup has 12 command words, whereas a normal
630 NT1 session setup has 13. See the cifs spec. */
631 if (CVAL(inbuf, smb_wct) == 12 &&
632 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
633 if (!global_spnego_negotiated) {
634 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
635 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
638 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
641 smb_bufsize = SVAL(inbuf,smb_vwv2);
643 if (Protocol < PROTOCOL_NT1) {
644 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
645 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
646 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
650 lm_resp = data_blob(smb_buf(inbuf), passlen1);
652 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
653 /* Ensure null termination */
654 plaintext_password.data[passlen1] = 0;
657 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
661 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
662 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
663 enum remote_arch_types ra_type = get_remote_arch();
664 char *p = smb_buf(inbuf);
666 if(global_client_caps == 0)
667 global_client_caps = IVAL(inbuf,smb_vwv11);
669 /* client_caps is used as final determination if client is NT or Win95.
670 This is needed to return the correct error codes in some
674 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
675 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
676 set_remote_arch( RA_WIN95);
681 /* both Win95 and WinNT stuff up the password lengths for
682 non-encrypting systems. Uggh.
684 if passlen1==24 its a win95 system, and its setting the
685 password length incorrectly. Luckily it still works with the
686 default code because Win95 will null terminate the password
689 if passlen1>0 and passlen2>0 then maybe its a NT box and its
690 setting passlen2 to some random value which really stuffs
691 things up. we need to fix that one. */
693 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
697 /* check for nasty tricks */
698 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
699 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
702 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
703 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
706 /* Save the lanman2 password and the NT md4 password. */
708 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
713 lm_resp = data_blob(p, passlen1);
714 nt_resp = data_blob(p+passlen1, passlen2);
717 srvstr_pull(inbuf, pass, smb_buf(inbuf),
718 sizeof(pass), passlen1, STR_TERMINATE);
719 plaintext_password = data_blob(pass, strlen(pass)+1);
722 p += passlen1 + passlen2;
723 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
724 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
725 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
726 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
727 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
728 domain,native_os,native_lanman));
731 /* don't allow for weird usernames or domains */
732 alpha_strcpy(user, user, ". _-$", sizeof(user));
733 alpha_strcpy(domain, domain, ". _-", sizeof(domain));
734 if (strstr(user, "..") || strstr(domain,"..")) {
735 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
738 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
741 if (global_spnego_negotiated) {
743 /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */
745 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
746 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
748 pstrcpy(sub_user, user);
750 pstrcpy(sub_user, lp_guestaccount());
753 pstrcpy(current_user_info.smb_name,sub_user);
755 reload_services(True);
757 if (lp_security() == SEC_SHARE) {
758 /* in share level we should ignore any passwords */
760 data_blob_free(&lm_resp);
761 data_blob_free(&nt_resp);
762 data_blob_clear_free(&plaintext_password);
764 map_username(sub_user);
765 add_session_user(sub_user);
766 /* Then force it to null for the benfit of the code below */
772 nt_status = check_guest_password(&server_info);
774 } else if (doencrypt) {
775 if (!make_user_info_for_reply_enc(&user_info,
778 nt_status = NT_STATUS_NO_MEMORY;
780 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
785 struct auth_context *plaintext_auth_context = NULL;
787 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
788 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
790 if (!make_user_info_for_reply(&user_info,
792 plaintext_password)) {
793 nt_status = NT_STATUS_NO_MEMORY;
796 if (NT_STATUS_IS_OK(nt_status)) {
797 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
801 (plaintext_auth_context->free)(&plaintext_auth_context);
806 free_user_info(&user_info);
808 data_blob_free(&lm_resp);
809 data_blob_free(&nt_resp);
810 data_blob_clear_free(&plaintext_password);
812 if (!NT_STATUS_IS_OK(nt_status)) {
813 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
816 if (!NT_STATUS_IS_OK(nt_status)) {
817 return ERROR_NT(nt_status_squash(nt_status));
820 /* it's ok - setup a reply */
821 if (Protocol < PROTOCOL_NT1) {
822 set_message(outbuf,3,0,True);
824 set_message(outbuf,3,0,True);
825 add_signature(outbuf);
826 /* perhaps grab OS version here?? */
829 if (server_info->guest) {
830 SSVAL(outbuf,smb_vwv2,1);
833 /* register the name and uid as being validated, so further connections
834 to a uid can get through without a password, on the same VC */
836 sess_vuid = register_vuid(server_info, sub_user);
838 free_server_info(&server_info);
840 if (sess_vuid == -1) {
841 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
845 SSVAL(outbuf,smb_uid,sess_vuid);
846 SSVAL(inbuf,smb_uid,sess_vuid);
849 max_send = MIN(max_send,smb_bufsize);
851 done_sesssetup = True;
853 END_PROFILE(SMBsesssetupX);
854 return chain_reply(inbuf,outbuf,length,bufsize);