2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1998-2001
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 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.
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"
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",
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);
56 /****************************************************************************
57 Add the standard 'Samba' signature to the end of the session setup.
58 ****************************************************************************/
60 static int add_signature(char *outbuf, char *p)
65 fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
67 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
68 p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE);
69 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
71 return PTR_DIFF(p, start);
74 /****************************************************************************
75 Send a security blob via a session setup reply.
76 ****************************************************************************/
78 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
79 DATA_BLOB blob, NTSTATUS nt_status)
83 set_message(outbuf,4,0,True);
85 nt_status = nt_status_squash(nt_status);
86 SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
87 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
88 SSVAL(outbuf, smb_vwv3, blob.length);
91 /* should we cap this? */
92 memcpy(p, blob.data, blob.length);
95 p += add_signature( outbuf, p );
97 set_message_end(outbuf,p);
99 return send_smb(smbd_server_fd(),outbuf);
102 /****************************************************************************
103 Do a 'guest' logon, getting back the
104 ****************************************************************************/
106 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
108 struct auth_context *auth_context;
109 auth_usersupplied_info *user_info = NULL;
112 unsigned char chal[8];
116 DEBUG(3,("Got anonymous request\n"));
118 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
122 if (!make_user_info_guest(&user_info)) {
123 (auth_context->free)(&auth_context);
124 return NT_STATUS_NO_MEMORY;
127 nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
128 (auth_context->free)(&auth_context);
129 free_user_info(&user_info);
135 /****************************************************************************
136 reply to a session setup spnego negotiate packet for kerberos
137 ****************************************************************************/
138 static int reply_spnego_kerberos(connection_struct *conn,
139 char *inbuf, char *outbuf,
140 int length, int bufsize,
145 const struct passwd *pw;
150 DATA_BLOB ap_rep, ap_rep_wrapped, response;
151 auth_serversupplied_info *server_info = NULL;
152 DATA_BLOB session_key;
154 BOOL foreign = False;
155 DATA_BLOB nullblob = data_blob(NULL, 0);
158 ZERO_STRUCT(auth_data);
160 ZERO_STRUCT(ap_rep_wrapped);
161 ZERO_STRUCT(response);
163 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
164 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
167 ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, &session_key);
169 data_blob_free(&ticket);
171 if (!NT_STATUS_IS_OK(ret)) {
172 DEBUG(1,("Failed to verify incoming ticket!\n"));
173 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
176 data_blob_free(&auth_data);
178 DEBUG(3,("Ticket name is [%s]\n", client));
180 p = strchr_m(client, '@');
182 DEBUG(3,("Doesn't look like a valid principal\n"));
183 data_blob_free(&ap_rep);
185 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
189 if (!strequal(p+1, lp_realm())) {
190 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
191 if (!lp_allow_trusted_domains()) {
192 data_blob_free(&ap_rep);
194 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
199 /* this gives a fully qualified user name (ie. with full realm).
200 that leads to very long usernames, but what else can we do? */
202 asprintf(&user, "%s%c%s", p+1, *lp_winbind_separator(), client);
204 pw = smb_getpwnam( user );
210 DEBUG(1,("Username %s is invalid on this system\n",user));
211 data_blob_free(&ap_rep);
212 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
215 /* setup the string used by %U */
217 sub_set_smb_name(pw->pw_name);
218 reload_services(True);
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 /* register_vuid keeps the server info */
227 sess_vuid = register_vuid(server_info, session_key, nullblob, user);
231 if (sess_vuid == -1) {
232 ret = NT_STATUS_LOGON_FAILURE;
234 set_message(outbuf,4,0,True);
235 SSVAL(outbuf, smb_vwv3, 0);
237 if (server_info->guest) {
238 SSVAL(outbuf,smb_vwv2,1);
241 SSVAL(outbuf, smb_uid, sess_vuid);
243 if (!server_info->guest) {
244 /* We need to start the signing engine
245 * here but a W2K client sends the old
246 * "BSRSPYL " signature instead of the
247 * correct one. Subsequent packets will
250 srv_check_sign_mac(inbuf);
254 /* wrap that up in a nice GSS-API wrapping */
255 if (NT_STATUS_IS_OK(ret)) {
256 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
258 ap_rep_wrapped = data_blob(NULL, 0);
260 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
261 reply_sesssetup_blob(conn, outbuf, response, ret);
263 data_blob_free(&ap_rep);
264 data_blob_free(&ap_rep_wrapped);
265 data_blob_free(&response);
267 return -1; /* already replied */
271 /****************************************************************************
272 Send a session setup reply, wrapped in SPNEGO.
273 Get vuid and check first.
274 End the NTLMSSP exchange context if we are OK/complete fail
275 ***************************************************************************/
277 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
278 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
279 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status)
283 struct auth_serversupplied_info *server_info = NULL;
285 if (NT_STATUS_IS_OK(nt_status)) {
286 server_info = (*auth_ntlmssp_state)->server_info;
288 nt_status = do_map_to_guest(nt_status,
290 (*auth_ntlmssp_state)->ntlmssp_state->user,
291 (*auth_ntlmssp_state)->ntlmssp_state->domain);
294 if (NT_STATUS_IS_OK(nt_status)) {
296 DATA_BLOB nullblob = data_blob(NULL, 0);
297 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
299 /* register_vuid keeps the server info */
300 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
301 (*auth_ntlmssp_state)->server_info = NULL;
303 if (sess_vuid == -1) {
304 nt_status = NT_STATUS_LOGON_FAILURE;
307 set_message(outbuf,4,0,True);
308 SSVAL(outbuf, smb_vwv3, 0);
310 if (server_info->guest) {
311 SSVAL(outbuf,smb_vwv2,1);
314 SSVAL(outbuf,smb_uid,sess_vuid);
316 if (!server_info->guest) {
317 /* We need to start the signing engine
318 * here but a W2K client sends the old
319 * "BSRSPYL " signature instead of the
320 * correct one. Subsequent packets will
323 srv_check_sign_mac(inbuf);
328 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
329 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
330 data_blob_free(&response);
332 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
333 and the other end, that we are not finished yet. */
335 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
336 auth_ntlmssp_end(auth_ntlmssp_state);
342 /****************************************************************************
343 Reply to a session setup spnego negotiate packet.
344 ****************************************************************************/
346 static int reply_spnego_negotiate(connection_struct *conn,
349 int length, int bufsize,
352 char *OIDs[ASN1_MAX_OIDS];
356 BOOL got_kerberos = False;
359 /* parse out the OIDs and the first sec blob */
360 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
361 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
364 /* only look at the first OID for determining the mechToken --
365 accoirding to RFC2478, we should choose the one we want
366 and renegotiate, but i smell a client bug here..
368 Problem observed when connecting to a member (samba box)
369 of an AD domain as a user in a Samba domain. Samba member
370 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
371 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
372 NTLMSSP mechtoken. --jerry */
374 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
375 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
379 for (i=0;OIDs[i];i++) {
380 DEBUG(3,("Got OID %s\n", OIDs[i]));
383 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
386 if (got_kerberos && (SEC_ADS == lp_security())) {
387 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
388 length, bufsize, &secblob);
389 data_blob_free(&secblob);
394 if (global_ntlmssp_state) {
395 auth_ntlmssp_end(&global_ntlmssp_state);
398 nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
399 if (!NT_STATUS_IS_OK(nt_status)) {
400 return ERROR_NT(nt_status);
403 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
406 data_blob_free(&secblob);
408 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
411 data_blob_free(&chal);
413 /* already replied */
417 /****************************************************************************
418 Reply to a session setup spnego auth packet.
419 ****************************************************************************/
421 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
422 int length, int bufsize,
425 DATA_BLOB auth, auth_reply;
426 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
428 if (!spnego_parse_auth(blob1, &auth)) {
430 file_save("auth.dat", blob1.data, blob1.length);
432 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
435 if (!global_ntlmssp_state) {
436 /* auth before negotiatiate? */
437 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
440 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
443 data_blob_free(&auth);
445 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
446 &auth_reply, nt_status);
448 data_blob_free(&auth_reply);
450 /* and tell smbd that we have already replied to this packet */
454 /****************************************************************************
455 Reply to a session setup command.
456 ****************************************************************************/
458 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
460 int length,int bufsize)
466 fstring native_os, native_lanman, primary_domain;
468 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
469 enum remote_arch_types ra_type = get_remote_arch();
471 DEBUG(3,("Doing spnego session setup\n"));
473 if (global_client_caps == 0) {
474 global_client_caps = IVAL(inbuf,smb_vwv10);
476 if (!(global_client_caps & CAP_STATUS32)) {
477 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
482 p = (uint8 *)smb_buf(inbuf);
484 if (data_blob_len == 0) {
485 /* an invalid request */
486 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
489 bufrem = smb_bufrem(inbuf, p);
490 /* pull the spnego blob */
491 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
494 file_save("negotiate.dat", blob1.data, blob1.length);
497 p2 = inbuf + smb_vwv13 + data_blob_len;
498 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
499 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
500 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
501 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
502 native_os, native_lanman, primary_domain));
504 if ( ra_type == RA_WIN2K ) {
505 /* Windows 2003 doesn't set the native lanman string,
506 but does set primary domain which is a bug I think */
508 if ( !strlen(native_lanman) )
509 ra_lanman_string( primary_domain );
511 ra_lanman_string( native_lanman );
514 if (blob1.data[0] == ASN1_APPLICATION(0)) {
515 /* its a negTokenTarg packet */
516 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
517 data_blob_free(&blob1);
521 if (blob1.data[0] == ASN1_CONTEXT(1)) {
522 /* its a auth packet */
523 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
524 data_blob_free(&blob1);
528 /* what sort of packet is this? */
529 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
531 data_blob_free(&blob1);
533 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
536 /****************************************************************************
537 On new VC == 0, shutdown *all* old connections and users.
538 It seems that only NT4.x does this. At W2K and above (XP etc.).
539 a new session setup with VC==0 is ignored.
540 ****************************************************************************/
542 static void setup_new_vc_session(void)
544 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
547 invalidate_all_vuids();
551 /****************************************************************************
552 Reply to a session setup command.
553 ****************************************************************************/
555 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
556 int length,int bufsize)
562 DATA_BLOB plaintext_password;
564 fstring sub_user; /* Sainitised username for substituion */
567 fstring native_lanman;
568 fstring primary_domain;
569 static BOOL done_sesssetup = False;
570 extern BOOL global_encrypted_passwords_negotiated;
571 extern BOOL global_spnego_negotiated;
575 auth_usersupplied_info *user_info = NULL;
576 extern struct auth_context *negprot_global_auth_context;
577 auth_serversupplied_info *server_info = NULL;
581 BOOL doencrypt = global_encrypted_passwords_negotiated;
583 DATA_BLOB session_key;
585 START_PROFILE(SMBsesssetupX);
587 ZERO_STRUCT(lm_resp);
588 ZERO_STRUCT(nt_resp);
589 ZERO_STRUCT(plaintext_password);
591 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
593 /* a SPNEGO session setup has 12 command words, whereas a normal
594 NT1 session setup has 13. See the cifs spec. */
595 if (CVAL(inbuf, smb_wct) == 12 &&
596 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
597 if (!global_spnego_negotiated) {
598 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
599 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
602 if (SVAL(inbuf,smb_vwv4) == 0) {
603 setup_new_vc_session();
605 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
608 smb_bufsize = SVAL(inbuf,smb_vwv2);
610 if (Protocol < PROTOCOL_NT1) {
611 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
612 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
613 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
617 lm_resp = data_blob(smb_buf(inbuf), passlen1);
619 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
620 /* Ensure null termination */
621 plaintext_password.data[passlen1] = 0;
624 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
628 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
629 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
630 enum remote_arch_types ra_type = get_remote_arch();
631 char *p = smb_buf(inbuf);
632 char *save_p = smb_buf(inbuf);
636 if(global_client_caps == 0) {
637 global_client_caps = IVAL(inbuf,smb_vwv11);
639 if (!(global_client_caps & CAP_STATUS32)) {
640 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
643 /* client_caps is used as final determination if client is NT or Win95.
644 This is needed to return the correct error codes in some
648 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
649 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
650 set_remote_arch( RA_WIN95);
656 /* both Win95 and WinNT stuff up the password lengths for
657 non-encrypting systems. Uggh.
659 if passlen1==24 its a win95 system, and its setting the
660 password length incorrectly. Luckily it still works with the
661 default code because Win95 will null terminate the password
664 if passlen1>0 and passlen2>0 then maybe its a NT box and its
665 setting passlen2 to some random value which really stuffs
666 things up. we need to fix that one. */
668 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
672 /* check for nasty tricks */
673 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
674 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
677 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
678 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
681 /* Save the lanman2 password and the NT md4 password. */
683 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
688 lm_resp = data_blob(p, passlen1);
689 nt_resp = data_blob(p+passlen1, passlen2);
692 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
694 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
695 /* NT4.0 stuffs up plaintext unicode password lengths... */
696 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
697 sizeof(pass), passlen1, STR_TERMINATE);
699 srvstr_pull(inbuf, pass, smb_buf(inbuf),
700 sizeof(pass), unic ? passlen2 : passlen1,
703 plaintext_password = data_blob(pass, strlen(pass)+1);
706 p += passlen1 + passlen2;
707 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
708 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
709 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
710 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
712 /* not documented or decoded by Ethereal but there is one more string
713 in the extra bytes which is the same as the PrimaryDomain when using
714 extended security. Windows NT 4 and 2003 use this string to store
715 the native lanman string. Windows 9x does not include a string here
716 at all so we have to check if we have any extra bytes left */
718 byte_count = SVAL(inbuf, smb_vwv13);
719 if ( PTR_DIFF(p, save_p) < byte_count)
720 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
722 fstrcpy( primary_domain, "null" );
724 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
725 domain, native_os, native_lanman, primary_domain));
727 if ( ra_type == RA_WIN2K ) {
728 if ( strlen(native_lanman) == 0 )
729 ra_lanman_string( primary_domain );
731 ra_lanman_string( native_lanman );
736 if (SVAL(inbuf,smb_vwv4) == 0) {
737 setup_new_vc_session();
740 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
743 if (global_spnego_negotiated) {
745 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
747 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
748 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
750 fstrcpy(sub_user, user);
752 /* setup the string used by %U */
753 sub_set_smb_name(user);
755 fstrcpy(sub_user, lp_guestaccount());
758 sub_set_smb_name(sub_user);
760 reload_services(True);
762 if (lp_security() == SEC_SHARE) {
763 /* in share level we should ignore any passwords */
765 data_blob_free(&lm_resp);
766 data_blob_free(&nt_resp);
767 data_blob_clear_free(&plaintext_password);
769 map_username(sub_user);
770 add_session_user(sub_user);
771 /* Then force it to null for the benfit of the code below */
777 nt_status = check_guest_password(&server_info);
779 } else if (doencrypt) {
780 if (!negprot_global_auth_context) {
781 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
782 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
784 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
786 if (NT_STATUS_IS_OK(nt_status)) {
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 if (!NT_STATUS_IS_OK(nt_status)) {
816 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
819 if (!NT_STATUS_IS_OK(nt_status)) {
820 data_blob_free(&nt_resp);
821 data_blob_free(&lm_resp);
822 data_blob_clear_free(&plaintext_password);
823 return ERROR_NT(nt_status_squash(nt_status));
826 if (server_info->nt_session_key.data) {
827 session_key = data_blob(server_info->nt_session_key.data, server_info->nt_session_key.length);
828 } else if (server_info->lm_session_key.length >= 8 && lm_resp.length == 24) {
829 session_key = data_blob(NULL, 16);
830 SMBsesskeygen_lmv1(server_info->lm_session_key.data, lm_resp.data,
834 data_blob_free(&lm_resp);
835 data_blob_clear_free(&plaintext_password);
837 /* it's ok - setup a reply */
838 set_message(outbuf,3,0,True);
839 if (Protocol >= PROTOCOL_NT1) {
840 char *p = smb_buf( outbuf );
841 p += add_signature( outbuf, p );
842 set_message_end( outbuf, p );
843 /* perhaps grab OS version here?? */
846 if (server_info->guest) {
847 SSVAL(outbuf,smb_vwv2,1);
850 /* register the name and uid as being validated, so further connections
851 to a uid can get through without a password, on the same VC */
853 /* register_vuid keeps the server info */
854 sess_vuid = register_vuid(server_info, session_key, nt_resp, sub_user);
855 data_blob_free(&nt_resp);
857 if (sess_vuid == -1) {
858 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
861 if (!server_info->guest && !srv_check_sign_mac(inbuf)) {
862 exit_server("reply_sesssetup_and_X: bad smb signature");
865 SSVAL(outbuf,smb_uid,sess_vuid);
866 SSVAL(inbuf,smb_uid,sess_vuid);
869 max_send = MIN(max_send,smb_bufsize);
871 done_sesssetup = True;
873 END_PROFILE(SMBsesssetupX);
874 return chain_reply(inbuf,outbuf,length,bufsize);