diff options
-rw-r--r-- | source4/auth/auth.h | 1 | ||||
-rw-r--r-- | source4/auth/auth_sam.c | 7 | ||||
-rw-r--r-- | source4/auth/ntlm_check.c | 27 | ||||
-rw-r--r-- | source4/rpc_server/netlogon/dcerpc_netlogon.c | 3 | ||||
-rw-r--r-- | source4/torture/rpc/samlogon.c | 23 |
5 files changed, 52 insertions, 9 deletions
diff --git a/source4/auth/auth.h b/source4/auth/auth.h index 55168a5beb..9f2e0b6a07 100644 --- a/source4/auth/auth.h +++ b/source4/auth/auth.h @@ -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, diff --git a/source4/auth/auth_sam.c b/source4/auth/auth_sam.c index e17eea8087..44609bb7f8 100644 --- a/source4/auth/auth_sam.c +++ b/source4/auth/auth_sam.c @@ -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); diff --git a/source4/auth/ntlm_check.c b/source4/auth/ntlm_check.c index 0856b82856..fc2a45efad 100644 --- a/source4/auth/ntlm_check.c +++ b/source4/auth/ntlm_check.c @@ -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; } diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 6366a58f4a..63c211baec 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -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: diff --git a/source4/torture/rpc/samlogon.c b/source4/torture/rpc/samlogon.c index 1094c2886e..36201aa210 100644 --- a/source4/torture/rpc/samlogon.c +++ b/source4/torture/rpc/samlogon.c @@ -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; } |