1/*
2   Unix SMB/CIFS implementation.
3
4   KDC Server startup
5
6   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2008
7   Copyright (C) Andrew Tridgell	2005
8   Copyright (C) Stefan Metzmacher	2005
9
10   This program is free software; you can redistribute it and/or modify
11   it under the terms of the GNU General Public License as published by
12   the Free Software Foundation; either version 3 of the License, or
13   (at your option) any later version.
14
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19
20   You should have received a copy of the GNU General Public License
21   along with this program.  If not, see <http://www.gnu.org/licenses/>.
22*/
23
24#include "includes.h"
25#include "smbd/service_task.h"
26#include "smbd/service.h"
27#include "smbd/service_stream.h"
28#include "smbd/process_model.h"
29#include "lib/events/events.h"
30#include "lib/socket/socket.h"
31#include "system/network.h"
32#include "../lib/util/dlinklist.h"
33#include "lib/messaging/irpc.h"
34#include "lib/stream/packet.h"
35#include "librpc/gen_ndr/samr.h"
36#include "librpc/gen_ndr/ndr_irpc.h"
37#include "librpc/gen_ndr/ndr_krb5pac.h"
38#include "lib/socket/netif.h"
39#include "param/param.h"
40#include "kdc/kdc.h"
41#include "librpc/gen_ndr/ndr_misc.h"
42
43
44/* Disgusting hack to get a mem_ctx and lp_ctx into the hdb plugin, when
45 * used as a keytab */
46TALLOC_CTX *hdb_samba4_mem_ctx;
47struct tevent_context *hdb_samba4_ev_ctx;
48struct loadparm_context *hdb_samba4_lp_ctx;
49
50/* hold all the info needed to send a reply */
51struct kdc_reply {
52	struct kdc_reply *next, *prev;
53	struct socket_address *dest;
54	DATA_BLOB packet;
55};
56
57typedef bool (*kdc_process_fn_t)(struct kdc_server *kdc,
58				 TALLOC_CTX *mem_ctx,
59				 DATA_BLOB *input,
60				 DATA_BLOB *reply,
61				 struct socket_address *peer_addr,
62				 struct socket_address *my_addr,
63				 int datagram);
64
65/* hold information about one kdc socket */
66struct kdc_socket {
67	struct socket_context *sock;
68	struct kdc_server *kdc;
69	struct tevent_fd *fde;
70
71	/* a queue of outgoing replies that have been deferred */
72	struct kdc_reply *send_queue;
73
74	kdc_process_fn_t process;
75};
76/*
77  state of an open tcp connection
78*/
79struct kdc_tcp_connection {
80	/* stream connection we belong to */
81	struct stream_connection *conn;
82
83	/* the kdc_server the connection belongs to */
84	struct kdc_server *kdc;
85
86	struct packet_context *packet;
87
88	kdc_process_fn_t process;
89};
90
91/*
92  handle fd send events on a KDC socket
93*/
94static void kdc_send_handler(struct kdc_socket *kdc_socket)
95{
96	while (kdc_socket->send_queue) {
97		struct kdc_reply *rep = kdc_socket->send_queue;
98		NTSTATUS status;
99		size_t sendlen;
100
101		status = socket_sendto(kdc_socket->sock, &rep->packet, &sendlen,
102				       rep->dest);
103		if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
104			break;
105		}
106		if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_BUFFER_SIZE)) {
107			/* Replace with a krb err, response to big */
108		}
109
110		DLIST_REMOVE(kdc_socket->send_queue, rep);
111		talloc_free(rep);
112	}
113
114	if (kdc_socket->send_queue == NULL) {
115		EVENT_FD_NOT_WRITEABLE(kdc_socket->fde);
116	}
117}
118
119
120/*
121  handle fd recv events on a KDC socket
122*/
123static void kdc_recv_handler(struct kdc_socket *kdc_socket)
124{
125	NTSTATUS status;
126	TALLOC_CTX *tmp_ctx = talloc_new(kdc_socket);
127	DATA_BLOB blob;
128	struct kdc_reply *rep;
129	DATA_BLOB reply;
130	size_t nread, dsize;
131	struct socket_address *src;
132	struct socket_address *my_addr;
133	int ret;
134
135	status = socket_pending(kdc_socket->sock, &dsize);
136	if (!NT_STATUS_IS_OK(status)) {
137		talloc_free(tmp_ctx);
138		return;
139	}
140
141	blob = data_blob_talloc(tmp_ctx, NULL, dsize);
142	if (blob.data == NULL) {
143		/* hope this is a temporary low memory condition */
144		talloc_free(tmp_ctx);
145		return;
146	}
147
148	status = socket_recvfrom(kdc_socket->sock, blob.data, blob.length, &nread,
149				 tmp_ctx, &src);
150	if (!NT_STATUS_IS_OK(status)) {
151		talloc_free(tmp_ctx);
152		return;
153	}
154	blob.length = nread;
155
156	DEBUG(10,("Received krb5 UDP packet of length %lu from %s:%u\n",
157		 (long)blob.length, src->addr, (uint16_t)src->port));
158
159	my_addr = socket_get_my_addr(kdc_socket->sock, tmp_ctx);
160	if (!my_addr) {
161		talloc_free(tmp_ctx);
162		return;
163	}
164
165
166	/* Call krb5 */
167	ret = kdc_socket->process(kdc_socket->kdc,
168				  tmp_ctx,
169				  &blob,
170				  &reply,
171				  src, my_addr,
172				  1 /* Datagram */);
173	if (!ret) {
174		talloc_free(tmp_ctx);
175		return;
176	}
177
178	/* queue a pending reply */
179	rep = talloc(kdc_socket, struct kdc_reply);
180	if (rep == NULL) {
181		talloc_free(tmp_ctx);
182		return;
183	}
184	rep->dest         = talloc_steal(rep, src);
185	rep->packet       = reply;
186	talloc_steal(rep, reply.data);
187
188	if (rep->packet.data == NULL) {
189		talloc_free(rep);
190		talloc_free(tmp_ctx);
191		return;
192	}
193
194	DLIST_ADD_END(kdc_socket->send_queue, rep, struct kdc_reply *);
195	EVENT_FD_WRITEABLE(kdc_socket->fde);
196	talloc_free(tmp_ctx);
197}
198
199/*
200  handle fd events on a KDC socket
201*/
202static void kdc_socket_handler(struct tevent_context *ev, struct tevent_fd *fde,
203			       uint16_t flags, void *private_data)
204{
205	struct kdc_socket *kdc_socket = talloc_get_type(private_data, struct kdc_socket);
206	if (flags & EVENT_FD_WRITE) {
207		kdc_send_handler(kdc_socket);
208	}
209	if (flags & EVENT_FD_READ) {
210		kdc_recv_handler(kdc_socket);
211	}
212}
213
214static void kdc_tcp_terminate_connection(struct kdc_tcp_connection *kdcconn, const char *reason)
215{
216	stream_terminate_connection(kdcconn->conn, reason);
217}
218
219/*
220  receive a full packet on a KDC connection
221*/
222static NTSTATUS kdc_tcp_recv(void *private_data, DATA_BLOB blob)
223{
224	struct kdc_tcp_connection *kdcconn = talloc_get_type(private_data,
225							     struct kdc_tcp_connection);
226	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
227	TALLOC_CTX *tmp_ctx = talloc_new(kdcconn);
228	int ret;
229	DATA_BLOB input, reply;
230	struct socket_address *src_addr;
231	struct socket_address *my_addr;
232
233	talloc_steal(tmp_ctx, blob.data);
234
235	src_addr = socket_get_peer_addr(kdcconn->conn->socket, tmp_ctx);
236	if (!src_addr) {
237		talloc_free(tmp_ctx);
238		return NT_STATUS_NO_MEMORY;
239	}
240
241	my_addr = socket_get_my_addr(kdcconn->conn->socket, tmp_ctx);
242	if (!my_addr) {
243		talloc_free(tmp_ctx);
244		return NT_STATUS_NO_MEMORY;
245	}
246
247	/* Call krb5 */
248	input = data_blob_const(blob.data + 4, blob.length - 4);
249
250	ret = kdcconn->process(kdcconn->kdc,
251			       tmp_ctx,
252			       &input,
253			       &reply,
254			       src_addr,
255			       my_addr,
256			       0 /* Not datagram */);
257	if (!ret) {
258		talloc_free(tmp_ctx);
259		return NT_STATUS_INTERNAL_ERROR;
260	}
261
262	/* and now encode the reply */
263	blob = data_blob_talloc(kdcconn, NULL, reply.length + 4);
264	if (!blob.data) {
265		talloc_free(tmp_ctx);
266		return NT_STATUS_NO_MEMORY;
267	}
268
269	RSIVAL(blob.data, 0, reply.length);
270	memcpy(blob.data + 4, reply.data, reply.length);
271
272	status = packet_send(kdcconn->packet, blob);
273	if (!NT_STATUS_IS_OK(status)) {
274		talloc_free(tmp_ctx);
275		return status;
276	}
277
278	/* the call isn't needed any more */
279	talloc_free(tmp_ctx);
280	return NT_STATUS_OK;
281}
282
283/*
284  receive some data on a KDC connection
285*/
286static void kdc_tcp_recv_handler(struct stream_connection *conn, uint16_t flags)
287{
288	struct kdc_tcp_connection *kdcconn = talloc_get_type(conn->private_data,
289							     struct kdc_tcp_connection);
290	packet_recv(kdcconn->packet);
291}
292
293/*
294  called on a tcp recv error
295*/
296static void kdc_tcp_recv_error(void *private_data, NTSTATUS status)
297{
298	struct kdc_tcp_connection *kdcconn = talloc_get_type(private_data,
299					     struct kdc_tcp_connection);
300	kdc_tcp_terminate_connection(kdcconn, nt_errstr(status));
301}
302
303/*
304  called when we can write to a connection
305*/
306static void kdc_tcp_send(struct stream_connection *conn, uint16_t flags)
307{
308	struct kdc_tcp_connection *kdcconn = talloc_get_type(conn->private_data,
309							     struct kdc_tcp_connection);
310	packet_queue_run(kdcconn->packet);
311}
312
313/**
314   Wrapper for krb5_kdc_process_krb5_request, converting to/from Samba
315   calling conventions
316*/
317
318static bool kdc_process(struct kdc_server *kdc,
319			TALLOC_CTX *mem_ctx,
320			DATA_BLOB *input,
321			DATA_BLOB *reply,
322			struct socket_address *peer_addr,
323			struct socket_address *my_addr,
324			int datagram_reply)
325{
326	int ret;
327	krb5_data k5_reply;
328	krb5_data_zero(&k5_reply);
329
330	krb5_kdc_update_time(NULL);
331
332	DEBUG(10,("Received KDC packet of length %lu from %s:%d\n",
333		  (long)input->length - 4, peer_addr->addr, peer_addr->port));
334
335	ret = krb5_kdc_process_krb5_request(kdc->smb_krb5_context->krb5_context,
336					    kdc->config,
337					    input->data, input->length,
338					    &k5_reply,
339					    peer_addr->addr,
340					    peer_addr->sockaddr,
341					    datagram_reply);
342	if (ret == -1) {
343		*reply = data_blob(NULL, 0);
344		return false;
345	}
346	if (k5_reply.length) {
347		*reply = data_blob_talloc(mem_ctx, k5_reply.data, k5_reply.length);
348		krb5_data_free(&k5_reply);
349	} else {
350		*reply = data_blob(NULL, 0);
351	}
352	return true;
353}
354
355/*
356  called when we get a new connection
357*/
358static void kdc_tcp_generic_accept(struct stream_connection *conn, kdc_process_fn_t process_fn)
359{
360	struct kdc_server *kdc = talloc_get_type(conn->private_data, struct kdc_server);
361	struct kdc_tcp_connection *kdcconn;
362
363	kdcconn = talloc_zero(conn, struct kdc_tcp_connection);
364	if (!kdcconn) {
365		stream_terminate_connection(conn, "kdc_tcp_accept: out of memory");
366		return;
367	}
368	kdcconn->conn	 = conn;
369	kdcconn->kdc	 = kdc;
370	kdcconn->process = process_fn;
371	conn->private_data    = kdcconn;
372
373	kdcconn->packet = packet_init(kdcconn);
374	if (kdcconn->packet == NULL) {
375		kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_accept: out of memory");
376		return;
377	}
378	packet_set_private(kdcconn->packet, kdcconn);
379	packet_set_socket(kdcconn->packet, conn->socket);
380	packet_set_callback(kdcconn->packet, kdc_tcp_recv);
381	packet_set_full_request(kdcconn->packet, packet_full_request_u32);
382	packet_set_error_handler(kdcconn->packet, kdc_tcp_recv_error);
383	packet_set_event_context(kdcconn->packet, conn->event.ctx);
384	packet_set_fde(kdcconn->packet, conn->event.fde);
385	packet_set_serialise(kdcconn->packet);
386}
387
388static void kdc_tcp_accept(struct stream_connection *conn)
389{
390	kdc_tcp_generic_accept(conn, kdc_process);
391}
392
393static const struct stream_server_ops kdc_tcp_stream_ops = {
394	.name			= "kdc_tcp",
395	.accept_connection	= kdc_tcp_accept,
396	.recv_handler		= kdc_tcp_recv_handler,
397	.send_handler		= kdc_tcp_send
398};
399
400static void kpasswdd_tcp_accept(struct stream_connection *conn)
401{
402	kdc_tcp_generic_accept(conn, kpasswdd_process);
403}
404
405static const struct stream_server_ops kpasswdd_tcp_stream_ops = {
406	.name			= "kpasswdd_tcp",
407	.accept_connection	= kpasswdd_tcp_accept,
408	.recv_handler		= kdc_tcp_recv_handler,
409	.send_handler		= kdc_tcp_send
410};
411
412/*
413  start listening on the given address
414*/
415static NTSTATUS kdc_add_socket(struct kdc_server *kdc, const char *address,
416			       uint16_t kdc_port, uint16_t kpasswd_port)
417{
418	const struct model_ops *model_ops;
419 	struct kdc_socket *kdc_socket;
420 	struct kdc_socket *kpasswd_socket;
421	struct socket_address *kdc_address, *kpasswd_address;
422	NTSTATUS status;
423
424	kdc_socket = talloc(kdc, struct kdc_socket);
425	NT_STATUS_HAVE_NO_MEMORY(kdc_socket);
426
427	kpasswd_socket = talloc(kdc, struct kdc_socket);
428	NT_STATUS_HAVE_NO_MEMORY(kpasswd_socket);
429
430	status = socket_create("ip", SOCKET_TYPE_DGRAM, &kdc_socket->sock, 0);
431	if (!NT_STATUS_IS_OK(status)) {
432		talloc_free(kdc_socket);
433		return status;
434	}
435
436	status = socket_create("ip", SOCKET_TYPE_DGRAM, &kpasswd_socket->sock, 0);
437	if (!NT_STATUS_IS_OK(status)) {
438		talloc_free(kpasswd_socket);
439		return status;
440	}
441
442	kdc_socket->kdc = kdc;
443	kdc_socket->send_queue = NULL;
444	kdc_socket->process = kdc_process;
445
446	talloc_steal(kdc_socket, kdc_socket->sock);
447
448	kdc_socket->fde = event_add_fd(kdc->task->event_ctx, kdc,
449				       socket_get_fd(kdc_socket->sock), EVENT_FD_READ,
450				       kdc_socket_handler, kdc_socket);
451
452	kdc_address = socket_address_from_strings(kdc_socket, kdc_socket->sock->backend_name,
453						  address, kdc_port);
454	NT_STATUS_HAVE_NO_MEMORY(kdc_address);
455
456	status = socket_listen(kdc_socket->sock, kdc_address, 0, 0);
457	if (!NT_STATUS_IS_OK(status)) {
458		DEBUG(0,("Failed to bind to %s:%d UDP for kdc - %s\n",
459			 address, kdc_port, nt_errstr(status)));
460		talloc_free(kdc_socket);
461		return status;
462	}
463
464	kpasswd_socket->kdc = kdc;
465	kpasswd_socket->send_queue = NULL;
466	kpasswd_socket->process = kpasswdd_process;
467
468	talloc_steal(kpasswd_socket, kpasswd_socket->sock);
469
470	kpasswd_socket->fde = event_add_fd(kdc->task->event_ctx, kdc,
471					   socket_get_fd(kpasswd_socket->sock), EVENT_FD_READ,
472					   kdc_socket_handler, kpasswd_socket);
473
474	kpasswd_address = socket_address_from_strings(kpasswd_socket, kpasswd_socket->sock->backend_name,
475						      address, kpasswd_port);
476	NT_STATUS_HAVE_NO_MEMORY(kpasswd_address);
477
478	status = socket_listen(kpasswd_socket->sock, kpasswd_address, 0, 0);
479	if (!NT_STATUS_IS_OK(status)) {
480		DEBUG(0,("Failed to bind to %s:%d UDP for kpasswd - %s\n",
481			 address, kpasswd_port, nt_errstr(status)));
482		talloc_free(kpasswd_socket);
483		return status;
484	}
485
486	/* within the kdc task we want to be a single process, so
487	   ask for the single process model ops and pass these to the
488	   stream_setup_socket() call. */
489	model_ops = process_model_startup(kdc->task->event_ctx, "single");
490	if (!model_ops) {
491		DEBUG(0,("Can't find 'single' process model_ops\n"));
492		talloc_free(kdc_socket);
493		return NT_STATUS_INTERNAL_ERROR;
494	}
495
496	status = stream_setup_socket(kdc->task->event_ctx,
497				     kdc->task->lp_ctx,
498				     model_ops,
499				     &kdc_tcp_stream_ops,
500				     "ip", address, &kdc_port,
501				     lp_socket_options(kdc->task->lp_ctx),
502				     kdc);
503	if (!NT_STATUS_IS_OK(status)) {
504		DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
505			 address, kdc_port, nt_errstr(status)));
506		talloc_free(kdc_socket);
507		return status;
508	}
509
510	status = stream_setup_socket(kdc->task->event_ctx,
511				     kdc->task->lp_ctx,
512				     model_ops,
513				     &kpasswdd_tcp_stream_ops,
514				     "ip", address, &kpasswd_port,
515				     lp_socket_options(kdc->task->lp_ctx),
516				     kdc);
517	if (!NT_STATUS_IS_OK(status)) {
518		DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
519			 address, kpasswd_port, nt_errstr(status)));
520		talloc_free(kdc_socket);
521		return status;
522	}
523
524	return NT_STATUS_OK;
525}
526
527
528/*
529  setup our listening sockets on the configured network interfaces
530*/
531static NTSTATUS kdc_startup_interfaces(struct kdc_server *kdc, struct loadparm_context *lp_ctx,
532				       struct interface *ifaces)
533{
534	int num_interfaces;
535	TALLOC_CTX *tmp_ctx = talloc_new(kdc);
536	NTSTATUS status;
537	int i;
538
539	num_interfaces = iface_count(ifaces);
540
541	for (i=0; i<num_interfaces; i++) {
542		const char *address = talloc_strdup(tmp_ctx, iface_n_ip(ifaces, i));
543		status = kdc_add_socket(kdc, address, lp_krb5_port(lp_ctx),
544					lp_kpasswd_port(lp_ctx));
545		NT_STATUS_NOT_OK_RETURN(status);
546	}
547
548	talloc_free(tmp_ctx);
549
550	return NT_STATUS_OK;
551}
552
553
554static NTSTATUS kdc_check_generic_kerberos(struct irpc_message *msg,
555				 struct kdc_check_generic_kerberos *r)
556{
557	struct PAC_Validate pac_validate;
558	DATA_BLOB srv_sig;
559	struct PAC_SIGNATURE_DATA kdc_sig;
560	struct kdc_server *kdc = talloc_get_type(msg->private_data, struct kdc_server);
561	enum ndr_err_code ndr_err;
562	krb5_enctype etype;
563	int ret;
564	hdb_entry_ex ent;
565	krb5_principal principal;
566	krb5_keyblock keyblock;
567	Key *key;
568
569	/* There is no reply to this request */
570	r->out.generic_reply = data_blob(NULL, 0);
571
572	ndr_err = ndr_pull_struct_blob(&r->in.generic_request, msg,
573				       lp_iconv_convenience(kdc->task->lp_ctx),
574				       &pac_validate,
575				       (ndr_pull_flags_fn_t)ndr_pull_PAC_Validate);
576	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
577		return NT_STATUS_INVALID_PARAMETER;
578	}
579
580	if (pac_validate.MessageType != 3) {
581		/* We don't implement any other message types - such as certificate validation - yet */
582		return NT_STATUS_INVALID_PARAMETER;
583	}
584
585	if (pac_validate.ChecksumAndSignature.length != (pac_validate.ChecksumLength + pac_validate.SignatureLength)
586	    || pac_validate.ChecksumAndSignature.length < pac_validate.ChecksumLength
587	    || pac_validate.ChecksumAndSignature.length < pac_validate.SignatureLength ) {
588		return NT_STATUS_INVALID_PARAMETER;
589	}
590
591	srv_sig = data_blob_const(pac_validate.ChecksumAndSignature.data,
592				  pac_validate.ChecksumLength);
593
594	if (pac_validate.SignatureType == CKSUMTYPE_HMAC_MD5) {
595		etype = ETYPE_ARCFOUR_HMAC_MD5;
596	} else {
597		ret = krb5_cksumtype_to_enctype(kdc->smb_krb5_context->krb5_context, pac_validate.SignatureType,
598						&etype);
599		if (ret != 0) {
600			return NT_STATUS_LOGON_FAILURE;
601		}
602	}
603
604	ret = krb5_make_principal(kdc->smb_krb5_context->krb5_context, &principal,
605				  lp_realm(kdc->task->lp_ctx),
606				  "krbtgt", lp_realm(kdc->task->lp_ctx),
607				  NULL);
608
609	if (ret != 0) {
610		return NT_STATUS_NO_MEMORY;
611	}
612
613	ret = kdc->config->db[0]->hdb_fetch(kdc->smb_krb5_context->krb5_context,
614					    kdc->config->db[0],
615					    principal,
616					    HDB_F_GET_KRBTGT | HDB_F_DECRYPT,
617					    &ent);
618
619	if (ret != 0) {
620		hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent);
621		krb5_free_principal(kdc->smb_krb5_context->krb5_context, principal);
622
623		return NT_STATUS_LOGON_FAILURE;
624	}
625
626	ret = hdb_enctype2key(kdc->smb_krb5_context->krb5_context, &ent.entry, etype, &key);
627
628	if (ret != 0) {
629		hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent);
630		krb5_free_principal(kdc->smb_krb5_context->krb5_context, principal);
631		return NT_STATUS_LOGON_FAILURE;
632	}
633
634	keyblock = key->key;
635
636	kdc_sig.type = pac_validate.SignatureType;
637	kdc_sig.signature = data_blob_const(&pac_validate.ChecksumAndSignature.data[pac_validate.ChecksumLength],
638					    pac_validate.SignatureLength);
639	ret = check_pac_checksum(msg, srv_sig, &kdc_sig,
640			   kdc->smb_krb5_context->krb5_context, &keyblock);
641
642	hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent);
643	krb5_free_principal(kdc->smb_krb5_context->krb5_context, principal);
644
645	if (ret != 0) {
646		return NT_STATUS_LOGON_FAILURE;
647	}
648
649	return NT_STATUS_OK;
650}
651
652
653/*
654  startup the kdc task
655*/
656static void kdc_task_init(struct task_server *task)
657{
658	struct kdc_server *kdc;
659	NTSTATUS status;
660	krb5_error_code ret;
661	struct interface *ifaces;
662
663	switch (lp_server_role(task->lp_ctx)) {
664	case ROLE_STANDALONE:
665		task_server_terminate(task, "kdc: no KDC required in standalone configuration", false);
666		return;
667	case ROLE_DOMAIN_MEMBER:
668		task_server_terminate(task, "kdc: no KDC required in member server configuration", false);
669		return;
670	case ROLE_DOMAIN_CONTROLLER:
671		/* Yes, we want a KDC */
672		break;
673	}
674
675	load_interfaces(task, lp_interfaces(task->lp_ctx), &ifaces);
676
677	if (iface_count(ifaces) == 0) {
678		task_server_terminate(task, "kdc: no network interfaces configured", false);
679		return;
680	}
681
682	task_server_set_title(task, "task[kdc]");
683
684	kdc = talloc(task, struct kdc_server);
685	if (kdc == NULL) {
686		task_server_terminate(task, "kdc: out of memory", true);
687		return;
688	}
689
690	kdc->task = task;
691
692	initialize_krb5_error_table();
693
694	ret = smb_krb5_init_context(kdc, task->event_ctx, task->lp_ctx, &kdc->smb_krb5_context);
695	if (ret) {
696		DEBUG(1,("kdc_task_init: krb5_init_context failed (%s)\n",
697			 error_message(ret)));
698		task_server_terminate(task, "kdc: krb5_init_context failed", true);
699		return;
700	}
701
702	krb5_add_et_list(kdc->smb_krb5_context->krb5_context, initialize_hdb_error_table_r);
703
704	ret = krb5_kdc_get_config(kdc->smb_krb5_context->krb5_context,
705				  &kdc->config);
706	if(ret) {
707		task_server_terminate(task, "kdc: failed to get KDC configuration", true);
708		return;
709	}
710
711	kdc->config->logf = kdc->smb_krb5_context->logf;
712	kdc->config->db = talloc(kdc, struct HDB *);
713	if (!kdc->config->db) {
714		task_server_terminate(task, "kdc: out of memory", true);
715		return;
716	}
717	kdc->config->num_db = 1;
718
719	status = hdb_samba4_create_kdc(kdc, task->event_ctx, task->lp_ctx,
720				       kdc->smb_krb5_context->krb5_context,
721				       &kdc->config->db[0]);
722	if (!NT_STATUS_IS_OK(status)) {
723		task_server_terminate(task, "kdc: hdb_samba4_create_kdc (setup KDC database) failed", true);
724		return;
725	}
726
727	/* Register hdb-samba4 hooks for use as a keytab */
728
729	kdc->hdb_samba4_context = talloc(kdc, struct hdb_samba4_context);
730	if (!kdc->hdb_samba4_context) {
731		task_server_terminate(task, "kdc: out of memory", true);
732		return;
733	}
734
735	kdc->hdb_samba4_context->ev_ctx = task->event_ctx;
736	kdc->hdb_samba4_context->lp_ctx = task->lp_ctx;
737
738	ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context,
739				   PLUGIN_TYPE_DATA, "hdb",
740				   &hdb_samba4);
741	if(ret) {
742		task_server_terminate(task, "kdc: failed to register hdb keytab", true);
743		return;
744	}
745
746	ret = krb5_kt_register(kdc->smb_krb5_context->krb5_context, &hdb_kt_ops);
747	if(ret) {
748		task_server_terminate(task, "kdc: failed to register hdb keytab", true);
749		return;
750	}
751
752	/* Registar WinDC hooks */
753	ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context,
754				   PLUGIN_TYPE_DATA, "windc",
755				   &windc_plugin_table);
756	if(ret) {
757		task_server_terminate(task, "kdc: failed to register hdb keytab", true);
758		return;
759	}
760
761	krb5_kdc_windc_init(kdc->smb_krb5_context->krb5_context);
762
763	/* start listening on the configured network interfaces */
764	status = kdc_startup_interfaces(kdc, task->lp_ctx, ifaces);
765	if (!NT_STATUS_IS_OK(status)) {
766		task_server_terminate(task, "kdc failed to setup interfaces", true);
767		return;
768	}
769
770	status = IRPC_REGISTER(task->msg_ctx, irpc, KDC_CHECK_GENERIC_KERBEROS,
771			       kdc_check_generic_kerberos, kdc);
772	if (!NT_STATUS_IS_OK(status)) {
773		task_server_terminate(task, "nbtd failed to setup monitoring", true);
774		return;
775	}
776
777	irpc_add_name(task->msg_ctx, "kdc_server");
778}
779
780
781/* called at smbd startup - register ourselves as a server service */
782NTSTATUS server_service_kdc_init(void)
783{
784	return register_server_service("kdc", kdc_task_init);
785}
786