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"
40 struct dnsupdate_service
{
41 struct task_server
*task
;
42 struct auth_session_info
*system_session_info
;
43 struct ldb_context
*samdb
;
45 /* status for periodic config file update */
48 struct tevent_timer
*te
;
49 struct tevent_req
*subreq
;
53 /* status for periodic DNS name check */
56 struct tevent_timer
*te
;
57 struct tevent_req
*subreq
;
63 called when rndc reload has finished
65 static void dnsupdate_rndc_done(struct tevent_req
*subreq
)
67 struct dnsupdate_service
*service
= tevent_req_callback_data(subreq
,
68 struct dnsupdate_service
);
72 service
->confupdate
.subreq
= NULL
;
74 ret
= samba_runcmd_recv(subreq
, &sys_errno
);
77 service
->confupdate
.status
= map_nt_error_from_unix(sys_errno
);
79 service
->confupdate
.status
= NT_STATUS_OK
;
82 if (!NT_STATUS_IS_OK(service
->confupdate
.status
)) {
83 DEBUG(0,(__location__
": Failed rndc update - %s\n",
84 nt_errstr(service
->confupdate
.status
)));
86 DEBUG(3,("Completed rndc reload OK\n"));
91 called every 'dnsupdate:conf interval' seconds
93 static void dnsupdate_rebuild(struct dnsupdate_service
*service
)
97 struct ldb_result
*res
;
98 const char *tmp_path
, *path
, *path_static
;
99 char *static_policies
;
102 const char *attrs
[] = { "sAMAccountName", NULL
};
103 const char *realm
= lp_realm(service
->task
->lp_ctx
);
104 TALLOC_CTX
*tmp_ctx
= talloc_new(service
);
105 const char * const *rndc_command
= lp_rndc_command(service
->task
->lp_ctx
);
107 /* abort any pending script run */
108 TALLOC_FREE(service
->confupdate
.subreq
);
110 ret
= ldb_search(service
->samdb
, tmp_ctx
, &res
, NULL
, LDB_SCOPE_SUBTREE
,
111 attrs
, "(&(primaryGroupID=%u)(objectClass=computer))",
113 if (ret
!= LDB_SUCCESS
) {
114 DEBUG(0,(__location__
": Unable to find DCs list - %s", ldb_errstring(service
->samdb
)));
115 talloc_free(tmp_ctx
);
119 path
= lp_parm_string(service
->task
->lp_ctx
, NULL
, "dnsupdate", "path");
121 path
= private_path(tmp_ctx
, service
->task
->lp_ctx
, "named.conf.update");
124 path_static
= lp_parm_string(service
->task
->lp_ctx
, NULL
, "dnsupdate", "extra_static_grant_rules");
125 if (path_static
== NULL
) {
126 path_static
= private_path(tmp_ctx
, service
->task
->lp_ctx
, "named.conf.update.static");
129 tmp_path
= talloc_asprintf(tmp_ctx
, "%s.tmp", path
);
130 if (path
== NULL
|| tmp_path
== NULL
|| path_static
== NULL
) {
131 DEBUG(0,(__location__
": Unable to get paths\n"));
132 talloc_free(tmp_ctx
);
136 static_policies
= file_load(path_static
, &size
, 0, tmp_ctx
);
139 fd
= open(tmp_path
, O_CREAT
|O_TRUNC
|O_WRONLY
, 0444);
141 DEBUG(1,(__location__
": Unable to open %s - %s\n", tmp_path
, strerror(errno
)));
142 talloc_free(tmp_ctx
);
146 dprintf(fd
, "/* this file is auto-generated - do not edit */\n");
147 dprintf(fd
, "update-policy {\n");
148 if( static_policies
!= NULL
) {
149 dprintf(fd
, "/* Start of static entries */\n");
150 dprintf(fd
, "%s\n",static_policies
);
151 dprintf(fd
, "/* End of static entries */\n");
153 dprintf(fd
, "\tgrant %s ms-self * A AAAA;\n", realm
);
154 dprintf(fd
, "\tgrant administrator@%s wildcard * A AAAA SRV CNAME TXT;\n", realm
);
156 for (i
=0; i
<res
->count
; i
++) {
157 const char *acctname
;
158 acctname
= ldb_msg_find_attr_as_string(res
->msgs
[i
],
159 "sAMAccountName", NULL
);
160 if (!acctname
) continue;
161 dprintf(fd
, "\tgrant %s@%s wildcard * A AAAA SRV CNAME;\n",
168 if (NT_STATUS_IS_OK(service
->confupdate
.status
) &&
169 file_compare(tmp_path
, path
) == true) {
171 talloc_free(tmp_ctx
);
175 if (rename(tmp_path
, path
) != 0) {
176 DEBUG(0,(__location__
": Failed to rename %s to %s - %s\n",
177 tmp_path
, path
, strerror(errno
)));
178 talloc_free(tmp_ctx
);
182 DEBUG(2,("Loading new DNS update grant rules\n"));
183 service
->confupdate
.subreq
= samba_runcmd_send(service
,
184 service
->task
->event_ctx
,
185 timeval_current_ofs(10, 0),
189 if (service
->confupdate
.subreq
== NULL
) {
190 DEBUG(0,(__location__
": samba_runcmd_send() failed with no memory\n"));
191 talloc_free(tmp_ctx
);
194 tevent_req_set_callback(service
->confupdate
.subreq
,
198 talloc_free(tmp_ctx
);
201 static NTSTATUS
dnsupdate_confupdate_schedule(struct dnsupdate_service
*service
);
204 called every 'dnsupdate:conf interval' seconds
206 static void dnsupdate_confupdate_handler_te(struct tevent_context
*ev
, struct tevent_timer
*te
,
207 struct timeval t
, void *ptr
)
209 struct dnsupdate_service
*service
= talloc_get_type(ptr
, struct dnsupdate_service
);
211 dnsupdate_rebuild(service
);
212 dnsupdate_confupdate_schedule(service
);
216 static NTSTATUS
dnsupdate_confupdate_schedule(struct dnsupdate_service
*service
)
218 service
->confupdate
.te
= tevent_add_timer(service
->task
->event_ctx
, service
,
219 timeval_current_ofs(service
->confupdate
.interval
, 0),
220 dnsupdate_confupdate_handler_te
, service
);
221 NT_STATUS_HAVE_NO_MEMORY(service
->confupdate
.te
);
227 called when dns update script has finished
229 static void dnsupdate_nameupdate_done(struct tevent_req
*subreq
)
231 struct dnsupdate_service
*service
= tevent_req_callback_data(subreq
,
232 struct dnsupdate_service
);
236 service
->nameupdate
.subreq
= NULL
;
238 ret
= samba_runcmd_recv(subreq
, &sys_errno
);
241 service
->nameupdate
.status
= map_nt_error_from_unix(sys_errno
);
243 service
->nameupdate
.status
= NT_STATUS_OK
;
246 if (!NT_STATUS_IS_OK(service
->nameupdate
.status
)) {
247 DEBUG(0,(__location__
": Failed DNS update - %s\n",
248 nt_errstr(service
->nameupdate
.status
)));
250 DEBUG(3,("Completed DNS update check OK\n"));
255 called every 'dnsupdate:name interval' seconds
257 static void dnsupdate_check_names(struct dnsupdate_service
*service
)
259 const char * const *dns_update_command
= lp_dns_update_command(service
->task
->lp_ctx
);
261 /* kill any existing child */
262 TALLOC_FREE(service
->nameupdate
.subreq
);
264 DEBUG(3,("Calling DNS name update script\n"));
265 service
->nameupdate
.subreq
= samba_runcmd_send(service
,
266 service
->task
->event_ctx
,
267 timeval_current_ofs(10, 0),
271 if (service
->nameupdate
.subreq
== NULL
) {
272 DEBUG(0,(__location__
": samba_runcmd_send() failed with no memory\n"));
275 tevent_req_set_callback(service
->nameupdate
.subreq
,
276 dnsupdate_nameupdate_done
,
280 static NTSTATUS
dnsupdate_nameupdate_schedule(struct dnsupdate_service
*service
);
283 called every 'dnsupdate:name interval' seconds
285 static void dnsupdate_nameupdate_handler_te(struct tevent_context
*ev
, struct tevent_timer
*te
,
286 struct timeval t
, void *ptr
)
288 struct dnsupdate_service
*service
= talloc_get_type(ptr
, struct dnsupdate_service
);
290 dnsupdate_check_names(service
);
291 dnsupdate_nameupdate_schedule(service
);
295 static NTSTATUS
dnsupdate_nameupdate_schedule(struct dnsupdate_service
*service
)
297 service
->nameupdate
.te
= tevent_add_timer(service
->task
->event_ctx
, service
,
298 timeval_current_ofs(service
->nameupdate
.interval
, 0),
299 dnsupdate_nameupdate_handler_te
, service
);
300 NT_STATUS_HAVE_NO_MEMORY(service
->nameupdate
.te
);
305 startup the dns update task
307 static void dnsupdate_task_init(struct task_server
*task
)
310 struct dnsupdate_service
*service
;
312 if (lp_server_role(task
->lp_ctx
) != ROLE_DOMAIN_CONTROLLER
) {
313 /* not useful for non-DC */
317 task_server_set_title(task
, "task[dnsupdate]");
319 service
= talloc_zero(task
, struct dnsupdate_service
);
321 task_server_terminate(task
, "dnsupdate_task_init: out of memory", true);
324 service
->task
= task
;
325 task
->private_data
= service
;
327 service
->system_session_info
= system_session(service
->task
->lp_ctx
);
328 if (!service
->system_session_info
) {
329 task_server_terminate(task
,
330 "dnsupdate: Failed to obtain server credentials\n",
335 service
->samdb
= samdb_connect(service
, service
->task
->event_ctx
, task
->lp_ctx
,
336 service
->system_session_info
);
337 if (!service
->samdb
) {
338 task_server_terminate(task
, "dnsupdate: Failed to connect to local samdb\n",
343 service
->confupdate
.interval
= lp_parm_int(task
->lp_ctx
, NULL
,
344 "dnsupdate", "config interval", 60); /* in seconds */
346 service
->nameupdate
.interval
= lp_parm_int(task
->lp_ctx
, NULL
,
347 "dnsupdate", "name interval", 600); /* in seconds */
349 dnsupdate_rebuild(service
);
350 status
= dnsupdate_confupdate_schedule(service
);
351 if (!NT_STATUS_IS_OK(status
)) {
352 task_server_terminate(task
, talloc_asprintf(task
,
353 "dnsupdate: Failed to confupdate schedule: %s\n",
354 nt_errstr(status
)), true);
358 dnsupdate_check_names(service
);
359 status
= dnsupdate_nameupdate_schedule(service
);
360 if (!NT_STATUS_IS_OK(status
)) {
361 task_server_terminate(task
, talloc_asprintf(task
,
362 "dnsupdate: Failed to nameupdate schedule: %s\n",
363 nt_errstr(status
)), true);
367 irpc_add_name(task
->msg_ctx
, "dnsupdate");
369 /* create the intial file */
370 dnsupdate_rebuild(service
);
375 register ourselves as a available server
377 NTSTATUS
server_service_dnsupdate_init(void)
379 return register_server_service("dnsupdate", dnsupdate_task_init
);