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;
29 on a logon error possibly map the error to success if "map to guest"
32 static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info,
33 const char *user, const char *domain)
35 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
36 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
37 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
38 DEBUG(3,("No such user %s [%s] - using guest account\n",
40 status = make_server_info_guest(server_info);
44 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
45 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
46 DEBUG(3,("Registered username %s for guest access\n",user));
47 status = make_server_info_guest(server_info);
54 /****************************************************************************
55 Add the standard 'Samba' signature to the end of the session setup.
56 ****************************************************************************/
58 static int add_signature(char *outbuf, char *p)
63 fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
65 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
66 p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE);
67 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
69 return PTR_DIFF(p, start);
72 /****************************************************************************
73 Send a security blob via a session setup reply.
74 ****************************************************************************/
76 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
77 DATA_BLOB blob, NTSTATUS nt_status)
81 set_message(outbuf,4,0,True);
83 nt_status = nt_status_squash(nt_status);
84 SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
85 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
86 SSVAL(outbuf, smb_vwv3, blob.length);
89 /* should we cap this? */
90 memcpy(p, blob.data, blob.length);
93 p += add_signature( outbuf, p );
95 set_message_end(outbuf,p);
98 return send_smb(smbd_server_fd(),outbuf);
101 /****************************************************************************
102 Do a 'guest' logon, getting back the
103 ****************************************************************************/
105 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
107 struct auth_context *auth_context;
108 auth_usersupplied_info *user_info = NULL;
111 unsigned char chal[8];
115 DEBUG(3,("Got anonymous request\n"));
117 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
121 if (!make_user_info_guest(&user_info)) {
122 (auth_context->free)(&auth_context);
123 return NT_STATUS_NO_MEMORY;
126 nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
127 (auth_context->free)(&auth_context);
128 free_user_info(&user_info);
134 /****************************************************************************
135 reply to a session setup spnego negotiate packet for kerberos
136 ****************************************************************************/
137 static int reply_spnego_kerberos(connection_struct *conn,
138 char *inbuf, char *outbuf,
139 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;
158 PAC_LOGON_INFO *logon_info = NULL;
161 ZERO_STRUCT(pac_data);
163 ZERO_STRUCT(ap_rep_wrapped);
164 ZERO_STRUCT(response);
166 mem_ctx = talloc_init("reply_spnego_kerberos");
168 return ERROR_NT(NT_STATUS_NO_MEMORY);
170 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
171 talloc_destroy(mem_ctx);
172 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
175 ret = ads_verify_ticket(mem_ctx, lp_realm(), &ticket, &client, &pac_data, &ap_rep, &session_key);
177 data_blob_free(&ticket);
179 if (!NT_STATUS_IS_OK(ret)) {
180 DEBUG(1,("Failed to verify incoming ticket!\n"));
181 talloc_destroy(mem_ctx);
182 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
185 DEBUG(3,("Ticket name is [%s]\n", client));
187 p = strchr_m(client, '@');
189 DEBUG(3,("Doesn't look like a valid principal\n"));
190 data_blob_free(&ap_rep);
191 data_blob_free(&session_key);
193 talloc_destroy(mem_ctx);
194 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
199 /* save the PAC data if we have it */
202 logon_info = get_logon_info_from_pac(pac_data);
203 netsamlogon_cache_store( client, &logon_info->info3 );
206 if (!strequal(p+1, lp_realm())) {
207 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
208 if (!lp_allow_trusted_domains()) {
209 data_blob_free(&ap_rep);
210 data_blob_free(&session_key);
212 talloc_destroy(mem_ctx);
213 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
217 /* this gives a fully qualified user name (ie. with full realm).
218 that leads to very long usernames, but what else can we do? */
222 if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
224 unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
225 domain = netbios_domain_name;
226 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
230 /* If we have winbind running, we can (and must) shorten the
231 username by using the short netbios name. Otherwise we will
232 have inconsistent user names. With Kerberos, we get the
233 fully qualified realm, with ntlmssp we get the short
234 name. And even w2k3 does use ntlmssp if you for example
235 connect to an ip address. */
237 struct winbindd_request wb_request;
238 struct winbindd_response wb_response;
239 NSS_STATUS wb_result;
241 ZERO_STRUCT(wb_request);
242 ZERO_STRUCT(wb_response);
244 DEBUG(10, ("Mapping [%s] to short name\n", domain));
246 fstrcpy(wb_request.domain_name, domain);
248 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
249 &wb_request, &wb_response);
251 if (wb_result == NSS_STATUS_SUCCESS) {
253 fstrcpy(netbios_domain_name,
254 wb_response.data.domain_info.name);
255 domain = netbios_domain_name;
257 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
259 DEBUG(3, ("Could not find short name -- winbind "
264 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
266 /* lookup the passwd struct, create a new user if necessary */
268 map_username( user );
270 pw = smb_getpwnam( user, real_username, True );
273 /* this was originally the behavior of Samba 2.2, if a user
274 did not have a local uid but has been authenticated, then
275 map them to a guest account */
277 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
278 map_domainuser_to_guest = True;
279 fstrcpy(user,lp_guestaccount());
280 pw = smb_getpwnam( user, real_username, True );
283 /* extra sanity check that the guest account is valid */
286 DEBUG(1,("Username %s is invalid on this system\n", user));
288 data_blob_free(&ap_rep);
289 data_blob_free(&session_key);
290 talloc_destroy(mem_ctx);
291 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
295 /* setup the string used by %U */
297 sub_set_smb_name( real_username );
298 reload_services(True);
299 if ( map_domainuser_to_guest ) {
300 make_server_info_guest(&server_info);
301 } else if (logon_info) {
302 ret = make_server_info_pac(&server_info, real_username, pw, logon_info);
304 if ( !NT_STATUS_IS_OK(ret) ) {
305 DEBUG(1,("make_server_info_pac failed!\n"));
307 data_blob_free(&ap_rep);
308 data_blob_free(&session_key);
310 talloc_destroy(mem_ctx);
311 return ERROR_NT(ret);
315 ret = make_server_info_pw(&server_info, real_username, pw);
317 if ( !NT_STATUS_IS_OK(ret) ) {
318 DEBUG(1,("make_server_info_from_pw failed!\n"));
320 data_blob_free(&ap_rep);
321 data_blob_free(&session_key);
323 talloc_destroy(mem_ctx);
324 return ERROR_NT(ret);
327 /* make_server_info_pw does not set the domain. Without this we end up
328 * with the local netbios name in substitutions for %D. */
330 if (server_info->sam_account != NULL) {
331 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
338 /* register_vuid keeps the server info */
339 /* register_vuid takes ownership of session_key, no need to free after this.
340 A better interface would copy it.... */
341 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
345 if (sess_vuid == -1) {
346 ret = NT_STATUS_LOGON_FAILURE;
348 /* current_user_info is changed on new vuid */
349 reload_services( True );
351 set_message(outbuf,4,0,True);
352 SSVAL(outbuf, smb_vwv3, 0);
354 if (server_info->guest) {
355 SSVAL(outbuf,smb_vwv2,1);
358 SSVAL(outbuf, smb_uid, sess_vuid);
360 if (!server_info->guest && !srv_signing_started()) {
361 /* We need to start the signing engine
362 * here but a W2K client sends the old
363 * "BSRSPYL " signature instead of the
364 * correct one. Subsequent packets will
367 srv_check_sign_mac(inbuf, False);
371 /* wrap that up in a nice GSS-API wrapping */
372 if (NT_STATUS_IS_OK(ret)) {
373 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
375 ap_rep_wrapped = data_blob(NULL, 0);
377 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
378 reply_sesssetup_blob(conn, outbuf, response, ret);
380 data_blob_free(&ap_rep);
381 data_blob_free(&ap_rep_wrapped);
382 data_blob_free(&response);
383 talloc_destroy(mem_ctx);
385 return -1; /* already replied */
389 /****************************************************************************
390 Send a session setup reply, wrapped in SPNEGO.
391 Get vuid and check first.
392 End the NTLMSSP exchange context if we are OK/complete fail
393 This should be split into two functions, one to handle each
394 leg of the NTLM auth steps.
395 ***************************************************************************/
397 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
399 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
400 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
405 struct auth_serversupplied_info *server_info = NULL;
407 if (NT_STATUS_IS_OK(nt_status)) {
408 server_info = (*auth_ntlmssp_state)->server_info;
410 nt_status = do_map_to_guest(nt_status,
412 (*auth_ntlmssp_state)->ntlmssp_state->user,
413 (*auth_ntlmssp_state)->ntlmssp_state->domain);
416 if (NT_STATUS_IS_OK(nt_status)) {
418 DATA_BLOB nullblob = data_blob(NULL, 0);
419 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
421 /* register_vuid keeps the server info */
422 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
423 (*auth_ntlmssp_state)->server_info = NULL;
425 if (sess_vuid == -1) {
426 nt_status = NT_STATUS_LOGON_FAILURE;
429 /* current_user_info is changed on new vuid */
430 reload_services( True );
432 set_message(outbuf,4,0,True);
433 SSVAL(outbuf, smb_vwv3, 0);
435 if (server_info->guest) {
436 SSVAL(outbuf,smb_vwv2,1);
439 SSVAL(outbuf,smb_uid,sess_vuid);
441 if (!server_info->guest && !srv_signing_started()) {
442 /* We need to start the signing engine
443 * here but a W2K client sends the old
444 * "BSRSPYL " signature instead of the
445 * correct one. Subsequent packets will
449 srv_check_sign_mac(inbuf, False);
455 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
457 response = *ntlmssp_blob;
460 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
462 data_blob_free(&response);
465 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
466 and the other end, that we are not finished yet. */
468 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
469 /* NB. This is *NOT* an error case. JRA */
470 auth_ntlmssp_end(auth_ntlmssp_state);
471 /* Kill the intermediate vuid */
472 invalidate_vuid(vuid);
478 /****************************************************************************
479 Reply to a session setup spnego negotiate packet.
480 ****************************************************************************/
482 static int reply_spnego_negotiate(connection_struct *conn,
486 int length, int bufsize,
488 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
490 char *OIDs[ASN1_MAX_OIDS];
495 BOOL got_kerberos_mechanism = False;
499 /* parse out the OIDs and the first sec blob */
500 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
501 /* Kill the intermediate vuid */
502 invalidate_vuid(vuid);
504 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
507 /* only look at the first OID for determining the mechToken --
508 accoirding to RFC2478, we should choose the one we want
509 and renegotiate, but i smell a client bug here..
511 Problem observed when connecting to a member (samba box)
512 of an AD domain as a user in a Samba domain. Samba member
513 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
514 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
515 NTLMSSP mechtoken. --jerry */
518 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
519 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
520 got_kerberos_mechanism = True;
524 for (i=0;OIDs[i];i++) {
525 DEBUG(3,("Got OID %s\n", OIDs[i]));
528 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
531 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
532 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
533 length, bufsize, &secblob);
534 data_blob_free(&secblob);
535 /* Kill the intermediate vuid */
536 invalidate_vuid(vuid);
542 if (*auth_ntlmssp_state) {
543 auth_ntlmssp_end(auth_ntlmssp_state);
546 nt_status = auth_ntlmssp_start(auth_ntlmssp_state);
547 if (!NT_STATUS_IS_OK(nt_status)) {
548 /* Kill the intermediate vuid */
549 invalidate_vuid(vuid);
551 return ERROR_NT(nt_status);
554 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
557 data_blob_free(&secblob);
559 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
560 &chal, nt_status, True);
562 data_blob_free(&chal);
564 /* already replied */
568 /****************************************************************************
569 Reply to a session setup spnego auth packet.
570 ****************************************************************************/
572 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
574 int length, int bufsize,
576 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
578 DATA_BLOB auth, auth_reply;
579 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
581 if (!spnego_parse_auth(blob1, &auth)) {
583 file_save("auth.dat", blob1.data, blob1.length);
585 /* Kill the intermediate vuid */
586 invalidate_vuid(vuid);
588 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
591 if (!*auth_ntlmssp_state) {
592 /* Kill the intermediate vuid */
593 invalidate_vuid(vuid);
595 /* auth before negotiatiate? */
596 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
599 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
602 data_blob_free(&auth);
604 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
606 &auth_reply, nt_status, True);
608 data_blob_free(&auth_reply);
610 /* and tell smbd that we have already replied to this packet */
614 /****************************************************************************
615 Reply to a session setup command.
616 ****************************************************************************/
618 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
620 int length,int bufsize)
626 fstring native_os, native_lanman, primary_domain;
628 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
629 enum remote_arch_types ra_type = get_remote_arch();
630 int vuid = SVAL(inbuf,smb_uid);
631 user_struct *vuser = NULL;
633 DEBUG(3,("Doing spnego session setup\n"));
635 if (global_client_caps == 0) {
636 global_client_caps = IVAL(inbuf,smb_vwv10);
638 if (!(global_client_caps & CAP_STATUS32)) {
639 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
644 p = (uint8 *)smb_buf(inbuf);
646 if (data_blob_len == 0) {
647 /* an invalid request */
648 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
651 bufrem = smb_bufrem(inbuf, p);
652 /* pull the spnego blob */
653 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
656 file_save("negotiate.dat", blob1.data, blob1.length);
659 p2 = inbuf + smb_vwv13 + data_blob_len;
660 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
661 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
662 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
663 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
664 native_os, native_lanman, primary_domain));
666 if ( ra_type == RA_WIN2K ) {
667 /* Windows 2003 doesn't set the native lanman string,
668 but does set primary domain which is a bug I think */
670 if ( !strlen(native_lanman) )
671 ra_lanman_string( primary_domain );
673 ra_lanman_string( native_lanman );
676 vuser = get_partial_auth_user_struct(vuid);
678 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
680 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
683 vuser = get_partial_auth_user_struct(vuid);
687 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
690 SSVAL(outbuf,smb_uid,vuid);
692 if (blob1.data[0] == ASN1_APPLICATION(0)) {
693 /* its a negTokenTarg packet */
694 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
695 &vuser->auth_ntlmssp_state);
696 data_blob_free(&blob1);
700 if (blob1.data[0] == ASN1_CONTEXT(1)) {
701 /* its a auth packet */
702 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
703 &vuser->auth_ntlmssp_state);
704 data_blob_free(&blob1);
708 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
711 if (!vuser->auth_ntlmssp_state) {
712 nt_status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
713 if (!NT_STATUS_IS_OK(nt_status)) {
714 /* Kill the intermediate vuid */
715 invalidate_vuid(vuid);
717 return ERROR_NT(nt_status);
721 nt_status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
724 data_blob_free(&blob1);
726 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
727 &vuser->auth_ntlmssp_state,
728 &chal, nt_status, False);
729 data_blob_free(&chal);
733 /* what sort of packet is this? */
734 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
736 data_blob_free(&blob1);
738 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
741 /****************************************************************************
742 On new VC == 0, shutdown *all* old connections and users.
743 It seems that only NT4.x does this. At W2K and above (XP etc.).
744 a new session setup with VC==0 is ignored.
745 ****************************************************************************/
747 static void setup_new_vc_session(void)
749 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
752 invalidate_all_vuids();
756 /****************************************************************************
757 Reply to a session setup command.
758 ****************************************************************************/
760 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
761 int length,int bufsize)
767 DATA_BLOB plaintext_password;
769 fstring sub_user; /* Sainitised username for substituion */
772 fstring native_lanman;
773 fstring primary_domain;
774 static BOOL done_sesssetup = False;
775 extern BOOL global_encrypted_passwords_negotiated;
776 extern BOOL global_spnego_negotiated;
777 extern enum protocol_types Protocol;
780 auth_usersupplied_info *user_info = NULL;
781 extern struct auth_context *negprot_global_auth_context;
782 auth_serversupplied_info *server_info = NULL;
786 BOOL doencrypt = global_encrypted_passwords_negotiated;
788 DATA_BLOB session_key;
790 START_PROFILE(SMBsesssetupX);
792 ZERO_STRUCT(lm_resp);
793 ZERO_STRUCT(nt_resp);
794 ZERO_STRUCT(plaintext_password);
796 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
798 /* a SPNEGO session setup has 12 command words, whereas a normal
799 NT1 session setup has 13. See the cifs spec. */
800 if (CVAL(inbuf, smb_wct) == 12 &&
801 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
802 if (!global_spnego_negotiated) {
803 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
804 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
807 if (SVAL(inbuf,smb_vwv4) == 0) {
808 setup_new_vc_session();
810 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
813 smb_bufsize = SVAL(inbuf,smb_vwv2);
815 if (Protocol < PROTOCOL_NT1) {
816 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
818 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
819 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
821 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
822 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
826 lm_resp = data_blob(smb_buf(inbuf), passlen1);
828 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
829 /* Ensure null termination */
830 plaintext_password.data[passlen1] = 0;
833 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
837 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
838 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
839 enum remote_arch_types ra_type = get_remote_arch();
840 char *p = smb_buf(inbuf);
841 char *save_p = smb_buf(inbuf);
845 if(global_client_caps == 0) {
846 global_client_caps = IVAL(inbuf,smb_vwv11);
848 if (!(global_client_caps & CAP_STATUS32)) {
849 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
852 /* client_caps is used as final determination if client is NT or Win95.
853 This is needed to return the correct error codes in some
857 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
858 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
859 set_remote_arch( RA_WIN95);
865 /* both Win95 and WinNT stuff up the password lengths for
866 non-encrypting systems. Uggh.
868 if passlen1==24 its a win95 system, and its setting the
869 password length incorrectly. Luckily it still works with the
870 default code because Win95 will null terminate the password
873 if passlen1>0 and passlen2>0 then maybe its a NT box and its
874 setting passlen2 to some random value which really stuffs
875 things up. we need to fix that one. */
877 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
881 /* check for nasty tricks */
882 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
883 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
886 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
887 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
890 /* Save the lanman2 password and the NT md4 password. */
892 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
897 lm_resp = data_blob(p, passlen1);
898 nt_resp = data_blob(p+passlen1, passlen2);
901 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
904 /* This was the previous fix. Not sure if it's still valid. JRA. */
905 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
906 /* NT4.0 stuffs up plaintext unicode password lengths... */
907 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
908 sizeof(pass), passlen1, STR_TERMINATE);
911 if (unic && (passlen2 == 0) && passlen1) {
912 /* Only a ascii plaintext password was sent. */
913 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
914 passlen1, STR_TERMINATE|STR_ASCII);
916 srvstr_pull(inbuf, pass, smb_buf(inbuf),
917 sizeof(pass), unic ? passlen2 : passlen1,
920 plaintext_password = data_blob(pass, strlen(pass)+1);
923 p += passlen1 + passlen2;
924 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
925 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
926 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
927 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
929 /* not documented or decoded by Ethereal but there is one more string
930 in the extra bytes which is the same as the PrimaryDomain when using
931 extended security. Windows NT 4 and 2003 use this string to store
932 the native lanman string. Windows 9x does not include a string here
933 at all so we have to check if we have any extra bytes left */
935 byte_count = SVAL(inbuf, smb_vwv13);
936 if ( PTR_DIFF(p, save_p) < byte_count)
937 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
939 fstrcpy( primary_domain, "null" );
941 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
942 domain, native_os, native_lanman, primary_domain));
944 if ( ra_type == RA_WIN2K ) {
945 if ( strlen(native_lanman) == 0 )
946 ra_lanman_string( primary_domain );
948 ra_lanman_string( native_lanman );
953 if (SVAL(inbuf,smb_vwv4) == 0) {
954 setup_new_vc_session();
957 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
960 if (global_spnego_negotiated) {
962 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
964 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
965 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
967 fstrcpy(sub_user, user);
969 fstrcpy(sub_user, lp_guestaccount());
972 sub_set_smb_name(sub_user);
974 reload_services(True);
976 if (lp_security() == SEC_SHARE) {
977 /* in share level we should ignore any passwords */
979 data_blob_free(&lm_resp);
980 data_blob_free(&nt_resp);
981 data_blob_clear_free(&plaintext_password);
983 map_username(sub_user);
984 add_session_user(sub_user);
985 /* Then force it to null for the benfit of the code below */
991 nt_status = check_guest_password(&server_info);
993 } else if (doencrypt) {
994 if (!negprot_global_auth_context) {
995 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
996 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
998 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1000 if (NT_STATUS_IS_OK(nt_status)) {
1001 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1006 struct auth_context *plaintext_auth_context = NULL;
1008 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
1009 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1011 if (!make_user_info_for_reply(&user_info,
1013 plaintext_password)) {
1014 nt_status = NT_STATUS_NO_MEMORY;
1017 if (NT_STATUS_IS_OK(nt_status)) {
1018 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1022 (plaintext_auth_context->free)(&plaintext_auth_context);
1027 free_user_info(&user_info);
1029 if (!NT_STATUS_IS_OK(nt_status)) {
1030 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1033 if (!NT_STATUS_IS_OK(nt_status)) {
1034 data_blob_free(&nt_resp);
1035 data_blob_free(&lm_resp);
1036 data_blob_clear_free(&plaintext_password);
1037 return ERROR_NT(nt_status_squash(nt_status));
1040 if (server_info->user_session_key.data) {
1041 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1043 session_key = data_blob(NULL, 0);
1046 data_blob_clear_free(&plaintext_password);
1048 /* it's ok - setup a reply */
1049 set_message(outbuf,3,0,True);
1050 if (Protocol >= PROTOCOL_NT1) {
1051 char *p = smb_buf( outbuf );
1052 p += add_signature( outbuf, p );
1053 set_message_end( outbuf, p );
1054 /* perhaps grab OS version here?? */
1057 if (server_info->guest) {
1058 SSVAL(outbuf,smb_vwv2,1);
1061 /* register the name and uid as being validated, so further connections
1062 to a uid can get through without a password, on the same VC */
1064 /* register_vuid keeps the server info */
1065 sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user);
1066 data_blob_free(&nt_resp);
1067 data_blob_free(&lm_resp);
1069 if (sess_vuid == -1) {
1070 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
1073 /* current_user_info is changed on new vuid */
1074 reload_services( True );
1076 if (!server_info->guest && !srv_signing_started() && !srv_check_sign_mac(inbuf, True)) {
1077 exit_server("reply_sesssetup_and_X: bad smb signature");
1080 SSVAL(outbuf,smb_uid,sess_vuid);
1081 SSVAL(inbuf,smb_uid,sess_vuid);
1083 if (!done_sesssetup)
1084 max_send = MIN(max_send,smb_bufsize);
1086 done_sesssetup = True;
1088 END_PROFILE(SMBsesssetupX);
1089 return chain_reply(inbuf,outbuf,length,bufsize);