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 /* current_user_info is changed on new vuid */
286 reload_services( True );
288 set_message(outbuf,4,0,True);
289 SSVAL(outbuf, smb_vwv3, 0);
291 if (server_info->guest) {
292 SSVAL(outbuf,smb_vwv2,1);
295 SSVAL(outbuf, smb_uid, sess_vuid);
297 if (!server_info->guest && !srv_signing_started()) {
298 /* We need to start the signing engine
299 * here but a W2K client sends the old
300 * "BSRSPYL " signature instead of the
301 * correct one. Subsequent packets will
304 srv_check_sign_mac(inbuf, False);
308 /* wrap that up in a nice GSS-API wrapping */
309 if (NT_STATUS_IS_OK(ret)) {
310 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
312 ap_rep_wrapped = data_blob(NULL, 0);
314 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
315 reply_sesssetup_blob(conn, outbuf, response, ret);
317 data_blob_free(&ap_rep);
318 data_blob_free(&ap_rep_wrapped);
319 data_blob_free(&response);
321 return -1; /* already replied */
325 /****************************************************************************
326 Send a session setup reply, wrapped in SPNEGO.
327 Get vuid and check first.
328 End the NTLMSSP exchange context if we are OK/complete fail
329 ***************************************************************************/
331 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
332 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
333 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status)
337 struct auth_serversupplied_info *server_info = NULL;
339 if (NT_STATUS_IS_OK(nt_status)) {
340 server_info = (*auth_ntlmssp_state)->server_info;
342 nt_status = do_map_to_guest(nt_status,
344 (*auth_ntlmssp_state)->ntlmssp_state->user,
345 (*auth_ntlmssp_state)->ntlmssp_state->domain);
348 if (NT_STATUS_IS_OK(nt_status)) {
350 DATA_BLOB nullblob = data_blob(NULL, 0);
351 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
353 /* register_vuid keeps the server info */
354 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
355 (*auth_ntlmssp_state)->server_info = NULL;
357 if (sess_vuid == -1) {
358 nt_status = NT_STATUS_LOGON_FAILURE;
361 /* current_user_info is changed on new vuid */
362 reload_services( True );
364 set_message(outbuf,4,0,True);
365 SSVAL(outbuf, smb_vwv3, 0);
367 if (server_info->guest) {
368 SSVAL(outbuf,smb_vwv2,1);
371 SSVAL(outbuf,smb_uid,sess_vuid);
373 if (!server_info->guest && !srv_signing_started()) {
374 /* We need to start the signing engine
375 * here but a W2K client sends the old
376 * "BSRSPYL " signature instead of the
377 * correct one. Subsequent packets will
381 srv_check_sign_mac(inbuf, False);
386 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
387 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
388 data_blob_free(&response);
390 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
391 and the other end, that we are not finished yet. */
393 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
394 auth_ntlmssp_end(auth_ntlmssp_state);
400 /****************************************************************************
401 Reply to a session setup spnego negotiate packet.
402 ****************************************************************************/
404 static int reply_spnego_negotiate(connection_struct *conn,
407 int length, int bufsize,
410 char *OIDs[ASN1_MAX_OIDS];
414 BOOL got_kerberos = False;
417 /* parse out the OIDs and the first sec blob */
418 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
419 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
422 /* only look at the first OID for determining the mechToken --
423 accoirding to RFC2478, we should choose the one we want
424 and renegotiate, but i smell a client bug here..
426 Problem observed when connecting to a member (samba box)
427 of an AD domain as a user in a Samba domain. Samba member
428 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
429 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
430 NTLMSSP mechtoken. --jerry */
432 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
433 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
437 for (i=0;OIDs[i];i++) {
438 DEBUG(3,("Got OID %s\n", OIDs[i]));
441 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
444 if (got_kerberos && (SEC_ADS == lp_security())) {
445 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
446 length, bufsize, &secblob);
447 data_blob_free(&secblob);
452 if (global_ntlmssp_state) {
453 auth_ntlmssp_end(&global_ntlmssp_state);
456 nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
457 if (!NT_STATUS_IS_OK(nt_status)) {
458 return ERROR_NT(nt_status);
461 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
464 data_blob_free(&secblob);
466 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
469 data_blob_free(&chal);
471 /* already replied */
475 /****************************************************************************
476 Reply to a session setup spnego auth packet.
477 ****************************************************************************/
479 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
480 int length, int bufsize,
483 DATA_BLOB auth, auth_reply;
484 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
486 if (!spnego_parse_auth(blob1, &auth)) {
488 file_save("auth.dat", blob1.data, blob1.length);
490 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
493 if (!global_ntlmssp_state) {
494 /* auth before negotiatiate? */
495 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
498 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
501 data_blob_free(&auth);
503 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
504 &auth_reply, nt_status);
506 data_blob_free(&auth_reply);
508 /* and tell smbd that we have already replied to this packet */
512 /****************************************************************************
513 Reply to a session setup command.
514 ****************************************************************************/
516 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
518 int length,int bufsize)
524 fstring native_os, native_lanman, primary_domain;
526 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
527 enum remote_arch_types ra_type = get_remote_arch();
529 DEBUG(3,("Doing spnego session setup\n"));
531 if (global_client_caps == 0) {
532 global_client_caps = IVAL(inbuf,smb_vwv10);
534 if (!(global_client_caps & CAP_STATUS32)) {
535 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
540 p = (uint8 *)smb_buf(inbuf);
542 if (data_blob_len == 0) {
543 /* an invalid request */
544 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
547 bufrem = smb_bufrem(inbuf, p);
548 /* pull the spnego blob */
549 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
552 file_save("negotiate.dat", blob1.data, blob1.length);
555 p2 = inbuf + smb_vwv13 + data_blob_len;
556 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
557 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
558 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
559 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
560 native_os, native_lanman, primary_domain));
562 if ( ra_type == RA_WIN2K ) {
563 /* Windows 2003 doesn't set the native lanman string,
564 but does set primary domain which is a bug I think */
566 if ( !strlen(native_lanman) )
567 ra_lanman_string( primary_domain );
569 ra_lanman_string( native_lanman );
572 if (blob1.data[0] == ASN1_APPLICATION(0)) {
573 /* its a negTokenTarg packet */
574 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
575 data_blob_free(&blob1);
579 if (blob1.data[0] == ASN1_CONTEXT(1)) {
580 /* its a auth packet */
581 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
582 data_blob_free(&blob1);
586 /* what sort of packet is this? */
587 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
589 data_blob_free(&blob1);
591 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
594 /****************************************************************************
595 On new VC == 0, shutdown *all* old connections and users.
596 It seems that only NT4.x does this. At W2K and above (XP etc.).
597 a new session setup with VC==0 is ignored.
598 ****************************************************************************/
600 static void setup_new_vc_session(void)
602 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
605 invalidate_all_vuids();
609 /****************************************************************************
610 Reply to a session setup command.
611 ****************************************************************************/
613 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
614 int length,int bufsize)
620 DATA_BLOB plaintext_password;
622 fstring sub_user; /* Sainitised username for substituion */
625 fstring native_lanman;
626 fstring primary_domain;
627 static BOOL done_sesssetup = False;
628 extern BOOL global_encrypted_passwords_negotiated;
629 extern BOOL global_spnego_negotiated;
633 auth_usersupplied_info *user_info = NULL;
634 extern struct auth_context *negprot_global_auth_context;
635 auth_serversupplied_info *server_info = NULL;
639 BOOL doencrypt = global_encrypted_passwords_negotiated;
641 DATA_BLOB session_key;
643 START_PROFILE(SMBsesssetupX);
645 ZERO_STRUCT(lm_resp);
646 ZERO_STRUCT(nt_resp);
647 ZERO_STRUCT(plaintext_password);
649 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
651 /* a SPNEGO session setup has 12 command words, whereas a normal
652 NT1 session setup has 13. See the cifs spec. */
653 if (CVAL(inbuf, smb_wct) == 12 &&
654 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
655 if (!global_spnego_negotiated) {
656 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
657 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
660 if (SVAL(inbuf,smb_vwv4) == 0) {
661 setup_new_vc_session();
663 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
666 smb_bufsize = SVAL(inbuf,smb_vwv2);
668 if (Protocol < PROTOCOL_NT1) {
669 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
670 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
671 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
675 lm_resp = data_blob(smb_buf(inbuf), passlen1);
677 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
678 /* Ensure null termination */
679 plaintext_password.data[passlen1] = 0;
682 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
686 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
687 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
688 enum remote_arch_types ra_type = get_remote_arch();
689 char *p = smb_buf(inbuf);
690 char *save_p = smb_buf(inbuf);
694 if(global_client_caps == 0) {
695 global_client_caps = IVAL(inbuf,smb_vwv11);
697 if (!(global_client_caps & CAP_STATUS32)) {
698 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
701 /* client_caps is used as final determination if client is NT or Win95.
702 This is needed to return the correct error codes in some
706 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
707 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
708 set_remote_arch( RA_WIN95);
714 /* both Win95 and WinNT stuff up the password lengths for
715 non-encrypting systems. Uggh.
717 if passlen1==24 its a win95 system, and its setting the
718 password length incorrectly. Luckily it still works with the
719 default code because Win95 will null terminate the password
722 if passlen1>0 and passlen2>0 then maybe its a NT box and its
723 setting passlen2 to some random value which really stuffs
724 things up. we need to fix that one. */
726 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
730 /* check for nasty tricks */
731 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
732 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
735 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
736 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
739 /* Save the lanman2 password and the NT md4 password. */
741 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
746 lm_resp = data_blob(p, passlen1);
747 nt_resp = data_blob(p+passlen1, passlen2);
750 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
752 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
753 /* NT4.0 stuffs up plaintext unicode password lengths... */
754 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
755 sizeof(pass), passlen1, STR_TERMINATE);
757 srvstr_pull(inbuf, pass, smb_buf(inbuf),
758 sizeof(pass), unic ? passlen2 : passlen1,
761 plaintext_password = data_blob(pass, strlen(pass)+1);
764 p += passlen1 + passlen2;
765 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
766 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
767 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
768 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
770 /* not documented or decoded by Ethereal but there is one more string
771 in the extra bytes which is the same as the PrimaryDomain when using
772 extended security. Windows NT 4 and 2003 use this string to store
773 the native lanman string. Windows 9x does not include a string here
774 at all so we have to check if we have any extra bytes left */
776 byte_count = SVAL(inbuf, smb_vwv13);
777 if ( PTR_DIFF(p, save_p) < byte_count)
778 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
780 fstrcpy( primary_domain, "null" );
782 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
783 domain, native_os, native_lanman, primary_domain));
785 if ( ra_type == RA_WIN2K ) {
786 if ( strlen(native_lanman) == 0 )
787 ra_lanman_string( primary_domain );
789 ra_lanman_string( native_lanman );
794 if (SVAL(inbuf,smb_vwv4) == 0) {
795 setup_new_vc_session();
798 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
801 if (global_spnego_negotiated) {
803 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
805 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
806 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
808 fstrcpy(sub_user, user);
810 /* setup the string used by %U */
811 sub_set_smb_name(user);
813 fstrcpy(sub_user, lp_guestaccount());
816 sub_set_smb_name(sub_user);
818 reload_services(True);
820 if (lp_security() == SEC_SHARE) {
821 /* in share level we should ignore any passwords */
823 data_blob_free(&lm_resp);
824 data_blob_free(&nt_resp);
825 data_blob_clear_free(&plaintext_password);
827 map_username(sub_user);
828 add_session_user(sub_user);
829 /* Then force it to null for the benfit of the code below */
835 nt_status = check_guest_password(&server_info);
837 } else if (doencrypt) {
838 if (!negprot_global_auth_context) {
839 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
840 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
842 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
844 if (NT_STATUS_IS_OK(nt_status)) {
845 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
850 struct auth_context *plaintext_auth_context = NULL;
852 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
853 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
855 if (!make_user_info_for_reply(&user_info,
857 plaintext_password)) {
858 nt_status = NT_STATUS_NO_MEMORY;
861 if (NT_STATUS_IS_OK(nt_status)) {
862 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
866 (plaintext_auth_context->free)(&plaintext_auth_context);
871 free_user_info(&user_info);
873 if (!NT_STATUS_IS_OK(nt_status)) {
874 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
877 if (!NT_STATUS_IS_OK(nt_status)) {
878 data_blob_free(&nt_resp);
879 data_blob_free(&lm_resp);
880 data_blob_clear_free(&plaintext_password);
881 return ERROR_NT(nt_status_squash(nt_status));
884 if (server_info->nt_session_key.data) {
885 session_key = data_blob(server_info->nt_session_key.data, server_info->nt_session_key.length);
886 } else if (server_info->lm_session_key.length >= 8 && lm_resp.length == 24) {
887 session_key = data_blob(NULL, 16);
888 SMBsesskeygen_lmv1(server_info->lm_session_key.data, lm_resp.data,
891 session_key = data_blob(NULL, 0);
894 data_blob_free(&lm_resp);
895 data_blob_clear_free(&plaintext_password);
897 /* it's ok - setup a reply */
898 set_message(outbuf,3,0,True);
899 if (Protocol >= PROTOCOL_NT1) {
900 char *p = smb_buf( outbuf );
901 p += add_signature( outbuf, p );
902 set_message_end( outbuf, p );
903 /* perhaps grab OS version here?? */
906 if (server_info->guest) {
907 SSVAL(outbuf,smb_vwv2,1);
910 /* register the name and uid as being validated, so further connections
911 to a uid can get through without a password, on the same VC */
913 /* register_vuid keeps the server info */
914 sess_vuid = register_vuid(server_info, session_key, nt_resp, sub_user);
915 data_blob_free(&nt_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);