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;
157 BOOL map_domainuser_to_guest = False;
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);
186 data_blob_free(&session_key);
188 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
192 if (!strequal(p+1, lp_realm())) {
193 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
194 if (!lp_allow_trusted_domains()) {
195 data_blob_free(&ap_rep);
196 data_blob_free(&session_key);
198 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
202 /* this gives a fully qualified user name (ie. with full realm).
203 that leads to very long usernames, but what else can we do? */
208 /* If we have winbind running, we can (and must) shorten the
209 username by using the short netbios name. Otherwise we will
210 have inconsistent user names. With Kerberos, we get the
211 fully qualified realm, with ntlmssp we get the short
212 name. And even w2k3 does use ntlmssp if you for example
213 connect to an ip address. */
215 struct winbindd_request wb_request;
216 struct winbindd_response wb_response;
217 NSS_STATUS wb_result;
219 ZERO_STRUCT(wb_request);
220 ZERO_STRUCT(wb_response);
222 DEBUG(10, ("Mapping [%s] to short name\n", domain));
224 fstrcpy(wb_request.domain_name, domain);
226 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
227 &wb_request, &wb_response);
229 if (wb_result == NSS_STATUS_SUCCESS) {
231 fstrcpy(netbios_domain_name,
232 wb_response.data.domain_info.name);
233 domain = netbios_domain_name;
235 DEBUG(10, ("Mapped to [%s]\n", domain));
237 DEBUG(3, ("Could not find short name -- winbind "
242 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
244 /* lookup the passwd struct, create a new user if necessary */
246 map_username( user );
248 pw = smb_getpwnam( user, real_username, True );
251 /* this was originally the behavior of Samba 2.2, if a user
252 did not have a local uid but has been authenticated, then
253 map them to a guest account */
255 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
256 map_domainuser_to_guest = True;
257 fstrcpy(user,lp_guestaccount());
258 pw = smb_getpwnam( user, real_username, True );
261 /* extra sanity check that the guest account is valid */
264 DEBUG(1,("Username %s is invalid on this system\n", user));
266 data_blob_free(&ap_rep);
267 data_blob_free(&session_key);
268 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
272 /* setup the string used by %U */
274 sub_set_smb_name( real_username );
275 reload_services(True);
276 if ( map_domainuser_to_guest ) {
277 make_server_info_guest(&server_info);
279 ret = make_server_info_pw(&server_info, real_username, pw);
280 if ( !NT_STATUS_IS_OK(ret) ) {
281 DEBUG(1,("make_server_info_from_pw failed!\n"));
283 data_blob_free(&ap_rep);
284 data_blob_free(&session_key);
286 return ERROR_NT(ret);
291 /* make_server_info_pw does not set the domain. Without this we end up
292 * with the local netbios name in substitutions for %D. */
294 if (server_info->sam_account != NULL) {
295 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
298 /* register_vuid keeps the server info */
299 /* register_vuid takes ownership of session_key, no need to free after this.
300 A better interface would copy it.... */
301 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
305 if (sess_vuid == -1) {
306 ret = NT_STATUS_LOGON_FAILURE;
308 /* current_user_info is changed on new vuid */
309 reload_services( True );
311 set_message(outbuf,4,0,True);
312 SSVAL(outbuf, smb_vwv3, 0);
314 if (server_info->guest) {
315 SSVAL(outbuf,smb_vwv2,1);
318 SSVAL(outbuf, smb_uid, sess_vuid);
320 if (!server_info->guest && !srv_signing_started()) {
321 /* We need to start the signing engine
322 * here but a W2K client sends the old
323 * "BSRSPYL " signature instead of the
324 * correct one. Subsequent packets will
327 srv_check_sign_mac(inbuf, False);
331 /* wrap that up in a nice GSS-API wrapping */
332 if (NT_STATUS_IS_OK(ret)) {
333 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
335 ap_rep_wrapped = data_blob(NULL, 0);
337 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
338 reply_sesssetup_blob(conn, outbuf, response, ret);
340 data_blob_free(&ap_rep);
341 data_blob_free(&ap_rep_wrapped);
342 data_blob_free(&response);
344 return -1; /* already replied */
348 /****************************************************************************
349 Send a session setup reply, wrapped in SPNEGO.
350 Get vuid and check first.
351 End the NTLMSSP exchange context if we are OK/complete fail
352 ***************************************************************************/
354 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
355 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
356 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status)
360 struct auth_serversupplied_info *server_info = NULL;
362 if (NT_STATUS_IS_OK(nt_status)) {
363 server_info = (*auth_ntlmssp_state)->server_info;
365 nt_status = do_map_to_guest(nt_status,
367 (*auth_ntlmssp_state)->ntlmssp_state->user,
368 (*auth_ntlmssp_state)->ntlmssp_state->domain);
371 if (NT_STATUS_IS_OK(nt_status)) {
373 DATA_BLOB nullblob = data_blob(NULL, 0);
374 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
376 /* register_vuid keeps the server info */
377 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
378 (*auth_ntlmssp_state)->server_info = NULL;
380 if (sess_vuid == -1) {
381 nt_status = NT_STATUS_LOGON_FAILURE;
384 /* current_user_info is changed on new vuid */
385 reload_services( True );
387 set_message(outbuf,4,0,True);
388 SSVAL(outbuf, smb_vwv3, 0);
390 if (server_info->guest) {
391 SSVAL(outbuf,smb_vwv2,1);
394 SSVAL(outbuf,smb_uid,sess_vuid);
396 if (!server_info->guest && !srv_signing_started()) {
397 /* We need to start the signing engine
398 * here but a W2K client sends the old
399 * "BSRSPYL " signature instead of the
400 * correct one. Subsequent packets will
404 srv_check_sign_mac(inbuf, False);
409 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
410 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
411 data_blob_free(&response);
413 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
414 and the other end, that we are not finished yet. */
416 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
417 auth_ntlmssp_end(auth_ntlmssp_state);
423 /****************************************************************************
424 Reply to a session setup spnego negotiate packet.
425 ****************************************************************************/
427 static int reply_spnego_negotiate(connection_struct *conn,
430 int length, int bufsize,
433 char *OIDs[ASN1_MAX_OIDS];
438 BOOL got_kerberos_mechanism = False;
442 /* parse out the OIDs and the first sec blob */
443 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
444 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
447 /* only look at the first OID for determining the mechToken --
448 accoirding to RFC2478, we should choose the one we want
449 and renegotiate, but i smell a client bug here..
451 Problem observed when connecting to a member (samba box)
452 of an AD domain as a user in a Samba domain. Samba member
453 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
454 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
455 NTLMSSP mechtoken. --jerry */
458 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
459 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
460 got_kerberos_mechanism = True;
464 for (i=0;OIDs[i];i++) {
465 DEBUG(3,("Got OID %s\n", OIDs[i]));
468 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
471 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
472 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
473 length, bufsize, &secblob);
474 data_blob_free(&secblob);
479 if (global_ntlmssp_state) {
480 auth_ntlmssp_end(&global_ntlmssp_state);
483 nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
484 if (!NT_STATUS_IS_OK(nt_status)) {
485 return ERROR_NT(nt_status);
488 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
491 data_blob_free(&secblob);
493 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
496 data_blob_free(&chal);
498 /* already replied */
502 /****************************************************************************
503 Reply to a session setup spnego auth packet.
504 ****************************************************************************/
506 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
507 int length, int bufsize,
510 DATA_BLOB auth, auth_reply;
511 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
513 if (!spnego_parse_auth(blob1, &auth)) {
515 file_save("auth.dat", blob1.data, blob1.length);
517 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
520 if (!global_ntlmssp_state) {
521 /* auth before negotiatiate? */
522 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
525 nt_status = auth_ntlmssp_update(global_ntlmssp_state,
528 data_blob_free(&auth);
530 reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
531 &auth_reply, nt_status);
533 data_blob_free(&auth_reply);
535 /* and tell smbd that we have already replied to this packet */
539 /****************************************************************************
540 Reply to a session setup command.
541 ****************************************************************************/
543 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
545 int length,int bufsize)
551 fstring native_os, native_lanman, primary_domain;
553 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
554 enum remote_arch_types ra_type = get_remote_arch();
556 DEBUG(3,("Doing spnego session setup\n"));
558 if (global_client_caps == 0) {
559 global_client_caps = IVAL(inbuf,smb_vwv10);
561 if (!(global_client_caps & CAP_STATUS32)) {
562 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
567 p = (uint8 *)smb_buf(inbuf);
569 if (data_blob_len == 0) {
570 /* an invalid request */
571 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
574 bufrem = smb_bufrem(inbuf, p);
575 /* pull the spnego blob */
576 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
579 file_save("negotiate.dat", blob1.data, blob1.length);
582 p2 = inbuf + smb_vwv13 + data_blob_len;
583 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
584 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
585 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
586 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
587 native_os, native_lanman, primary_domain));
589 if ( ra_type == RA_WIN2K ) {
590 /* Windows 2003 doesn't set the native lanman string,
591 but does set primary domain which is a bug I think */
593 if ( !strlen(native_lanman) )
594 ra_lanman_string( primary_domain );
596 ra_lanman_string( native_lanman );
599 if (blob1.data[0] == ASN1_APPLICATION(0)) {
600 /* its a negTokenTarg packet */
601 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
602 data_blob_free(&blob1);
606 if (blob1.data[0] == ASN1_CONTEXT(1)) {
607 /* its a auth packet */
608 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
609 data_blob_free(&blob1);
613 /* what sort of packet is this? */
614 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
616 data_blob_free(&blob1);
618 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
621 /****************************************************************************
622 On new VC == 0, shutdown *all* old connections and users.
623 It seems that only NT4.x does this. At W2K and above (XP etc.).
624 a new session setup with VC==0 is ignored.
625 ****************************************************************************/
627 static void setup_new_vc_session(void)
629 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
632 invalidate_all_vuids();
636 /****************************************************************************
637 Reply to a session setup command.
638 ****************************************************************************/
640 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
641 int length,int bufsize)
647 DATA_BLOB plaintext_password;
649 fstring sub_user; /* Sainitised username for substituion */
652 fstring native_lanman;
653 fstring primary_domain;
654 static BOOL done_sesssetup = False;
655 extern BOOL global_encrypted_passwords_negotiated;
656 extern BOOL global_spnego_negotiated;
657 extern enum protocol_types Protocol;
660 auth_usersupplied_info *user_info = NULL;
661 extern struct auth_context *negprot_global_auth_context;
662 auth_serversupplied_info *server_info = NULL;
666 BOOL doencrypt = global_encrypted_passwords_negotiated;
668 DATA_BLOB session_key;
670 START_PROFILE(SMBsesssetupX);
672 ZERO_STRUCT(lm_resp);
673 ZERO_STRUCT(nt_resp);
674 ZERO_STRUCT(plaintext_password);
676 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
678 /* a SPNEGO session setup has 12 command words, whereas a normal
679 NT1 session setup has 13. See the cifs spec. */
680 if (CVAL(inbuf, smb_wct) == 12 &&
681 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
682 if (!global_spnego_negotiated) {
683 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
684 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
687 if (SVAL(inbuf,smb_vwv4) == 0) {
688 setup_new_vc_session();
690 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
693 smb_bufsize = SVAL(inbuf,smb_vwv2);
695 if (Protocol < PROTOCOL_NT1) {
696 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
698 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
699 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
701 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
702 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
706 lm_resp = data_blob(smb_buf(inbuf), passlen1);
708 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
709 /* Ensure null termination */
710 plaintext_password.data[passlen1] = 0;
713 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
717 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
718 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
719 enum remote_arch_types ra_type = get_remote_arch();
720 char *p = smb_buf(inbuf);
721 char *save_p = smb_buf(inbuf);
725 if(global_client_caps == 0) {
726 global_client_caps = IVAL(inbuf,smb_vwv11);
728 if (!(global_client_caps & CAP_STATUS32)) {
729 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
732 /* client_caps is used as final determination if client is NT or Win95.
733 This is needed to return the correct error codes in some
737 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
738 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
739 set_remote_arch( RA_WIN95);
745 /* both Win95 and WinNT stuff up the password lengths for
746 non-encrypting systems. Uggh.
748 if passlen1==24 its a win95 system, and its setting the
749 password length incorrectly. Luckily it still works with the
750 default code because Win95 will null terminate the password
753 if passlen1>0 and passlen2>0 then maybe its a NT box and its
754 setting passlen2 to some random value which really stuffs
755 things up. we need to fix that one. */
757 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
761 /* check for nasty tricks */
762 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
763 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
766 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
767 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
770 /* Save the lanman2 password and the NT md4 password. */
772 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
777 lm_resp = data_blob(p, passlen1);
778 nt_resp = data_blob(p+passlen1, passlen2);
781 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
784 /* This was the previous fix. Not sure if it's still valid. JRA. */
785 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
786 /* NT4.0 stuffs up plaintext unicode password lengths... */
787 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
788 sizeof(pass), passlen1, STR_TERMINATE);
791 if (unic && (passlen2 == 0) && passlen1) {
792 /* Only a ascii plaintext password was sent. */
793 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
794 passlen1, STR_TERMINATE|STR_ASCII);
796 srvstr_pull(inbuf, pass, smb_buf(inbuf),
797 sizeof(pass), unic ? passlen2 : passlen1,
800 plaintext_password = data_blob(pass, strlen(pass)+1);
803 p += passlen1 + passlen2;
804 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
805 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
806 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
807 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
809 /* not documented or decoded by Ethereal but there is one more string
810 in the extra bytes which is the same as the PrimaryDomain when using
811 extended security. Windows NT 4 and 2003 use this string to store
812 the native lanman string. Windows 9x does not include a string here
813 at all so we have to check if we have any extra bytes left */
815 byte_count = SVAL(inbuf, smb_vwv13);
816 if ( PTR_DIFF(p, save_p) < byte_count)
817 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
819 fstrcpy( primary_domain, "null" );
821 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
822 domain, native_os, native_lanman, primary_domain));
824 if ( ra_type == RA_WIN2K ) {
825 if ( strlen(native_lanman) == 0 )
826 ra_lanman_string( primary_domain );
828 ra_lanman_string( native_lanman );
833 if (SVAL(inbuf,smb_vwv4) == 0) {
834 setup_new_vc_session();
837 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
840 if (global_spnego_negotiated) {
842 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
844 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
845 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
847 fstrcpy(sub_user, user);
849 /* setup the string used by %U */
850 sub_set_smb_name(user);
852 fstrcpy(sub_user, lp_guestaccount());
855 sub_set_smb_name(sub_user);
857 reload_services(True);
859 if (lp_security() == SEC_SHARE) {
860 /* in share level we should ignore any passwords */
862 data_blob_free(&lm_resp);
863 data_blob_free(&nt_resp);
864 data_blob_clear_free(&plaintext_password);
866 map_username(sub_user);
867 add_session_user(sub_user);
868 /* Then force it to null for the benfit of the code below */
874 nt_status = check_guest_password(&server_info);
876 } else if (doencrypt) {
877 if (!negprot_global_auth_context) {
878 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
879 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
881 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
883 if (NT_STATUS_IS_OK(nt_status)) {
884 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
889 struct auth_context *plaintext_auth_context = NULL;
891 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
892 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
894 if (!make_user_info_for_reply(&user_info,
896 plaintext_password)) {
897 nt_status = NT_STATUS_NO_MEMORY;
900 if (NT_STATUS_IS_OK(nt_status)) {
901 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
905 (plaintext_auth_context->free)(&plaintext_auth_context);
910 free_user_info(&user_info);
912 if (!NT_STATUS_IS_OK(nt_status)) {
913 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
916 if (!NT_STATUS_IS_OK(nt_status)) {
917 data_blob_free(&nt_resp);
918 data_blob_free(&lm_resp);
919 data_blob_clear_free(&plaintext_password);
920 return ERROR_NT(nt_status_squash(nt_status));
923 if (server_info->user_session_key.data) {
924 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
926 session_key = data_blob(NULL, 0);
929 data_blob_clear_free(&plaintext_password);
931 /* it's ok - setup a reply */
932 set_message(outbuf,3,0,True);
933 if (Protocol >= PROTOCOL_NT1) {
934 char *p = smb_buf( outbuf );
935 p += add_signature( outbuf, p );
936 set_message_end( outbuf, p );
937 /* perhaps grab OS version here?? */
940 if (server_info->guest) {
941 SSVAL(outbuf,smb_vwv2,1);
944 /* register the name and uid as being validated, so further connections
945 to a uid can get through without a password, on the same VC */
947 /* register_vuid keeps the server info */
948 sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user);
949 data_blob_free(&nt_resp);
950 data_blob_free(&lm_resp);
952 if (sess_vuid == -1) {
953 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
956 /* current_user_info is changed on new vuid */
957 reload_services( True );
959 if (!server_info->guest && !srv_signing_started() && !srv_check_sign_mac(inbuf, True)) {
960 exit_server("reply_sesssetup_and_X: bad smb signature");
963 SSVAL(outbuf,smb_uid,sess_vuid);
964 SSVAL(inbuf,smb_uid,sess_vuid);
967 max_send = MIN(max_send,smb_bufsize);
969 done_sesssetup = True;
971 END_PROFILE(SMBsesssetupX);
972 return chain_reply(inbuf,outbuf,length,bufsize);