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,
144 char *client, *p, *domain;
145 fstring netbios_domain_name;
151 DATA_BLOB ap_rep, ap_rep_wrapped, response;
152 auth_serversupplied_info *server_info = NULL;
153 DATA_BLOB session_key;
155 BOOL foreign = False;
156 DATA_BLOB nullblob = data_blob(NULL, 0);
157 fstring real_username;
160 ZERO_STRUCT(auth_data);
162 ZERO_STRUCT(ap_rep_wrapped);
163 ZERO_STRUCT(response);
165 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
166 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
169 ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, &session_key);
171 data_blob_free(&ticket);
173 if (!NT_STATUS_IS_OK(ret)) {
174 DEBUG(1,("Failed to verify incoming ticket!\n"));
175 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
178 data_blob_free(&auth_data);
180 DEBUG(3,("Ticket name is [%s]\n", client));
182 p = strchr_m(client, '@');
184 DEBUG(3,("Doesn't look like a valid principal\n"));
185 data_blob_free(&ap_rep);
187 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
191 if (!strequal(p+1, lp_realm())) {
192 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
193 if (!lp_allow_trusted_domains()) {
194 data_blob_free(&ap_rep);
196 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
201 /* this gives a fully qualified user name (ie. with full realm).
202 that leads to very long usernames, but what else can we do? */
207 /* If we have winbind running, we can (and must) shorten the
208 username by using the short netbios name. Otherwise we will
209 have inconsistent user names. With Kerberos, we get the
210 fully qualified realm, with ntlmssp we get the short
211 name. And even w2k3 does use ntlmssp if you for example
212 connect to an ip address. */
214 struct winbindd_request wb_request;
215 struct winbindd_response wb_response;
216 NSS_STATUS wb_result;
218 ZERO_STRUCT(wb_request);
219 ZERO_STRUCT(wb_response);
221 DEBUG(10, ("Mapping [%s] to short name\n", domain));
223 fstrcpy(wb_request.domain_name, domain);
225 wb_result = winbindd_request(WINBINDD_DOMAIN_INFO,
226 &wb_request, &wb_response);
228 if (wb_result == NSS_STATUS_SUCCESS) {
230 fstrcpy(netbios_domain_name,
231 wb_response.data.domain_info.name);
232 domain = netbios_domain_name;
234 DEBUG(10, ("Mapped to [%s]\n", domain));
236 DEBUG(3, ("Could not find short name -- winbind "
241 asprintf(&user, "%s%c%s", domain, *lp_winbind_separator(), client);
243 /* lookup the passwd struct, create a new user if necessary */
245 pw = smb_getpwnam( user, real_username, True );
248 DEBUG(1,("Username %s is invalid on this system\n",user));
251 data_blob_free(&ap_rep);
252 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
255 /* setup the string used by %U */
257 sub_set_smb_name( real_username );
258 reload_services(True);
260 if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info, real_username, pw)))
262 DEBUG(1,("make_server_info_from_pw failed!\n"));
265 data_blob_free(&ap_rep);
266 return ERROR_NT(ret);
269 /* make_server_info_pw does not set the domain. Without this we end up
270 * with the local netbios name in substitutions for %D. */
272 if (server_info->sam_account != NULL) {
273 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
276 /* register_vuid keeps the server info */
277 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
282 if (sess_vuid == -1) {
283 ret = NT_STATUS_LOGON_FAILURE;
285 set_message(outbuf,4,0,True);
286 SSVAL(outbuf, smb_vwv3, 0);
288 if (server_info->guest) {
289 SSVAL(outbuf,smb_vwv2,1);
292 SSVAL(outbuf, smb_uid, sess_vuid);
294 if (!server_info->guest) {
295 /* We need to start the signing engine
296 * here but a W2K client sends the old
297 * "BSRSPYL " signature instead of the
298 * correct one. Subsequent packets will
301 srv_check_sign_mac(inbuf);
305 /* wrap that up in a nice GSS-API wrapping */
306 if (NT_STATUS_IS_OK(ret)) {
307 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
309 ap_rep_wrapped = data_blob(NULL, 0);
311 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
312 reply_sesssetup_blob(conn, outbuf, response, ret);
314 data_blob_free(&ap_rep);
315 data_blob_free(&ap_rep_wrapped);
316 data_blob_free(&response);
318 return -1; /* already replied */
322 /****************************************************************************
323 Send a session setup reply, wrapped in SPNEGO.
324 Get vuid and check first.
325 End the NTLMSSP exchange context if we are OK/complete fail
326 ***************************************************************************/
328 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
329 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
330 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status)
334 struct auth_serversupplied_info *server_info = NULL;
336 if (NT_STATUS_IS_OK(nt_status)) {
337 server_info = (*auth_ntlmssp_state)->server_info;
339 nt_status = do_map_to_guest(nt_status,
341 (*auth_ntlmssp_state)->ntlmssp_state->user,
342 (*auth_ntlmssp_state)->ntlmssp_state->domain);
345 if (NT_STATUS_IS_OK(nt_status)) {
347 DATA_BLOB nullblob = data_blob(NULL, 0);
348 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
350 /* register_vuid keeps the server info */
351 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
352 (*auth_ntlmssp_state)->server_info = NULL;
354 if (sess_vuid == -1) {
355 nt_status = NT_STATUS_LOGON_FAILURE;
358 set_message(outbuf,4,0,True);
359 SSVAL(outbuf, smb_vwv3, 0);
361 if (server_info->guest) {
362 SSVAL(outbuf,smb_vwv2,1);
365 SSVAL(outbuf,smb_uid,sess_vuid);
367 if (!server_info->guest) {
368 /* We need to start the signing engine
369 * here but a W2K client sends the old
370 * "BSRSPYL " signature instead of the
371 * correct one. Subsequent packets will
374 srv_check_sign_mac(inbuf);
379 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
380 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
381 data_blob_free(&response);
383 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
384 and the other end, that we are not finished yet. */
386 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
387 auth_ntlmssp_end(auth_ntlmssp_state);
393 /****************************************************************************
394 Reply to a session setup spnego negotiate packet.
395 ****************************************************************************/
397 static int reply_spnego_negotiate(connection_struct *conn,
400 int length, int bufsize,
403 char *OIDs[ASN1_MAX_OIDS];
407 BOOL got_kerberos = False;
410 /* parse out the OIDs and the first sec blob */
411 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
412 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
415 /* only look at the first OID for determining the mechToken --
416 accoirding to RFC2478, we should choose the one we want
417 and renegotiate, but i smell a client bug here..
419 Problem observed when connecting to a member (samba box)
420 of an AD domain as a user in a Samba domain. Samba member
421 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
422 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
423 NTLMSSP mechtoken. --jerry */
425 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
426 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
430 for (i=0;OIDs[i];i++) {
431 DEBUG(3,("Got OID %s\n", OIDs[i]));
434 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
437 if (got_kerberos && (SEC_ADS == lp_security())) {
438 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
439 length, bufsize, &secblob);
440 data_blob_free(&secblob);
445 if (global_ntlmssp_state) {
446 auth_ntlmssp_end(&global_ntlmssp_state);
449 nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
450 if (!NT_STATUS_IS_OK(nt_status)) {
451 return ERROR_NT(nt_status);
454 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
457 data_blob_free(&secblob);
459 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
462 data_blob_free(&chal);
464 /* already replied */
468 /****************************************************************************
469 Reply to a session setup spnego auth packet.
470 ****************************************************************************/
472 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
473 int length, int bufsize,
476 DATA_BLOB auth, auth_reply;
477 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
479 if (!spnego_parse_auth(blob1, &auth)) {
481 file_save("auth.dat", blob1.data, blob1.length);
483 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
486 if (!global_ntlmssp_state) {
487 /* auth before negotiatiate? */
488 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
491 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
494 data_blob_free(&auth);
496 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
497 &auth_reply, nt_status);
499 data_blob_free(&auth_reply);
501 /* and tell smbd that we have already replied to this packet */
505 /****************************************************************************
506 Reply to a session setup command.
507 ****************************************************************************/
509 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
511 int length,int bufsize)
517 fstring native_os, native_lanman, primary_domain;
519 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
520 enum remote_arch_types ra_type = get_remote_arch();
522 DEBUG(3,("Doing spnego session setup\n"));
524 if (global_client_caps == 0) {
525 global_client_caps = IVAL(inbuf,smb_vwv10);
527 if (!(global_client_caps & CAP_STATUS32)) {
528 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
533 p = (uint8 *)smb_buf(inbuf);
535 if (data_blob_len == 0) {
536 /* an invalid request */
537 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
540 bufrem = smb_bufrem(inbuf, p);
541 /* pull the spnego blob */
542 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
545 file_save("negotiate.dat", blob1.data, blob1.length);
548 p2 = inbuf + smb_vwv13 + data_blob_len;
549 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
550 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
551 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
552 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
553 native_os, native_lanman, primary_domain));
555 if ( ra_type == RA_WIN2K ) {
556 /* Windows 2003 doesn't set the native lanman string,
557 but does set primary domain which is a bug I think */
559 if ( !strlen(native_lanman) )
560 ra_lanman_string( primary_domain );
562 ra_lanman_string( native_lanman );
565 if (blob1.data[0] == ASN1_APPLICATION(0)) {
566 /* its a negTokenTarg packet */
567 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
568 data_blob_free(&blob1);
572 if (blob1.data[0] == ASN1_CONTEXT(1)) {
573 /* its a auth packet */
574 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
575 data_blob_free(&blob1);
579 /* what sort of packet is this? */
580 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
582 data_blob_free(&blob1);
584 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
587 /****************************************************************************
588 On new VC == 0, shutdown *all* old connections and users.
589 It seems that only NT4.x does this. At W2K and above (XP etc.).
590 a new session setup with VC==0 is ignored.
591 ****************************************************************************/
593 static void setup_new_vc_session(void)
595 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
598 invalidate_all_vuids();
602 /****************************************************************************
603 Reply to a session setup command.
604 ****************************************************************************/
606 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
607 int length,int bufsize)
613 DATA_BLOB plaintext_password;
615 fstring sub_user; /* Sainitised username for substituion */
618 fstring native_lanman;
619 fstring primary_domain;
620 static BOOL done_sesssetup = False;
621 extern BOOL global_encrypted_passwords_negotiated;
622 extern BOOL global_spnego_negotiated;
626 auth_usersupplied_info *user_info = NULL;
627 extern struct auth_context *negprot_global_auth_context;
628 auth_serversupplied_info *server_info = NULL;
632 BOOL doencrypt = global_encrypted_passwords_negotiated;
634 DATA_BLOB session_key;
636 START_PROFILE(SMBsesssetupX);
638 ZERO_STRUCT(lm_resp);
639 ZERO_STRUCT(nt_resp);
640 ZERO_STRUCT(plaintext_password);
642 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
644 /* a SPNEGO session setup has 12 command words, whereas a normal
645 NT1 session setup has 13. See the cifs spec. */
646 if (CVAL(inbuf, smb_wct) == 12 &&
647 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
648 if (!global_spnego_negotiated) {
649 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
650 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
653 if (SVAL(inbuf,smb_vwv4) == 0) {
654 setup_new_vc_session();
656 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
659 smb_bufsize = SVAL(inbuf,smb_vwv2);
661 if (Protocol < PROTOCOL_NT1) {
662 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
663 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
664 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
668 lm_resp = data_blob(smb_buf(inbuf), passlen1);
670 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
671 /* Ensure null termination */
672 plaintext_password.data[passlen1] = 0;
675 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
679 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
680 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
681 enum remote_arch_types ra_type = get_remote_arch();
682 char *p = smb_buf(inbuf);
683 char *save_p = smb_buf(inbuf);
687 if(global_client_caps == 0) {
688 global_client_caps = IVAL(inbuf,smb_vwv11);
690 if (!(global_client_caps & CAP_STATUS32)) {
691 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
694 /* client_caps is used as final determination if client is NT or Win95.
695 This is needed to return the correct error codes in some
699 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
700 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
701 set_remote_arch( RA_WIN95);
707 /* both Win95 and WinNT stuff up the password lengths for
708 non-encrypting systems. Uggh.
710 if passlen1==24 its a win95 system, and its setting the
711 password length incorrectly. Luckily it still works with the
712 default code because Win95 will null terminate the password
715 if passlen1>0 and passlen2>0 then maybe its a NT box and its
716 setting passlen2 to some random value which really stuffs
717 things up. we need to fix that one. */
719 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
723 /* check for nasty tricks */
724 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
725 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
728 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
729 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
732 /* Save the lanman2 password and the NT md4 password. */
734 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
739 lm_resp = data_blob(p, passlen1);
740 nt_resp = data_blob(p+passlen1, passlen2);
743 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
745 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
746 /* NT4.0 stuffs up plaintext unicode password lengths... */
747 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
748 sizeof(pass), passlen1, STR_TERMINATE);
750 srvstr_pull(inbuf, pass, smb_buf(inbuf),
751 sizeof(pass), unic ? passlen2 : passlen1,
754 plaintext_password = data_blob(pass, strlen(pass)+1);
757 p += passlen1 + passlen2;
758 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
759 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
760 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
761 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
763 /* not documented or decoded by Ethereal but there is one more string
764 in the extra bytes which is the same as the PrimaryDomain when using
765 extended security. Windows NT 4 and 2003 use this string to store
766 the native lanman string. Windows 9x does not include a string here
767 at all so we have to check if we have any extra bytes left */
769 byte_count = SVAL(inbuf, smb_vwv13);
770 if ( PTR_DIFF(p, save_p) < byte_count)
771 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
773 fstrcpy( primary_domain, "null" );
775 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
776 domain, native_os, native_lanman, primary_domain));
778 if ( ra_type == RA_WIN2K ) {
779 if ( strlen(native_lanman) == 0 )
780 ra_lanman_string( primary_domain );
782 ra_lanman_string( native_lanman );
787 if (SVAL(inbuf,smb_vwv4) == 0) {
788 setup_new_vc_session();
791 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
794 if (global_spnego_negotiated) {
796 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
798 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
799 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
801 fstrcpy(sub_user, user);
803 /* setup the string used by %U */
804 sub_set_smb_name(user);
806 fstrcpy(sub_user, lp_guestaccount());
809 sub_set_smb_name(sub_user);
811 reload_services(True);
813 if (lp_security() == SEC_SHARE) {
814 /* in share level we should ignore any passwords */
816 data_blob_free(&lm_resp);
817 data_blob_free(&nt_resp);
818 data_blob_clear_free(&plaintext_password);
820 map_username(sub_user);
821 add_session_user(sub_user);
822 /* Then force it to null for the benfit of the code below */
828 nt_status = check_guest_password(&server_info);
830 } else if (doencrypt) {
831 if (!negprot_global_auth_context) {
832 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
833 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
835 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
837 if (NT_STATUS_IS_OK(nt_status)) {
838 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
843 struct auth_context *plaintext_auth_context = NULL;
845 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
846 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
848 if (!make_user_info_for_reply(&user_info,
850 plaintext_password)) {
851 nt_status = NT_STATUS_NO_MEMORY;
854 if (NT_STATUS_IS_OK(nt_status)) {
855 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
859 (plaintext_auth_context->free)(&plaintext_auth_context);
864 free_user_info(&user_info);
866 if (!NT_STATUS_IS_OK(nt_status)) {
867 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
870 if (!NT_STATUS_IS_OK(nt_status)) {
871 data_blob_free(&nt_resp);
872 data_blob_free(&lm_resp);
873 data_blob_clear_free(&plaintext_password);
874 return ERROR_NT(nt_status_squash(nt_status));
877 if (server_info->nt_session_key.data) {
878 session_key = data_blob(server_info->nt_session_key.data, server_info->nt_session_key.length);
879 } else if (server_info->lm_session_key.length >= 8 && lm_resp.length == 24) {
880 session_key = data_blob(NULL, 16);
881 SMBsesskeygen_lmv1(server_info->lm_session_key.data, lm_resp.data,
884 session_key = data_blob(NULL, 0);
887 data_blob_free(&lm_resp);
888 data_blob_clear_free(&plaintext_password);
890 /* it's ok - setup a reply */
891 set_message(outbuf,3,0,True);
892 if (Protocol >= PROTOCOL_NT1) {
893 char *p = smb_buf( outbuf );
894 p += add_signature( outbuf, p );
895 set_message_end( outbuf, p );
896 /* perhaps grab OS version here?? */
899 if (server_info->guest) {
900 SSVAL(outbuf,smb_vwv2,1);
903 /* register the name and uid as being validated, so further connections
904 to a uid can get through without a password, on the same VC */
906 /* register_vuid keeps the server info */
907 sess_vuid = register_vuid(server_info, session_key, nt_resp, sub_user);
908 data_blob_free(&nt_resp);
910 if (sess_vuid == -1) {
911 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
914 if (!server_info->guest && !srv_check_sign_mac(inbuf)) {
915 exit_server("reply_sesssetup_and_X: bad smb signature");
918 SSVAL(outbuf,smb_uid,sess_vuid);
919 SSVAL(inbuf,smb_uid,sess_vuid);
922 max_send = MIN(max_send,smb_bufsize);
924 done_sesssetup = True;
926 END_PROFILE(SMBsesssetupX);
927 return chain_reply(inbuf,outbuf,length,bufsize);