s4-rodc: add a trigger message for REPL_SECRET to auth_sam
authorAndrew Tridgell <tridge@samba.org>
Sun, 12 Sep 2010 00:06:39 +0000 (10:06 +1000)
committerAndrew Tridgell <tridge@samba.org>
Wed, 15 Sep 2010 05:39:34 +0000 (15:39 +1000)
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 <abartlet@samba.org>

source4/auth/ntlm/auth_sam.c
source4/dsdb/repl/drepl_service.c
source4/librpc/idl/irpc.idl

index fdcc5bd90ea9705b59b576a62511d6267f536bd7..8de33ffa7826fa4cc6ab4f7208a6e45e91a7d761 100644 (file)
@@ -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);
index 2c436172f1563566b2e161851e5a617202f36f5c..9a353b0c1fc0254b84958ab86c5771a69fd80410 100644 (file)
@@ -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);
 }
 
index 1639d49138e1b63c6a85a260320906485f581698..d6c4f84db9d227780739aa484a0878d85b199d60 100644 (file)
@@ -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
+               );
 }