From 13a8745cae2b38c8071b182a4c020305c76e62b8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 12 Sep 2010 10:06:39 +1000 Subject: s4-rodc: add a trigger message for REPL_SECRET to auth_sam when an RODC tries to authenticate against an account and the account has no password information it needs to send a message to the drepl server to tell it to try and replicate the secret information from a writeable DC Pair-Programmed-With: Andrew Bartlett --- source4/auth/ntlm/auth_sam.c | 52 +++++++++++++++++++++++++++++++++++++++ source4/dsdb/repl/drepl_service.c | 14 +++++++++++ source4/librpc/idl/irpc.idl | 7 ++++++ 3 files changed, 73 insertions(+) diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c index fdcc5bd90e..8de33ffa78 100644 --- a/source4/auth/ntlm/auth_sam.c +++ b/source4/auth/ntlm/auth_sam.c @@ -32,6 +32,8 @@ #include "dsdb/samdb/samdb.h" #include "dsdb/common/util.h" #include "param/param.h" +#include "librpc/gen_ndr/ndr_irpc_c.h" +#include "lib/messaging/irpc.h" extern const char *user_attrs[]; extern const char *domain_ref_attrs[]; @@ -135,6 +137,37 @@ static NTSTATUS authsam_password_ok(struct auth_context *auth_context, } +/* + send a message to the drepl server telling it to initiate a + REPL_SECRET getncchanges extended op to fetch the users secrets + */ +static void auth_sam_trigger_repl_secret(TALLOC_CTX *mem_ctx, struct auth_context *auth_context, + struct ldb_dn *user_dn) +{ + struct dcerpc_binding_handle *irpc_handle; + struct drepl_trigger_repl_secret r; + struct tevent_req *req; + + irpc_handle = irpc_binding_handle_by_name(mem_ctx, auth_context->msg_ctx, + "dreplsrv", + &ndr_table_irpc); + if (irpc_handle == NULL) { + DEBUG(1,(__location__ ": Unable to get binding handle for dreplsrv\n")); + return; + } + + r.in.user_dn = ldb_dn_get_linearized(user_dn); + + req = dcerpc_drepl_trigger_repl_secret_r_send(mem_ctx, + auth_context->event_ctx, + irpc_handle, + &r); + + /* we aren't interested in a reply */ + talloc_free(req); + talloc_free(irpc_handle); +} + static NTSTATUS authsam_authenticate(struct auth_context *auth_context, TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx, @@ -165,6 +198,25 @@ static NTSTATUS authsam_authenticate(struct auth_context *auth_context, nt_status = samdb_result_passwords(mem_ctx, auth_context->lp_ctx, msg, &lm_pwd, &nt_pwd); NT_STATUS_NOT_OK_RETURN(nt_status); + if (lm_pwd == NULL && nt_pwd == NULL) { + bool am_rodc; + if (samdb_rodc(auth_context->sam_ctx, &am_rodc) == LDB_SUCCESS && am_rodc) { + /* we don't have passwords for this + * account. We are an RODC, and this account + * may be one for which we either are denied + * REPL_SECRET replication or we haven't yet + * done the replication. We return + * NT_STATUS_NOT_IMPLEMENTED which tells the + * auth code to try the next authentication + * mechanism. We also send a message to our + * drepl server to tell it to try and + * replicate the secrets for this account. + */ + auth_sam_trigger_repl_secret(mem_ctx, auth_context, msg->dn); + return NT_STATUS_NOT_IMPLEMENTED; + } + } + nt_status = authsam_password_ok(auth_context, mem_ctx, acct_flags, lm_pwd, nt_pwd, user_info, user_sess_key, lm_sess_key); diff --git a/source4/dsdb/repl/drepl_service.c b/source4/dsdb/repl/drepl_service.c index 2c436172f1..9a353b0c1f 100644 --- a/source4/dsdb/repl/drepl_service.c +++ b/source4/dsdb/repl/drepl_service.c @@ -351,6 +351,19 @@ static NTSTATUS drepl_take_FSMO_role(struct irpc_message *msg, return NT_STATUS_OK; } +/** + * Called when the auth code wants us to try and replicate + * a users secrets + */ +static NTSTATUS drepl_trigger_repl_secret(struct irpc_message *msg, + struct drepl_trigger_repl_secret *r) +{ + /* we are not going to be sending a reply to this request */ + msg->no_reply = true; + DEBUG(0,(__location__ ": got drepl_trigger_repl_secret with %s\n", r->in.user_dn)); + return NT_STATUS_OK; +} + /* startup the dsdb replicator service task */ @@ -441,6 +454,7 @@ static void dreplsrv_task_init(struct task_server *task) IRPC_REGISTER(task->msg_ctx, irpc, DREPLSRV_REFRESH, dreplsrv_refresh, service); IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICASYNC, drepl_replica_sync, service); IRPC_REGISTER(task->msg_ctx, irpc, DREPL_TAKEFSMOROLE, drepl_take_FSMO_role, service); + IRPC_REGISTER(task->msg_ctx, irpc, DREPL_TRIGGER_REPL_SECRET, drepl_trigger_repl_secret, service); messaging_register(task->msg_ctx, service, MSG_DREPL_ALLOCATE_RID, dreplsrv_allocate_rid); } diff --git a/source4/librpc/idl/irpc.idl b/source4/librpc/idl/irpc.idl index 1639d49138..d6c4f84db9 100644 --- a/source4/librpc/idl/irpc.idl +++ b/source4/librpc/idl/irpc.idl @@ -173,4 +173,11 @@ import "misc.idl", "security.idl", "nbt.idl"; [in] uint32 role ); + /* + * message to tell the drepl server to initiate a REPL_SECRET + * replication of a users secrets + */ + void drepl_trigger_repl_secret( + [in] astring user_dn + ); } -- cgit