s4 dns: Allow to specify static grant entries to be added to the dynamicaly generated...
[samba.git] / source4 / dsdb / dns / dns_update.c
index 9252ffbe4b45d385b34d8f817aeaef801f51cf67..1420bb7f4b0f616dd296d7b919780caf3e630a97 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Unix SMB/CIFS mplementation.
 
-   DNS udpate service
+   DNS update service
 
    Copyright (C) Andrew Tridgell 2009
 
@@ -46,7 +46,7 @@ struct dnsupdate_service {
        struct {
                uint32_t interval;
                struct tevent_timer *te;
-               struct composite_context *c;
+               struct tevent_req *subreq;
                NTSTATUS status;
        } confupdate;
 
@@ -54,7 +54,7 @@ struct dnsupdate_service {
        struct {
                uint32_t interval;
                struct tevent_timer *te;
-               struct composite_context *c;
+               struct tevent_req *subreq;
                NTSTATUS status;
        } nameupdate;
 };
@@ -62,18 +62,29 @@ struct dnsupdate_service {
 /*
   called when rndc reload has finished
  */
-static void dnsupdate_rndc_done(struct composite_context *c)
+static void dnsupdate_rndc_done(struct tevent_req *subreq)
 {
-       struct dnsupdate_service *service = talloc_get_type_abort(c->async.private_data,
-                                                                 struct dnsupdate_service);
-       service->confupdate.status = composite_wait(c);
+       struct dnsupdate_service *service = tevent_req_callback_data(subreq,
+                                           struct dnsupdate_service);
+       int ret;
+       int sys_errno;
+
+       service->confupdate.subreq = NULL;
+
+       ret = samba_runcmd_recv(subreq, &sys_errno);
+       TALLOC_FREE(subreq);
+       if (ret != 0) {
+               service->confupdate.status = map_nt_error_from_unix(sys_errno);
+       } else {
+               service->confupdate.status = NT_STATUS_OK;
+       }
+
        if (!NT_STATUS_IS_OK(service->confupdate.status)) {
                DEBUG(0,(__location__ ": Failed rndc update - %s\n",
                         nt_errstr(service->confupdate.status)));
-               return;
+       } else {
+               DEBUG(3,("Completed rndc reload OK\n"));
        }
-       talloc_free(c);
-       service->confupdate.c = NULL;
 }
 
 /*
@@ -82,12 +93,19 @@ static void dnsupdate_rndc_done(struct composite_context *c)
 static void dnsupdate_rebuild(struct dnsupdate_service *service)
 {
        int ret;
+       size_t size;
        struct ldb_result *res;
-       const char *tmp_path, *path;
-       int fd, i;
+       const char *tmp_path, *path, *path_static;
+       char *static_policies;
+       int fd;
+       unsigned int i;
        const char *attrs[] = { "sAMAccountName", NULL };
        const char *realm = lp_realm(service->task->lp_ctx);
        TALLOC_CTX *tmp_ctx = talloc_new(service);
+       const char * const *rndc_command = lp_rndc_command(service->task->lp_ctx);
+
+       /* abort any pending script run */
+       TALLOC_FREE(service->confupdate.subreq);
 
        ret = ldb_search(service->samdb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
                         attrs, "(&(primaryGroupID=%u)(objectClass=computer))",
@@ -103,13 +121,20 @@ static void dnsupdate_rebuild(struct dnsupdate_service *service)
                path = private_path(tmp_ctx, service->task->lp_ctx, "named.conf.update");
        }
 
+       path_static = lp_parm_string(service->task->lp_ctx, NULL, "dnsupdate", "extra_static_grant_rules");
+       if (path_static == NULL) {
+               path_static = private_path(tmp_ctx, service->task->lp_ctx, "named.conf.update.static");
+       }
+
        tmp_path = talloc_asprintf(tmp_ctx, "%s.tmp", path);
-       if (path == NULL || tmp_path == NULL) {
-               DEBUG(0,(__location__ ": Unable to get paths"));
+       if (path == NULL || tmp_path == NULL || path_static == NULL ) {
+               DEBUG(0,(__location__ ": Unable to get paths\n"));
                talloc_free(tmp_ctx);
                return;
        }
 
+       static_policies = file_load(path_static, &size, 0, tmp_ctx);
+
        unlink(tmp_path);
        fd = open(tmp_path, O_CREAT|O_TRUNC|O_WRONLY, 0444);
        if (fd == -1) {
@@ -120,6 +145,11 @@ static void dnsupdate_rebuild(struct dnsupdate_service *service)
 
        dprintf(fd, "/* this file is auto-generated - do not edit */\n");
        dprintf(fd, "update-policy {\n");
+       if( static_policies != NULL ) {
+               dprintf(fd, "/* Start of static entries */\n");
+               dprintf(fd, "%s\n",static_policies);
+               dprintf(fd, "/* End of static entries */\n");
+       }
        dprintf(fd, "\tgrant %s ms-self * A AAAA;\n", realm);
        dprintf(fd, "\tgrant administrator@%s wildcard * A AAAA SRV CNAME TXT;\n", realm);
 
@@ -134,10 +164,6 @@ static void dnsupdate_rebuild(struct dnsupdate_service *service)
        dprintf(fd, "};\n");
        close(fd);
 
-       if (service->confupdate.c != NULL) {
-               talloc_free(service->confupdate.c);
-               service->confupdate.c = NULL;
-       }
 
        if (NT_STATUS_IS_OK(service->confupdate.status) &&
            file_compare(tmp_path, path) == true) {
@@ -154,13 +180,20 @@ static void dnsupdate_rebuild(struct dnsupdate_service *service)
        }
 
        DEBUG(2,("Loading new DNS update grant rules\n"));
-       service->confupdate.c = samba_runcmd(service->task->event_ctx, service,
-                                          timeval_current_ofs(10, 0),
-                                          2, 0,
-                                          lp_rndc_command(service->task->lp_ctx),
-                                          "reload", NULL);
-       service->confupdate.c->async.fn = dnsupdate_rndc_done;
-       service->confupdate.c->async.private_data = service;
+       service->confupdate.subreq = samba_runcmd_send(service,
+                                                      service->task->event_ctx,
+                                                      timeval_current_ofs(10, 0),
+                                                      2, 0,
+                                                      rndc_command,
+                                                      "reload", NULL);
+       if (service->confupdate.subreq == NULL) {
+               DEBUG(0,(__location__ ": samba_runcmd_send() failed with no memory\n"));
+               talloc_free(tmp_ctx);
+               return;
+       }
+       tevent_req_set_callback(service->confupdate.subreq,
+                               dnsupdate_rndc_done,
+                               service);
 
        talloc_free(tmp_ctx);
 }
@@ -193,18 +226,29 @@ static NTSTATUS dnsupdate_confupdate_schedule(struct dnsupdate_service *service)
 /*
   called when dns update script has finished
  */
-static void dnsupdate_nameupdate_done(struct composite_context *c)
+static void dnsupdate_nameupdate_done(struct tevent_req *subreq)
 {
-       struct dnsupdate_service *service = talloc_get_type_abort(c->async.private_data,
-                                                                 struct dnsupdate_service);
-       service->nameupdate.status = composite_wait(c);
+       struct dnsupdate_service *service = tevent_req_callback_data(subreq,
+                                           struct dnsupdate_service);
+       int ret;
+       int sys_errno;
+
+       service->nameupdate.subreq = NULL;
+
+       ret = samba_runcmd_recv(subreq, &sys_errno);
+       TALLOC_FREE(subreq);
+       if (ret != 0) {
+               service->nameupdate.status = map_nt_error_from_unix(sys_errno);
+       } else {
+               service->nameupdate.status = NT_STATUS_OK;
+       }
+
        if (!NT_STATUS_IS_OK(service->nameupdate.status)) {
                DEBUG(0,(__location__ ": Failed DNS update - %s\n",
                         nt_errstr(service->nameupdate.status)));
-               return;
+       } else {
+               DEBUG(3,("Completed DNS update check OK\n"));
        }
-       talloc_free(c);
-       service->nameupdate.c = NULL;
 }
 
 /*
@@ -212,20 +256,25 @@ static void dnsupdate_nameupdate_done(struct composite_context *c)
  */
 static void dnsupdate_check_names(struct dnsupdate_service *service)
 {
+       const char * const *dns_update_command = lp_dns_update_command(service->task->lp_ctx);
+
        /* kill any existing child */
-       if (service->nameupdate.c != NULL) {
-               talloc_free(service->nameupdate.c);
-               service->nameupdate.c = NULL;
-       }
+       TALLOC_FREE(service->nameupdate.subreq);
 
        DEBUG(3,("Calling DNS name update script\n"));
-       service->nameupdate.c = samba_runcmd(service->task->event_ctx, service,
-                                            timeval_current_ofs(10, 0),
-                                            2, 0,
-                                            lp_dns_update_command(service->task->lp_ctx),
-                                            NULL);
-       service->nameupdate.c->async.fn = dnsupdate_nameupdate_done;
-       service->nameupdate.c->async.private_data = service;
+       service->nameupdate.subreq = samba_runcmd_send(service,
+                                                      service->task->event_ctx,
+                                                      timeval_current_ofs(10, 0),
+                                                      2, 0,
+                                                      dns_update_command,
+                                                      NULL);
+       if (service->nameupdate.subreq == NULL) {
+               DEBUG(0,(__location__ ": samba_runcmd_send() failed with no memory\n"));
+               return;
+       }
+       tevent_req_set_callback(service->nameupdate.subreq,
+                               dnsupdate_nameupdate_done,
+                               service);
 }
 
 static NTSTATUS dnsupdate_nameupdate_schedule(struct dnsupdate_service *service);
@@ -297,6 +346,7 @@ static void dnsupdate_task_init(struct task_server *task)
        service->nameupdate.interval    = lp_parm_int(task->lp_ctx, NULL,
                                                      "dnsupdate", "name interval", 600); /* in seconds */
 
+       dnsupdate_rebuild(service);
        status = dnsupdate_confupdate_schedule(service);
        if (!NT_STATUS_IS_OK(status)) {
                task_server_terminate(task, talloc_asprintf(task,
@@ -305,6 +355,7 @@ static void dnsupdate_task_init(struct task_server *task)
                return;
        }
 
+       dnsupdate_check_names(service);
        status = dnsupdate_nameupdate_schedule(service);
        if (!NT_STATUS_IS_OK(status)) {
                task_server_terminate(task, talloc_asprintf(task,