librpc: Do not include the ndr_table for libnet_join.idl and libnetapi.idl in the...
[Samba.git] / source4 / kdc / kdc-service-mit.c
blobdd6902f083d52694eb4bbfe1bed69e23dac5840c
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/smbd/service.h"
29 #include "source4/smbd/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 /* PROTOTYPES */
45 static void mitkdc_server_done(struct tevent_req *subreq);
47 static int kdc_server_destroy(struct kdc_server *kdc)
49 if (kdc->private_data != NULL) {
50 kadm5_destroy(kdc->private_data);
53 return 0;
56 static NTSTATUS startup_kpasswd_server(TALLOC_CTX *mem_ctx,
57 struct kdc_server *kdc,
58 struct loadparm_context *lp_ctx,
59 struct interface *ifaces)
61 int num_interfaces;
62 int i;
63 TALLOC_CTX *tmp_ctx;
64 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
65 uint16_t kpasswd_port;
66 bool done_wildcard = false;
67 bool ok;
69 kpasswd_port = lpcfg_kpasswd_port(lp_ctx);
70 if (kpasswd_port == 0) {
71 return NT_STATUS_OK;
74 tmp_ctx = talloc_named_const(mem_ctx, 0, "kpasswd");
75 if (tmp_ctx == NULL) {
76 return NT_STATUS_NO_MEMORY;
79 num_interfaces = iface_list_count(ifaces);
81 ok = lpcfg_bind_interfaces_only(lp_ctx);
82 if (!ok) {
83 int num_binds = 0;
84 char **wcard;
86 wcard = iface_list_wildcard(tmp_ctx);
87 if (wcard == NULL) {
88 status = NT_STATUS_NO_MEMORY;
89 goto out;
92 for (i = 0; wcard[i] != NULL; i++) {
93 status = kdc_add_socket(kdc,
94 kdc->task->model_ops,
95 "kpasswd",
96 wcard[i],
97 kpasswd_port,
98 kpasswd_process,
99 false);
100 if (NT_STATUS_IS_OK(status)) {
101 num_binds++;
104 talloc_free(wcard);
106 if (num_binds == 0) {
107 status = NT_STATUS_INVALID_PARAMETER_MIX;
108 goto out;
111 done_wildcard = true;
114 for (i = 0; i < num_interfaces; i++) {
115 const char *address = talloc_strdup(tmp_ctx, iface_list_n_ip(ifaces, i));
117 status = kdc_add_socket(kdc,
118 kdc->task->model_ops,
119 "kpasswd",
120 address,
121 kpasswd_port,
122 kpasswd_process,
123 done_wildcard);
124 if (NT_STATUS_IS_OK(status)) {
125 goto out;
129 out:
130 talloc_free(tmp_ctx);
131 return status;
135 * Startup a copy of the krb5kdc as a child daemon
137 NTSTATUS mitkdc_task_init(struct task_server *task)
139 struct tevent_req *subreq;
140 const char * const *kdc_cmd;
141 struct interface *ifaces;
142 char *kdc_config = NULL;
143 struct kdc_server *kdc;
144 krb5_error_code code;
145 NTSTATUS status;
146 kadm5_ret_t ret;
147 kadm5_config_params config;
148 void *server_handle;
150 task_server_set_title(task, "task[mitkdc_parent]");
152 switch (lpcfg_server_role(task->lp_ctx)) {
153 case ROLE_STANDALONE:
154 task_server_terminate(task,
155 "The KDC is not required in standalone "
156 "server configuration, terminate!",
157 false);
158 return NT_STATUS_INVALID_DOMAIN_ROLE;
159 case ROLE_DOMAIN_MEMBER:
160 task_server_terminate(task,
161 "The KDC is not required in member "
162 "server configuration",
163 false);
164 return NT_STATUS_INVALID_DOMAIN_ROLE;
165 case ROLE_ACTIVE_DIRECTORY_DC:
166 /* Yes, we want to start the KDC */
167 break;
170 /* Load interfaces for kpasswd */
171 load_interface_list(task, task->lp_ctx, &ifaces);
172 if (iface_list_count(ifaces) == 0) {
173 task_server_terminate(task,
174 "KDC: no network interfaces configured",
175 false);
176 return NT_STATUS_UNSUCCESSFUL;
179 kdc_config = talloc_asprintf(task,
180 "%s/kdc.conf",
181 lpcfg_private_dir(task->lp_ctx));
182 if (kdc_config == NULL) {
183 task_server_terminate(task,
184 "KDC: no memory",
185 false);
186 return NT_STATUS_NO_MEMORY;
188 setenv("KRB5_KDC_PROFILE", kdc_config, 0);
189 TALLOC_FREE(kdc_config);
191 /* start it as a child process */
192 kdc_cmd = lpcfg_mit_kdc_command(task->lp_ctx);
194 subreq = samba_runcmd_send(task,
195 task->event_ctx,
196 timeval_zero(),
197 1, /* stdout log level */
198 0, /* stderr log level */
199 kdc_cmd,
200 "-n", /* Don't go into background */
201 #if 0
202 "-w 2", /* Start two workers */
203 #endif
204 NULL);
205 if (subreq == NULL) {
206 DEBUG(0, ("Failed to start MIT KDC as child daemon\n"));
208 task_server_terminate(task,
209 "Failed to startup mitkdc task",
210 true);
211 return NT_STATUS_INTERNAL_ERROR;
214 tevent_req_set_callback(subreq, mitkdc_server_done, task);
216 DEBUG(5,("Started krb5kdc process\n"));
218 status = samba_setup_mit_kdc_irpc(task);
219 if (!NT_STATUS_IS_OK(status)) {
220 task_server_terminate(task,
221 "Failed to setup kdc irpc service",
222 true);
225 DEBUG(5,("Started irpc service for kdc_server\n"));
227 kdc = talloc_zero(task, struct kdc_server);
228 if (kdc == NULL) {
229 task_server_terminate(task, "KDC: Out of memory", true);
230 return NT_STATUS_NO_MEMORY;
232 talloc_set_destructor(kdc, kdc_server_destroy);
234 kdc->task = task;
236 kdc->base_ctx = talloc_zero(kdc, struct samba_kdc_base_context);
237 if (kdc->base_ctx == NULL) {
238 task_server_terminate(task, "KDC: Out of memory", true);
239 return NT_STATUS_NO_MEMORY;
242 kdc->base_ctx->ev_ctx = task->event_ctx;
243 kdc->base_ctx->lp_ctx = task->lp_ctx;
245 initialize_krb5_error_table();
247 code = smb_krb5_init_context(kdc,
248 kdc->task->lp_ctx,
249 &kdc->smb_krb5_context);
250 if (code != 0) {
251 task_server_terminate(task,
252 "KDC: Unable to initialize krb5 context",
253 true);
254 return NT_STATUS_INTERNAL_ERROR;
257 code = kadm5_init_krb5_context(&kdc->smb_krb5_context->krb5_context);
258 if (code != 0) {
259 task_server_terminate(task,
260 "KDC: Unable to init kadm5 krb5_context",
261 true);
262 return NT_STATUS_INTERNAL_ERROR;
265 ZERO_STRUCT(config);
266 config.mask = KADM5_CONFIG_REALM;
267 config.realm = discard_const_p(char, lpcfg_realm(kdc->task->lp_ctx));
269 ret = kadm5_init(kdc->smb_krb5_context->krb5_context,
270 discard_const_p(char, "kpasswd"),
271 NULL, /* pass */
272 discard_const_p(char, "kpasswd"),
273 &config,
274 KADM5_STRUCT_VERSION,
275 KADM5_API_VERSION_4,
276 NULL,
277 &server_handle);
278 if (ret != 0) {
279 task_server_terminate(task,
280 "KDC: Initialize kadm5",
281 true);
282 return NT_STATUS_INTERNAL_ERROR;
284 kdc->private_data = server_handle;
286 code = krb5_db_register_keytab(kdc->smb_krb5_context->krb5_context);
287 if (code != 0) {
288 task_server_terminate(task,
289 "KDC: Unable to KDB",
290 true);
291 return NT_STATUS_INTERNAL_ERROR;
294 kdc->keytab_name = talloc_asprintf(kdc, "KDB:");
295 if (kdc->keytab_name == NULL) {
296 task_server_terminate(task,
297 "KDC: Out of memory",
298 true);
299 return NT_STATUS_NO_MEMORY;
302 kdc->samdb = samdb_connect(kdc,
303 kdc->task->event_ctx,
304 kdc->task->lp_ctx,
305 system_session(kdc->task->lp_ctx),
306 NULL,
308 if (kdc->samdb == NULL) {
309 task_server_terminate(task,
310 "KDC: Unable to connect to samdb",
311 true);
312 return NT_STATUS_CONNECTION_INVALID;
315 status = startup_kpasswd_server(kdc,
316 kdc,
317 task->lp_ctx,
318 ifaces);
319 if (!NT_STATUS_IS_OK(status)) {
320 task_server_terminate(task,
321 "KDC: Unable to start kpasswd server",
322 true);
323 return status;
326 DEBUG(5,("Started kpasswd service for kdc_server\n"));
328 return NT_STATUS_OK;
332 * This gets called the kdc exits.
334 static void mitkdc_server_done(struct tevent_req *subreq)
336 struct task_server *task =
337 tevent_req_callback_data(subreq,
338 struct task_server);
339 int sys_errno;
340 int ret;
342 ret = samba_runcmd_recv(subreq, &sys_errno);
343 if (ret != 0) {
344 DEBUG(0, ("The MIT KDC daemon died with exit status %d\n",
345 sys_errno));
346 } else {
347 DEBUG(0,("The MIT KDC daemon exited normally\n"));
350 task_server_terminate(task, "mitkdc child process exited", true);
353 /* Called at MIT KRB5 startup - register ourselves as a server service */
354 NTSTATUS server_service_mitkdc_init(TALLOC_CTX *mem_ctx);
356 NTSTATUS server_service_mitkdc_init(TALLOC_CTX *mem_ctx)
358 static const struct service_details details = {
359 .inhibit_fork_on_accept = true,
361 * Need to prevent pre-forking on kdc.
362 * The task_init function is run on the master process only
363 * and the irpc process name is registered in it's event loop.
364 * The child worker processes initialise their event loops on
365 * fork, so are not listening for the irpc event.
367 * The master process does not wait on that event context
368 * the master process is responsible for managing the worker
369 * processes not performing work.
371 .inhibit_pre_fork = true,
372 .task_init = mitkdc_task_init,
373 .post_fork = NULL
375 return register_server_service(mem_ctx, "kdc", &details);