fix WinXP & Win2K3 remote_arch and check pointer in ntlmssp code before dereferencing
[Samba.git] / source / smbd / sesssetup.c
blob674f6145d39bb4eaaef50d47899d59bc0115ba6d
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 2002
7 Copyright (C) Luke Howard 2003
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 uint32 global_client_caps = 0;
28 static struct auth_ntlmssp_state *global_ntlmssp_state;
31 on a logon error possibly map the error to success if "map to guest"
32 is set approriately
34 static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info,
35 const char *user, const char *domain)
37 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
38 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
39 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
40 DEBUG(3,("No such user %s [%s] - using guest account\n",
41 user, domain));
42 status = make_server_info_guest(server_info);
46 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
47 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
48 DEBUG(3,("Registered username %s for guest access\n",user));
49 status = make_server_info_guest(server_info);
53 return status;
57 /****************************************************************************
58 Add the standard 'Samba' signature to the end of the session setup.
59 ****************************************************************************/
60 static void add_signature(char *outbuf)
62 char *p;
63 p = smb_buf(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 send a security blob via a session setup reply
72 ****************************************************************************/
73 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
74 DATA_BLOB blob, NTSTATUS nt_status)
76 char *p;
78 set_message(outbuf,4,0,True);
80 /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end
81 that we aren't finished yet */
83 nt_status = nt_status_squash(nt_status);
84 SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
85 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
86 SSVAL(outbuf, smb_vwv3, blob.length);
87 p = smb_buf(outbuf);
89 /* should we cap this? */
90 memcpy(p, blob.data, blob.length);
91 p += blob.length;
93 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
94 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
95 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
96 set_message_end(outbuf,p);
98 return send_smb(smbd_server_fd(),outbuf);
101 /****************************************************************************
102 Do a 'guest' logon, getting back the
103 ****************************************************************************/
104 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
106 struct auth_context *auth_context;
107 auth_usersupplied_info *user_info = NULL;
109 NTSTATUS nt_status;
110 unsigned char chal[8];
112 ZERO_STRUCT(chal);
114 DEBUG(3,("Got anonymous request\n"));
116 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
117 return nt_status;
120 if (!make_user_info_guest(&user_info)) {
121 (auth_context->free)(&auth_context);
122 return NT_STATUS_NO_MEMORY;
125 nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
126 (auth_context->free)(&auth_context);
127 free_user_info(&user_info);
128 return nt_status;
132 #ifdef HAVE_KRB5
133 /****************************************************************************
134 reply to a session setup spnego negotiate packet for kerberos
135 ****************************************************************************/
136 static int reply_spnego_kerberos(connection_struct *conn,
137 char *inbuf, char *outbuf,
138 int length, int bufsize,
139 DATA_BLOB *secblob)
141 DATA_BLOB ticket;
142 char *client, *p;
143 const struct passwd *pw;
144 char *user;
145 int sess_vuid;
146 NTSTATUS ret;
147 DATA_BLOB auth_data;
148 DATA_BLOB ap_rep, ap_rep_wrapped, response;
149 auth_serversupplied_info *server_info = NULL;
150 ADS_STRUCT *ads;
151 uint8 session_key[16];
152 uint8 tok_id[2];
153 BOOL foreign = False;
155 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
156 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
159 ads = ads_init_simple();
161 if (!ads) {
162 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
165 ads->auth.realm = strdup(lp_realm());
167 ret = ads_verify_ticket(ads, &ticket, &client, &auth_data, &ap_rep, session_key);
168 if (!NT_STATUS_IS_OK(ret)) {
169 DEBUG(1,("Failed to verify incoming ticket!\n"));
170 ads_destroy(&ads);
171 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
174 data_blob_free(&auth_data);
176 DEBUG(3,("Ticket name is [%s]\n", client));
178 p = strchr_m(client, '@');
179 if (!p) {
180 DEBUG(3,("Doesn't look like a valid principal\n"));
181 ads_destroy(&ads);
182 data_blob_free(&ap_rep);
183 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
186 *p = 0;
187 if (strcasecmp(p+1, ads->auth.realm) != 0) {
188 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
189 if (!lp_allow_trusted_domains()) {
190 data_blob_free(&ap_rep);
191 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
193 foreign = True;
196 /* this gives a fully qualified user name (ie. with full realm).
197 that leads to very long usernames, but what else can we do? */
198 asprintf(&user, "%s%s%s", p+1, lp_winbind_separator(), client);
200 pw = Get_Pwnam(user);
201 if (!pw && !foreign) {
202 pw = Get_Pwnam(client);
203 SAFE_FREE(user);
204 user = smb_xstrdup(client);
207 ads_destroy(&ads);
209 /* setup the string used by %U */
210 sub_set_smb_name(user);
212 reload_services(True);
214 if (!pw) {
215 DEBUG(1,("Username %s is invalid on this system\n",user));
216 data_blob_free(&ap_rep);
217 return ERROR_NT(NT_STATUS_NO_SUCH_USER);
220 if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) {
221 DEBUG(1,("make_server_info_from_pw failed!\n"));
222 data_blob_free(&ap_rep);
223 return ERROR_NT(ret);
226 /* Copy out the session key from the AP_REQ. */
227 memcpy(server_info->session_key, session_key, sizeof(session_key));
229 /* register_vuid keeps the server info */
230 sess_vuid = register_vuid(server_info, user);
232 free(user);
234 if (sess_vuid == -1) {
235 ret = NT_STATUS_LOGON_FAILURE;
236 } else {
237 set_message(outbuf,4,0,True);
238 SSVAL(outbuf, smb_vwv3, 0);
240 if (server_info->guest) {
241 SSVAL(outbuf,smb_vwv2,1);
244 SSVAL(outbuf, smb_uid, sess_vuid);
247 /* wrap that up in a nice GSS-API wrapping */
248 if (NT_STATUS_IS_OK(ret)) {
249 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
250 } else {
251 ap_rep_wrapped = data_blob(NULL, 0);
253 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
254 reply_sesssetup_blob(conn, outbuf, response, ret);
256 data_blob_free(&ap_rep);
257 data_blob_free(&ap_rep_wrapped);
258 data_blob_free(&response);
260 return -1; /* already replied */
262 #endif
265 /****************************************************************************
266 send a session setup reply, wrapped in SPNEGO.
267 get vuid and check first.
268 end the NTLMSSP exchange context if we are OK/complete fail
269 ***************************************************************************/
270 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf,
271 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
272 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status)
274 BOOL ret;
275 DATA_BLOB response;
276 struct auth_serversupplied_info *server_info;
277 server_info = (*auth_ntlmssp_state)->server_info;
279 if (!NT_STATUS_IS_OK(nt_status)) {
280 nt_status = do_map_to_guest(nt_status,
281 &server_info,
282 (*auth_ntlmssp_state)->ntlmssp_state->user,
283 (*auth_ntlmssp_state)->ntlmssp_state->domain);
286 if (NT_STATUS_IS_OK(nt_status)) {
287 int sess_vuid;
288 /* register_vuid keeps the server info */
289 sess_vuid = register_vuid(server_info, (*auth_ntlmssp_state)->ntlmssp_state->user);
290 (*auth_ntlmssp_state)->server_info = NULL;
292 if (sess_vuid == -1) {
293 nt_status = NT_STATUS_LOGON_FAILURE;
294 } else {
296 set_message(outbuf,4,0,True);
297 SSVAL(outbuf, smb_vwv3, 0);
299 if (server_info->guest) {
300 SSVAL(outbuf,smb_vwv2,1);
303 SSVAL(outbuf,smb_uid,sess_vuid);
307 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
308 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
309 data_blob_free(&response);
311 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
312 auth_ntlmssp_end(auth_ntlmssp_state);
315 return ret;
318 /****************************************************************************
319 reply to a session setup spnego negotiate packet
320 ****************************************************************************/
321 static int reply_spnego_negotiate(connection_struct *conn,
322 char *inbuf,
323 char *outbuf,
324 int length, int bufsize,
325 DATA_BLOB blob1)
327 char *OIDs[ASN1_MAX_OIDS];
328 DATA_BLOB secblob;
329 int i;
330 DATA_BLOB chal;
331 BOOL got_kerberos = False;
332 NTSTATUS nt_status;
334 /* parse out the OIDs and the first sec blob */
335 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
336 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
339 for (i=0;OIDs[i];i++) {
340 DEBUG(3,("Got OID %s\n", OIDs[i]));
341 if (strcmp(OID_KERBEROS5, OIDs[i]) == 0 ||
342 strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) {
343 got_kerberos = True;
345 free(OIDs[i]);
347 DEBUG(3,("Got secblob of size %d\n", secblob.length));
349 #ifdef HAVE_KRB5
350 if (got_kerberos && (SEC_ADS == lp_security())) {
351 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
352 length, bufsize, &secblob);
353 data_blob_free(&secblob);
354 return ret;
356 #endif
358 if (global_ntlmssp_state) {
359 auth_ntlmssp_end(&global_ntlmssp_state);
362 nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
363 if (!NT_STATUS_IS_OK(nt_status)) {
364 return ERROR_NT(nt_status);
367 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
368 secblob, &chal);
370 data_blob_free(&secblob);
372 reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state,
373 &chal, nt_status);
375 data_blob_free(&chal);
377 /* already replied */
378 return -1;
382 /****************************************************************************
383 reply to a session setup spnego auth packet
384 ****************************************************************************/
385 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
386 int length, int bufsize,
387 DATA_BLOB blob1)
389 DATA_BLOB auth, auth_reply;
390 NTSTATUS nt_status;
392 if (!spnego_parse_auth(blob1, &auth)) {
393 #if 0
394 file_save("auth.dat", blob1.data, blob1.length);
395 #endif
396 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
399 if ( global_ntlmssp_state ) {
400 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
401 auth, &auth_reply);
404 data_blob_free(&auth);
406 reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state,
407 &auth_reply, nt_status);
409 data_blob_free(&auth_reply);
411 /* and tell smbd that we have already replied to this packet */
412 return -1;
416 /****************************************************************************
417 reply to a session setup command
418 ****************************************************************************/
419 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
420 char *outbuf,
421 int length,int bufsize)
423 uint8 *p;
424 DATA_BLOB blob1;
425 int ret;
426 size_t bufrem;
427 fstring native_os, native_lanman;
428 char *p2;
429 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
430 enum remote_arch_types ra_type = get_remote_arch();
432 DEBUG(3,("Doing spnego session setup\n"));
434 if (global_client_caps == 0) {
435 global_client_caps = IVAL(inbuf,smb_vwv10);
438 p = (uint8 *)smb_buf(inbuf);
440 if (data_blob_len == 0) {
441 /* an invalid request */
442 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
445 bufrem = smb_bufrem(inbuf, p);
446 /* pull the spnego blob */
447 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
449 #if 0
450 file_save("negotiate.dat", blob1.data, blob1.length);
451 #endif
453 p2 = inbuf + smb_vwv13 + data_blob_len;
454 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
455 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
456 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s]\n", native_os, native_lanman));
458 if ( ra_type == RA_WIN2K )
459 ra_lanman_string( native_lanman );
461 if (blob1.data[0] == ASN1_APPLICATION(0)) {
462 /* its a negTokenTarg packet */
463 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
464 data_blob_free(&blob1);
465 return ret;
468 if (blob1.data[0] == ASN1_CONTEXT(1)) {
469 /* its a auth packet */
470 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
471 data_blob_free(&blob1);
472 return ret;
475 /* what sort of packet is this? */
476 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
478 data_blob_free(&blob1);
480 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
484 /****************************************************************************
485 reply to a session setup command
486 ****************************************************************************/
487 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
488 int length,int bufsize)
490 int sess_vuid;
491 int smb_bufsize;
492 DATA_BLOB lm_resp;
493 DATA_BLOB nt_resp;
494 DATA_BLOB plaintext_password;
495 fstring user;
496 fstring sub_user; /* Sainitised username for substituion */
497 fstring domain;
498 fstring native_os;
499 fstring native_lanman;
500 static BOOL done_sesssetup = False;
501 extern BOOL global_encrypted_passwords_negotiated;
502 extern BOOL global_spnego_negotiated;
503 extern int Protocol;
504 extern int max_send;
506 auth_usersupplied_info *user_info = NULL;
507 extern struct auth_context *negprot_global_auth_context;
508 auth_serversupplied_info *server_info = NULL;
510 NTSTATUS nt_status;
512 BOOL doencrypt = global_encrypted_passwords_negotiated;
514 START_PROFILE(SMBsesssetupX);
516 ZERO_STRUCT(lm_resp);
517 ZERO_STRUCT(nt_resp);
518 ZERO_STRUCT(plaintext_password);
520 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
522 /* a SPNEGO session setup has 12 command words, whereas a normal
523 NT1 session setup has 13. See the cifs spec. */
524 if (CVAL(inbuf, smb_wct) == 12 &&
525 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
526 if (!global_spnego_negotiated) {
527 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
528 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
531 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
534 smb_bufsize = SVAL(inbuf,smb_vwv2);
536 if (Protocol < PROTOCOL_NT1) {
537 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
538 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
539 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
542 if (doencrypt) {
543 lm_resp = data_blob(smb_buf(inbuf), passlen1);
544 } else {
545 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
546 /* Ensure null termination */
547 plaintext_password.data[passlen1] = 0;
550 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
551 *domain = 0;
553 } else {
554 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
555 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
556 enum remote_arch_types ra_type = get_remote_arch();
557 char *p = smb_buf(inbuf);
559 if(global_client_caps == 0)
560 global_client_caps = IVAL(inbuf,smb_vwv11);
562 /* client_caps is used as final determination if client is NT or Win95.
563 This is needed to return the correct error codes in some
564 circumstances.
567 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
568 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
569 set_remote_arch( RA_WIN95);
573 if (!doencrypt) {
574 /* both Win95 and WinNT stuff up the password lengths for
575 non-encrypting systems. Uggh.
577 if passlen1==24 its a win95 system, and its setting the
578 password length incorrectly. Luckily it still works with the
579 default code because Win95 will null terminate the password
580 anyway
582 if passlen1>0 and passlen2>0 then maybe its a NT box and its
583 setting passlen2 to some random value which really stuffs
584 things up. we need to fix that one. */
586 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
587 passlen2 = 0;
590 /* check for nasty tricks */
591 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
592 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
595 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
596 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
599 /* Save the lanman2 password and the NT md4 password. */
601 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
602 doencrypt = False;
605 if (doencrypt) {
606 lm_resp = data_blob(p, passlen1);
607 nt_resp = data_blob(p+passlen1, passlen2);
608 } else {
609 pstring pass;
610 srvstr_pull(inbuf, pass, smb_buf(inbuf),
611 sizeof(pass), passlen1, STR_TERMINATE);
612 plaintext_password = data_blob(pass, strlen(pass)+1);
615 p += passlen1 + passlen2;
616 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
617 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
618 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
619 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
620 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
621 domain,native_os,native_lanman));
623 if ( ra_type == RA_WIN2K )
624 ra_lanman_string( native_lanman );
628 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
630 if (*user) {
631 if (global_spnego_negotiated) {
633 /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */
635 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
636 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
638 fstrcpy(sub_user, user);
640 /* setup the string used by %U */
641 sub_set_smb_name(user);
642 } else {
643 fstrcpy(sub_user, lp_guestaccount());
646 sub_set_smb_name(sub_user);
648 reload_services(True);
650 if (lp_security() == SEC_SHARE) {
651 /* in share level we should ignore any passwords */
653 data_blob_free(&lm_resp);
654 data_blob_free(&nt_resp);
655 data_blob_clear_free(&plaintext_password);
657 map_username(sub_user);
658 add_session_user(sub_user);
659 /* Then force it to null for the benfit of the code below */
660 *user = 0;
663 if (!*user) {
665 nt_status = check_guest_password(&server_info);
667 } else if (doencrypt) {
668 if (!negprot_global_auth_context) {
669 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
670 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
672 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
673 lm_resp, nt_resp);
674 if (NT_STATUS_IS_OK(nt_status)) {
675 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
676 user_info,
677 &server_info);
679 } else {
680 struct auth_context *plaintext_auth_context = NULL;
681 const uint8 *chal;
682 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
683 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
685 if (!make_user_info_for_reply(&user_info,
686 user, domain, chal,
687 plaintext_password)) {
688 nt_status = NT_STATUS_NO_MEMORY;
691 if (NT_STATUS_IS_OK(nt_status)) {
692 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
693 user_info,
694 &server_info);
696 (plaintext_auth_context->free)(&plaintext_auth_context);
701 free_user_info(&user_info);
703 data_blob_free(&lm_resp);
704 data_blob_free(&nt_resp);
705 data_blob_clear_free(&plaintext_password);
707 if (!NT_STATUS_IS_OK(nt_status)) {
708 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
711 if (!NT_STATUS_IS_OK(nt_status)) {
712 return ERROR_NT(nt_status_squash(nt_status));
715 /* it's ok - setup a reply */
716 set_message(outbuf,3,0,True);
717 if (Protocol >= PROTOCOL_NT1) {
718 add_signature(outbuf);
719 /* perhaps grab OS version here?? */
722 if (server_info->guest) {
723 SSVAL(outbuf,smb_vwv2,1);
726 /* register the name and uid as being validated, so further connections
727 to a uid can get through without a password, on the same VC */
729 /* register_vuid keeps the server info */
730 sess_vuid = register_vuid(server_info, sub_user);
732 if (sess_vuid == -1) {
733 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
736 SSVAL(outbuf,smb_uid,sess_vuid);
737 SSVAL(inbuf,smb_uid,sess_vuid);
739 if (!done_sesssetup)
740 max_send = MIN(max_send,smb_bufsize);
742 done_sesssetup = True;
744 END_PROFILE(SMBsesssetupX);
745 return chain_reply(inbuf,outbuf,length,bufsize);