diff options
author | Andrew Tridgell <tridge@samba.org> | 2010-09-27 21:08:43 -0700 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2010-09-27 22:55:05 -0700 |
commit | 0bbbfa04f60b173912cedcfe08590fe43b5c2872 (patch) | |
tree | cf4fc9cec7aa95cfe0f34f8d04ccb875436f16fe | |
parent | c4d2b6fbc21625dc5ed2063e5ad699309fa5a3e1 (diff) | |
download | samba-0bbbfa04f60b173912cedcfe08590fe43b5c2872.tar.gz samba-0bbbfa04f60b173912cedcfe08590fe43b5c2872.tar.bz2 samba-0bbbfa04f60b173912cedcfe08590fe43b5c2872.zip |
s4-dns: implemented RODC DNS update in dns update task
Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>
-rw-r--r-- | source4/dsdb/dns/dns_update.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/source4/dsdb/dns/dns_update.c b/source4/dsdb/dns/dns_update.c index e9f93038b6..fbfca192ba 100644 --- a/source4/dsdb/dns/dns_update.c +++ b/source4/dsdb/dns/dns_update.c @@ -36,6 +36,8 @@ #include "param/param.h" #include "system/filesys.h" #include "libcli/composite/composite.h" +#include "libcli/security/dom_sid.h" +#include "librpc/gen_ndr/ndr_irpc.h" struct dnsupdate_service { struct task_server *task; @@ -347,6 +349,200 @@ static NTSTATUS dnsupdate_nameupdate_schedule(struct dnsupdate_service *service) return NT_STATUS_OK; } + +struct dnsupdate_RODC_state { + struct irpc_message *msg; + struct dnsupdate_RODC *r; + char *tmp_path; + int fd; +}; + +static int dnsupdate_RODC_destructor(struct dnsupdate_RODC_state *st) +{ + if (st->fd != -1) { + close(st->fd); + } + unlink(st->tmp_path); + return 0; +} + +/* + called when the DNS update has completed + */ +static void dnsupdate_RODC_callback(struct tevent_req *req) +{ + struct dnsupdate_RODC_state *st = + tevent_req_callback_data(req, + struct dnsupdate_RODC_state); + int sys_errno; + int i, ret; + + ret = samba_runcmd_recv(req, &sys_errno); + talloc_free(req); + if (ret != 0) { + st->r->out.result = map_nt_error_from_unix(sys_errno); + DEBUG(2,(__location__ ": RODC DNS Update failed: %s\n", nt_errstr(st->r->out.result))); + } else { + st->r->out.result = NT_STATUS_OK; + DEBUG(3,(__location__ ": RODC DNS Update OK\n")); + } + + for (i=0; i<st->r->in.dns_names->count; i++) { + st->r->out.dns_names->names[i].status = NT_STATUS_V(st->r->out.result); + } + + irpc_send_reply(st->msg, NT_STATUS_OK); +} + + +/** + * Called when we get a RODC DNS update request from the netlogon + * rpc server + */ +static NTSTATUS dnsupdate_dnsupdate_RODC(struct irpc_message *msg, + struct dnsupdate_RODC *r) +{ + struct dnsupdate_service *s = talloc_get_type(msg->private_data, + struct dnsupdate_service); + const char * const *dns_update_command = lpcfg_dns_update_command(s->task->lp_ctx); + struct dnsupdate_RODC_state *st; + struct tevent_req *req; + int i, ret; + struct GUID ntds_guid; + const char *site, *dnsdomain, *dnsforest, *ntdsguid, *hostname; + struct ldb_dn *sid_dn; + const char *attrs[] = { "dNSHostName", NULL }; + struct ldb_result *res; + + st = talloc_zero(msg, struct dnsupdate_RODC_state); + if (!st) { + r->out.result = NT_STATUS_NO_MEMORY; + return NT_STATUS_OK; + } + + st->r = r; + st->msg = msg; + + st->tmp_path = smbd_tmp_path(st, s->task->lp_ctx, "rodcdns.XXXXXX"); + if (!st->tmp_path) { + talloc_free(st); + r->out.result = NT_STATUS_NO_MEMORY; + return NT_STATUS_OK; + } + + st->fd = mkstemp(st->tmp_path); + if (st->fd == -1) { + DEBUG(0,("Unable to create a temporary file for RODC dnsupdate\n")); + talloc_free(st); + r->out.result = NT_STATUS_INTERNAL_DB_CORRUPTION; + return NT_STATUS_OK; + } + + talloc_set_destructor(st, dnsupdate_RODC_destructor); + + sid_dn = ldb_dn_new_fmt(st, s->samdb, "<SID=%s>", dom_sid_string(st, r->in.dom_sid)); + if (!sid_dn) { + talloc_free(st); + r->out.result = NT_STATUS_NO_MEMORY; + return NT_STATUS_OK; + } + + /* work out the site */ + ret = samdb_find_site_for_computer(s->samdb, st, sid_dn, &site); + if (ret != LDB_SUCCESS) { + DEBUG(2, (__location__ ": Unable to find site for computer %s\n", + ldb_dn_get_linearized(sid_dn))); + talloc_free(st); + r->out.result = NT_STATUS_NO_SUCH_USER; + return NT_STATUS_OK; + } + + /* work out the ntdsguid */ + ret = samdb_find_ntdsguid_for_computer(s->samdb, sid_dn, &ntds_guid); + ntdsguid = GUID_string(st, &ntds_guid); + if (ret != LDB_SUCCESS || !ntdsguid) { + DEBUG(2, (__location__ ": Unable to find NTDS GUID for computer %s\n", + ldb_dn_get_linearized(sid_dn))); + talloc_free(st); + r->out.result = NT_STATUS_NO_SUCH_USER; + return NT_STATUS_OK; + } + + + /* find dnsdomain and dnsforest */ + dnsdomain = lpcfg_realm(s->task->lp_ctx); + dnsforest = dnsdomain; + + /* find the hostname */ + ret = dsdb_search_dn(s->samdb, st, &res, sid_dn, attrs, 0); + if (ret == LDB_SUCCESS) { + hostname = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL); + } + if (ret != LDB_SUCCESS || !hostname) { + DEBUG(2, (__location__ ": Unable to find NTDS GUID for computer %s\n", + ldb_dn_get_linearized(sid_dn))); + talloc_free(st); + r->out.result = NT_STATUS_NO_SUCH_USER; + return NT_STATUS_OK; + } + + + for (i=0; i<st->r->in.dns_names->count; i++) { + struct NL_DNS_NAME_INFO *n = &r->in.dns_names->names[i]; + switch (n->type) { + case NlDnsLdapAtSite: + dprintf(st->fd, "SRV _ldap._tcp.%s._sites.%s. %s %u\n", + site, dnsdomain, hostname, n->port); + break; + case NlDnsGcAtSite: + dprintf(st->fd, "SRV _ldap._tcp.%s._sites.gc._msdcs.%s. %s %u\n", + site, dnsdomain, hostname, n->port); + break; + case NlDnsDsaCname: + dprintf(st->fd, "CNAME %s._msdcs.%s. %s\n", + ntdsguid, dnsforest, hostname); + break; + case NlDnsKdcAtSite: + dprintf(st->fd, "SRV _kerberos._tcp.%s._sites.dc._msdcs.%s. %s %u\n", + site, dnsdomain, hostname, n->port); + break; + case NlDnsDcAtSite: + dprintf(st->fd, "SRV _ldap._tcp.%s._sites.dc._msdcs.%s. %s %u\n", + site, dnsdomain, hostname, n->port); + break; + case NlDnsRfc1510KdcAtSite: + dprintf(st->fd, "SRV _kerberos._tcp.%s._sites.%s. %s %u\n", + site, dnsdomain, hostname, n->port); + break; + case NlDnsGenericGcAtSite: + dprintf(st->fd, "SRV _gc._tcp.%s._sites.%s. %s %u\n", + site, dnsforest, hostname, n->port); + break; + } + } + + close(st->fd); + st->fd = -1; + + DEBUG(3,("Calling RODC DNS name update script %s\n", st->tmp_path)); + req = samba_runcmd_send(st, + s->task->event_ctx, + timeval_current_ofs(20, 0), + 2, 0, + dns_update_command, + "--update-list", + st->tmp_path, + NULL); + NT_STATUS_HAVE_NO_MEMORY(req); + + /* setup the callback */ + tevent_req_set_callback(req, dnsupdate_RODC_callback, st); + + msg->defer_reply = true; + + return NT_STATUS_OK; +} + /* startup the dns update task */ @@ -412,6 +608,9 @@ static void dnsupdate_task_init(struct task_server *task) irpc_add_name(task->msg_ctx, "dnsupdate"); + IRPC_REGISTER(task->msg_ctx, irpc, DNSUPDATE_RODC, + dnsupdate_dnsupdate_RODC, service); + /* create the intial file */ dnsupdate_rebuild(service); |