adding some initiaial code to sert %a to Win2K3 (using Native LanMan string from...
[Samba.git] / source / smbd / sesssetup.c
blob70158a9015fcf63d462fe7119b0502177985f4c7
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 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
400 auth, &auth_reply);
402 data_blob_free(&auth);
404 reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state,
405 &auth_reply, nt_status);
407 data_blob_free(&auth_reply);
409 /* and tell smbd that we have already replied to this packet */
410 return -1;
414 /****************************************************************************
415 reply to a session setup command
416 ****************************************************************************/
417 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
418 char *outbuf,
419 int length,int bufsize)
421 uint8 *p;
422 DATA_BLOB blob1;
423 int ret;
424 size_t bufrem;
426 DEBUG(3,("Doing spnego session setup\n"));
428 if (global_client_caps == 0) {
429 global_client_caps = IVAL(inbuf,smb_vwv10);
432 p = (uint8 *)smb_buf(inbuf);
434 if (SVAL(inbuf, smb_vwv7) == 0) {
435 /* an invalid request */
436 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
439 bufrem = smb_bufrem(inbuf, p);
440 /* pull the spnego blob */
441 blob1 = data_blob(p, MIN(bufrem, SVAL(inbuf, smb_vwv7)));
443 #if 0
444 file_save("negotiate.dat", blob1.data, blob1.length);
445 #endif
447 if (blob1.data[0] == ASN1_APPLICATION(0)) {
448 /* its a negTokenTarg packet */
449 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
450 data_blob_free(&blob1);
451 return ret;
454 if (blob1.data[0] == ASN1_CONTEXT(1)) {
455 /* its a auth packet */
456 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
457 data_blob_free(&blob1);
458 return ret;
461 /* what sort of packet is this? */
462 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
464 data_blob_free(&blob1);
466 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
470 /****************************************************************************
471 reply to a session setup command
472 ****************************************************************************/
473 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
474 int length,int bufsize)
476 int sess_vuid;
477 int smb_bufsize;
478 DATA_BLOB lm_resp;
479 DATA_BLOB nt_resp;
480 DATA_BLOB plaintext_password;
481 fstring user;
482 fstring sub_user; /* Sainitised username for substituion */
483 fstring domain;
484 fstring native_os;
485 fstring native_lanman;
486 static BOOL done_sesssetup = False;
487 extern BOOL global_encrypted_passwords_negotiated;
488 extern BOOL global_spnego_negotiated;
489 extern int Protocol;
490 extern int max_send;
492 auth_usersupplied_info *user_info = NULL;
493 extern struct auth_context *negprot_global_auth_context;
494 auth_serversupplied_info *server_info = NULL;
496 NTSTATUS nt_status;
498 BOOL doencrypt = global_encrypted_passwords_negotiated;
500 START_PROFILE(SMBsesssetupX);
502 ZERO_STRUCT(lm_resp);
503 ZERO_STRUCT(nt_resp);
504 ZERO_STRUCT(plaintext_password);
506 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
508 /* a SPNEGO session setup has 12 command words, whereas a normal
509 NT1 session setup has 13. See the cifs spec. */
510 if (CVAL(inbuf, smb_wct) == 12 &&
511 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
512 if (!global_spnego_negotiated) {
513 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
514 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
517 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
520 smb_bufsize = SVAL(inbuf,smb_vwv2);
522 if (Protocol < PROTOCOL_NT1) {
523 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
524 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
525 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
528 if (doencrypt) {
529 lm_resp = data_blob(smb_buf(inbuf), passlen1);
530 } else {
531 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
532 /* Ensure null termination */
533 plaintext_password.data[passlen1] = 0;
536 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
537 *domain = 0;
539 } else {
540 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
541 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
542 enum remote_arch_types ra_type = get_remote_arch();
543 char *p = smb_buf(inbuf);
545 if(global_client_caps == 0)
546 global_client_caps = IVAL(inbuf,smb_vwv11);
548 /* client_caps is used as final determination if client is NT or Win95.
549 This is needed to return the correct error codes in some
550 circumstances.
553 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
554 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
555 set_remote_arch( RA_WIN95);
559 if (!doencrypt) {
560 /* both Win95 and WinNT stuff up the password lengths for
561 non-encrypting systems. Uggh.
563 if passlen1==24 its a win95 system, and its setting the
564 password length incorrectly. Luckily it still works with the
565 default code because Win95 will null terminate the password
566 anyway
568 if passlen1>0 and passlen2>0 then maybe its a NT box and its
569 setting passlen2 to some random value which really stuffs
570 things up. we need to fix that one. */
572 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
573 passlen2 = 0;
576 /* check for nasty tricks */
577 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
578 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
581 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
582 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
585 /* Save the lanman2 password and the NT md4 password. */
587 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
588 doencrypt = False;
591 if (doencrypt) {
592 lm_resp = data_blob(p, passlen1);
593 nt_resp = data_blob(p+passlen1, passlen2);
594 } else {
595 pstring pass;
596 srvstr_pull(inbuf, pass, smb_buf(inbuf),
597 sizeof(pass), passlen1, STR_TERMINATE);
598 plaintext_password = data_blob(pass, strlen(pass)+1);
601 p += passlen1 + passlen2;
602 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
603 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
604 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
605 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
606 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
607 domain,native_os,native_lanman));
610 * we distinguish between 2K and XP by the "Native Lan Manager" string
611 * WinXP => "Windows 2002 5.1"
612 * Win2k => "Windows 2000 5.0"
613 * NT4 => "Windows NT 4.0"
614 * Win9x => "Windows 4.0"
617 if ( ra_type == RA_WIN2K ) {
618 if ( 0 == strcmp( native_lanman, "Windows 2002 5.1" ) )
619 set_remote_arch( RA_WINXP );
620 else if ( 0 == strcmp( native_lanman, "Windows .NET 5.2" ) )
621 set_remote_arch( RA_WIN2K3 );
627 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
629 if (*user) {
630 if (global_spnego_negotiated) {
632 /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */
634 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
635 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
637 fstrcpy(sub_user, user);
639 /* setup the string used by %U */
640 sub_set_smb_name(user);
641 } else {
642 fstrcpy(sub_user, lp_guestaccount());
645 sub_set_smb_name(sub_user);
647 reload_services(True);
649 if (lp_security() == SEC_SHARE) {
650 /* in share level we should ignore any passwords */
652 data_blob_free(&lm_resp);
653 data_blob_free(&nt_resp);
654 data_blob_clear_free(&plaintext_password);
656 map_username(sub_user);
657 add_session_user(sub_user);
658 /* Then force it to null for the benfit of the code below */
659 *user = 0;
662 if (!*user) {
664 nt_status = check_guest_password(&server_info);
666 } else if (doencrypt) {
667 if (!negprot_global_auth_context) {
668 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
669 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
671 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
672 lm_resp, nt_resp);
673 if (NT_STATUS_IS_OK(nt_status)) {
674 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
675 user_info,
676 &server_info);
678 } else {
679 struct auth_context *plaintext_auth_context = NULL;
680 const uint8 *chal;
681 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
682 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
684 if (!make_user_info_for_reply(&user_info,
685 user, domain, chal,
686 plaintext_password)) {
687 nt_status = NT_STATUS_NO_MEMORY;
690 if (NT_STATUS_IS_OK(nt_status)) {
691 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
692 user_info,
693 &server_info);
695 (plaintext_auth_context->free)(&plaintext_auth_context);
700 free_user_info(&user_info);
702 data_blob_free(&lm_resp);
703 data_blob_free(&nt_resp);
704 data_blob_clear_free(&plaintext_password);
706 if (!NT_STATUS_IS_OK(nt_status)) {
707 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
710 if (!NT_STATUS_IS_OK(nt_status)) {
711 return ERROR_NT(nt_status_squash(nt_status));
714 /* it's ok - setup a reply */
715 set_message(outbuf,3,0,True);
716 if (Protocol >= PROTOCOL_NT1) {
717 add_signature(outbuf);
718 /* perhaps grab OS version here?? */
721 if (server_info->guest) {
722 SSVAL(outbuf,smb_vwv2,1);
725 /* register the name and uid as being validated, so further connections
726 to a uid can get through without a password, on the same VC */
728 /* register_vuid keeps the server info */
729 sess_vuid = register_vuid(server_info, sub_user);
731 if (sess_vuid == -1) {
732 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
735 SSVAL(outbuf,smb_uid,sess_vuid);
736 SSVAL(inbuf,smb_uid,sess_vuid);
738 if (!done_sesssetup)
739 max_send = MIN(max_send,smb_bufsize);
741 done_sesssetup = True;
743 END_PROFILE(SMBsesssetupX);
744 return chain_reply(inbuf,outbuf,length,bufsize);