r11370: Samba4 now passes it's own RPC-SAMLOGON test again.
authorAndrew Bartlett <abartlet@samba.org>
Fri, 28 Oct 2005 11:20:48 +0000 (11:20 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:45:27 +0000 (13:45 -0500)
This avoids the nasty user@DOMAIN test for now, as it has very odd
semantics with NTLMv2.

Allow only user accounts to do an interactive login.

Andrew Bartlett
(This used to be commit 690cad8083e176b2e58fc243a11a003a78ce4074)

source4/auth/auth.h
source4/auth/auth_sam.c
source4/auth/ntlm_check.c
source4/rpc_server/netlogon/dcerpc_netlogon.c
source4/torture/rpc/samlogon.c

index 55168a5bebe8b8b3c616fdcb67eb9d62d0c6099d..9f2e0b6a078c1dbc64c1d033ad9a8c54c148c766 100644 (file)
@@ -39,6 +39,7 @@
 #define USER_INFO_CASE_INSENSITIVE_USERNAME 0x01 /* username may be in any case */
 #define USER_INFO_CASE_INSENSITIVE_PASSWORD 0x02 /* password may be in any case */
 #define USER_INFO_DONT_CHECK_UNIX_ACCOUNT   0x04 /* dont check unix account status */
+#define USER_INFO_INTERACTIVE_LOGON         0x08 /* dont check unix account status */
 
 enum auth_password_state {
        AUTH_PASSWORD_RESPONSE,
index e17eea80874c7d1f219baaaa3dcea023cf07a185..44609bb7f838a89a4d6028c67312c1256854488d 100644 (file)
@@ -370,6 +370,13 @@ static NTSTATUS authsam_authenticate(struct auth_context *auth_context,
                return NT_STATUS_ACCOUNT_LOCKED_OUT;
        }
 
+       /* You can only do an interactive login to normal accounts */
+       if (user_info->flags & USER_INFO_INTERACTIVE_LOGON) {
+               if (!(acct_flags & ACB_NORMAL)) {
+                       return NT_STATUS_NO_SUCH_USER;
+               }
+       }
+
        nt_status = samdb_result_passwords(mem_ctx, msgs[0], &lm_pwd, &nt_pwd);
        NT_STATUS_NOT_OK_RETURN(nt_status);
 
index 0856b828565ef69c24c2c7b6eed26edd3e1afdd6..fc2a45efad87ddd00dbd06845e11b005513ce3ea 100644 (file)
@@ -245,6 +245,9 @@ NTSTATUS hash_password_check(TALLOC_CTX *mem_ctx,
                                 username));
                        return NT_STATUS_WRONG_PASSWORD;
                }
+               if (strchr_m(username, '@')) {
+                       return NT_STATUS_NOT_FOUND;
+               }
 
                if (memcmp(client_lanman->hash, stored_lanman->hash, sizeof(stored_lanman->hash)) == 0) {
                        return NT_STATUS_OK;
@@ -254,6 +257,9 @@ NTSTATUS hash_password_check(TALLOC_CTX *mem_ctx,
                        return NT_STATUS_WRONG_PASSWORD;
                }
        }
+       if (strchr_m(username, '@')) {
+               return NT_STATUS_NOT_FOUND;
+       }
        return NT_STATUS_WRONG_PASSWORD;
 }
 
@@ -304,20 +310,27 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
            && (memcmp(challenge->data, zeros, challenge->length) == 0 )) {
                struct samr_Password client_nt;
                struct samr_Password client_lm;
-               uint8_t dospwd[14]; 
+               uint8_t dospwd[15]; 
+               char *unix_pw;
 
                DEBUG(4,("ntlm_password_check: checking plaintext passwords for user %s\n",
                         username));
                mdfour(client_nt.hash, nt_response->data, nt_response->length);
                ZERO_STRUCT(dospwd);
                
-               memcpy(dospwd, lm_response->data, MIN(lm_response->length, sizeof(dospwd)));
+               convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, 
+                                     lm_response->data, lm_response->length, 
+                                     (void **)&unix_pw);
+
                /* Only the fisrt 14 chars are considered, password need not be null terminated. */
+               push_ascii(dospwd, unix_pw, sizeof(dospwd), STR_UPPER);
                
                /* we *might* need to upper-case the string here */
                E_P16((const uint8_t *)dospwd, client_lm.hash);
                
-               return hash_password_check(mem_ctx, &client_lm, &client_nt, 
+               return hash_password_check(mem_ctx, 
+                                          lm_response->length ? &client_lm : NULL, 
+                                          nt_response->length ? &client_nt : NULL, 
                                           username,  
                                           stored_lanman, stored_nt);
        }
@@ -424,6 +437,9 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
        } else if (!stored_lanman) {
                DEBUG(3,("ntlm_password_check: NO LanMan password set for user %s (and no NT password supplied)\n",
                         username));
+       } else if (strchr_m(username, '@')) {
+               DEBUG(3,("ntlm_password_check: NO LanMan password allowed for username@realm logins (user: %s)\n",
+                        username));
        } else {
                DEBUG(4,("ntlm_password_check: Checking LM password\n"));
                if (smb_pwd_check_ntlmv1(mem_ctx,
@@ -572,6 +588,11 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
        } else {
                DEBUG(3,("ntlm_password_check: LM password and LMv2 failed for user %s, and NT MD4 password in LM field not permitted\n",username));
        }
+
+       /* Try and match error codes */
+       if (strchr_m(username, '@')) {
+               return NT_STATUS_NOT_FOUND;
+       }
        return NT_STATUS_WRONG_PASSWORD;
 }
 
index 6366a58f4a0be958df85053bb44e20bcd2664a4d..63c211baec0b48d94db1c01d4dbefc0f33baaea9 100644 (file)
@@ -417,6 +417,9 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_
                        return NT_STATUS_NO_MEMORY;
                }
                *user_info->password.hash.nt = r->in.logon.password->ntpassword;
+
+               user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
+
                break;          
        case 2:
        case 6:
index 1094c2886e834d6743d6f08c493dc99d88129ce5..36201aa210fe0b72d02367045b88bc99a33473a6 100644 (file)
@@ -304,6 +304,8 @@ static BOOL test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm
                        return True;
                }
                return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
+       } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
+               return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
        } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
                SAFE_FREE(*error_string);
                asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
@@ -633,6 +635,8 @@ static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state,
                        return True;
                }
                return break_which == BREAK_BOTH;
+       } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
+               return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
        } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
                SAFE_FREE(*error_string);
                asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
@@ -799,6 +803,8 @@ static BOOL test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state,
                        return True;
                }
                return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
+       } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
+               return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
        } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
                SAFE_FREE(*error_string);
                asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
@@ -1181,6 +1187,8 @@ static BOOL test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_brea
                        return True;
                }
                return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
+       } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
+               return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
        } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
                SAFE_FREE(*error_string);
                asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
@@ -1387,7 +1395,8 @@ BOOL test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                           const char *comment,
                           const char *workstation_name,
                           const char *account_domain, const char *account_name,
-                          const char *plain_pass, NTSTATUS expected_error)
+                          const char *plain_pass, uint32_t parameter_control, 
+                          NTSTATUS expected_error)
 {
        NTSTATUS status;
        TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_InteractiveLogon function-level context");
@@ -1411,7 +1420,7 @@ BOOL test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        r.in.flags = 0;
 
        pinfo.identity_info.domain_name.string = account_domain;
-       pinfo.identity_info.parameter_control = 0;
+       pinfo.identity_info.parameter_control = parameter_control;
        pinfo.identity_info.logon_id_low = 0;
        pinfo.identity_info.logon_id_high = 0;
        pinfo.identity_info.account_name.string = account_name;
@@ -1581,7 +1590,7 @@ BOOL torture_rpc_samlogon(void)
                                                cli_credentials_get_domain(cmdline_credentials)
                                        ),
                                .password      = cli_credentials_get_password(cmdline_credentials),
-                               .network_login = False,
+                               .network_login = False, /* works for some things, but not NTLMv2.  Odd */
                                .expected_interactive_error = NT_STATUS_OK,
                                .expected_network_error     = NT_STATUS_OK
                        },
@@ -1634,7 +1643,7 @@ BOOL torture_rpc_samlogon(void)
                                                                cli_credentials_get_domain(machine_credentials)
                                        ), 
                                .password      = cli_credentials_get_password(machine_credentials),
-                               .network_login = False,
+                               .network_login = False, /* works for some things, but not NTLMv2.  Odd */
                                .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
                                .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
                        },
@@ -1680,7 +1689,7 @@ BOOL torture_rpc_samlogon(void)
                                                                 TEST_USER_NAME,
                                                                 userdomain),
                                .password      = user_password,
-                               .network_login = False,
+                               .network_login = False, /* works for some things, but not NTLMv2.  Odd */
                                .expected_interactive_error = NT_STATUS_OK,
                                .expected_network_error     = NT_STATUS_OK
                        },
@@ -1706,6 +1715,7 @@ BOOL torture_rpc_samlogon(void)
                                                   usercreds[ci].domain,
                                                   usercreds[ci].username,
                                                   usercreds[ci].password,
+                                                  usercreds[ci].parameter_control,
                                                   usercreds[ci].expected_interactive_error)) {
                                ret = False;
                        }
@@ -1736,6 +1746,7 @@ BOOL torture_rpc_samlogon(void)
                                                   usercreds[0].domain,
                                                   usercreds[0].username,
                                                   usercreds[0].password,
+                                                  usercreds[0].parameter_control,
                                                   usercreds[0].expected_interactive_error)) {
                                ret = False;
                        }
@@ -1748,7 +1759,7 @@ BOOL torture_rpc_samlogon(void)
                                                   usercreds[0].password,
                                                   usercreds[0].parameter_control,
                                                   usercreds[0].expected_network_error,
-                                                  usercreds[ci].old_password,
+                                                  usercreds[0].old_password,
                                                   1)) {
                                        ret = False;
                                }