diff options
author | Andrew Bartlett <abartlet@samba.org> | 2001-09-26 13:55:59 +0000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2001-09-26 13:55:59 +0000 |
commit | 41821943daef5a4fd077e38068539ae4e24121b3 (patch) | |
tree | 3694b89ec3ea0c5fb67c97a112940b2a16210f26 /source3 | |
parent | 865467c82f39a98afa3c65f25b7e24137f904e93 (diff) | |
download | samba-41821943daef5a4fd077e38068539ae4e24121b3.tar.gz samba-41821943daef5a4fd077e38068539ae4e24121b3.tar.bz2 samba-41821943daef5a4fd077e38068539ae4e24121b3.zip |
Kill of the reply.c end of the workstaion trust account mess.
Fix the NT errror codes, this time in line with WinXP/2k.
- Return the normal error codes, expect for bad user/bad password. These map
to logon failure, as a quick security hack. We follow suit.
Simplfy some of the password extraction code, the auth subsytem has the
intelegence to sort this stuff out, no need to do it here.
Move to 'global_encrypted_passwords_negotiated' to determine the use of
unencrypted hacks, replacing the current mess.
Andrew Bartlett
(This used to be commit c04f063573c61d8ef3f43815bbb9b6b076dc23eb)
Diffstat (limited to 'source3')
-rw-r--r-- | source3/smbd/negprot.c | 32 | ||||
-rw-r--r-- | source3/smbd/reply.c | 198 |
2 files changed, 61 insertions, 169 deletions
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index b065cab53e..82222e6725 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -26,6 +26,7 @@ extern int Protocol; extern int max_recv; extern fstring global_myworkgroup; extern fstring remote_machine; +BOOL global_encrypted_passwords_negotiated; /**************************************************************************** reply for the core protocol @@ -66,16 +67,17 @@ static int reply_lanman1(char *outbuf) { int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); int secword=0; - BOOL doencrypt = lp_encrypted_passwords(); time_t t = time(NULL); + global_encrypted_passwords_negotiated = lp_encrypted_passwords(); + if (lp_security()>=SEC_USER) secword |= 1; - if (doencrypt) secword |= 2; + if (global_encrypted_passwords_negotiated) secword |= 2; - set_message(outbuf,13,doencrypt?8:0,True); + set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True); SSVAL(outbuf,smb_vwv1,secword); /* Create a token value and add it to the outgoing packet. */ - if (doencrypt) + if (global_encrypted_passwords_negotiated) generate_next_challenge(smb_buf(outbuf)); Protocol = PROTOCOL_LANMAN1; @@ -103,25 +105,26 @@ static int reply_lanman2(char *outbuf) { int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); int secword=0; - BOOL doencrypt = lp_encrypted_passwords(); time_t t = time(NULL); struct cli_state *cli = NULL; char cryptkey[8]; char crypt_len = 0; + global_encrypted_passwords_negotiated = lp_encrypted_passwords(); + if (lp_security() == SEC_SERVER) { cli = server_cryptkey(); } if (cli) { DEBUG(3,("using password server validation\n")); - doencrypt = ((cli->sec_mode & 2) != 0); + global_encrypted_passwords_negotiated = ((cli->sec_mode & 2) != 0); } if (lp_security()>=SEC_USER) secword |= 1; - if (doencrypt) secword |= 2; + if (global_encrypted_passwords_negotiated) secword |= 2; - if (doencrypt) { + if (global_encrypted_passwords_negotiated) { crypt_len = 8; if (!cli) { generate_next_challenge(cryptkey); @@ -134,7 +137,7 @@ static int reply_lanman2(char *outbuf) set_message(outbuf,13,crypt_len,True); SSVAL(outbuf,smb_vwv1,secword); SIVAL(outbuf,smb_vwv6,sys_getpid()); - if (doencrypt) + if (global_encrypted_passwords_negotiated) memcpy(smb_buf(outbuf), cryptkey, 8); Protocol = PROTOCOL_LANMAN2; @@ -162,13 +165,14 @@ static int reply_nt1(char *outbuf) CAP_LEVEL_II_OPLOCKS|CAP_STATUS32; int secword=0; - BOOL doencrypt = lp_encrypted_passwords(); time_t t = time(NULL); struct cli_state *cli = NULL; char cryptkey[8]; char crypt_len = 0; char *p, *q; + global_encrypted_passwords_negotiated = lp_encrypted_passwords(); + if (lp_security() == SEC_SERVER) { DEBUG(5,("attempting password server validation\n")); cli = server_cryptkey(); @@ -178,12 +182,12 @@ static int reply_nt1(char *outbuf) if (cli) { DEBUG(3,("using password server validation\n")); - doencrypt = ((cli->sec_mode & 2) != 0); + global_encrypted_passwords_negotiated = ((cli->sec_mode & 2) != 0); } else { DEBUG(3,("not using password server validation\n")); } - if (doencrypt) { + if (global_encrypted_passwords_negotiated) { crypt_len = 8; if (!cli) { generate_next_challenge(cryptkey); @@ -216,7 +220,7 @@ static int reply_nt1(char *outbuf) capabilities |= CAP_DFS; if (lp_security() >= SEC_USER) secword |= 1; - if (doencrypt) secword |= 2; + if (global_encrypted_passwords_negotiated) secword |= 2; set_message(outbuf,17,0,True); @@ -235,7 +239,7 @@ static int reply_nt1(char *outbuf) SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60); p = q = smb_buf(outbuf); - if (doencrypt) memcpy(p, cryptkey, 8); + if (global_encrypted_passwords_negotiated) memcpy(p, cryptkey, 8); p += 8; p += srvstr_push(outbuf, p, global_myworkgroup, -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 572ed90b32..dbd149afcf 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -43,6 +43,7 @@ uint32 global_client_caps = 0; unsigned int smb_echo_count = 0; extern fstring remote_machine; +extern BOOL global_encrypted_passwords_negotiated; /**************************************************************************** report a possible attack via the password buffer overflow bug @@ -246,7 +247,6 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt passlen = strlen(password); } - /* * the service name can be either: \\server\share * or share directly like on the DELL PowerVault 705 @@ -374,107 +374,6 @@ int reply_ioctl(connection_struct *conn, } /**************************************************************************** - This function breaks the authentication split. It needs sorting out. - I can't see why we can't hadle this INSIDE the check_password, as in then - end all it does it spit out an nt_status code. - ****************************************************************************/ -/**************************************************************************** - always return an error: it's just a matter of which one... - ****************************************************************************/ -static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user, - char *smb_passwd, int smb_passlen, - char *smb_nt_passwd, int smb_nt_passlen) -{ - /* check if trust account exists */ - SAM_ACCOUNT *sam_trust_acct = NULL; - uint16 acct_ctrl; - BOOL ret; - auth_usersupplied_info user_info; - auth_serversupplied_info server_info; - AUTH_STR domain, smb_username, wksta_name; - - ZERO_STRUCT(user_info); - ZERO_STRUCT(server_info); - ZERO_STRUCT(domain); - ZERO_STRUCT(smb_username); - ZERO_STRUCT(wksta_name); - - domain.str = lp_workgroup(); - domain.len = strlen(domain.str); - - user_info.requested_domain = domain; - user_info.domain = domain; - - smb_username.str = user; - smb_username.len = strlen(smb_username.str); - - user_info.unix_username = smb_username; /* For the time-being */ - user_info.smb_username = smb_username; - - user_info.wksta_name = wksta_name; - - user_info.lm_resp.buffer = (uint8 *)smb_passwd; - user_info.lm_resp.len = smb_passlen; - user_info.nt_resp.buffer = (uint8 *)smb_nt_passwd; - user_info.nt_resp.len = smb_nt_passlen; - - if (!last_challenge(user_info.chal)) { - DEBUG(1,("smb_password_ok: no challenge done - password failed\n")); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - - pdb_init_sam(&sam_trust_acct); - - if (lp_security() == SEC_USER) { - ret = pdb_getsampwnam(sam_trust_acct, user); - } else { - DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user)); - pdb_free_sam(sam_trust_acct); - return(ERROR_NT(NT_STATUS_LOGON_FAILURE)); - } - - if (ret == False) { - /* lkclXXXX: workstation entry doesn't exist */ - DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user)); - pdb_free_sam(sam_trust_acct); - return(ERROR_NT(NT_STATUS_NO_SUCH_USER)); - } else { - if ((smb_passlen != 24) || (smb_nt_passlen != 24)) { - DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user)); - pdb_free_sam(sam_trust_acct); - return(ERROR_NT(NT_STATUS_LOGON_FAILURE)); - } - - if (!NT_STATUS_IS_OK(smb_password_ok(sam_trust_acct, &user_info, &server_info))) { - DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user)); - pdb_free_sam(sam_trust_acct); - return(ERROR_NT(NT_STATUS_LOGON_FAILURE)); - } - - acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct); - pdb_free_sam(sam_trust_acct); - if (acct_ctrl & ACB_DOMTRUST) { - DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user)); - return(ERROR_NT(NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)); - } - - if (acct_ctrl & ACB_SVRTRUST) { - DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user)); - return(ERROR_NT(NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT)); - } - - if (acct_ctrl & ACB_WSTRUST) { - DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user)); - return(ERROR_NT(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)); - } - } - - /* don't know what to do: indicate logon failure */ - return(ERROR_NT(NT_STATUS_LOGON_FAILURE)); -} - - -/**************************************************************************** reply to a session setup command ****************************************************************************/ @@ -496,14 +395,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int fstring native_lanman; BOOL guest=False; static BOOL done_sesssetup = False; - BOOL doencrypt = lp_encrypted_passwords(); + BOOL doencrypt = global_encrypted_passwords_negotiated; START_PROFILE(SMBsesssetupX); - ZERO_STRUCT(smb_apasswd); - ZERO_STRUCT(smb_ntpasswd); + *smb_apasswd = *smb_ntpasswd = 0; smb_bufsize = SVAL(inbuf,smb_vwv2); - + if (Protocol < PROTOCOL_NT1) { smb_apasslen = SVAL(inbuf,smb_vwv7); if (smb_apasslen > MAX_PASS_LEN) { @@ -513,7 +411,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE); - + if (!doencrypt && (lp_security() != SEC_SERVER)) { smb_apasslen = strlen(smb_apasswd); } @@ -585,27 +483,22 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int } } - if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) { - /* Save the lanman2 password and the NT md4 password. */ - smb_apasslen = passlen1; - memcpy(smb_apasswd,p,smb_apasslen); - smb_apasswd[smb_apasslen] = 0; - smb_ntpasslen = passlen2; - memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen); - smb_ntpasswd[smb_ntpasslen] = 0; - } else { - /* we use the first password that they gave */ - smb_apasslen = passlen1; - StrnCpy(smb_apasswd,p,smb_apasslen); - - /* trim the password */ - smb_apasslen = strlen(smb_apasswd); + /* Save the lanman2 password and the NT md4 password. */ + smb_apasslen = passlen1; + memcpy(smb_apasswd,p,smb_apasslen); - /* wfwg sometimes uses a space instead of a null */ - if (strequal(smb_apasswd," ")) { - smb_apasslen = 0; - *smb_apasswd = 0; - } + smb_ntpasslen = passlen2; + memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen); + + if (smb_apasslen != 24 || !doencrypt) { + /* trim the password */ + smb_apasslen = strlen(smb_apasswd); + + /* wfwg sometimes uses a space instead of a null */ + if (strequal(smb_apasswd," ")) { + smb_apasslen = 0; + *smb_apasswd = 0; + } } p += passlen1 + passlen2; @@ -640,18 +533,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int } - DEBUG(3,("sesssetupX:name=[%s]@[%s]\n",user, remote_machine)); - - /* If name ends in $ then I think it's asking about whether a */ - /* computer with that name (minus the $) has access. For now */ - /* say yes to everything ending in $. */ - - if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) { - END_PROFILE(SMBsesssetupX); - return session_trust_account(conn, inbuf, outbuf, user, - smb_apasswd, smb_apasslen, - smb_ntpasswd, smb_ntpasslen); - } + DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",user, domain, remote_machine)); if (done_sesssetup && lp_restrict_anonymous()) { /* tests show that even if browsing is done over already validated connections @@ -731,21 +613,27 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if NT_STATUS_IS_OK(nt_status) { - } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) - && lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) { - DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain)); - pstrcpy(user,lp_guestaccount(-1)); - guest = True; - - } else if ((NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) - || NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) - && (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { - pstrcpy(user,lp_guestaccount(-1)); - DEBUG(3,("Registered username %s for guest access\n",user)); - guest = True; - + } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) { + if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || + (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) { + DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain)); + pstrcpy(user,lp_guestaccount(-1)); + guest = True; + } else { + /* Match WinXP and don't give the game away */ + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } + } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) { + if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) { + pstrcpy(user,lp_guestaccount(-1)); + DEBUG(3,("Registered username %s for guest access\n",user)); + guest = True; + } else { + /* Match WinXP and don't give the game away */ + return ERROR_NT(NT_STATUS_LOGON_FAILURE); + } } else { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + return ERROR_NT(nt_status); } } @@ -792,10 +680,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int /* register the name and uid as being validated, so further connections to a uid can get through without a password, on the same VC */ - sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest, full_name); + sess_vuid = register_vuid(uid,gid,user,orig_user,domain,guest, full_name); if (sess_vuid == -1) { - return ERROR_DOS(ERRDOS,ERRnoaccess); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } |