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;
162 ZERO_STRUCT(pac_data);
164 ZERO_STRUCT(ap_rep_wrapped);
165 ZERO_STRUCT(response);
167 mem_ctx = talloc_init("reply_spnego_kerberos");
169 return ERROR_NT(NT_STATUS_NO_MEMORY);
171 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
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 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
185 logon_info = get_logon_info_from_pac(pac_data);
188 DEBUG(3,("Ticket name is [%s]\n", client));
190 p = strchr_m(client, '@');
192 DEBUG(3,("Doesn't look like a valid principal\n"));
193 data_blob_free(&ap_rep);
194 data_blob_free(&session_key);
196 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
200 if (!strequal(p+1, lp_realm())) {
201 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
202 if (!lp_allow_trusted_domains()) {
203 data_blob_free(&ap_rep);
204 data_blob_free(&session_key);
206 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
210 /* this gives a fully qualified user name (ie. with full realm).
211 that leads to very long usernames, but what else can we do? */
215 if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
217 unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
218 domain = netbios_domain_name;
219 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
223 /* If we have winbind running, we can (and must) shorten the
224 username by using the short netbios name. Otherwise we will
225 have inconsistent user names. With Kerberos, we get the
226 fully qualified realm, with ntlmssp we get the short
227 name. And even w2k3 does use ntlmssp if you for example
228 connect to an ip address. */
230 struct winbindd_request wb_request;
231 struct winbindd_response wb_response;
232 NSS_STATUS wb_result;
234 ZERO_STRUCT(wb_request);
235 ZERO_STRUCT(wb_response);
237 DEBUG(10, ("Mapping [%s] to short name\n", domain));
239 fstrcpy(wb_request.domain_name, domain);
241 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
242 &wb_request, &wb_response);
244 if (wb_result == NSS_STATUS_SUCCESS) {
246 fstrcpy(netbios_domain_name,
247 wb_response.data.domain_info.name);
248 domain = netbios_domain_name;
250 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
252 DEBUG(3, ("Could not find short name -- winbind "
257 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
259 /* lookup the passwd struct, create a new user if necessary */
261 map_username( user );
263 pw = smb_getpwnam( user, real_username, True );
266 /* this was originally the behavior of Samba 2.2, if a user
267 did not have a local uid but has been authenticated, then
268 map them to a guest account */
270 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
271 map_domainuser_to_guest = True;
272 fstrcpy(user,lp_guestaccount());
273 pw = smb_getpwnam( user, real_username, True );
276 /* extra sanity check that the guest account is valid */
279 DEBUG(1,("Username %s is invalid on this system\n", user));
281 data_blob_free(&ap_rep);
282 data_blob_free(&session_key);
283 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
287 /* setup the string used by %U */
289 sub_set_smb_name( real_username );
290 reload_services(True);
291 if ( map_domainuser_to_guest ) {
292 make_server_info_guest(&server_info);
293 } else if (logon_info) {
294 ret = make_server_info_pac(&server_info, real_username, pw, logon_info);
296 if ( !NT_STATUS_IS_OK(ret) ) {
297 DEBUG(1,("make_server_info_pac failed!\n"));
299 data_blob_free(&ap_rep);
300 data_blob_free(&session_key);
302 return ERROR_NT(ret);
306 ret = make_server_info_pw(&server_info, real_username, pw);
308 if ( !NT_STATUS_IS_OK(ret) ) {
309 DEBUG(1,("make_server_info_from_pw failed!\n"));
311 data_blob_free(&ap_rep);
312 data_blob_free(&session_key);
314 return ERROR_NT(ret);
317 /* make_server_info_pw does not set the domain. Without this we end up
318 * with the local netbios name in substitutions for %D. */
320 if (server_info->sam_account != NULL) {
321 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
328 /* register_vuid keeps the server info */
329 /* register_vuid takes ownership of session_key, no need to free after this.
330 A better interface would copy it.... */
331 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
335 if (sess_vuid == -1) {
336 ret = NT_STATUS_LOGON_FAILURE;
338 /* current_user_info is changed on new vuid */
339 reload_services( True );
341 set_message(outbuf,4,0,True);
342 SSVAL(outbuf, smb_vwv3, 0);
344 if (server_info->guest) {
345 SSVAL(outbuf,smb_vwv2,1);
348 SSVAL(outbuf, smb_uid, sess_vuid);
350 if (!server_info->guest && !srv_signing_started()) {
351 /* We need to start the signing engine
352 * here but a W2K client sends the old
353 * "BSRSPYL " signature instead of the
354 * correct one. Subsequent packets will
357 srv_check_sign_mac(inbuf, False);
361 /* wrap that up in a nice GSS-API wrapping */
362 if (NT_STATUS_IS_OK(ret)) {
363 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
365 ap_rep_wrapped = data_blob(NULL, 0);
367 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
368 reply_sesssetup_blob(conn, outbuf, response, ret);
370 data_blob_free(&ap_rep);
371 data_blob_free(&ap_rep_wrapped);
372 data_blob_free(&response);
373 talloc_destroy(mem_ctx);
375 return -1; /* already replied */
379 /****************************************************************************
380 Send a session setup reply, wrapped in SPNEGO.
381 Get vuid and check first.
382 End the NTLMSSP exchange context if we are OK/complete fail
383 This should be split into two functions, one to handle each
384 leg of the NTLM auth steps.
385 ***************************************************************************/
387 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
389 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
390 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
395 struct auth_serversupplied_info *server_info = NULL;
397 if (NT_STATUS_IS_OK(nt_status)) {
398 server_info = (*auth_ntlmssp_state)->server_info;
400 nt_status = do_map_to_guest(nt_status,
402 (*auth_ntlmssp_state)->ntlmssp_state->user,
403 (*auth_ntlmssp_state)->ntlmssp_state->domain);
406 if (NT_STATUS_IS_OK(nt_status)) {
408 DATA_BLOB nullblob = data_blob(NULL, 0);
409 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
411 /* register_vuid keeps the server info */
412 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
413 (*auth_ntlmssp_state)->server_info = NULL;
415 if (sess_vuid == -1) {
416 nt_status = NT_STATUS_LOGON_FAILURE;
419 /* current_user_info is changed on new vuid */
420 reload_services( True );
422 set_message(outbuf,4,0,True);
423 SSVAL(outbuf, smb_vwv3, 0);
425 if (server_info->guest) {
426 SSVAL(outbuf,smb_vwv2,1);
429 SSVAL(outbuf,smb_uid,sess_vuid);
431 if (!server_info->guest && !srv_signing_started()) {
432 /* We need to start the signing engine
433 * here but a W2K client sends the old
434 * "BSRSPYL " signature instead of the
435 * correct one. Subsequent packets will
439 srv_check_sign_mac(inbuf, False);
445 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
447 response = *ntlmssp_blob;
450 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
452 data_blob_free(&response);
455 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
456 and the other end, that we are not finished yet. */
458 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
459 /* NB. This is *NOT* an error case. JRA */
460 auth_ntlmssp_end(auth_ntlmssp_state);
461 /* Kill the intermediate vuid */
462 invalidate_vuid(vuid);
468 /****************************************************************************
469 Reply to a session setup spnego negotiate packet.
470 ****************************************************************************/
472 static int reply_spnego_negotiate(connection_struct *conn,
476 int length, int bufsize,
478 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
480 char *OIDs[ASN1_MAX_OIDS];
485 BOOL got_kerberos_mechanism = False;
489 /* parse out the OIDs and the first sec blob */
490 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
491 /* Kill the intermediate vuid */
492 invalidate_vuid(vuid);
494 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
497 /* only look at the first OID for determining the mechToken --
498 accoirding to RFC2478, we should choose the one we want
499 and renegotiate, but i smell a client bug here..
501 Problem observed when connecting to a member (samba box)
502 of an AD domain as a user in a Samba domain. Samba member
503 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
504 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
505 NTLMSSP mechtoken. --jerry */
508 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
509 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
510 got_kerberos_mechanism = True;
514 for (i=0;OIDs[i];i++) {
515 DEBUG(3,("Got OID %s\n", OIDs[i]));
518 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
521 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
522 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
523 length, bufsize, &secblob);
524 data_blob_free(&secblob);
525 /* Kill the intermediate vuid */
526 invalidate_vuid(vuid);
532 if (*auth_ntlmssp_state) {
533 auth_ntlmssp_end(auth_ntlmssp_state);
536 nt_status = auth_ntlmssp_start(auth_ntlmssp_state);
537 if (!NT_STATUS_IS_OK(nt_status)) {
538 /* Kill the intermediate vuid */
539 invalidate_vuid(vuid);
541 return ERROR_NT(nt_status);
544 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
547 data_blob_free(&secblob);
549 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
550 &chal, nt_status, True);
552 data_blob_free(&chal);
554 /* already replied */
558 /****************************************************************************
559 Reply to a session setup spnego auth packet.
560 ****************************************************************************/
562 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
564 int length, int bufsize,
566 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
568 DATA_BLOB auth, auth_reply;
569 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
571 if (!spnego_parse_auth(blob1, &auth)) {
573 file_save("auth.dat", blob1.data, blob1.length);
575 /* Kill the intermediate vuid */
576 invalidate_vuid(vuid);
578 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
581 if (!*auth_ntlmssp_state) {
582 /* Kill the intermediate vuid */
583 invalidate_vuid(vuid);
585 /* auth before negotiatiate? */
586 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
589 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
592 data_blob_free(&auth);
594 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
596 &auth_reply, nt_status, True);
598 data_blob_free(&auth_reply);
600 /* and tell smbd that we have already replied to this packet */
604 /****************************************************************************
605 Reply to a session setup command.
606 ****************************************************************************/
608 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
610 int length,int bufsize)
616 fstring native_os, native_lanman, primary_domain;
618 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
619 enum remote_arch_types ra_type = get_remote_arch();
620 int vuid = SVAL(inbuf,smb_uid);
621 user_struct *vuser = NULL;
623 DEBUG(3,("Doing spnego session setup\n"));
625 if (global_client_caps == 0) {
626 global_client_caps = IVAL(inbuf,smb_vwv10);
628 if (!(global_client_caps & CAP_STATUS32)) {
629 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
634 p = (uint8 *)smb_buf(inbuf);
636 if (data_blob_len == 0) {
637 /* an invalid request */
638 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
641 bufrem = smb_bufrem(inbuf, p);
642 /* pull the spnego blob */
643 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
646 file_save("negotiate.dat", blob1.data, blob1.length);
649 p2 = inbuf + smb_vwv13 + data_blob_len;
650 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
651 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
652 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
653 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
654 native_os, native_lanman, primary_domain));
656 if ( ra_type == RA_WIN2K ) {
657 /* Windows 2003 doesn't set the native lanman string,
658 but does set primary domain which is a bug I think */
660 if ( !strlen(native_lanman) )
661 ra_lanman_string( primary_domain );
663 ra_lanman_string( native_lanman );
666 vuser = get_partial_auth_user_struct(vuid);
668 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
670 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
673 vuser = get_partial_auth_user_struct(vuid);
677 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
680 SSVAL(outbuf,smb_uid,vuid);
682 if (blob1.data[0] == ASN1_APPLICATION(0)) {
683 /* its a negTokenTarg packet */
684 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
685 &vuser->auth_ntlmssp_state);
686 data_blob_free(&blob1);
690 if (blob1.data[0] == ASN1_CONTEXT(1)) {
691 /* its a auth packet */
692 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
693 &vuser->auth_ntlmssp_state);
694 data_blob_free(&blob1);
698 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
701 if (!vuser->auth_ntlmssp_state) {
702 nt_status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
703 if (!NT_STATUS_IS_OK(nt_status)) {
704 /* Kill the intermediate vuid */
705 invalidate_vuid(vuid);
707 return ERROR_NT(nt_status);
711 nt_status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
714 data_blob_free(&blob1);
716 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
717 &vuser->auth_ntlmssp_state,
718 &chal, nt_status, False);
719 data_blob_free(&chal);
723 /* what sort of packet is this? */
724 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
726 data_blob_free(&blob1);
728 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
731 /****************************************************************************
732 On new VC == 0, shutdown *all* old connections and users.
733 It seems that only NT4.x does this. At W2K and above (XP etc.).
734 a new session setup with VC==0 is ignored.
735 ****************************************************************************/
737 static void setup_new_vc_session(void)
739 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
742 invalidate_all_vuids();
746 /****************************************************************************
747 Reply to a session setup command.
748 ****************************************************************************/
750 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
751 int length,int bufsize)
757 DATA_BLOB plaintext_password;
759 fstring sub_user; /* Sainitised username for substituion */
762 fstring native_lanman;
763 fstring primary_domain;
764 static BOOL done_sesssetup = False;
765 extern BOOL global_encrypted_passwords_negotiated;
766 extern BOOL global_spnego_negotiated;
767 extern enum protocol_types Protocol;
770 auth_usersupplied_info *user_info = NULL;
771 extern struct auth_context *negprot_global_auth_context;
772 auth_serversupplied_info *server_info = NULL;
776 BOOL doencrypt = global_encrypted_passwords_negotiated;
778 DATA_BLOB session_key;
780 START_PROFILE(SMBsesssetupX);
782 ZERO_STRUCT(lm_resp);
783 ZERO_STRUCT(nt_resp);
784 ZERO_STRUCT(plaintext_password);
786 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
788 /* a SPNEGO session setup has 12 command words, whereas a normal
789 NT1 session setup has 13. See the cifs spec. */
790 if (CVAL(inbuf, smb_wct) == 12 &&
791 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
792 if (!global_spnego_negotiated) {
793 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
794 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
797 if (SVAL(inbuf,smb_vwv4) == 0) {
798 setup_new_vc_session();
800 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
803 smb_bufsize = SVAL(inbuf,smb_vwv2);
805 if (Protocol < PROTOCOL_NT1) {
806 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
808 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
809 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
811 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
812 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
816 lm_resp = data_blob(smb_buf(inbuf), passlen1);
818 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
819 /* Ensure null termination */
820 plaintext_password.data[passlen1] = 0;
823 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
827 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
828 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
829 enum remote_arch_types ra_type = get_remote_arch();
830 char *p = smb_buf(inbuf);
831 char *save_p = smb_buf(inbuf);
835 if(global_client_caps == 0) {
836 global_client_caps = IVAL(inbuf,smb_vwv11);
838 if (!(global_client_caps & CAP_STATUS32)) {
839 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
842 /* client_caps is used as final determination if client is NT or Win95.
843 This is needed to return the correct error codes in some
847 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
848 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
849 set_remote_arch( RA_WIN95);
855 /* both Win95 and WinNT stuff up the password lengths for
856 non-encrypting systems. Uggh.
858 if passlen1==24 its a win95 system, and its setting the
859 password length incorrectly. Luckily it still works with the
860 default code because Win95 will null terminate the password
863 if passlen1>0 and passlen2>0 then maybe its a NT box and its
864 setting passlen2 to some random value which really stuffs
865 things up. we need to fix that one. */
867 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
871 /* check for nasty tricks */
872 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
873 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
876 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
877 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
880 /* Save the lanman2 password and the NT md4 password. */
882 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
887 lm_resp = data_blob(p, passlen1);
888 nt_resp = data_blob(p+passlen1, passlen2);
891 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
894 /* This was the previous fix. Not sure if it's still valid. JRA. */
895 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
896 /* NT4.0 stuffs up plaintext unicode password lengths... */
897 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
898 sizeof(pass), passlen1, STR_TERMINATE);
901 if (unic && (passlen2 == 0) && passlen1) {
902 /* Only a ascii plaintext password was sent. */
903 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
904 passlen1, STR_TERMINATE|STR_ASCII);
906 srvstr_pull(inbuf, pass, smb_buf(inbuf),
907 sizeof(pass), unic ? passlen2 : passlen1,
910 plaintext_password = data_blob(pass, strlen(pass)+1);
913 p += passlen1 + passlen2;
914 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
915 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
916 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
917 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
919 /* not documented or decoded by Ethereal but there is one more string
920 in the extra bytes which is the same as the PrimaryDomain when using
921 extended security. Windows NT 4 and 2003 use this string to store
922 the native lanman string. Windows 9x does not include a string here
923 at all so we have to check if we have any extra bytes left */
925 byte_count = SVAL(inbuf, smb_vwv13);
926 if ( PTR_DIFF(p, save_p) < byte_count)
927 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
929 fstrcpy( primary_domain, "null" );
931 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
932 domain, native_os, native_lanman, primary_domain));
934 if ( ra_type == RA_WIN2K ) {
935 if ( strlen(native_lanman) == 0 )
936 ra_lanman_string( primary_domain );
938 ra_lanman_string( native_lanman );
943 if (SVAL(inbuf,smb_vwv4) == 0) {
944 setup_new_vc_session();
947 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
950 if (global_spnego_negotiated) {
952 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
954 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
955 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
957 fstrcpy(sub_user, user);
959 /* setup the string used by %U */
960 sub_set_smb_name(user);
962 fstrcpy(sub_user, lp_guestaccount());
965 sub_set_smb_name(sub_user);
967 reload_services(True);
969 if (lp_security() == SEC_SHARE) {
970 /* in share level we should ignore any passwords */
972 data_blob_free(&lm_resp);
973 data_blob_free(&nt_resp);
974 data_blob_clear_free(&plaintext_password);
976 map_username(sub_user);
977 add_session_user(sub_user);
978 /* Then force it to null for the benfit of the code below */
984 nt_status = check_guest_password(&server_info);
986 } else if (doencrypt) {
987 if (!negprot_global_auth_context) {
988 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
989 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
991 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
993 if (NT_STATUS_IS_OK(nt_status)) {
994 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
999 struct auth_context *plaintext_auth_context = NULL;
1001 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
1002 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1004 if (!make_user_info_for_reply(&user_info,
1006 plaintext_password)) {
1007 nt_status = NT_STATUS_NO_MEMORY;
1010 if (NT_STATUS_IS_OK(nt_status)) {
1011 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1015 (plaintext_auth_context->free)(&plaintext_auth_context);
1020 free_user_info(&user_info);
1022 if (!NT_STATUS_IS_OK(nt_status)) {
1023 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1026 if (!NT_STATUS_IS_OK(nt_status)) {
1027 data_blob_free(&nt_resp);
1028 data_blob_free(&lm_resp);
1029 data_blob_clear_free(&plaintext_password);
1030 return ERROR_NT(nt_status_squash(nt_status));
1033 if (server_info->user_session_key.data) {
1034 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1036 session_key = data_blob(NULL, 0);
1039 data_blob_clear_free(&plaintext_password);
1041 /* it's ok - setup a reply */
1042 set_message(outbuf,3,0,True);
1043 if (Protocol >= PROTOCOL_NT1) {
1044 char *p = smb_buf( outbuf );
1045 p += add_signature( outbuf, p );
1046 set_message_end( outbuf, p );
1047 /* perhaps grab OS version here?? */
1050 if (server_info->guest) {
1051 SSVAL(outbuf,smb_vwv2,1);
1054 /* register the name and uid as being validated, so further connections
1055 to a uid can get through without a password, on the same VC */
1057 /* register_vuid keeps the server info */
1058 sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user);
1059 data_blob_free(&nt_resp);
1060 data_blob_free(&lm_resp);
1062 if (sess_vuid == -1) {
1063 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
1066 /* current_user_info is changed on new vuid */
1067 reload_services( True );
1069 if (!server_info->guest && !srv_signing_started() && !srv_check_sign_mac(inbuf, True)) {
1070 exit_server("reply_sesssetup_and_X: bad smb signature");
1073 SSVAL(outbuf,smb_uid,sess_vuid);
1074 SSVAL(inbuf,smb_uid,sess_vuid);
1076 if (!done_sesssetup)
1077 max_send = MIN(max_send,smb_bufsize);
1079 done_sesssetup = True;
1081 END_PROFILE(SMBsesssetupX);
1082 return chain_reply(inbuf,outbuf,length,bufsize);