2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1998-2001
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jim McDonough 2002
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 uint32 global_client_caps = 0;
26 static struct auth_context *ntlmssp_auth_context = NULL;
29 on a logon error possibly map the error to success if "map to guest"
32 static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info,
33 const char *user, const char *domain)
35 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
36 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
37 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
38 DEBUG(3,("No such user %s [%s] - using guest account\n",
40 make_server_info_guest(server_info);
41 status = NT_STATUS_OK;
45 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
46 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
47 DEBUG(3,("Registered username %s for guest access\n",user));
48 make_server_info_guest(server_info);
49 status = NT_STATUS_OK;
57 /****************************************************************************
58 Add the standard 'Samba' signature to the end of the session setup.
59 ****************************************************************************/
60 static void add_signature(char *outbuf)
64 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
65 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
66 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
67 set_message_end(outbuf,p);
70 /****************************************************************************
71 Do a 'guest' logon, getting back the
72 ****************************************************************************/
73 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
75 struct auth_context *auth_context;
76 auth_usersupplied_info *user_info = NULL;
79 unsigned char chal[8];
83 DEBUG(3,("Got anonymous request\n"));
85 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
89 if (!make_user_info_guest(&user_info)) {
90 (auth_context->free)(&auth_context);
91 return NT_STATUS_NO_MEMORY;
94 nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
95 (auth_context->free)(&auth_context);
96 free_user_info(&user_info);
102 /****************************************************************************
103 reply to a session setup spnego negotiate packet for kerberos
104 ****************************************************************************/
105 static int reply_spnego_kerberos(connection_struct *conn,
106 char *inbuf, char *outbuf,
107 int length, int bufsize,
112 const struct passwd *pw;
117 auth_serversupplied_info *server_info = NULL;
120 if (!spnego_parse_krb5_wrap(*secblob, &ticket)) {
121 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
124 ads = ads_init_simple();
127 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
130 ads->auth.realm = strdup(lp_realm());
132 ret = ads_verify_ticket(ads, &ticket, &client, &auth_data);
133 if (!NT_STATUS_IS_OK(ret)) {
134 DEBUG(1,("Failed to verify incoming ticket!\n"));
136 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
139 DEBUG(3,("Ticket name is [%s]\n", client));
141 p = strchr_m(client, '@');
143 DEBUG(3,("Doesn't look like a valid principal\n"));
145 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
149 if (strcasecmp(p+1, ads->auth.realm) != 0) {
150 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
151 if (!lp_allow_trusted_domains()) {
152 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
154 /* this gives a fully qualified user name (ie. with full realm).
155 that leads to very long usernames, but what else can we do? */
156 asprintf(&user, "%s%s%s", p+1, lp_winbind_separator(), client);
158 user = strdup(client);
162 /* the password is good - let them in */
163 pw = smb_getpwnam(user,False);
164 if (!pw && !strstr(user, lp_winbind_separator())) {
166 /* try it with a winbind domain prefix */
167 asprintf(&user2, "%s%s%s", lp_workgroup(), lp_winbind_separator(), user);
168 pw = smb_getpwnam(user2,False);
176 DEBUG(1,("Username %s is invalid on this system\n",user));
177 return ERROR_NT(NT_STATUS_NO_SUCH_USER);
180 if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) {
181 DEBUG(1,("make_server_info_from_pw failed!\n"));
182 return ERROR_NT(ret);
185 sess_vuid = register_vuid(server_info, user);
188 free_server_info(&server_info);
190 if (sess_vuid == -1) {
191 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
194 set_message(outbuf,4,0,True);
195 SSVAL(outbuf, smb_vwv3, 0);
196 add_signature(outbuf);
198 SSVAL(outbuf,smb_uid,sess_vuid);
199 SSVAL(inbuf,smb_uid,sess_vuid);
201 return chain_reply(inbuf,outbuf,length,bufsize);
206 /****************************************************************************
207 send a security blob via a session setup reply
208 ****************************************************************************/
209 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
210 DATA_BLOB blob, uint32 errcode)
214 set_message(outbuf,4,0,True);
216 /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end
217 that we aren't finished yet */
219 SIVAL(outbuf, smb_rcls, errcode);
220 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
221 SSVAL(outbuf, smb_vwv3, blob.length);
223 memcpy(p, blob.data, blob.length);
225 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
226 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
227 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
228 set_message_end(outbuf,p);
230 return send_smb(smbd_server_fd(),outbuf);
233 /****************************************************************************
234 reply to a session setup spnego negotiate packet
235 ****************************************************************************/
236 static int reply_spnego_negotiate(connection_struct *conn,
239 int length, int bufsize,
242 char *OIDs[ASN1_MAX_OIDS];
245 uint32 ntlmssp_command, neg_flags, chal_flags;
246 DATA_BLOB chal, spnego_chal;
247 const uint8 *cryptkey;
248 BOOL got_kerberos = False;
250 extern pstring global_myname;
251 char *cliname=NULL, *domname=NULL;
253 /* parse out the OIDs and the first sec blob */
254 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
255 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
258 for (i=0;OIDs[i];i++) {
259 DEBUG(3,("Got OID %s\n", OIDs[i]));
260 if (strcmp(OID_KERBEROS5, OIDs[i]) == 0 ||
261 strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) {
266 DEBUG(3,("Got secblob of size %d\n", secblob.length));
269 if (got_kerberos && (SEC_ADS == lp_security())) {
270 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
271 length, bufsize, &secblob);
272 data_blob_free(&secblob);
277 /* parse the NTLMSSP packet */
279 file_save("secblob.dat", secblob.data, secblob.length);
282 if (!msrpc_parse(&secblob, "CddAA",
288 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
291 data_blob_free(&secblob);
293 if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
294 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
297 debug_ntlmssp_flags(neg_flags);
299 if (ntlmssp_auth_context) {
300 (ntlmssp_auth_context->free)(&ntlmssp_auth_context);
303 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&ntlmssp_auth_context))) {
304 return ERROR_NT(nt_status);
307 cryptkey = ntlmssp_auth_context->get_ntlm_challenge(ntlmssp_auth_context);
309 /* Give them the challenge. For now, ignore neg_flags and just
310 return the flags we want. Obviously this is not correct */
312 chal_flags = NTLMSSP_NEGOTIATE_UNICODE |
313 NTLMSSP_NEGOTIATE_128 |
314 NTLMSSP_NEGOTIATE_NTLM |
315 NTLMSSP_CHAL_TARGET_INFO;
317 if (neg_flags & NTLMSSP_NEGOTIATE_NTLM2)
318 chal_flags |= NTLMSSP_NEGOTIATE_NTLM2;
321 DATA_BLOB domain_blob, struct_blob;
322 fstring dnsname, dnsdomname;
324 msrpc_gen(&domain_blob,
328 fstrcpy(dnsdomname, lp_realm());
329 strlower(dnsdomname);
331 fstrcpy(dnsname, global_myname);
332 fstrcat(dnsname, ".");
333 fstrcat(dnsname, lp_realm());
336 msrpc_gen(&struct_blob, "aaaaa",
343 msrpc_gen(&chal, "CdUdbddB",
350 struct_blob.data, struct_blob.length);
352 data_blob_free(&domain_blob);
353 data_blob_free(&struct_blob);
356 if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) {
357 DEBUG(3,("Failed to generate challenge\n"));
358 data_blob_free(&chal);
359 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
362 /* now tell the client to send the auth packet */
363 reply_sesssetup_blob(conn, outbuf, spnego_chal, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED));
365 data_blob_free(&chal);
366 data_blob_free(&spnego_chal);
368 /* and tell smbd that we have already replied to this packet */
373 /****************************************************************************
374 reply to a session setup spnego auth packet
375 ****************************************************************************/
376 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
377 int length, int bufsize,
380 DATA_BLOB auth, response;
381 char *workgroup = NULL, *user = NULL, *machine = NULL;
382 DATA_BLOB lmhash, nthash, sess_key;
383 DATA_BLOB plaintext_password = data_blob(NULL, 0);
384 uint32 ntlmssp_command, neg_flags;
388 uint32 auth_flags = AUTH_FLAG_NONE;
389 auth_usersupplied_info *user_info = NULL;
390 auth_serversupplied_info *server_info = NULL;
392 /* we must have setup the auth context by now */
393 if (!ntlmssp_auth_context) {
394 DEBUG(2,("ntlmssp_auth_context is NULL in reply_spnego_auth\n"));
395 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
398 if (!spnego_parse_auth(blob1, &auth)) {
400 file_save("auth.dat", blob1.data, blob1.length);
402 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
405 /* now the NTLMSSP encoded auth hashes */
406 if (!msrpc_parse(&auth, "CdBBUUUBd",
416 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
419 data_blob_free(&auth);
420 data_blob_free(&sess_key);
422 DEBUG(3,("Got user=[%s] workgroup=[%s] machine=[%s] len1=%d len2=%d\n",
423 user, workgroup, machine, lmhash.length, nthash.length));
425 /* the client has given us its machine name (which we otherwise would not get on port 445).
426 we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
428 set_remote_machine_name(machine);
430 reload_services(True);
433 file_save("nthash1.dat", nthash.data, nthash.length);
434 file_save("lmhash1.dat", lmhash.data, lmhash.length);
438 auth_flags |= AUTH_FLAG_LM_RESP;
441 if (nthash.length == 24) {
442 auth_flags |= AUTH_FLAG_NTLM_RESP;
443 } else if (nthash.length > 24) {
444 auth_flags |= AUTH_FLAG_NTLMv2_RESP;
447 if (!make_user_info_map(&user_info,
453 return ERROR_NT(NT_STATUS_NO_MEMORY);
456 nt_status = ntlmssp_auth_context->check_ntlm_password(ntlmssp_auth_context, user_info, &server_info);
458 if (!NT_STATUS_IS_OK(nt_status)) {
459 nt_status = do_map_to_guest(nt_status, &server_info, user, workgroup);
462 SAFE_FREE(workgroup);
465 (ntlmssp_auth_context->free)(&ntlmssp_auth_context);
467 free_user_info(&user_info);
469 data_blob_free(&lmhash);
471 data_blob_free(&nthash);
473 if (!NT_STATUS_IS_OK(nt_status)) {
475 return ERROR_NT(nt_status_squash(nt_status));
478 as_guest = server_info->guest;
480 sess_vuid = register_vuid(server_info, user);
481 free_server_info(&server_info);
485 if (sess_vuid == -1) {
486 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
489 set_message(outbuf,4,0,True);
490 SSVAL(outbuf, smb_vwv3, 0);
493 SSVAL(outbuf,smb_vwv2,1);
496 add_signature(outbuf);
498 SSVAL(outbuf,smb_uid,sess_vuid);
499 SSVAL(inbuf,smb_uid,sess_vuid);
501 response = spnego_gen_auth_response();
502 reply_sesssetup_blob(conn, outbuf, response, 0);
504 /* and tell smbd that we have already replied to this packet */
509 /****************************************************************************
510 reply to a session setup spnego anonymous packet
511 ****************************************************************************/
512 static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf,
513 int length, int bufsize)
516 auth_serversupplied_info *server_info = NULL;
519 nt_status = check_guest_password(&server_info);
521 if (!NT_STATUS_IS_OK(nt_status)) {
522 return ERROR_NT(nt_status_squash(nt_status));
525 sess_vuid = register_vuid(server_info, lp_guestaccount());
527 free_server_info(&server_info);
529 if (sess_vuid == -1) {
530 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
533 set_message(outbuf,4,0,True);
534 SSVAL(outbuf, smb_vwv3, 0);
535 add_signature(outbuf);
537 SSVAL(outbuf,smb_uid,sess_vuid);
538 SSVAL(inbuf,smb_uid,sess_vuid);
540 return chain_reply(inbuf,outbuf,length,bufsize);
544 /****************************************************************************
545 reply to a session setup command
546 ****************************************************************************/
547 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,char *outbuf,
548 int length,int bufsize)
554 DEBUG(3,("Doing spnego session setup\n"));
556 if (global_client_caps == 0) {
557 global_client_caps = IVAL(inbuf,smb_vwv10);
560 p = (uint8 *)smb_buf(inbuf);
562 if (SVAL(inbuf, smb_vwv7) == 0) {
563 /* an anonymous request */
564 return reply_spnego_anonymous(conn, inbuf, outbuf, length, bufsize);
567 /* pull the spnego blob */
568 blob1 = data_blob(p, SVAL(inbuf, smb_vwv7));
571 file_save("negotiate.dat", blob1.data, blob1.length);
574 if (blob1.data[0] == ASN1_APPLICATION(0)) {
575 /* its a negTokenTarg packet */
576 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
577 data_blob_free(&blob1);
581 if (blob1.data[0] == ASN1_CONTEXT(1)) {
582 /* its a auth packet */
583 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
584 data_blob_free(&blob1);
588 /* what sort of packet is this? */
589 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
591 data_blob_free(&blob1);
593 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
597 /****************************************************************************
598 reply to a session setup command
599 ****************************************************************************/
600 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
601 int length,int bufsize)
607 DATA_BLOB plaintext_password;
609 pstring sub_user; /* Sainitised username for substituion */
612 fstring native_lanman;
613 static BOOL done_sesssetup = False;
614 extern BOOL global_encrypted_passwords_negotiated;
615 extern BOOL global_spnego_negotiated;
617 extern userdom_struct current_user_info;
620 auth_usersupplied_info *user_info = NULL;
621 extern struct auth_context *negprot_global_auth_context;
622 auth_serversupplied_info *server_info = NULL;
626 BOOL doencrypt = global_encrypted_passwords_negotiated;
628 START_PROFILE(SMBsesssetupX);
630 ZERO_STRUCT(lm_resp);
631 ZERO_STRUCT(nt_resp);
632 ZERO_STRUCT(plaintext_password);
634 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
636 /* a SPNEGO session setup has 12 command words, whereas a normal
637 NT1 session setup has 13. See the cifs spec. */
638 if (CVAL(inbuf, smb_wct) == 12 &&
639 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
640 if (!global_spnego_negotiated) {
641 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
642 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
645 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
648 smb_bufsize = SVAL(inbuf,smb_vwv2);
650 if (Protocol < PROTOCOL_NT1) {
651 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
652 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
653 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
657 lm_resp = data_blob(smb_buf(inbuf), passlen1);
659 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
660 /* Ensure null termination */
661 plaintext_password.data[passlen1] = 0;
664 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
668 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
669 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
670 enum remote_arch_types ra_type = get_remote_arch();
671 char *p = smb_buf(inbuf);
673 if(global_client_caps == 0)
674 global_client_caps = IVAL(inbuf,smb_vwv11);
676 /* client_caps is used as final determination if client is NT or Win95.
677 This is needed to return the correct error codes in some
681 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
682 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
683 set_remote_arch( RA_WIN95);
688 /* both Win95 and WinNT stuff up the password lengths for
689 non-encrypting systems. Uggh.
691 if passlen1==24 its a win95 system, and its setting the
692 password length incorrectly. Luckily it still works with the
693 default code because Win95 will null terminate the password
696 if passlen1>0 and passlen2>0 then maybe its a NT box and its
697 setting passlen2 to some random value which really stuffs
698 things up. we need to fix that one. */
700 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
704 /* check for nasty tricks */
705 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
706 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
709 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
710 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
713 /* Save the lanman2 password and the NT md4 password. */
715 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
720 lm_resp = data_blob(p, passlen1);
721 nt_resp = data_blob(p+passlen1, passlen2);
724 srvstr_pull(inbuf, pass, smb_buf(inbuf),
725 sizeof(pass), passlen1, STR_TERMINATE);
726 plaintext_password = data_blob(pass, strlen(pass)+1);
729 p += passlen1 + passlen2;
730 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
731 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
732 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
733 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
734 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
735 domain,native_os,native_lanman));
738 /* don't allow for weird usernames or domains */
739 alpha_strcpy(user, user, ". _-$", sizeof(user));
740 alpha_strcpy(domain, domain, ". _-", sizeof(domain));
741 if (strstr(user, "..") || strstr(domain,"..")) {
742 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
745 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
748 if (global_spnego_negotiated) {
750 /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */
752 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
753 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
755 pstrcpy(sub_user, user);
757 pstrcpy(sub_user, lp_guestaccount());
760 pstrcpy(current_user_info.smb_name,sub_user);
762 reload_services(True);
764 if (lp_security() == SEC_SHARE) {
765 /* in share level we should ignore any passwords */
767 data_blob_free(&lm_resp);
768 data_blob_free(&nt_resp);
769 data_blob_clear_free(&plaintext_password);
771 map_username(sub_user);
772 add_session_user(sub_user);
773 /* Then force it to null for the benfit of the code below */
779 nt_status = check_guest_password(&server_info);
781 } else if (doencrypt) {
782 if (!make_user_info_for_reply_enc(&user_info,
785 nt_status = NT_STATUS_NO_MEMORY;
787 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
792 struct auth_context *plaintext_auth_context = NULL;
794 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
795 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
797 if (!make_user_info_for_reply(&user_info,
799 plaintext_password)) {
800 nt_status = NT_STATUS_NO_MEMORY;
803 if (NT_STATUS_IS_OK(nt_status)) {
804 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
808 (plaintext_auth_context->free)(&plaintext_auth_context);
813 free_user_info(&user_info);
815 data_blob_free(&lm_resp);
816 data_blob_free(&nt_resp);
817 data_blob_clear_free(&plaintext_password);
819 if (!NT_STATUS_IS_OK(nt_status)) {
820 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
823 if (!NT_STATUS_IS_OK(nt_status)) {
824 return ERROR_NT(nt_status_squash(nt_status));
827 /* it's ok - setup a reply */
828 if (Protocol < PROTOCOL_NT1) {
829 set_message(outbuf,3,0,True);
831 set_message(outbuf,3,0,True);
832 add_signature(outbuf);
833 /* perhaps grab OS version here?? */
836 if (server_info->guest) {
837 SSVAL(outbuf,smb_vwv2,1);
840 /* register the name and uid as being validated, so further connections
841 to a uid can get through without a password, on the same VC */
843 sess_vuid = register_vuid(server_info, sub_user);
845 free_server_info(&server_info);
847 if (sess_vuid == -1) {
848 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
852 SSVAL(outbuf,smb_uid,sess_vuid);
853 SSVAL(inbuf,smb_uid,sess_vuid);
856 max_send = MIN(max_send,smb_bufsize);
858 done_sesssetup = True;
860 END_PROFILE(SMBsesssetupX);
861 return chain_reply(inbuf,outbuf,length,bufsize);