s3:script: Replace --merge by --merge-by-timestamp in samba-log-parser
[Samba.git] / source4 / kdc / kdc-service-mit.c
blobd8ed1e199866efdfa341d24f62616bdfb21eb7cb
1 /*
2 Unix SMB/CIFS implementation.
4 Start MIT krb5kdc server within Samba AD
6 Copyright (c) 2014-2016 Andreas Schneider <asn@samba.org>
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/>.
22 #include "includes.h"
23 #include "talloc.h"
24 #include "tevent.h"
25 #include "system/filesys.h"
26 #include "lib/param/param.h"
27 #include "lib/util/samba_util.h"
28 #include "source4/samba/service.h"
29 #include "source4/samba/process_model.h"
30 #include "kdc/kdc-service-mit.h"
31 #include "dynconfig.h"
32 #include "libds/common/roles.h"
33 #include "lib/socket/netif.h"
34 #include "samba/session.h"
35 #include "dsdb/samdb/samdb.h"
36 #include "kdc/samba_kdc.h"
37 #include "kdc/kdc-server.h"
38 #include "kdc/kpasswd-service.h"
39 #include <kadm5/admin.h>
40 #include <kdb.h>
42 #include "source4/kdc/mit_kdc_irpc.h"
44 #undef DBGC_CLASS
45 #define DBGC_CLASS DBGC_KERBEROS
47 /* PROTOTYPES */
48 static void mitkdc_server_done(struct tevent_req *subreq);
50 static int kdc_server_destroy(struct kdc_server *kdc)
52 if (kdc->private_data != NULL) {
53 kadm5_destroy(kdc->private_data);
56 return 0;
59 static NTSTATUS startup_kpasswd_server(TALLOC_CTX *mem_ctx,
60 struct kdc_server *kdc,
61 struct loadparm_context *lp_ctx,
62 struct interface *ifaces)
64 int num_interfaces;
65 int i;
66 TALLOC_CTX *tmp_ctx;
67 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
68 uint16_t kpasswd_port;
69 bool done_wildcard = false;
70 bool ok;
72 kpasswd_port = lpcfg_kpasswd_port(lp_ctx);
73 if (kpasswd_port == 0) {
74 return NT_STATUS_OK;
77 tmp_ctx = talloc_named_const(mem_ctx, 0, "kpasswd");
78 if (tmp_ctx == NULL) {
79 return NT_STATUS_NO_MEMORY;
82 num_interfaces = iface_list_count(ifaces);
84 ok = lpcfg_bind_interfaces_only(lp_ctx);
85 if (!ok) {
86 int num_binds = 0;
87 char **wcard;
89 wcard = iface_list_wildcard(tmp_ctx);
90 if (wcard == NULL) {
91 status = NT_STATUS_NO_MEMORY;
92 goto out;
95 for (i = 0; wcard[i] != NULL; i++) {
96 status = kdc_add_socket(kdc,
97 kdc->task->model_ops,
98 "kpasswd",
99 wcard[i],
100 kpasswd_port,
101 kpasswd_process,
102 false);
103 if (NT_STATUS_IS_OK(status)) {
104 num_binds++;
107 talloc_free(wcard);
109 if (num_binds == 0) {
110 status = NT_STATUS_INVALID_PARAMETER_MIX;
111 goto out;
114 done_wildcard = true;
117 for (i = 0; i < num_interfaces; i++) {
118 const char *address = talloc_strdup(tmp_ctx, iface_list_n_ip(ifaces, i));
120 status = kdc_add_socket(kdc,
121 kdc->task->model_ops,
122 "kpasswd",
123 address,
124 kpasswd_port,
125 kpasswd_process,
126 done_wildcard);
127 if (NT_STATUS_IS_OK(status)) {
128 goto out;
132 out:
133 talloc_free(tmp_ctx);
134 return status;
138 * Startup a copy of the krb5kdc as a child daemon
140 NTSTATUS mitkdc_task_init(struct task_server *task)
142 struct tevent_req *subreq;
143 const char * const *kdc_cmd;
144 struct interface *ifaces;
145 char *kdc_config = NULL;
146 struct kdc_server *kdc;
147 krb5_error_code code;
148 NTSTATUS status;
149 kadm5_ret_t ret;
150 kadm5_config_params config;
151 void *server_handle;
152 int dbglvl = 0;
154 task_server_set_title(task, "task[mitkdc_parent]");
156 switch (lpcfg_server_role(task->lp_ctx)) {
157 case ROLE_STANDALONE:
158 task_server_terminate(task,
159 "The KDC is not required in standalone "
160 "server configuration, terminate!",
161 false);
162 return NT_STATUS_INVALID_DOMAIN_ROLE;
163 case ROLE_DOMAIN_MEMBER:
164 task_server_terminate(task,
165 "The KDC is not required in member "
166 "server configuration",
167 false);
168 return NT_STATUS_INVALID_DOMAIN_ROLE;
169 case ROLE_ACTIVE_DIRECTORY_DC:
170 /* Yes, we want to start the KDC */
171 break;
174 /* Load interfaces for kpasswd */
175 load_interface_list(task, task->lp_ctx, &ifaces);
176 if (iface_list_count(ifaces) == 0) {
177 task_server_terminate(task,
178 "KDC: no network interfaces configured",
179 false);
180 return NT_STATUS_UNSUCCESSFUL;
183 kdc_config = talloc_asprintf(task,
184 "%s/kdc.conf",
185 lpcfg_private_dir(task->lp_ctx));
186 if (kdc_config == NULL) {
187 task_server_terminate(task,
188 "KDC: no memory",
189 false);
190 return NT_STATUS_NO_MEMORY;
192 setenv("KRB5_KDC_PROFILE", kdc_config, 0);
193 TALLOC_FREE(kdc_config);
195 dbglvl = debuglevel_get_class(DBGC_KERBEROS);
196 if (dbglvl >= 10) {
197 char *kdc_trace_file = talloc_asprintf(task,
198 "%s/mit_kdc_trace.log",
199 get_dyn_LOGFILEBASE());
200 if (kdc_trace_file == NULL) {
201 task_server_terminate(task,
202 "KDC: no memory",
203 false);
204 return NT_STATUS_NO_MEMORY;
207 setenv("KRB5_TRACE", kdc_trace_file, 1);
210 /* start it as a child process */
211 kdc_cmd = lpcfg_mit_kdc_command(task->lp_ctx);
213 subreq = samba_runcmd_send(task,
214 task->event_ctx,
215 timeval_zero(),
216 1, /* stdout log level */
217 0, /* stderr log level */
218 kdc_cmd,
219 "-n", /* Don't go into background */
220 #if 0
221 "-w 2", /* Start two workers */
222 #endif
223 NULL);
224 if (subreq == NULL) {
225 DEBUG(0, ("Failed to start MIT KDC as child daemon\n"));
227 task_server_terminate(task,
228 "Failed to startup mitkdc task",
229 true);
230 return NT_STATUS_INTERNAL_ERROR;
233 tevent_req_set_callback(subreq, mitkdc_server_done, task);
235 DEBUG(5,("Started krb5kdc process\n"));
237 status = samba_setup_mit_kdc_irpc(task);
238 if (!NT_STATUS_IS_OK(status)) {
239 task_server_terminate(task,
240 "Failed to setup kdc irpc service",
241 true);
244 DEBUG(5,("Started irpc service for kdc_server\n"));
246 kdc = talloc_zero(task, struct kdc_server);
247 if (kdc == NULL) {
248 task_server_terminate(task, "KDC: Out of memory", true);
249 return NT_STATUS_NO_MEMORY;
251 talloc_set_destructor(kdc, kdc_server_destroy);
253 kdc->task = task;
255 kdc->base_ctx = talloc_zero(kdc, struct samba_kdc_base_context);
256 if (kdc->base_ctx == NULL) {
257 task_server_terminate(task, "KDC: Out of memory", true);
258 return NT_STATUS_NO_MEMORY;
261 kdc->base_ctx->ev_ctx = task->event_ctx;
262 kdc->base_ctx->lp_ctx = task->lp_ctx;
264 initialize_krb5_error_table();
266 code = smb_krb5_init_context(kdc,
267 kdc->task->lp_ctx,
268 &kdc->smb_krb5_context);
269 if (code != 0) {
270 task_server_terminate(task,
271 "KDC: Unable to initialize krb5 context",
272 true);
273 return NT_STATUS_INTERNAL_ERROR;
276 code = kadm5_init_krb5_context(&kdc->smb_krb5_context->krb5_context);
277 if (code != 0) {
278 task_server_terminate(task,
279 "KDC: Unable to init kadm5 krb5_context",
280 true);
281 return NT_STATUS_INTERNAL_ERROR;
284 ZERO_STRUCT(config);
285 config.mask = KADM5_CONFIG_REALM;
286 config.realm = discard_const_p(char, lpcfg_realm(kdc->task->lp_ctx));
288 ret = kadm5_init(kdc->smb_krb5_context->krb5_context,
289 discard_const_p(char, "kpasswd"),
290 NULL, /* pass */
291 discard_const_p(char, "kpasswd"),
292 &config,
293 KADM5_STRUCT_VERSION,
294 KADM5_API_VERSION_4,
295 NULL,
296 &server_handle);
297 if (ret != 0) {
298 task_server_terminate(task,
299 "KDC: Initialize kadm5",
300 true);
301 return NT_STATUS_INTERNAL_ERROR;
303 kdc->private_data = server_handle;
305 code = krb5_db_register_keytab(kdc->smb_krb5_context->krb5_context);
306 if (code != 0) {
307 task_server_terminate(task,
308 "KDC: Unable to KDB",
309 true);
310 return NT_STATUS_INTERNAL_ERROR;
313 kdc->kpasswd_keytab_name = talloc_asprintf(kdc, "KDB:");
314 if (kdc->kpasswd_keytab_name == NULL) {
315 task_server_terminate(task,
316 "KDC: Out of memory",
317 true);
318 return NT_STATUS_NO_MEMORY;
321 kdc->samdb = samdb_connect(kdc,
322 kdc->task->event_ctx,
323 kdc->task->lp_ctx,
324 system_session(kdc->task->lp_ctx),
325 NULL,
327 if (kdc->samdb == NULL) {
328 task_server_terminate(task,
329 "KDC: Unable to connect to samdb",
330 true);
331 return NT_STATUS_CONNECTION_INVALID;
334 status = startup_kpasswd_server(kdc,
335 kdc,
336 task->lp_ctx,
337 ifaces);
338 if (!NT_STATUS_IS_OK(status)) {
339 task_server_terminate(task,
340 "KDC: Unable to start kpasswd server",
341 true);
342 return status;
345 DEBUG(5,("Started kpasswd service for kdc_server\n"));
347 return NT_STATUS_OK;
351 * This gets called the kdc exits.
353 static void mitkdc_server_done(struct tevent_req *subreq)
355 struct task_server *task =
356 tevent_req_callback_data(subreq,
357 struct task_server);
358 int sys_errno;
359 int ret;
361 ret = samba_runcmd_recv(subreq, &sys_errno);
362 if (ret != 0) {
363 DEBUG(0, ("The MIT KDC daemon died with exit status %d\n",
364 sys_errno));
365 } else {
366 DEBUG(0,("The MIT KDC daemon exited normally\n"));
369 task_server_terminate(task, "mitkdc child process exited", true);
372 /* Called at MIT KRB5 startup - register ourselves as a server service */
373 NTSTATUS server_service_mitkdc_init(TALLOC_CTX *mem_ctx);
375 NTSTATUS server_service_mitkdc_init(TALLOC_CTX *mem_ctx)
377 static const struct service_details details = {
378 .inhibit_fork_on_accept = true,
380 * Need to prevent pre-forking on kdc.
381 * The task_init function is run on the master process only
382 * and the irpc process name is registered in it's event loop.
383 * The child worker processes initialise their event loops on
384 * fork, so are not listening for the irpc event.
386 * The master process does not wait on that event context
387 * the master process is responsible for managing the worker
388 * processes not performing work.
390 .inhibit_pre_fork = true,
391 .task_init = mitkdc_task_init,
392 .post_fork = NULL
394 return register_server_service(mem_ctx, "kdc", &details);