2 Unix SMB/CIFS mplementation.
6 Copyright (C) Andrew Tridgell 2009
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 this module auto-creates the named.conf.update file, which tells
25 bind9 what KRB5 principals it should accept for updates to our zone
27 It also uses the samba_dnsupdate script to auto-create the right DNS
28 names for ourselves as a DC in the domain, using TSIG-GSS
32 #include "dsdb/samdb/samdb.h"
33 #include "auth/auth.h"
34 #include "smbd/service.h"
35 #include "lib/messaging/irpc.h"
36 #include "param/param.h"
37 #include "system/filesys.h"
38 #include "libcli/composite/composite.h"
39 #include "libcli/security/dom_sid.h"
40 #include "librpc/gen_ndr/ndr_irpc.h"
42 struct dnsupdate_service
{
43 struct task_server
*task
;
44 struct auth_session_info
*system_session_info
;
45 struct ldb_context
*samdb
;
47 /* status for periodic config file update */
50 struct tevent_timer
*te
;
51 struct tevent_req
*subreq
;
55 /* status for periodic DNS name check */
58 struct tevent_timer
*te
;
59 struct tevent_req
*subreq
;
60 struct tevent_req
*spnreq
;
66 called when rndc reload has finished
68 static void dnsupdate_rndc_done(struct tevent_req
*subreq
)
70 struct dnsupdate_service
*service
= tevent_req_callback_data(subreq
,
71 struct dnsupdate_service
);
75 service
->confupdate
.subreq
= NULL
;
77 ret
= samba_runcmd_recv(subreq
, &sys_errno
);
80 service
->confupdate
.status
= map_nt_error_from_unix(sys_errno
);
82 service
->confupdate
.status
= NT_STATUS_OK
;
85 if (!NT_STATUS_IS_OK(service
->confupdate
.status
)) {
86 DEBUG(0,(__location__
": Failed rndc update - %s\n",
87 nt_errstr(service
->confupdate
.status
)));
89 DEBUG(3,("Completed rndc reload OK\n"));
94 called every 'dnsupdate:conf interval' seconds
96 static void dnsupdate_rebuild(struct dnsupdate_service
*service
)
100 struct ldb_result
*res
;
101 const char *tmp_path
, *path
, *path_static
;
102 char *static_policies
;
105 const char *attrs
[] = { "sAMAccountName", NULL
};
106 const char *realm
= lpcfg_realm(service
->task
->lp_ctx
);
107 TALLOC_CTX
*tmp_ctx
= talloc_new(service
);
108 const char * const *rndc_command
= lpcfg_rndc_command(service
->task
->lp_ctx
);
110 /* abort any pending script run */
111 TALLOC_FREE(service
->confupdate
.subreq
);
113 ret
= ldb_search(service
->samdb
, tmp_ctx
, &res
, NULL
, LDB_SCOPE_SUBTREE
,
114 attrs
, "(|(samaccountname=administrator)(&(primaryGroupID=%u)(objectClass=computer)))",
116 if (ret
!= LDB_SUCCESS
) {
117 DEBUG(0,(__location__
": Unable to find DCs list - %s", ldb_errstring(service
->samdb
)));
118 talloc_free(tmp_ctx
);
122 path
= lpcfg_parm_string(service
->task
->lp_ctx
, NULL
, "dnsupdate", "path");
124 path
= private_path(tmp_ctx
, service
->task
->lp_ctx
, "named.conf.update");
127 path_static
= lpcfg_parm_string(service
->task
->lp_ctx
, NULL
, "dnsupdate", "extra_static_grant_rules");
128 if (path_static
== NULL
) {
129 path_static
= private_path(tmp_ctx
, service
->task
->lp_ctx
, "named.conf.update.static");
132 tmp_path
= talloc_asprintf(tmp_ctx
, "%s.tmp", path
);
133 if (path
== NULL
|| tmp_path
== NULL
|| path_static
== NULL
) {
134 DEBUG(0,(__location__
": Unable to get paths\n"));
135 talloc_free(tmp_ctx
);
139 static_policies
= file_load(path_static
, &size
, 0, tmp_ctx
);
142 fd
= open(tmp_path
, O_CREAT
|O_TRUNC
|O_WRONLY
, 0444);
144 DEBUG(1,(__location__
": Unable to open %s - %s\n", tmp_path
, strerror(errno
)));
145 talloc_free(tmp_ctx
);
149 dprintf(fd
, "/* this file is auto-generated - do not edit */\n");
150 dprintf(fd
, "update-policy {\n");
151 if( static_policies
!= NULL
) {
152 dprintf(fd
, "/* Start of static entries */\n");
153 dprintf(fd
, "%s\n",static_policies
);
154 dprintf(fd
, "/* End of static entries */\n");
156 dprintf(fd
, "\tgrant %s ms-self * A AAAA;\n", realm
);
158 for (i
=0; i
<res
->count
; i
++) {
159 const char *acctname
;
160 acctname
= ldb_msg_find_attr_as_string(res
->msgs
[i
],
161 "sAMAccountName", NULL
);
162 if (!acctname
) continue;
163 dprintf(fd
, "\tgrant %s@%s wildcard * A AAAA SRV CNAME;\n",
170 if (NT_STATUS_IS_OK(service
->confupdate
.status
) &&
171 file_compare(tmp_path
, path
) == true) {
173 talloc_free(tmp_ctx
);
177 if (rename(tmp_path
, path
) != 0) {
178 DEBUG(0,(__location__
": Failed to rename %s to %s - %s\n",
179 tmp_path
, path
, strerror(errno
)));
180 talloc_free(tmp_ctx
);
184 DEBUG(2,("Loading new DNS update grant rules\n"));
185 service
->confupdate
.subreq
= samba_runcmd_send(service
,
186 service
->task
->event_ctx
,
187 timeval_current_ofs(10, 0),
191 if (service
->confupdate
.subreq
== NULL
) {
192 DEBUG(0,(__location__
": samba_runcmd_send() failed with no memory\n"));
193 talloc_free(tmp_ctx
);
196 tevent_req_set_callback(service
->confupdate
.subreq
,
200 talloc_free(tmp_ctx
);
203 static NTSTATUS
dnsupdate_confupdate_schedule(struct dnsupdate_service
*service
);
206 called every 'dnsupdate:conf interval' seconds
208 static void dnsupdate_confupdate_handler_te(struct tevent_context
*ev
, struct tevent_timer
*te
,
209 struct timeval t
, void *ptr
)
211 struct dnsupdate_service
*service
= talloc_get_type(ptr
, struct dnsupdate_service
);
213 dnsupdate_rebuild(service
);
214 dnsupdate_confupdate_schedule(service
);
218 static NTSTATUS
dnsupdate_confupdate_schedule(struct dnsupdate_service
*service
)
220 service
->confupdate
.te
= tevent_add_timer(service
->task
->event_ctx
, service
,
221 timeval_current_ofs(service
->confupdate
.interval
, 0),
222 dnsupdate_confupdate_handler_te
, service
);
223 NT_STATUS_HAVE_NO_MEMORY(service
->confupdate
.te
);
229 called when dns update script has finished
231 static void dnsupdate_nameupdate_done(struct tevent_req
*subreq
)
233 struct dnsupdate_service
*service
= tevent_req_callback_data(subreq
,
234 struct dnsupdate_service
);
238 service
->nameupdate
.subreq
= NULL
;
240 ret
= samba_runcmd_recv(subreq
, &sys_errno
);
243 service
->nameupdate
.status
= map_nt_error_from_unix(sys_errno
);
245 service
->nameupdate
.status
= NT_STATUS_OK
;
248 if (!NT_STATUS_IS_OK(service
->nameupdate
.status
)) {
249 DEBUG(0,(__location__
": Failed DNS update - %s\n",
250 nt_errstr(service
->nameupdate
.status
)));
252 DEBUG(3,("Completed DNS update check OK\n"));
258 called when spn update script has finished
260 static void dnsupdate_spnupdate_done(struct tevent_req
*subreq
)
262 struct dnsupdate_service
*service
= tevent_req_callback_data(subreq
,
263 struct dnsupdate_service
);
267 service
->nameupdate
.spnreq
= NULL
;
269 ret
= samba_runcmd_recv(subreq
, &sys_errno
);
272 service
->nameupdate
.status
= map_nt_error_from_unix(sys_errno
);
274 service
->nameupdate
.status
= NT_STATUS_OK
;
277 if (!NT_STATUS_IS_OK(service
->nameupdate
.status
)) {
278 DEBUG(0,(__location__
": Failed SPN update - %s\n",
279 nt_errstr(service
->nameupdate
.status
)));
281 DEBUG(3,("Completed SPN update check OK\n"));
286 called every 'dnsupdate:name interval' seconds
288 static void dnsupdate_check_names(struct dnsupdate_service
*service
)
290 const char * const *dns_update_command
= lpcfg_dns_update_command(service
->task
->lp_ctx
);
291 const char * const *spn_update_command
= lpcfg_spn_update_command(service
->task
->lp_ctx
);
293 /* kill any existing child */
294 TALLOC_FREE(service
->nameupdate
.subreq
);
296 DEBUG(3,("Calling DNS name update script\n"));
297 service
->nameupdate
.subreq
= samba_runcmd_send(service
,
298 service
->task
->event_ctx
,
299 timeval_current_ofs(20, 0),
303 if (service
->nameupdate
.subreq
== NULL
) {
304 DEBUG(0,(__location__
": samba_runcmd_send() failed with no memory\n"));
307 tevent_req_set_callback(service
->nameupdate
.subreq
,
308 dnsupdate_nameupdate_done
,
311 DEBUG(3,("Calling SPN name update script\n"));
312 service
->nameupdate
.spnreq
= samba_runcmd_send(service
,
313 service
->task
->event_ctx
,
314 timeval_current_ofs(20, 0),
318 if (service
->nameupdate
.spnreq
== NULL
) {
319 DEBUG(0,(__location__
": samba_runcmd_send() failed with no memory\n"));
322 tevent_req_set_callback(service
->nameupdate
.spnreq
,
323 dnsupdate_spnupdate_done
,
327 static NTSTATUS
dnsupdate_nameupdate_schedule(struct dnsupdate_service
*service
);
330 called every 'dnsupdate:name interval' seconds
332 static void dnsupdate_nameupdate_handler_te(struct tevent_context
*ev
, struct tevent_timer
*te
,
333 struct timeval t
, void *ptr
)
335 struct dnsupdate_service
*service
= talloc_get_type(ptr
, struct dnsupdate_service
);
337 dnsupdate_check_names(service
);
338 dnsupdate_nameupdate_schedule(service
);
342 static NTSTATUS
dnsupdate_nameupdate_schedule(struct dnsupdate_service
*service
)
344 service
->nameupdate
.te
= tevent_add_timer(service
->task
->event_ctx
, service
,
345 timeval_current_ofs(service
->nameupdate
.interval
, 0),
346 dnsupdate_nameupdate_handler_te
, service
);
347 NT_STATUS_HAVE_NO_MEMORY(service
->nameupdate
.te
);
352 struct dnsupdate_RODC_state
{
353 struct irpc_message
*msg
;
354 struct dnsupdate_RODC
*r
;
359 static int dnsupdate_RODC_destructor(struct dnsupdate_RODC_state
*st
)
364 unlink(st
->tmp_path
);
369 called when the DNS update has completed
371 static void dnsupdate_RODC_callback(struct tevent_req
*req
)
373 struct dnsupdate_RODC_state
*st
=
374 tevent_req_callback_data(req
,
375 struct dnsupdate_RODC_state
);
379 ret
= samba_runcmd_recv(req
, &sys_errno
);
382 st
->r
->out
.result
= map_nt_error_from_unix(sys_errno
);
383 DEBUG(2,(__location__
": RODC DNS Update failed: %s\n", nt_errstr(st
->r
->out
.result
)));
385 st
->r
->out
.result
= NT_STATUS_OK
;
386 DEBUG(3,(__location__
": RODC DNS Update OK\n"));
389 for (i
=0; i
<st
->r
->in
.dns_names
->count
; i
++) {
390 st
->r
->out
.dns_names
->names
[i
].status
= NT_STATUS_V(st
->r
->out
.result
);
393 irpc_send_reply(st
->msg
, NT_STATUS_OK
);
398 * Called when we get a RODC DNS update request from the netlogon
401 static NTSTATUS
dnsupdate_dnsupdate_RODC(struct irpc_message
*msg
,
402 struct dnsupdate_RODC
*r
)
404 struct dnsupdate_service
*s
= talloc_get_type(msg
->private_data
,
405 struct dnsupdate_service
);
406 const char * const *dns_update_command
= lpcfg_dns_update_command(s
->task
->lp_ctx
);
407 struct dnsupdate_RODC_state
*st
;
408 struct tevent_req
*req
;
410 struct GUID ntds_guid
;
411 const char *site
, *dnsdomain
, *dnsforest
, *ntdsguid
, *hostname
;
412 struct ldb_dn
*sid_dn
;
413 const char *attrs
[] = { "dNSHostName", NULL
};
414 struct ldb_result
*res
;
416 st
= talloc_zero(msg
, struct dnsupdate_RODC_state
);
418 r
->out
.result
= NT_STATUS_NO_MEMORY
;
425 st
->tmp_path
= smbd_tmp_path(st
, s
->task
->lp_ctx
, "rodcdns.XXXXXX");
428 r
->out
.result
= NT_STATUS_NO_MEMORY
;
432 st
->fd
= mkstemp(st
->tmp_path
);
434 DEBUG(0,("Unable to create a temporary file for RODC dnsupdate\n"));
436 r
->out
.result
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
440 talloc_set_destructor(st
, dnsupdate_RODC_destructor
);
442 sid_dn
= ldb_dn_new_fmt(st
, s
->samdb
, "<SID=%s>", dom_sid_string(st
, r
->in
.dom_sid
));
445 r
->out
.result
= NT_STATUS_NO_MEMORY
;
449 /* work out the site */
450 ret
= samdb_find_site_for_computer(s
->samdb
, st
, sid_dn
, &site
);
451 if (ret
!= LDB_SUCCESS
) {
452 DEBUG(2, (__location__
": Unable to find site for computer %s\n",
453 ldb_dn_get_linearized(sid_dn
)));
455 r
->out
.result
= NT_STATUS_NO_SUCH_USER
;
459 /* work out the ntdsguid */
460 ret
= samdb_find_ntdsguid_for_computer(s
->samdb
, sid_dn
, &ntds_guid
);
461 ntdsguid
= GUID_string(st
, &ntds_guid
);
462 if (ret
!= LDB_SUCCESS
|| !ntdsguid
) {
463 DEBUG(2, (__location__
": Unable to find NTDS GUID for computer %s\n",
464 ldb_dn_get_linearized(sid_dn
)));
466 r
->out
.result
= NT_STATUS_NO_SUCH_USER
;
471 /* find dnsdomain and dnsforest */
472 dnsdomain
= lpcfg_realm(s
->task
->lp_ctx
);
473 dnsforest
= dnsdomain
;
475 /* find the hostname */
476 ret
= dsdb_search_dn(s
->samdb
, st
, &res
, sid_dn
, attrs
, 0);
477 if (ret
== LDB_SUCCESS
) {
478 hostname
= ldb_msg_find_attr_as_string(res
->msgs
[0], "dNSHostName", NULL
);
480 if (ret
!= LDB_SUCCESS
|| !hostname
) {
481 DEBUG(2, (__location__
": Unable to find NTDS GUID for computer %s\n",
482 ldb_dn_get_linearized(sid_dn
)));
484 r
->out
.result
= NT_STATUS_NO_SUCH_USER
;
489 for (i
=0; i
<st
->r
->in
.dns_names
->count
; i
++) {
490 struct NL_DNS_NAME_INFO
*n
= &r
->in
.dns_names
->names
[i
];
492 case NlDnsLdapAtSite
:
493 dprintf(st
->fd
, "SRV _ldap._tcp.%s._sites.%s. %s %u\n",
494 site
, dnsdomain
, hostname
, n
->port
);
497 dprintf(st
->fd
, "SRV _ldap._tcp.%s._sites.gc._msdcs.%s. %s %u\n",
498 site
, dnsdomain
, hostname
, n
->port
);
501 dprintf(st
->fd
, "CNAME %s._msdcs.%s. %s\n",
502 ntdsguid
, dnsforest
, hostname
);
505 dprintf(st
->fd
, "SRV _kerberos._tcp.%s._sites.dc._msdcs.%s. %s %u\n",
506 site
, dnsdomain
, hostname
, n
->port
);
509 dprintf(st
->fd
, "SRV _ldap._tcp.%s._sites.dc._msdcs.%s. %s %u\n",
510 site
, dnsdomain
, hostname
, n
->port
);
512 case NlDnsRfc1510KdcAtSite
:
513 dprintf(st
->fd
, "SRV _kerberos._tcp.%s._sites.%s. %s %u\n",
514 site
, dnsdomain
, hostname
, n
->port
);
516 case NlDnsGenericGcAtSite
:
517 dprintf(st
->fd
, "SRV _gc._tcp.%s._sites.%s. %s %u\n",
518 site
, dnsforest
, hostname
, n
->port
);
526 DEBUG(3,("Calling RODC DNS name update script %s\n", st
->tmp_path
));
527 req
= samba_runcmd_send(st
,
529 timeval_current_ofs(20, 0),
535 NT_STATUS_HAVE_NO_MEMORY(req
);
537 /* setup the callback */
538 tevent_req_set_callback(req
, dnsupdate_RODC_callback
, st
);
540 msg
->defer_reply
= true;
546 startup the dns update task
548 static void dnsupdate_task_init(struct task_server
*task
)
551 struct dnsupdate_service
*service
;
553 if (lpcfg_server_role(task
->lp_ctx
) != ROLE_DOMAIN_CONTROLLER
) {
554 /* not useful for non-DC */
558 task_server_set_title(task
, "task[dnsupdate]");
560 service
= talloc_zero(task
, struct dnsupdate_service
);
562 task_server_terminate(task
, "dnsupdate_task_init: out of memory", true);
565 service
->task
= task
;
566 task
->private_data
= service
;
568 service
->system_session_info
= system_session(service
->task
->lp_ctx
);
569 if (!service
->system_session_info
) {
570 task_server_terminate(task
,
571 "dnsupdate: Failed to obtain server credentials\n",
576 service
->samdb
= samdb_connect(service
, service
->task
->event_ctx
, task
->lp_ctx
,
577 service
->system_session_info
, 0);
578 if (!service
->samdb
) {
579 task_server_terminate(task
, "dnsupdate: Failed to connect to local samdb\n",
584 service
->confupdate
.interval
= lpcfg_parm_int(task
->lp_ctx
, NULL
,
585 "dnsupdate", "config interval", 60); /* in seconds */
587 service
->nameupdate
.interval
= lpcfg_parm_int(task
->lp_ctx
, NULL
,
588 "dnsupdate", "name interval", 600); /* in seconds */
590 dnsupdate_rebuild(service
);
591 status
= dnsupdate_confupdate_schedule(service
);
592 if (!NT_STATUS_IS_OK(status
)) {
593 task_server_terminate(task
, talloc_asprintf(task
,
594 "dnsupdate: Failed to confupdate schedule: %s\n",
595 nt_errstr(status
)), true);
599 dnsupdate_check_names(service
);
600 status
= dnsupdate_nameupdate_schedule(service
);
601 if (!NT_STATUS_IS_OK(status
)) {
602 task_server_terminate(task
, talloc_asprintf(task
,
603 "dnsupdate: Failed to nameupdate schedule: %s\n",
604 nt_errstr(status
)), true);
608 irpc_add_name(task
->msg_ctx
, "dnsupdate");
610 IRPC_REGISTER(task
->msg_ctx
, irpc
, DNSUPDATE_RODC
,
611 dnsupdate_dnsupdate_RODC
, service
);
613 /* create the intial file */
614 dnsupdate_rebuild(service
);
619 register ourselves as a available server
621 NTSTATUS
server_service_dnsupdate_init(void)
623 return register_server_service("dnsupdate", dnsupdate_task_init
);