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 map_username( user );
247 pw = smb_getpwnam( user, real_username, True );
250 DEBUG(1,("Username %s is invalid on this system\n",user));
253 data_blob_free(&ap_rep);
254 data_blob_free(&session_key);
255 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
258 /* setup the string used by %U */
260 sub_set_smb_name( real_username );
261 reload_services(True);
263 if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info, real_username, pw)))
265 DEBUG(1,("make_server_info_from_pw failed!\n"));
268 data_blob_free(&ap_rep);
269 data_blob_free(&session_key);
270 return ERROR_NT(ret);
273 /* make_server_info_pw does not set the domain. Without this we end up
274 * with the local netbios name in substitutions for %D. */
276 if (server_info->sam_account != NULL) {
277 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
280 /* register_vuid keeps the server info */
281 /* register_vuid takes ownership of session_key, no need to free after this.
282 A better interface would copy it.... */
283 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
288 if (sess_vuid == -1) {
289 ret = NT_STATUS_LOGON_FAILURE;
291 /* current_user_info is changed on new vuid */
292 reload_services( True );
294 set_message(outbuf,4,0,True);
295 SSVAL(outbuf, smb_vwv3, 0);
297 if (server_info->guest) {
298 SSVAL(outbuf,smb_vwv2,1);
301 SSVAL(outbuf, smb_uid, sess_vuid);
303 if (!server_info->guest && !srv_signing_started()) {
304 /* We need to start the signing engine
305 * here but a W2K client sends the old
306 * "BSRSPYL " signature instead of the
307 * correct one. Subsequent packets will
310 srv_check_sign_mac(inbuf, False);
314 /* wrap that up in a nice GSS-API wrapping */
315 if (NT_STATUS_IS_OK(ret)) {
316 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
318 ap_rep_wrapped = data_blob(NULL, 0);
320 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
321 reply_sesssetup_blob(conn, outbuf, response, ret);
323 data_blob_free(&ap_rep);
324 data_blob_free(&ap_rep_wrapped);
325 data_blob_free(&response);
327 return -1; /* already replied */
331 /****************************************************************************
332 Send a session setup reply, wrapped in SPNEGO.
333 Get vuid and check first.
334 End the NTLMSSP exchange context if we are OK/complete fail
335 ***************************************************************************/
337 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
338 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
339 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status)
343 struct auth_serversupplied_info *server_info = NULL;
345 if (NT_STATUS_IS_OK(nt_status)) {
346 server_info = (*auth_ntlmssp_state)->server_info;
348 nt_status = do_map_to_guest(nt_status,
350 (*auth_ntlmssp_state)->ntlmssp_state->user,
351 (*auth_ntlmssp_state)->ntlmssp_state->domain);
354 if (NT_STATUS_IS_OK(nt_status)) {
356 DATA_BLOB nullblob = data_blob(NULL, 0);
357 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
359 /* register_vuid keeps the server info */
360 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
361 (*auth_ntlmssp_state)->server_info = NULL;
363 if (sess_vuid == -1) {
364 nt_status = NT_STATUS_LOGON_FAILURE;
367 /* current_user_info is changed on new vuid */
368 reload_services( True );
370 set_message(outbuf,4,0,True);
371 SSVAL(outbuf, smb_vwv3, 0);
373 if (server_info->guest) {
374 SSVAL(outbuf,smb_vwv2,1);
377 SSVAL(outbuf,smb_uid,sess_vuid);
379 if (!server_info->guest && !srv_signing_started()) {
380 /* We need to start the signing engine
381 * here but a W2K client sends the old
382 * "BSRSPYL " signature instead of the
383 * correct one. Subsequent packets will
387 srv_check_sign_mac(inbuf, False);
392 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
393 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
394 data_blob_free(&response);
396 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
397 and the other end, that we are not finished yet. */
399 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
400 auth_ntlmssp_end(auth_ntlmssp_state);
406 /****************************************************************************
407 Reply to a session setup spnego negotiate packet.
408 ****************************************************************************/
410 static int reply_spnego_negotiate(connection_struct *conn,
413 int length, int bufsize,
416 char *OIDs[ASN1_MAX_OIDS];
420 BOOL got_kerberos = False;
423 /* parse out the OIDs and the first sec blob */
424 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
425 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
428 /* only look at the first OID for determining the mechToken --
429 accoirding to RFC2478, we should choose the one we want
430 and renegotiate, but i smell a client bug here..
432 Problem observed when connecting to a member (samba box)
433 of an AD domain as a user in a Samba domain. Samba member
434 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
435 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
436 NTLMSSP mechtoken. --jerry */
438 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
439 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
443 for (i=0;OIDs[i];i++) {
444 DEBUG(3,("Got OID %s\n", OIDs[i]));
447 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
450 if (got_kerberos && (SEC_ADS == lp_security())) {
451 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
452 length, bufsize, &secblob);
453 data_blob_free(&secblob);
458 if (global_ntlmssp_state) {
459 auth_ntlmssp_end(&global_ntlmssp_state);
462 nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
463 if (!NT_STATUS_IS_OK(nt_status)) {
464 return ERROR_NT(nt_status);
467 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
470 data_blob_free(&secblob);
472 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
475 data_blob_free(&chal);
477 /* already replied */
481 /****************************************************************************
482 Reply to a session setup spnego auth packet.
483 ****************************************************************************/
485 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
486 int length, int bufsize,
489 DATA_BLOB auth, auth_reply;
490 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
492 if (!spnego_parse_auth(blob1, &auth)) {
494 file_save("auth.dat", blob1.data, blob1.length);
496 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
499 if (!global_ntlmssp_state) {
500 /* auth before negotiatiate? */
501 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
504 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
507 data_blob_free(&auth);
509 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
510 &auth_reply, nt_status);
512 data_blob_free(&auth_reply);
514 /* and tell smbd that we have already replied to this packet */
518 /****************************************************************************
519 Reply to a session setup command.
520 ****************************************************************************/
522 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
524 int length,int bufsize)
530 fstring native_os, native_lanman, primary_domain;
532 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
533 enum remote_arch_types ra_type = get_remote_arch();
535 DEBUG(3,("Doing spnego session setup\n"));
537 if (global_client_caps == 0) {
538 global_client_caps = IVAL(inbuf,smb_vwv10);
540 if (!(global_client_caps & CAP_STATUS32)) {
541 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
546 p = (uint8 *)smb_buf(inbuf);
548 if (data_blob_len == 0) {
549 /* an invalid request */
550 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
553 bufrem = smb_bufrem(inbuf, p);
554 /* pull the spnego blob */
555 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
558 file_save("negotiate.dat", blob1.data, blob1.length);
561 p2 = inbuf + smb_vwv13 + data_blob_len;
562 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
563 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
564 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
565 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
566 native_os, native_lanman, primary_domain));
568 if ( ra_type == RA_WIN2K ) {
569 /* Windows 2003 doesn't set the native lanman string,
570 but does set primary domain which is a bug I think */
572 if ( !strlen(native_lanman) )
573 ra_lanman_string( primary_domain );
575 ra_lanman_string( native_lanman );
578 if (blob1.data[0] == ASN1_APPLICATION(0)) {
579 /* its a negTokenTarg packet */
580 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
581 data_blob_free(&blob1);
585 if (blob1.data[0] == ASN1_CONTEXT(1)) {
586 /* its a auth packet */
587 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
588 data_blob_free(&blob1);
592 /* what sort of packet is this? */
593 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
595 data_blob_free(&blob1);
597 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
600 /****************************************************************************
601 On new VC == 0, shutdown *all* old connections and users.
602 It seems that only NT4.x does this. At W2K and above (XP etc.).
603 a new session setup with VC==0 is ignored.
604 ****************************************************************************/
606 static void setup_new_vc_session(void)
608 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
611 invalidate_all_vuids();
615 /****************************************************************************
616 Reply to a session setup command.
617 ****************************************************************************/
619 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
620 int length,int bufsize)
626 DATA_BLOB plaintext_password;
628 fstring sub_user; /* Sainitised username for substituion */
631 fstring native_lanman;
632 fstring primary_domain;
633 static BOOL done_sesssetup = False;
634 extern BOOL global_encrypted_passwords_negotiated;
635 extern BOOL global_spnego_negotiated;
639 auth_usersupplied_info *user_info = NULL;
640 extern struct auth_context *negprot_global_auth_context;
641 auth_serversupplied_info *server_info = NULL;
645 BOOL doencrypt = global_encrypted_passwords_negotiated;
647 DATA_BLOB session_key;
649 START_PROFILE(SMBsesssetupX);
651 ZERO_STRUCT(lm_resp);
652 ZERO_STRUCT(nt_resp);
653 ZERO_STRUCT(plaintext_password);
655 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
657 /* a SPNEGO session setup has 12 command words, whereas a normal
658 NT1 session setup has 13. See the cifs spec. */
659 if (CVAL(inbuf, smb_wct) == 12 &&
660 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
661 if (!global_spnego_negotiated) {
662 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
663 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
666 if (SVAL(inbuf,smb_vwv4) == 0) {
667 setup_new_vc_session();
669 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
672 smb_bufsize = SVAL(inbuf,smb_vwv2);
674 if (Protocol < PROTOCOL_NT1) {
675 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
676 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
677 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
681 lm_resp = data_blob(smb_buf(inbuf), passlen1);
683 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
684 /* Ensure null termination */
685 plaintext_password.data[passlen1] = 0;
688 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
692 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
693 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
694 enum remote_arch_types ra_type = get_remote_arch();
695 char *p = smb_buf(inbuf);
696 char *save_p = smb_buf(inbuf);
700 if(global_client_caps == 0) {
701 global_client_caps = IVAL(inbuf,smb_vwv11);
703 if (!(global_client_caps & CAP_STATUS32)) {
704 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
707 /* client_caps is used as final determination if client is NT or Win95.
708 This is needed to return the correct error codes in some
712 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
713 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
714 set_remote_arch( RA_WIN95);
720 /* both Win95 and WinNT stuff up the password lengths for
721 non-encrypting systems. Uggh.
723 if passlen1==24 its a win95 system, and its setting the
724 password length incorrectly. Luckily it still works with the
725 default code because Win95 will null terminate the password
728 if passlen1>0 and passlen2>0 then maybe its a NT box and its
729 setting passlen2 to some random value which really stuffs
730 things up. we need to fix that one. */
732 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
736 /* check for nasty tricks */
737 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
738 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
741 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
742 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
745 /* Save the lanman2 password and the NT md4 password. */
747 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
752 lm_resp = data_blob(p, passlen1);
753 nt_resp = data_blob(p+passlen1, passlen2);
756 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
758 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
759 /* NT4.0 stuffs up plaintext unicode password lengths... */
760 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
761 sizeof(pass), passlen1, STR_TERMINATE);
763 srvstr_pull(inbuf, pass, smb_buf(inbuf),
764 sizeof(pass), unic ? passlen2 : passlen1,
767 plaintext_password = data_blob(pass, strlen(pass)+1);
770 p += passlen1 + passlen2;
771 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
772 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
773 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
774 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
776 /* not documented or decoded by Ethereal but there is one more string
777 in the extra bytes which is the same as the PrimaryDomain when using
778 extended security. Windows NT 4 and 2003 use this string to store
779 the native lanman string. Windows 9x does not include a string here
780 at all so we have to check if we have any extra bytes left */
782 byte_count = SVAL(inbuf, smb_vwv13);
783 if ( PTR_DIFF(p, save_p) < byte_count)
784 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
786 fstrcpy( primary_domain, "null" );
788 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
789 domain, native_os, native_lanman, primary_domain));
791 if ( ra_type == RA_WIN2K ) {
792 if ( strlen(native_lanman) == 0 )
793 ra_lanman_string( primary_domain );
795 ra_lanman_string( native_lanman );
800 if (SVAL(inbuf,smb_vwv4) == 0) {
801 setup_new_vc_session();
804 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
807 if (global_spnego_negotiated) {
809 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
811 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
812 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
814 fstrcpy(sub_user, user);
816 /* setup the string used by %U */
817 sub_set_smb_name(user);
819 fstrcpy(sub_user, lp_guestaccount());
822 sub_set_smb_name(sub_user);
824 reload_services(True);
826 if (lp_security() == SEC_SHARE) {
827 /* in share level we should ignore any passwords */
829 data_blob_free(&lm_resp);
830 data_blob_free(&nt_resp);
831 data_blob_clear_free(&plaintext_password);
833 map_username(sub_user);
834 add_session_user(sub_user);
835 /* Then force it to null for the benfit of the code below */
841 nt_status = check_guest_password(&server_info);
843 } else if (doencrypt) {
844 if (!negprot_global_auth_context) {
845 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
846 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
848 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
850 if (NT_STATUS_IS_OK(nt_status)) {
851 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
856 struct auth_context *plaintext_auth_context = NULL;
858 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
859 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
861 if (!make_user_info_for_reply(&user_info,
863 plaintext_password)) {
864 nt_status = NT_STATUS_NO_MEMORY;
867 if (NT_STATUS_IS_OK(nt_status)) {
868 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
872 (plaintext_auth_context->free)(&plaintext_auth_context);
877 free_user_info(&user_info);
879 if (!NT_STATUS_IS_OK(nt_status)) {
880 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
883 if (!NT_STATUS_IS_OK(nt_status)) {
884 data_blob_free(&nt_resp);
885 data_blob_free(&lm_resp);
886 data_blob_clear_free(&plaintext_password);
887 return ERROR_NT(nt_status_squash(nt_status));
890 if (server_info->user_session_key.data) {
891 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
893 session_key = data_blob(NULL, 0);
896 data_blob_clear_free(&plaintext_password);
898 /* it's ok - setup a reply */
899 set_message(outbuf,3,0,True);
900 if (Protocol >= PROTOCOL_NT1) {
901 char *p = smb_buf( outbuf );
902 p += add_signature( outbuf, p );
903 set_message_end( outbuf, p );
904 /* perhaps grab OS version here?? */
907 if (server_info->guest) {
908 SSVAL(outbuf,smb_vwv2,1);
911 /* register the name and uid as being validated, so further connections
912 to a uid can get through without a password, on the same VC */
914 /* register_vuid keeps the server info */
915 sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user);
916 data_blob_free(&nt_resp);
917 data_blob_free(&lm_resp);
919 if (sess_vuid == -1) {
920 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
923 /* current_user_info is changed on new vuid */
924 reload_services( True );
926 if (!server_info->guest && !srv_signing_started() && !srv_check_sign_mac(inbuf, True)) {
927 exit_server("reply_sesssetup_and_X: bad smb signature");
930 SSVAL(outbuf,smb_uid,sess_vuid);
931 SSVAL(inbuf,smb_uid,sess_vuid);
934 max_send = MIN(max_send,smb_bufsize);
936 done_sesssetup = True;
938 END_PROFILE(SMBsesssetupX);
939 return chain_reply(inbuf,outbuf,length,bufsize);