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 = Get_Pwnam(user);
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 = Get_Pwnam(user2);
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 char *cliname=NULL, *domname=NULL;
252 /* parse out the OIDs and the first sec blob */
253 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
254 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
257 for (i=0;OIDs[i];i++) {
258 DEBUG(3,("Got OID %s\n", OIDs[i]));
259 if (strcmp(OID_KERBEROS5, OIDs[i]) == 0 ||
260 strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) {
265 DEBUG(3,("Got secblob of size %d\n", secblob.length));
268 if (got_kerberos && (SEC_ADS == lp_security())) {
269 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
270 length, bufsize, &secblob);
271 data_blob_free(&secblob);
276 /* parse the NTLMSSP packet */
278 file_save("secblob.dat", secblob.data, secblob.length);
281 if (!msrpc_parse(&secblob, "CddAA",
287 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
290 data_blob_free(&secblob);
292 if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
293 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
296 debug_ntlmssp_flags(neg_flags);
298 if (ntlmssp_auth_context) {
299 (ntlmssp_auth_context->free)(&ntlmssp_auth_context);
302 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&ntlmssp_auth_context))) {
303 return ERROR_NT(nt_status);
306 cryptkey = ntlmssp_auth_context->get_ntlm_challenge(ntlmssp_auth_context);
308 /* Give them the challenge. For now, ignore neg_flags and just
309 return the flags we want. Obviously this is not correct */
311 chal_flags = NTLMSSP_NEGOTIATE_UNICODE |
312 NTLMSSP_NEGOTIATE_128 |
313 NTLMSSP_NEGOTIATE_NTLM |
314 NTLMSSP_CHAL_TARGET_INFO;
317 DATA_BLOB domain_blob, struct_blob;
318 fstring dnsname, dnsdomname;
320 msrpc_gen(&domain_blob,
324 fstrcpy(dnsdomname, (SEC_ADS == lp_security())?lp_realm():"");
325 strlower(dnsdomname);
327 fstrcpy(dnsname, global_myname());
328 fstrcat(dnsname, ".");
329 fstrcat(dnsname, dnsdomname);
332 msrpc_gen(&struct_blob, "aaaaa",
339 msrpc_gen(&chal, "CdUdbddB",
346 struct_blob.data, struct_blob.length);
348 data_blob_free(&domain_blob);
349 data_blob_free(&struct_blob);
352 if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) {
353 DEBUG(3,("Failed to generate challenge\n"));
354 data_blob_free(&chal);
355 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
358 /* now tell the client to send the auth packet */
359 reply_sesssetup_blob(conn, outbuf, spnego_chal, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED));
361 data_blob_free(&chal);
362 data_blob_free(&spnego_chal);
364 /* and tell smbd that we have already replied to this packet */
369 /****************************************************************************
370 reply to a session setup spnego auth packet
371 ****************************************************************************/
372 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
373 int length, int bufsize,
376 DATA_BLOB auth, response;
377 char *workgroup = NULL, *user = NULL, *machine = NULL;
378 DATA_BLOB lmhash, nthash, sess_key;
379 DATA_BLOB plaintext_password = data_blob(NULL, 0);
380 uint32 ntlmssp_command, neg_flags;
384 uint32 auth_flags = AUTH_FLAG_NONE;
385 auth_usersupplied_info *user_info = NULL;
386 auth_serversupplied_info *server_info = NULL;
388 /* we must have setup the auth context by now */
389 if (!ntlmssp_auth_context) {
390 DEBUG(2,("ntlmssp_auth_context is NULL in reply_spnego_auth\n"));
391 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
394 if (!spnego_parse_auth(blob1, &auth)) {
396 file_save("auth.dat", blob1.data, blob1.length);
398 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
401 /* now the NTLMSSP encoded auth hashes */
402 if (!msrpc_parse(&auth, "CdBBUUUBd",
412 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
415 data_blob_free(&auth);
416 data_blob_free(&sess_key);
418 DEBUG(3,("Got user=[%s] workgroup=[%s] machine=[%s] len1=%d len2=%d\n",
419 user, workgroup, machine, lmhash.length, nthash.length));
421 /* the client has given us its machine name (which we otherwise would not get on port 445).
422 we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
424 set_remote_machine_name(machine);
426 reload_services(True);
429 file_save("nthash1.dat", nthash.data, nthash.length);
430 file_save("lmhash1.dat", lmhash.data, lmhash.length);
434 auth_flags |= AUTH_FLAG_LM_RESP;
437 if (nthash.length == 24) {
438 auth_flags |= AUTH_FLAG_NTLM_RESP;
439 } else if (nthash.length > 24) {
440 auth_flags |= AUTH_FLAG_NTLMv2_RESP;
443 nt_status = make_user_info_map(&user_info, user, workgroup, machine,
444 lmhash, nthash, plaintext_password,
447 /* it looks a bit weird, but this function returns int type... */
448 if (!NT_STATUS_IS_OK(nt_status)) {
449 return ERROR_NT(NT_STATUS_NO_MEMORY);
452 nt_status = ntlmssp_auth_context->check_ntlm_password(ntlmssp_auth_context, user_info, &server_info);
454 if (!NT_STATUS_IS_OK(nt_status)) {
455 nt_status = do_map_to_guest(nt_status, &server_info, user, workgroup);
458 SAFE_FREE(workgroup);
461 (ntlmssp_auth_context->free)(&ntlmssp_auth_context);
463 free_user_info(&user_info);
465 data_blob_free(&lmhash);
467 data_blob_free(&nthash);
469 if (!NT_STATUS_IS_OK(nt_status)) {
471 return ERROR_NT(nt_status_squash(nt_status));
474 as_guest = server_info->guest;
476 sess_vuid = register_vuid(server_info, user);
477 free_server_info(&server_info);
481 if (sess_vuid == -1) {
482 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
485 set_message(outbuf,4,0,True);
486 SSVAL(outbuf, smb_vwv3, 0);
489 SSVAL(outbuf,smb_vwv2,1);
492 add_signature(outbuf);
494 SSVAL(outbuf,smb_uid,sess_vuid);
495 SSVAL(inbuf,smb_uid,sess_vuid);
497 response = spnego_gen_auth_response();
498 reply_sesssetup_blob(conn, outbuf, response, 0);
500 /* and tell smbd that we have already replied to this packet */
505 /****************************************************************************
506 reply to a session setup spnego anonymous packet
507 ****************************************************************************/
508 static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf,
509 int length, int bufsize)
512 auth_serversupplied_info *server_info = NULL;
515 nt_status = check_guest_password(&server_info);
517 if (!NT_STATUS_IS_OK(nt_status)) {
518 return ERROR_NT(nt_status_squash(nt_status));
521 sess_vuid = register_vuid(server_info, lp_guestaccount());
523 free_server_info(&server_info);
525 if (sess_vuid == -1) {
526 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
529 set_message(outbuf,4,0,True);
530 SSVAL(outbuf, smb_vwv3, 0);
531 add_signature(outbuf);
533 SSVAL(outbuf,smb_uid,sess_vuid);
534 SSVAL(inbuf,smb_uid,sess_vuid);
536 return chain_reply(inbuf,outbuf,length,bufsize);
540 /****************************************************************************
541 reply to a session setup command
542 ****************************************************************************/
543 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,char *outbuf,
544 int length,int bufsize)
550 DEBUG(3,("Doing spnego session setup\n"));
552 if (global_client_caps == 0) {
553 global_client_caps = IVAL(inbuf,smb_vwv10);
556 p = (uint8 *)smb_buf(inbuf);
558 if (SVAL(inbuf, smb_vwv7) == 0) {
559 /* an anonymous request */
560 return reply_spnego_anonymous(conn, inbuf, outbuf, length, bufsize);
563 /* pull the spnego blob */
564 blob1 = data_blob(p, SVAL(inbuf, smb_vwv7));
567 file_save("negotiate.dat", blob1.data, blob1.length);
570 if (blob1.data[0] == ASN1_APPLICATION(0)) {
571 /* its a negTokenTarg packet */
572 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
573 data_blob_free(&blob1);
577 if (blob1.data[0] == ASN1_CONTEXT(1)) {
578 /* its a auth packet */
579 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
580 data_blob_free(&blob1);
584 /* what sort of packet is this? */
585 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
587 data_blob_free(&blob1);
589 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
593 /****************************************************************************
594 reply to a session setup command
595 ****************************************************************************/
596 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
597 int length,int bufsize)
603 DATA_BLOB plaintext_password;
605 pstring sub_user; /* Sainitised username for substituion */
608 fstring native_lanman;
609 static BOOL done_sesssetup = False;
610 extern BOOL global_encrypted_passwords_negotiated;
611 extern BOOL global_spnego_negotiated;
613 extern userdom_struct current_user_info;
616 auth_usersupplied_info *user_info = NULL;
617 extern struct auth_context *negprot_global_auth_context;
618 auth_serversupplied_info *server_info = NULL;
622 BOOL doencrypt = global_encrypted_passwords_negotiated;
624 START_PROFILE(SMBsesssetupX);
626 ZERO_STRUCT(lm_resp);
627 ZERO_STRUCT(nt_resp);
628 ZERO_STRUCT(plaintext_password);
630 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
632 /* a SPNEGO session setup has 12 command words, whereas a normal
633 NT1 session setup has 13. See the cifs spec. */
634 if (CVAL(inbuf, smb_wct) == 12 &&
635 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
636 if (!global_spnego_negotiated) {
637 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
638 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
641 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
644 smb_bufsize = SVAL(inbuf,smb_vwv2);
646 if (Protocol < PROTOCOL_NT1) {
647 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
648 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
649 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
653 lm_resp = data_blob(smb_buf(inbuf), passlen1);
655 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
656 /* Ensure null termination */
657 plaintext_password.data[passlen1] = 0;
660 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
664 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
665 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
666 enum remote_arch_types ra_type = get_remote_arch();
667 char *p = smb_buf(inbuf);
669 if(global_client_caps == 0)
670 global_client_caps = IVAL(inbuf,smb_vwv11);
672 /* client_caps is used as final determination if client is NT or Win95.
673 This is needed to return the correct error codes in some
677 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
678 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
679 set_remote_arch( RA_WIN95);
684 /* both Win95 and WinNT stuff up the password lengths for
685 non-encrypting systems. Uggh.
687 if passlen1==24 its a win95 system, and its setting the
688 password length incorrectly. Luckily it still works with the
689 default code because Win95 will null terminate the password
692 if passlen1>0 and passlen2>0 then maybe its a NT box and its
693 setting passlen2 to some random value which really stuffs
694 things up. we need to fix that one. */
696 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
700 /* check for nasty tricks */
701 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
702 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
705 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
706 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
709 /* Save the lanman2 password and the NT md4 password. */
711 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
716 lm_resp = data_blob(p, passlen1);
717 nt_resp = data_blob(p+passlen1, passlen2);
720 srvstr_pull(inbuf, pass, smb_buf(inbuf),
721 sizeof(pass), passlen1, STR_TERMINATE);
722 plaintext_password = data_blob(pass, strlen(pass)+1);
725 p += passlen1 + passlen2;
726 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
727 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
728 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
729 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
730 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
731 domain,native_os,native_lanman));
734 /* don't allow for weird usernames or domains */
735 alpha_strcpy(user, user, ". _-$", sizeof(user));
736 alpha_strcpy(domain, domain, ". _-@", sizeof(domain));
737 if (strstr(user, "..") || strstr(domain,"..")) {
738 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
741 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
744 if (global_spnego_negotiated) {
746 /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */
748 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
749 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
751 pstrcpy(sub_user, user);
753 pstrcpy(sub_user, lp_guestaccount());
756 pstrcpy(current_user_info.smb_name,sub_user);
758 reload_services(True);
760 if (lp_security() == SEC_SHARE) {
761 /* in share level we should ignore any passwords */
763 data_blob_free(&lm_resp);
764 data_blob_free(&nt_resp);
765 data_blob_clear_free(&plaintext_password);
767 map_username(sub_user);
768 add_session_user(sub_user);
769 /* Then force it to null for the benfit of the code below */
775 nt_status = check_guest_password(&server_info);
777 } else if (doencrypt) {
778 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
780 if (NT_STATUS_IS_OK(nt_status)) {
781 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
786 struct auth_context *plaintext_auth_context = NULL;
788 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
789 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
791 if (!make_user_info_for_reply(&user_info,
793 plaintext_password)) {
794 nt_status = NT_STATUS_NO_MEMORY;
797 if (NT_STATUS_IS_OK(nt_status)) {
798 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
802 (plaintext_auth_context->free)(&plaintext_auth_context);
807 free_user_info(&user_info);
809 data_blob_free(&lm_resp);
810 data_blob_free(&nt_resp);
811 data_blob_clear_free(&plaintext_password);
813 if (!NT_STATUS_IS_OK(nt_status)) {
814 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
817 if (!NT_STATUS_IS_OK(nt_status)) {
818 return ERROR_NT(nt_status_squash(nt_status));
821 /* it's ok - setup a reply */
822 if (Protocol < PROTOCOL_NT1) {
823 set_message(outbuf,3,0,True);
825 set_message(outbuf,3,0,True);
826 add_signature(outbuf);
827 /* perhaps grab OS version here?? */
830 if (server_info->guest) {
831 SSVAL(outbuf,smb_vwv2,1);
834 /* register the name and uid as being validated, so further connections
835 to a uid can get through without a password, on the same VC */
837 sess_vuid = register_vuid(server_info, sub_user);
839 free_server_info(&server_info);
841 if (sess_vuid == -1) {
842 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
846 SSVAL(outbuf,smb_uid,sess_vuid);
847 SSVAL(inbuf,smb_uid,sess_vuid);
850 max_send = MIN(max_send,smb_bufsize);
852 done_sesssetup = True;
854 END_PROFILE(SMBsesssetupX);
855 return chain_reply(inbuf,outbuf,length,bufsize);