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 = data_blob(NULL, 0);
155 DATA_BLOB nullblob = data_blob(NULL, 0);
156 fstring real_username;
159 ZERO_STRUCT(auth_data);
161 ZERO_STRUCT(ap_rep_wrapped);
162 ZERO_STRUCT(response);
164 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
165 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
168 ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, &session_key);
170 data_blob_free(&ticket);
172 if (!NT_STATUS_IS_OK(ret)) {
173 DEBUG(1,("Failed to verify incoming ticket!\n"));
174 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
177 data_blob_free(&auth_data);
179 DEBUG(3,("Ticket name is [%s]\n", client));
181 p = strchr_m(client, '@');
183 DEBUG(3,("Doesn't look like a valid principal\n"));
184 data_blob_free(&ap_rep);
185 data_blob_free(&session_key);
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);
195 data_blob_free(&session_key);
197 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 data_blob_free(&session_key);
253 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
256 /* setup the string used by %U */
258 sub_set_smb_name( real_username );
259 reload_services(True);
261 if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info, real_username, pw)))
263 DEBUG(1,("make_server_info_from_pw failed!\n"));
266 data_blob_free(&ap_rep);
267 data_blob_free(&session_key);
268 return ERROR_NT(ret);
271 /* make_server_info_pw does not set the domain. Without this we end up
272 * with the local netbios name in substitutions for %D. */
274 if (server_info->sam_account != NULL) {
275 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
278 /* register_vuid keeps the server info */
279 /* register_vuid takes ownership of session_key, no need to free after this.
280 A better interface would copy it.... */
281 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
286 if (sess_vuid == -1) {
287 ret = NT_STATUS_LOGON_FAILURE;
289 /* current_user_info is changed on new vuid */
290 reload_services( True );
292 set_message(outbuf,4,0,True);
293 SSVAL(outbuf, smb_vwv3, 0);
295 if (server_info->guest) {
296 SSVAL(outbuf,smb_vwv2,1);
299 SSVAL(outbuf, smb_uid, sess_vuid);
301 if (!server_info->guest && !srv_signing_started()) {
302 /* We need to start the signing engine
303 * here but a W2K client sends the old
304 * "BSRSPYL " signature instead of the
305 * correct one. Subsequent packets will
308 srv_check_sign_mac(inbuf, False);
312 /* wrap that up in a nice GSS-API wrapping */
313 if (NT_STATUS_IS_OK(ret)) {
314 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
316 ap_rep_wrapped = data_blob(NULL, 0);
318 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
319 reply_sesssetup_blob(conn, outbuf, response, ret);
321 data_blob_free(&ap_rep);
322 data_blob_free(&ap_rep_wrapped);
323 data_blob_free(&response);
325 return -1; /* already replied */
329 /****************************************************************************
330 Send a session setup reply, wrapped in SPNEGO.
331 Get vuid and check first.
332 End the NTLMSSP exchange context if we are OK/complete fail
333 ***************************************************************************/
335 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
336 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
337 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status)
341 struct auth_serversupplied_info *server_info = NULL;
343 if (NT_STATUS_IS_OK(nt_status)) {
344 server_info = (*auth_ntlmssp_state)->server_info;
346 nt_status = do_map_to_guest(nt_status,
348 (*auth_ntlmssp_state)->ntlmssp_state->user,
349 (*auth_ntlmssp_state)->ntlmssp_state->domain);
352 if (NT_STATUS_IS_OK(nt_status)) {
354 DATA_BLOB nullblob = data_blob(NULL, 0);
355 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
357 /* register_vuid keeps the server info */
358 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
359 (*auth_ntlmssp_state)->server_info = NULL;
361 if (sess_vuid == -1) {
362 nt_status = NT_STATUS_LOGON_FAILURE;
365 /* current_user_info is changed on new vuid */
366 reload_services( True );
368 set_message(outbuf,4,0,True);
369 SSVAL(outbuf, smb_vwv3, 0);
371 if (server_info->guest) {
372 SSVAL(outbuf,smb_vwv2,1);
375 SSVAL(outbuf,smb_uid,sess_vuid);
377 if (!server_info->guest && !srv_signing_started()) {
378 /* We need to start the signing engine
379 * here but a W2K client sends the old
380 * "BSRSPYL " signature instead of the
381 * correct one. Subsequent packets will
385 srv_check_sign_mac(inbuf, False);
390 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
391 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
392 data_blob_free(&response);
394 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
395 and the other end, that we are not finished yet. */
397 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
398 auth_ntlmssp_end(auth_ntlmssp_state);
404 /****************************************************************************
405 Reply to a session setup spnego negotiate packet.
406 ****************************************************************************/
408 static int reply_spnego_negotiate(connection_struct *conn,
411 int length, int bufsize,
414 char *OIDs[ASN1_MAX_OIDS];
418 BOOL got_kerberos = False;
421 /* parse out the OIDs and the first sec blob */
422 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
423 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
426 /* only look at the first OID for determining the mechToken --
427 accoirding to RFC2478, we should choose the one we want
428 and renegotiate, but i smell a client bug here..
430 Problem observed when connecting to a member (samba box)
431 of an AD domain as a user in a Samba domain. Samba member
432 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
433 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
434 NTLMSSP mechtoken. --jerry */
436 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
437 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
441 for (i=0;OIDs[i];i++) {
442 DEBUG(3,("Got OID %s\n", OIDs[i]));
445 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
448 if (got_kerberos && (SEC_ADS == lp_security())) {
449 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
450 length, bufsize, &secblob);
451 data_blob_free(&secblob);
456 if (global_ntlmssp_state) {
457 auth_ntlmssp_end(&global_ntlmssp_state);
460 nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
461 if (!NT_STATUS_IS_OK(nt_status)) {
462 return ERROR_NT(nt_status);
465 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
468 data_blob_free(&secblob);
470 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
473 data_blob_free(&chal);
475 /* already replied */
479 /****************************************************************************
480 Reply to a session setup spnego auth packet.
481 ****************************************************************************/
483 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
484 int length, int bufsize,
487 DATA_BLOB auth, auth_reply;
488 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
490 if (!spnego_parse_auth(blob1, &auth)) {
492 file_save("auth.dat", blob1.data, blob1.length);
494 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
497 if (!global_ntlmssp_state) {
498 /* auth before negotiatiate? */
499 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
502 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
505 data_blob_free(&auth);
507 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
508 &auth_reply, nt_status);
510 data_blob_free(&auth_reply);
512 /* and tell smbd that we have already replied to this packet */
516 /****************************************************************************
517 Reply to a session setup command.
518 ****************************************************************************/
520 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
522 int length,int bufsize)
528 fstring native_os, native_lanman, primary_domain;
530 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
531 enum remote_arch_types ra_type = get_remote_arch();
533 DEBUG(3,("Doing spnego session setup\n"));
535 if (global_client_caps == 0) {
536 global_client_caps = IVAL(inbuf,smb_vwv10);
538 if (!(global_client_caps & CAP_STATUS32)) {
539 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
544 p = (uint8 *)smb_buf(inbuf);
546 if (data_blob_len == 0) {
547 /* an invalid request */
548 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
551 bufrem = smb_bufrem(inbuf, p);
552 /* pull the spnego blob */
553 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
556 file_save("negotiate.dat", blob1.data, blob1.length);
559 p2 = inbuf + smb_vwv13 + data_blob_len;
560 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
561 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
562 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
563 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
564 native_os, native_lanman, primary_domain));
566 if ( ra_type == RA_WIN2K ) {
567 /* Windows 2003 doesn't set the native lanman string,
568 but does set primary domain which is a bug I think */
570 if ( !strlen(native_lanman) )
571 ra_lanman_string( primary_domain );
573 ra_lanman_string( native_lanman );
576 if (blob1.data[0] == ASN1_APPLICATION(0)) {
577 /* its a negTokenTarg packet */
578 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
579 data_blob_free(&blob1);
583 if (blob1.data[0] == ASN1_CONTEXT(1)) {
584 /* its a auth packet */
585 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
586 data_blob_free(&blob1);
590 /* what sort of packet is this? */
591 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
593 data_blob_free(&blob1);
595 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
598 /****************************************************************************
599 On new VC == 0, shutdown *all* old connections and users.
600 It seems that only NT4.x does this. At W2K and above (XP etc.).
601 a new session setup with VC==0 is ignored.
602 ****************************************************************************/
604 static void setup_new_vc_session(void)
606 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
609 invalidate_all_vuids();
613 /****************************************************************************
614 Reply to a session setup command.
615 ****************************************************************************/
617 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
618 int length,int bufsize)
624 DATA_BLOB plaintext_password;
626 fstring sub_user; /* Sainitised username for substituion */
629 fstring native_lanman;
630 fstring primary_domain;
631 static BOOL done_sesssetup = False;
632 extern BOOL global_encrypted_passwords_negotiated;
633 extern BOOL global_spnego_negotiated;
637 auth_usersupplied_info *user_info = NULL;
638 extern struct auth_context *negprot_global_auth_context;
639 auth_serversupplied_info *server_info = NULL;
643 BOOL doencrypt = global_encrypted_passwords_negotiated;
645 DATA_BLOB session_key;
647 START_PROFILE(SMBsesssetupX);
649 ZERO_STRUCT(lm_resp);
650 ZERO_STRUCT(nt_resp);
651 ZERO_STRUCT(plaintext_password);
653 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
655 /* a SPNEGO session setup has 12 command words, whereas a normal
656 NT1 session setup has 13. See the cifs spec. */
657 if (CVAL(inbuf, smb_wct) == 12 &&
658 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
659 if (!global_spnego_negotiated) {
660 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
661 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
664 if (SVAL(inbuf,smb_vwv4) == 0) {
665 setup_new_vc_session();
667 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
670 smb_bufsize = SVAL(inbuf,smb_vwv2);
672 if (Protocol < PROTOCOL_NT1) {
673 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
674 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
675 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
679 lm_resp = data_blob(smb_buf(inbuf), passlen1);
681 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
682 /* Ensure null termination */
683 plaintext_password.data[passlen1] = 0;
686 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
690 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
691 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
692 enum remote_arch_types ra_type = get_remote_arch();
693 char *p = smb_buf(inbuf);
694 char *save_p = smb_buf(inbuf);
698 if(global_client_caps == 0) {
699 global_client_caps = IVAL(inbuf,smb_vwv11);
701 if (!(global_client_caps & CAP_STATUS32)) {
702 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
705 /* client_caps is used as final determination if client is NT or Win95.
706 This is needed to return the correct error codes in some
710 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
711 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
712 set_remote_arch( RA_WIN95);
718 /* both Win95 and WinNT stuff up the password lengths for
719 non-encrypting systems. Uggh.
721 if passlen1==24 its a win95 system, and its setting the
722 password length incorrectly. Luckily it still works with the
723 default code because Win95 will null terminate the password
726 if passlen1>0 and passlen2>0 then maybe its a NT box and its
727 setting passlen2 to some random value which really stuffs
728 things up. we need to fix that one. */
730 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
734 /* check for nasty tricks */
735 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
736 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
739 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
740 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
743 /* Save the lanman2 password and the NT md4 password. */
745 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
750 lm_resp = data_blob(p, passlen1);
751 nt_resp = data_blob(p+passlen1, passlen2);
754 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
756 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
757 /* NT4.0 stuffs up plaintext unicode password lengths... */
758 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
759 sizeof(pass), passlen1, STR_TERMINATE);
761 srvstr_pull(inbuf, pass, smb_buf(inbuf),
762 sizeof(pass), unic ? passlen2 : passlen1,
765 plaintext_password = data_blob(pass, strlen(pass)+1);
768 p += passlen1 + passlen2;
769 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
770 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
771 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
772 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
774 /* not documented or decoded by Ethereal but there is one more string
775 in the extra bytes which is the same as the PrimaryDomain when using
776 extended security. Windows NT 4 and 2003 use this string to store
777 the native lanman string. Windows 9x does not include a string here
778 at all so we have to check if we have any extra bytes left */
780 byte_count = SVAL(inbuf, smb_vwv13);
781 if ( PTR_DIFF(p, save_p) < byte_count)
782 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
784 fstrcpy( primary_domain, "null" );
786 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
787 domain, native_os, native_lanman, primary_domain));
789 if ( ra_type == RA_WIN2K ) {
790 if ( strlen(native_lanman) == 0 )
791 ra_lanman_string( primary_domain );
793 ra_lanman_string( native_lanman );
798 if (SVAL(inbuf,smb_vwv4) == 0) {
799 setup_new_vc_session();
802 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
805 if (global_spnego_negotiated) {
807 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
809 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
810 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
812 fstrcpy(sub_user, user);
814 /* setup the string used by %U */
815 sub_set_smb_name(user);
817 fstrcpy(sub_user, lp_guestaccount());
820 sub_set_smb_name(sub_user);
822 reload_services(True);
824 if (lp_security() == SEC_SHARE) {
825 /* in share level we should ignore any passwords */
827 data_blob_free(&lm_resp);
828 data_blob_free(&nt_resp);
829 data_blob_clear_free(&plaintext_password);
831 map_username(sub_user);
832 add_session_user(sub_user);
833 /* Then force it to null for the benfit of the code below */
839 nt_status = check_guest_password(&server_info);
841 } else if (doencrypt) {
842 if (!negprot_global_auth_context) {
843 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
844 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
846 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
848 if (NT_STATUS_IS_OK(nt_status)) {
849 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
854 struct auth_context *plaintext_auth_context = NULL;
856 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
857 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
859 if (!make_user_info_for_reply(&user_info,
861 plaintext_password)) {
862 nt_status = NT_STATUS_NO_MEMORY;
865 if (NT_STATUS_IS_OK(nt_status)) {
866 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
870 (plaintext_auth_context->free)(&plaintext_auth_context);
875 free_user_info(&user_info);
877 if (!NT_STATUS_IS_OK(nt_status)) {
878 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
881 if (!NT_STATUS_IS_OK(nt_status)) {
882 data_blob_free(&nt_resp);
883 data_blob_free(&lm_resp);
884 data_blob_clear_free(&plaintext_password);
885 return ERROR_NT(nt_status_squash(nt_status));
888 if (server_info->user_session_key.data) {
889 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
891 session_key = data_blob(NULL, 0);
894 data_blob_clear_free(&plaintext_password);
896 /* it's ok - setup a reply */
897 set_message(outbuf,3,0,True);
898 if (Protocol >= PROTOCOL_NT1) {
899 char *p = smb_buf( outbuf );
900 p += add_signature( outbuf, p );
901 set_message_end( outbuf, p );
902 /* perhaps grab OS version here?? */
905 if (server_info->guest) {
906 SSVAL(outbuf,smb_vwv2,1);
909 /* register the name and uid as being validated, so further connections
910 to a uid can get through without a password, on the same VC */
912 /* register_vuid keeps the server info */
913 sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user);
914 data_blob_free(&nt_resp);
915 data_blob_free(&lm_resp);
917 if (sess_vuid == -1) {
918 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
921 /* current_user_info is changed on new vuid */
922 reload_services( True );
924 if (!server_info->guest && !srv_signing_started() && !srv_check_sign_mac(inbuf, True)) {
925 exit_server("reply_sesssetup_and_X: bad smb signature");
928 SSVAL(outbuf,smb_uid,sess_vuid);
929 SSVAL(inbuf,smb_uid,sess_vuid);
932 max_send = MIN(max_send,smb_bufsize);
934 done_sesssetup = True;
936 END_PROFILE(SMBsesssetupX);
937 return chain_reply(inbuf,outbuf,length,bufsize);