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 /* setup the string used by %U */
163 sub_set_smb_name(user);
165 reload_services(True);
167 /* the password is good - let them in */
168 pw = Get_Pwnam(user);
169 if (!pw && !strstr(user, lp_winbind_separator())) {
171 /* try it with a winbind domain prefix */
172 asprintf(&user2, "%s%s%s", lp_workgroup(), lp_winbind_separator(), user);
173 pw = Get_Pwnam(user2);
181 DEBUG(1,("Username %s is invalid on this system\n",user));
182 return ERROR_NT(NT_STATUS_NO_SUCH_USER);
185 if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) {
186 DEBUG(1,("make_server_info_from_pw failed!\n"));
187 return ERROR_NT(ret);
190 sess_vuid = register_vuid(server_info, user);
193 free_server_info(&server_info);
195 if (sess_vuid == -1) {
196 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
199 set_message(outbuf,4,0,True);
200 SSVAL(outbuf, smb_vwv3, 0);
201 add_signature(outbuf);
203 SSVAL(outbuf,smb_uid,sess_vuid);
204 SSVAL(inbuf,smb_uid,sess_vuid);
206 return chain_reply(inbuf,outbuf,length,bufsize);
211 /****************************************************************************
212 send a security blob via a session setup reply
213 ****************************************************************************/
214 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
215 DATA_BLOB blob, uint32 errcode)
219 set_message(outbuf,4,0,True);
221 /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end
222 that we aren't finished yet */
224 SIVAL(outbuf, smb_rcls, errcode);
225 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
226 SSVAL(outbuf, smb_vwv3, blob.length);
228 memcpy(p, blob.data, blob.length);
230 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
231 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
232 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
233 set_message_end(outbuf,p);
235 return send_smb(smbd_server_fd(),outbuf);
238 /****************************************************************************
239 reply to a session setup spnego negotiate packet
240 ****************************************************************************/
241 static int reply_spnego_negotiate(connection_struct *conn,
244 int length, int bufsize,
247 char *OIDs[ASN1_MAX_OIDS];
250 uint32 ntlmssp_command, neg_flags, chal_flags;
251 DATA_BLOB chal, spnego_chal;
252 const uint8 *cryptkey;
253 BOOL got_kerberos = False;
255 char *cliname=NULL, *domname=NULL;
257 /* parse out the OIDs and the first sec blob */
258 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
259 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
262 for (i=0;OIDs[i];i++) {
263 DEBUG(3,("Got OID %s\n", OIDs[i]));
264 if (strcmp(OID_KERBEROS5, OIDs[i]) == 0 ||
265 strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) {
270 DEBUG(3,("Got secblob of size %d\n", secblob.length));
273 if (got_kerberos && (SEC_ADS == lp_security())) {
274 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
275 length, bufsize, &secblob);
276 data_blob_free(&secblob);
281 /* parse the NTLMSSP packet */
283 file_save("secblob.dat", secblob.data, secblob.length);
286 if (!msrpc_parse(&secblob, "CddAA",
292 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
295 data_blob_free(&secblob);
297 if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
298 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
301 debug_ntlmssp_flags(neg_flags);
303 if (ntlmssp_auth_context) {
304 (ntlmssp_auth_context->free)(&ntlmssp_auth_context);
307 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&ntlmssp_auth_context))) {
308 return ERROR_NT(nt_status);
311 cryptkey = ntlmssp_auth_context->get_ntlm_challenge(ntlmssp_auth_context);
313 /* Give them the challenge. For now, ignore neg_flags and just
314 return the flags we want. Obviously this is not correct */
316 chal_flags = NTLMSSP_NEGOTIATE_UNICODE |
317 NTLMSSP_NEGOTIATE_128 |
318 NTLMSSP_NEGOTIATE_NTLM |
319 NTLMSSP_CHAL_TARGET_INFO;
322 DATA_BLOB domain_blob, struct_blob;
323 fstring dnsname, dnsdomname;
325 msrpc_gen(&domain_blob,
329 fstrcpy(dnsdomname, (SEC_ADS == lp_security())?lp_realm():"");
330 strlower(dnsdomname);
332 fstrcpy(dnsname, global_myname());
333 fstrcat(dnsname, ".");
334 fstrcat(dnsname, dnsdomname);
337 msrpc_gen(&struct_blob, "aaaaa",
344 msrpc_gen(&chal, "CdUdbddB",
351 struct_blob.data, struct_blob.length);
353 data_blob_free(&domain_blob);
354 data_blob_free(&struct_blob);
357 if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) {
358 DEBUG(3,("Failed to generate challenge\n"));
359 data_blob_free(&chal);
360 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
363 /* now tell the client to send the auth packet */
364 reply_sesssetup_blob(conn, outbuf, spnego_chal, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED));
366 data_blob_free(&chal);
367 data_blob_free(&spnego_chal);
369 /* and tell smbd that we have already replied to this packet */
374 /****************************************************************************
375 reply to a session setup spnego auth packet
376 ****************************************************************************/
377 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
378 int length, int bufsize,
381 DATA_BLOB auth, response;
382 char *workgroup = NULL, *user = NULL, *machine = NULL;
383 DATA_BLOB lmhash, nthash, sess_key;
384 DATA_BLOB plaintext_password = data_blob(NULL, 0);
385 uint32 ntlmssp_command, neg_flags;
389 uint32 auth_flags = AUTH_FLAG_NONE;
390 auth_usersupplied_info *user_info = NULL;
391 auth_serversupplied_info *server_info = NULL;
393 /* we must have setup the auth context by now */
394 if (!ntlmssp_auth_context) {
395 DEBUG(2,("ntlmssp_auth_context is NULL in reply_spnego_auth\n"));
396 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
399 if (!spnego_parse_auth(blob1, &auth)) {
401 file_save("auth.dat", blob1.data, blob1.length);
403 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
406 /* now the NTLMSSP encoded auth hashes */
407 if (!msrpc_parse(&auth, "CdBBUUUBd",
417 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
420 data_blob_free(&auth);
421 data_blob_free(&sess_key);
423 DEBUG(3,("Got user=[%s] workgroup=[%s] machine=[%s] len1=%d len2=%d\n",
424 user, workgroup, machine, lmhash.length, nthash.length));
426 /* the client has given us its machine name (which we otherwise would not get on port 445).
427 we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
429 set_remote_machine_name(machine);
431 /* setup the string used by %U */
432 sub_set_smb_name(user);
434 reload_services(True);
437 file_save("nthash1.dat", nthash.data, nthash.length);
438 file_save("lmhash1.dat", lmhash.data, lmhash.length);
442 auth_flags |= AUTH_FLAG_LM_RESP;
445 if (nthash.length == 24) {
446 auth_flags |= AUTH_FLAG_NTLM_RESP;
447 } else if (nthash.length > 24) {
448 auth_flags |= AUTH_FLAG_NTLMv2_RESP;
451 nt_status = make_user_info_map(&user_info, user, workgroup, machine,
452 lmhash, nthash, plaintext_password,
455 /* it looks a bit weird, but this function returns int type... */
456 if (!NT_STATUS_IS_OK(nt_status)) {
457 return ERROR_NT(NT_STATUS_NO_MEMORY);
460 nt_status = ntlmssp_auth_context->check_ntlm_password(ntlmssp_auth_context, user_info, &server_info);
462 if (!NT_STATUS_IS_OK(nt_status)) {
463 nt_status = do_map_to_guest(nt_status, &server_info, user, workgroup);
466 SAFE_FREE(workgroup);
469 (ntlmssp_auth_context->free)(&ntlmssp_auth_context);
471 free_user_info(&user_info);
473 data_blob_free(&lmhash);
475 data_blob_free(&nthash);
477 if (!NT_STATUS_IS_OK(nt_status)) {
479 return ERROR_NT(nt_status_squash(nt_status));
482 as_guest = server_info->guest;
484 sess_vuid = register_vuid(server_info, user);
485 free_server_info(&server_info);
489 if (sess_vuid == -1) {
490 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
493 set_message(outbuf,4,0,True);
494 SSVAL(outbuf, smb_vwv3, 0);
497 SSVAL(outbuf,smb_vwv2,1);
500 add_signature(outbuf);
502 SSVAL(outbuf,smb_uid,sess_vuid);
503 SSVAL(inbuf,smb_uid,sess_vuid);
505 response = spnego_gen_auth_response();
506 reply_sesssetup_blob(conn, outbuf, response, 0);
508 /* and tell smbd that we have already replied to this packet */
513 /****************************************************************************
514 reply to a session setup spnego anonymous packet
515 ****************************************************************************/
516 static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf,
517 int length, int bufsize)
520 auth_serversupplied_info *server_info = NULL;
523 nt_status = check_guest_password(&server_info);
525 if (!NT_STATUS_IS_OK(nt_status)) {
526 return ERROR_NT(nt_status_squash(nt_status));
529 sess_vuid = register_vuid(server_info, lp_guestaccount());
531 free_server_info(&server_info);
533 if (sess_vuid == -1) {
534 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
537 set_message(outbuf,4,0,True);
538 SSVAL(outbuf, smb_vwv3, 0);
539 add_signature(outbuf);
541 SSVAL(outbuf,smb_uid,sess_vuid);
542 SSVAL(inbuf,smb_uid,sess_vuid);
544 return chain_reply(inbuf,outbuf,length,bufsize);
548 /****************************************************************************
549 reply to a session setup command
550 ****************************************************************************/
551 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,char *outbuf,
552 int length,int bufsize)
558 DEBUG(3,("Doing spnego session setup\n"));
560 if (global_client_caps == 0) {
561 global_client_caps = IVAL(inbuf,smb_vwv10);
564 p = (uint8 *)smb_buf(inbuf);
566 if (SVAL(inbuf, smb_vwv7) == 0) {
567 /* an anonymous request */
568 return reply_spnego_anonymous(conn, inbuf, outbuf, length, bufsize);
571 /* pull the spnego blob */
572 blob1 = data_blob(p, SVAL(inbuf, smb_vwv7));
575 file_save("negotiate.dat", blob1.data, blob1.length);
578 if (blob1.data[0] == ASN1_APPLICATION(0)) {
579 /* its a negTokenTarg packet */
580 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
581 data_blob_free(&blob1);
585 if (blob1.data[0] == ASN1_CONTEXT(1)) {
586 /* its a auth packet */
587 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
588 data_blob_free(&blob1);
592 /* what sort of packet is this? */
593 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
595 data_blob_free(&blob1);
597 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
601 /****************************************************************************
602 reply to a session setup command
603 ****************************************************************************/
604 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
605 int length,int bufsize)
611 DATA_BLOB plaintext_password;
613 fstring sub_user; /* Sainitised username for substituion */
616 fstring native_lanman;
617 static BOOL done_sesssetup = False;
618 extern BOOL global_encrypted_passwords_negotiated;
619 extern BOOL global_spnego_negotiated;
621 extern userdom_struct current_user_info;
624 auth_usersupplied_info *user_info = NULL;
625 extern struct auth_context *negprot_global_auth_context;
626 auth_serversupplied_info *server_info = NULL;
630 BOOL doencrypt = global_encrypted_passwords_negotiated;
632 START_PROFILE(SMBsesssetupX);
634 ZERO_STRUCT(lm_resp);
635 ZERO_STRUCT(nt_resp);
636 ZERO_STRUCT(plaintext_password);
638 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
640 /* a SPNEGO session setup has 12 command words, whereas a normal
641 NT1 session setup has 13. See the cifs spec. */
642 if (CVAL(inbuf, smb_wct) == 12 &&
643 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
644 if (!global_spnego_negotiated) {
645 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
646 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
649 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
652 smb_bufsize = SVAL(inbuf,smb_vwv2);
654 if (Protocol < PROTOCOL_NT1) {
655 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
656 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
657 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
661 lm_resp = data_blob(smb_buf(inbuf), passlen1);
663 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
664 /* Ensure null termination */
665 plaintext_password.data[passlen1] = 0;
668 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
672 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
673 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
674 enum remote_arch_types ra_type = get_remote_arch();
675 char *p = smb_buf(inbuf);
677 if(global_client_caps == 0)
678 global_client_caps = IVAL(inbuf,smb_vwv11);
680 /* client_caps is used as final determination if client is NT or Win95.
681 This is needed to return the correct error codes in some
685 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
686 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
687 set_remote_arch( RA_WIN95);
692 /* both Win95 and WinNT stuff up the password lengths for
693 non-encrypting systems. Uggh.
695 if passlen1==24 its a win95 system, and its setting the
696 password length incorrectly. Luckily it still works with the
697 default code because Win95 will null terminate the password
700 if passlen1>0 and passlen2>0 then maybe its a NT box and its
701 setting passlen2 to some random value which really stuffs
702 things up. we need to fix that one. */
704 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
708 /* check for nasty tricks */
709 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
710 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
713 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
714 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
717 /* Save the lanman2 password and the NT md4 password. */
719 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
724 lm_resp = data_blob(p, passlen1);
725 nt_resp = data_blob(p+passlen1, passlen2);
728 srvstr_pull(inbuf, pass, smb_buf(inbuf),
729 sizeof(pass), passlen1, STR_TERMINATE);
730 plaintext_password = data_blob(pass, strlen(pass)+1);
733 p += passlen1 + passlen2;
734 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
735 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
736 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
737 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
738 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
739 domain,native_os,native_lanman));
742 /* don't allow for weird usernames or domains */
743 alpha_strcpy(user, user, ". _-$", sizeof(user));
744 alpha_strcpy(domain, domain, ". _-@", sizeof(domain));
745 if (strstr(user, "..") || strstr(domain,"..")) {
746 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
749 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
752 if (global_spnego_negotiated) {
754 /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */
756 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
757 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
759 fstrcpy(sub_user, user);
761 /* setup the string used by %U */
762 sub_set_smb_name(user);
764 fstrcpy(sub_user, lp_guestaccount());
767 fstrcpy(current_user_info.smb_name,sub_user);
769 reload_services(True);
771 if (lp_security() == SEC_SHARE) {
772 /* in share level we should ignore any passwords */
774 data_blob_free(&lm_resp);
775 data_blob_free(&nt_resp);
776 data_blob_clear_free(&plaintext_password);
778 map_username(sub_user);
779 add_session_user(sub_user);
780 /* Then force it to null for the benfit of the code below */
786 nt_status = check_guest_password(&server_info);
788 } else if (doencrypt) {
789 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
791 if (NT_STATUS_IS_OK(nt_status)) {
792 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
797 struct auth_context *plaintext_auth_context = NULL;
799 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
800 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
802 if (!make_user_info_for_reply(&user_info,
804 plaintext_password)) {
805 nt_status = NT_STATUS_NO_MEMORY;
808 if (NT_STATUS_IS_OK(nt_status)) {
809 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
813 (plaintext_auth_context->free)(&plaintext_auth_context);
818 free_user_info(&user_info);
820 data_blob_free(&lm_resp);
821 data_blob_free(&nt_resp);
822 data_blob_clear_free(&plaintext_password);
824 if (!NT_STATUS_IS_OK(nt_status)) {
825 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
828 if (!NT_STATUS_IS_OK(nt_status)) {
829 return ERROR_NT(nt_status_squash(nt_status));
832 /* it's ok - setup a reply */
833 if (Protocol < PROTOCOL_NT1) {
834 set_message(outbuf,3,0,True);
836 set_message(outbuf,3,0,True);
837 add_signature(outbuf);
838 /* perhaps grab OS version here?? */
841 if (server_info->guest) {
842 SSVAL(outbuf,smb_vwv2,1);
845 /* register the name and uid as being validated, so further connections
846 to a uid can get through without a password, on the same VC */
848 sess_vuid = register_vuid(server_info, sub_user);
850 free_server_info(&server_info);
852 if (sess_vuid == -1) {
853 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
857 SSVAL(outbuf,smb_uid,sess_vuid);
858 SSVAL(inbuf,smb_uid,sess_vuid);
861 max_send = MIN(max_send,smb_bufsize);
863 done_sesssetup = True;
865 END_PROFILE(SMBsesssetupX);
866 return chain_reply(inbuf,outbuf,length,bufsize);