mirror of
https://github.com/samba-team/samba.git
synced 2025-02-25 17:57:42 +03:00
s4:kdc: redirect pre-authentication failures to an RWDC
The most important case is that we still have a previous password cached at the RODC and the inbound replication hasn't wiped the cache yet and we also haven't triggered a new replication yet. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14865 Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
parent
27ee5ad713
commit
0f5d7ff1a9
@ -377,7 +377,6 @@
|
||||
^samba.tests.auth_log_pass_change.samba.tests.auth_log_pass_change.AuthLogPassChangeTests.test_rap_change_password\(ad_dc_ntvfs\)
|
||||
# We currently don't send referrals for LDAP modify of non-replicated attrs
|
||||
^samba4.ldap.rodc.python\(rodc\).__main__.RodcTests.test_modify_nonreplicated.*
|
||||
^samba4.ldap.rodc_rwdc.python.*.__main__.RodcRwdcTests.test_change_password_reveal_on_demand_kerberos
|
||||
# NETLOGON is disabled in any non-DC environments
|
||||
^samba.tests.netlogonsvc.python\(ad_member\)
|
||||
^samba.tests.netlogonsvc.python\(simpleserver\)
|
||||
|
@ -1146,8 +1146,7 @@ class RodcRwdcTests(password_lockout_base.BasePasswordTestCase):
|
||||
|
||||
creds2 = make_creds(username, password)
|
||||
self.try_ldap_logon(RWDC, creds2)
|
||||
# We can forward WRONG_PASSWORD over NTLM.
|
||||
# This SHOULD succeed.
|
||||
# The RODC forward WRONG_PASSWORD to the RWDC
|
||||
self.try_ldap_logon(RODC, creds2)
|
||||
|
||||
def test_change_password_reveal_on_demand_ntlm(self):
|
||||
|
@ -466,60 +466,6 @@ static void reset_bad_password_netlogon(TALLOC_CTX *mem_ctx,
|
||||
irpc_handle, &req);
|
||||
}
|
||||
|
||||
static void send_bad_password_netlogon(TALLOC_CTX *mem_ctx,
|
||||
struct samba_kdc_db_context *kdc_db_ctx,
|
||||
struct auth_usersupplied_info *user_info)
|
||||
{
|
||||
struct dcerpc_binding_handle *irpc_handle;
|
||||
struct winbind_SamLogon req;
|
||||
struct netr_IdentityInfo *identity_info;
|
||||
struct netr_NetworkInfo *network_info;
|
||||
|
||||
irpc_handle = irpc_binding_handle_by_name(mem_ctx, kdc_db_ctx->msg_ctx,
|
||||
"winbind_server",
|
||||
&ndr_table_winbind);
|
||||
if (irpc_handle == NULL) {
|
||||
DEBUG(0, ("Winbind forwarding for [%s]\\[%s] failed, "
|
||||
"no winbind_server running!\n",
|
||||
user_info->mapped.domain_name, user_info->mapped.account_name));
|
||||
return;
|
||||
}
|
||||
|
||||
network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
|
||||
if (network_info == NULL) {
|
||||
DEBUG(0, ("Winbind forwarding failed: No memory\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
identity_info = &network_info->identity_info;
|
||||
req.in.logon_level = 2;
|
||||
req.in.logon.network = network_info;
|
||||
|
||||
identity_info->domain_name.string = user_info->mapped.domain_name;
|
||||
identity_info->parameter_control = user_info->logon_parameters; /* TODO */
|
||||
identity_info->logon_id = user_info->logon_id;
|
||||
identity_info->account_name.string = user_info->mapped.account_name;
|
||||
identity_info->workstation.string
|
||||
= talloc_asprintf(identity_info, "krb5-bad-pw on RODC from %s",
|
||||
tsocket_address_string(user_info->remote_host,
|
||||
identity_info));
|
||||
if (identity_info->workstation.string == NULL) {
|
||||
DEBUG(0, ("Winbind forwarding failed: No memory allocating workstation string\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
req.in.validation_level = 3;
|
||||
|
||||
/*
|
||||
* The memory in identity_info and user_info only needs to be
|
||||
* valid until the end of this function call, as it will be
|
||||
* pushed to NDR during this call
|
||||
*/
|
||||
|
||||
dcerpc_winbind_SamLogon_r_send(mem_ctx, kdc_db_ctx->ev_ctx,
|
||||
irpc_handle, &req);
|
||||
}
|
||||
|
||||
static krb5_error_code hdb_samba4_audit(krb5_context context,
|
||||
HDB *db,
|
||||
hdb_entry *entry,
|
||||
@ -527,24 +473,18 @@ static krb5_error_code hdb_samba4_audit(krb5_context context,
|
||||
{
|
||||
struct samba_kdc_db_context *kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
|
||||
struct samba_kdc_db_context);
|
||||
|
||||
struct ldb_dn *domain_dn = ldb_get_default_basedn(kdc_db_ctx->samdb);
|
||||
uint64_t logon_id = generate_random_u64();
|
||||
|
||||
heim_object_t auth_details_obj = NULL;
|
||||
const char *auth_details = NULL;
|
||||
|
||||
char *etype_str = NULL;
|
||||
|
||||
heim_object_t hdb_auth_status_obj = NULL;
|
||||
int hdb_auth_status;
|
||||
|
||||
heim_object_t pa_type_obj = NULL;
|
||||
const char *pa_type = NULL;
|
||||
|
||||
struct auth_usersupplied_info ui;
|
||||
|
||||
size_t sa_socklen = 0;
|
||||
int final_ret = 0;
|
||||
|
||||
hdb_auth_status_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_AUTH_EVENT);
|
||||
if (hdb_auth_status_obj == NULL) {
|
||||
@ -645,6 +585,7 @@ static krb5_error_code hdb_samba4_audit(krb5_context context,
|
||||
const char *auth_description = NULL;
|
||||
NTSTATUS status;
|
||||
int ret;
|
||||
bool rwdc_fallback = false;
|
||||
|
||||
ret = tsocket_address_bsd_from_sockaddr(frame, r->addr,
|
||||
sa_socklen,
|
||||
@ -677,34 +618,44 @@ static krb5_error_code hdb_samba4_audit(krb5_context context,
|
||||
} else if (hdb_auth_status == KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY) {
|
||||
authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, domain_dn);
|
||||
status = NT_STATUS_WRONG_PASSWORD;
|
||||
/*
|
||||
* TODO We currently send a bad password via NETLOGON,
|
||||
* however, it should probably forward the ticket to
|
||||
* another KDC to allow login after password changes.
|
||||
*/
|
||||
if (kdc_db_ctx->rodc) {
|
||||
send_bad_password_netlogon(frame, kdc_db_ctx, &ui);
|
||||
}
|
||||
rwdc_fallback = kdc_db_ctx->rodc;
|
||||
} else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_LOCKED_OUT) {
|
||||
status = NT_STATUS_ACCOUNT_LOCKED_OUT;
|
||||
rwdc_fallback = kdc_db_ctx->rodc;
|
||||
} else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED) {
|
||||
if (pa_type != NULL && strncmp(pa_type, "PK-INIT", strlen("PK-INIT")) == 0) {
|
||||
status = NT_STATUS_PKINIT_NAME_MISMATCH;
|
||||
} else {
|
||||
status = NT_STATUS_ACCOUNT_RESTRICTION;
|
||||
}
|
||||
rwdc_fallback = kdc_db_ctx->rodc;
|
||||
} else if (hdb_auth_status == KDC_AUTH_EVENT_PREAUTH_FAILED) {
|
||||
if (pa_type != NULL && strncmp(pa_type, "PK-INIT", strlen("PK-INIT")) == 0) {
|
||||
status = NT_STATUS_PKINIT_FAILURE;
|
||||
} else {
|
||||
status = NT_STATUS_GENERIC_COMMAND_FAILED;
|
||||
}
|
||||
rwdc_fallback = kdc_db_ctx->rodc;
|
||||
} else {
|
||||
DBG_ERR("Unhandled hdb_auth_status=%d => INTERNAL_ERROR\n",
|
||||
hdb_auth_status);
|
||||
status = NT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if (rwdc_fallback) {
|
||||
/*
|
||||
* Forward the request to an RWDC in order
|
||||
* to give an authoritative answer to the client.
|
||||
*/
|
||||
auth_description = talloc_asprintf(frame,
|
||||
"%s,Forward-To-RWDC",
|
||||
ui.auth_description);
|
||||
if (auth_description != NULL) {
|
||||
ui.auth_description = auth_description;
|
||||
}
|
||||
final_ret = HDB_ERR_NOT_FOUND_HERE;
|
||||
}
|
||||
|
||||
log_authentication_event(kdc_db_ctx->msg_ctx,
|
||||
kdc_db_ctx->lp_ctx,
|
||||
&r->tv_start,
|
||||
@ -736,6 +687,8 @@ static krb5_error_code hdb_samba4_audit(krb5_context context,
|
||||
|
||||
ui.auth_description = pa_type;
|
||||
|
||||
/* Note this is not forwarded to an RWDC */
|
||||
|
||||
log_authentication_event(kdc_db_ctx->msg_ctx,
|
||||
kdc_db_ctx->lp_ctx,
|
||||
&r->tv_start,
|
||||
@ -750,7 +703,7 @@ static krb5_error_code hdb_samba4_audit(krb5_context context,
|
||||
|
||||
free(etype_str);
|
||||
|
||||
return 0;
|
||||
return final_ret;
|
||||
}
|
||||
|
||||
/* This interface is to be called by the KDC and libnet_keytab_dump,
|
||||
|
Loading…
x
Reference in New Issue
Block a user