1 /*
2    Unix SMB/CIFS implementation.
3 
4    Start MIT krb5kdc server within Samba AD
5 
6    Copyright (c) 2014-2016 Andreas Schneider <asn@samba.org>
7 
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.
12 
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.
17 
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/>.
20 */
21 
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 <kdb.h>
40 
41 #pragma clang diagnostic push
42 #pragma clang diagnostic ignored "-Wstrict-prototypes"
43 #include <kadm5/admin.h>
44 #pragma clang diagnostic pop
45 
46 #include "source4/kdc/mit_kdc_irpc.h"
47 
48 /* PROTOTYPES */
49 static void mitkdc_server_done(struct tevent_req *subreq);
50 
kdc_server_destroy(struct kdc_server * kdc)51 static int kdc_server_destroy(struct kdc_server *kdc)
52 {
53 	if (kdc->private_data != NULL) {
54 		kadm5_destroy(kdc->private_data);
55 	}
56 
57 	return 0;
58 }
59 
startup_kpasswd_server(TALLOC_CTX * mem_ctx,struct kdc_server * kdc,struct loadparm_context * lp_ctx,struct interface * ifaces)60 static NTSTATUS startup_kpasswd_server(TALLOC_CTX *mem_ctx,
61 				       struct kdc_server *kdc,
62 				       struct loadparm_context *lp_ctx,
63 				       struct interface *ifaces)
64 {
65 	int num_interfaces;
66 	int i;
67 	TALLOC_CTX *tmp_ctx;
68 	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
69 	uint16_t kpasswd_port;
70 	bool done_wildcard = false;
71 	bool ok;
72 
73 	kpasswd_port = lpcfg_kpasswd_port(lp_ctx);
74 	if (kpasswd_port == 0) {
75 		return NT_STATUS_OK;
76 	}
77 
78 	tmp_ctx = talloc_named_const(mem_ctx, 0, "kpasswd");
79 	if (tmp_ctx == NULL) {
80 		return NT_STATUS_NO_MEMORY;
81 	}
82 
83 	num_interfaces = iface_list_count(ifaces);
84 
85 	ok = lpcfg_bind_interfaces_only(lp_ctx);
86 	if (!ok) {
87 		int num_binds = 0;
88 		char **wcard;
89 
90 		wcard = iface_list_wildcard(tmp_ctx);
91 		if (wcard == NULL) {
92 			status = NT_STATUS_NO_MEMORY;
93 			goto out;
94 		}
95 
96 		for (i = 0; wcard[i] != NULL; i++) {
97 			status = kdc_add_socket(kdc,
98 						kdc->task->model_ops,
99 						"kpasswd",
100 						wcard[i],
101 						kpasswd_port,
102 						kpasswd_process,
103 						false);
104 			if (NT_STATUS_IS_OK(status)) {
105 				num_binds++;
106 			}
107 		}
108 		talloc_free(wcard);
109 
110 		if (num_binds == 0) {
111 			status = NT_STATUS_INVALID_PARAMETER_MIX;
112 			goto out;
113 		}
114 
115 		done_wildcard = true;
116 	}
117 
118 	for (i = 0; i < num_interfaces; i++) {
119 		const char *address = talloc_strdup(tmp_ctx, iface_list_n_ip(ifaces, i));
120 
121 		status = kdc_add_socket(kdc,
122 					kdc->task->model_ops,
123 					"kpasswd",
124 					address,
125 					kpasswd_port,
126 					kpasswd_process,
127 					done_wildcard);
128 		if (NT_STATUS_IS_OK(status)) {
129 			goto out;
130 		}
131 	}
132 
133 out:
134 	talloc_free(tmp_ctx);
135 	return status;
136 }
137 
138 /*
139  * Startup a copy of the krb5kdc as a child daemon
140  */
mitkdc_task_init(struct task_server * task)141 NTSTATUS mitkdc_task_init(struct task_server *task)
142 {
143 	struct tevent_req *subreq;
144 	const char * const *kdc_cmd;
145 	struct interface *ifaces;
146 	char *kdc_config = NULL;
147 	struct kdc_server *kdc;
148 	krb5_error_code code;
149 	NTSTATUS status;
150 	kadm5_ret_t ret;
151 	kadm5_config_params config;
152 	void *server_handle;
153 
154 	task_server_set_title(task, "task[mitkdc_parent]");
155 
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;
172 	}
173 
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;
181 	}
182 
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;
191 	}
192 	setenv("KRB5_KDC_PROFILE", kdc_config, 0);
193 	TALLOC_FREE(kdc_config);
194 
195 	/* start it as a child process */
196 	kdc_cmd = lpcfg_mit_kdc_command(task->lp_ctx);
197 
198 	subreq = samba_runcmd_send(task,
199 				   task->event_ctx,
200 				   timeval_zero(),
201 				   1, /* stdout log level */
202 				   0, /* stderr log level */
203 				   kdc_cmd,
204 				   "-n", /* Don't go into background */
205 #if 0
206 				   "-w 2", /* Start two workers */
207 #endif
208 				   NULL);
209 	if (subreq == NULL) {
210 		DEBUG(0, ("Failed to start MIT KDC as child daemon\n"));
211 
212 		task_server_terminate(task,
213 				      "Failed to startup mitkdc task",
214 				      true);
215 		return NT_STATUS_INTERNAL_ERROR;
216 	}
217 
218 	tevent_req_set_callback(subreq, mitkdc_server_done, task);
219 
220 	DEBUG(5,("Started krb5kdc process\n"));
221 
222 	status = samba_setup_mit_kdc_irpc(task);
223 	if (!NT_STATUS_IS_OK(status)) {
224 		task_server_terminate(task,
225 				      "Failed to setup kdc irpc service",
226 				      true);
227 	}
228 
229 	DEBUG(5,("Started irpc service for kdc_server\n"));
230 
231 	kdc = talloc_zero(task, struct kdc_server);
232 	if (kdc == NULL) {
233 		task_server_terminate(task, "KDC: Out of memory", true);
234 		return NT_STATUS_NO_MEMORY;
235 	}
236 	talloc_set_destructor(kdc, kdc_server_destroy);
237 
238 	kdc->task = task;
239 
240 	kdc->base_ctx = talloc_zero(kdc, struct samba_kdc_base_context);
241 	if (kdc->base_ctx == NULL) {
242 		task_server_terminate(task, "KDC: Out of memory", true);
243 		return NT_STATUS_NO_MEMORY;
244 	}
245 
246 	kdc->base_ctx->ev_ctx = task->event_ctx;
247 	kdc->base_ctx->lp_ctx = task->lp_ctx;
248 
249 	initialize_krb5_error_table();
250 
251 	code = smb_krb5_init_context(kdc,
252 				     kdc->task->lp_ctx,
253 				     &kdc->smb_krb5_context);
254 	if (code != 0) {
255 		task_server_terminate(task,
256 				      "KDC: Unable to initialize krb5 context",
257 				      true);
258 		return NT_STATUS_INTERNAL_ERROR;
259 	}
260 
261 	code = kadm5_init_krb5_context(&kdc->smb_krb5_context->krb5_context);
262 	if (code != 0) {
263 		task_server_terminate(task,
264 				      "KDC: Unable to init kadm5 krb5_context",
265 				      true);
266 		return NT_STATUS_INTERNAL_ERROR;
267 	}
268 
269 	ZERO_STRUCT(config);
270 	config.mask = KADM5_CONFIG_REALM;
271 	config.realm = discard_const_p(char, lpcfg_realm(kdc->task->lp_ctx));
272 
273 	ret = kadm5_init(kdc->smb_krb5_context->krb5_context,
274 			 discard_const_p(char, "kpasswd"),
275 			 NULL, /* pass */
276 			 discard_const_p(char, "kpasswd"),
277 			 &config,
278 			 KADM5_STRUCT_VERSION,
279 			 KADM5_API_VERSION_4,
280 			 NULL,
281 			 &server_handle);
282 	if (ret != 0) {
283 		task_server_terminate(task,
284 				      "KDC: Initialize kadm5",
285 				      true);
286 		return NT_STATUS_INTERNAL_ERROR;
287 	}
288 	kdc->private_data = server_handle;
289 
290 	code = krb5_db_register_keytab(kdc->smb_krb5_context->krb5_context);
291 	if (code != 0) {
292 		task_server_terminate(task,
293 				      "KDC: Unable to KDB",
294 				      true);
295 		return NT_STATUS_INTERNAL_ERROR;
296 	}
297 
298 	kdc->keytab_name = talloc_asprintf(kdc, "KDB:");
299 	if (kdc->keytab_name == NULL) {
300 		task_server_terminate(task,
301 				      "KDC: Out of memory",
302 				      true);
303 		return NT_STATUS_NO_MEMORY;
304 	}
305 
306 	kdc->samdb = samdb_connect(kdc,
307 				   kdc->task->event_ctx,
308 				   kdc->task->lp_ctx,
309 				   system_session(kdc->task->lp_ctx),
310 				   NULL,
311 				   0);
312 	if (kdc->samdb == NULL) {
313 		task_server_terminate(task,
314 				      "KDC: Unable to connect to samdb",
315 				      true);
316 		return NT_STATUS_CONNECTION_INVALID;
317 	}
318 
319 	status = startup_kpasswd_server(kdc,
320 				    kdc,
321 				    task->lp_ctx,
322 				    ifaces);
323 	if (!NT_STATUS_IS_OK(status)) {
324 		task_server_terminate(task,
325 				      "KDC: Unable to start kpasswd server",
326 				      true);
327 		return status;
328 	}
329 
330 	DEBUG(5,("Started kpasswd service for kdc_server\n"));
331 
332 	return NT_STATUS_OK;
333 }
334 
335 /*
336  * This gets called the kdc exits.
337  */
mitkdc_server_done(struct tevent_req * subreq)338 static void mitkdc_server_done(struct tevent_req *subreq)
339 {
340 	struct task_server *task =
341 		tevent_req_callback_data(subreq,
342 		struct task_server);
343 	int sys_errno;
344 	int ret;
345 
346 	ret = samba_runcmd_recv(subreq, &sys_errno);
347 	if (ret != 0) {
348 		DEBUG(0, ("The MIT KDC daemon died with exit status %d\n",
349 			  sys_errno));
350 	} else {
351 		DEBUG(0,("The MIT KDC daemon exited normally\n"));
352 	}
353 
354 	task_server_terminate(task, "mitkdc child process exited", true);
355 }
356 
357 /* Called at MIT KRB5 startup - register ourselves as a server service */
358 NTSTATUS server_service_mitkdc_init(TALLOC_CTX *mem_ctx);
359 
server_service_mitkdc_init(TALLOC_CTX * mem_ctx)360 NTSTATUS server_service_mitkdc_init(TALLOC_CTX *mem_ctx)
361 {
362 	static const struct service_details details = {
363 		.inhibit_fork_on_accept = true,
364 		/*
365 		 * Need to prevent pre-forking on kdc.
366 		 * The task_init function is run on the master process only
367 		 * and the irpc process name is registered in it's event loop.
368 		 * The child worker processes initialise their event loops on
369 		 * fork, so are not listening for the irpc event.
370 		 *
371 		 * The master process does not wait on that event context
372 		 * the master process is responsible for managing the worker
373 		 * processes not performing work.
374 		 */
375 		.inhibit_pre_fork = true,
376 		.task_init = mitkdc_task_init,
377 		.post_fork = NULL
378 	};
379 	return register_server_service(mem_ctx, "kdc", &details);
380 }
381