2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2008
7 Copyright (C) Andrew Tridgell 2005
8 Copyright (C) Stefan Metzmacher 2005
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.
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.
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/>.
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"
41 #include "librpc/gen_ndr/ndr_misc.h"
44 /* Disgusting hack to get a mem_ctx and lp_ctx into the hdb plugin, when
46 TALLOC_CTX
*hdb_samba4_mem_ctx
;
47 struct tevent_context
*hdb_samba4_ev_ctx
;
48 struct loadparm_context
*hdb_samba4_lp_ctx
;
50 /* hold all the info needed to send a reply */
52 struct kdc_reply
*next
, *prev
;
53 struct socket_address
*dest
;
57 typedef bool (*kdc_process_fn_t
)(struct kdc_server
*kdc
,
61 struct socket_address
*peer_addr
,
62 struct socket_address
*my_addr
,
65 /* hold information about one kdc socket */
67 struct socket_context
*sock
;
68 struct kdc_server
*kdc
;
69 struct tevent_fd
*fde
;
71 /* a queue of outgoing replies that have been deferred */
72 struct kdc_reply
*send_queue
;
74 kdc_process_fn_t process
;
77 state of an open tcp connection
79 struct kdc_tcp_connection
{
80 /* stream connection we belong to */
81 struct stream_connection
*conn
;
83 /* the kdc_server the connection belongs to */
84 struct kdc_server
*kdc
;
86 struct packet_context
*packet
;
88 kdc_process_fn_t process
;
92 handle fd send events on a KDC socket
94 static void kdc_send_handler(struct kdc_socket
*kdc_socket
)
96 while (kdc_socket
->send_queue
) {
97 struct kdc_reply
*rep
= kdc_socket
->send_queue
;
101 status
= socket_sendto(kdc_socket
->sock
, &rep
->packet
, &sendlen
,
103 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
106 if (NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_BUFFER_SIZE
)) {
107 /* Replace with a krb err, response to big */
110 DLIST_REMOVE(kdc_socket
->send_queue
, rep
);
114 if (kdc_socket
->send_queue
== NULL
) {
115 EVENT_FD_NOT_WRITEABLE(kdc_socket
->fde
);
121 handle fd recv events on a KDC socket
123 static void kdc_recv_handler(struct kdc_socket
*kdc_socket
)
126 TALLOC_CTX
*tmp_ctx
= talloc_new(kdc_socket
);
128 struct kdc_reply
*rep
;
131 struct socket_address
*src
;
132 struct socket_address
*my_addr
;
135 status
= socket_pending(kdc_socket
->sock
, &dsize
);
136 if (!NT_STATUS_IS_OK(status
)) {
137 talloc_free(tmp_ctx
);
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
);
148 status
= socket_recvfrom(kdc_socket
->sock
, blob
.data
, blob
.length
, &nread
,
150 if (!NT_STATUS_IS_OK(status
)) {
151 talloc_free(tmp_ctx
);
156 DEBUG(10,("Received krb5 UDP packet of length %lu from %s:%u\n",
157 (long)blob
.length
, src
->addr
, (uint16_t)src
->port
));
159 my_addr
= socket_get_my_addr(kdc_socket
->sock
, tmp_ctx
);
161 talloc_free(tmp_ctx
);
167 ret
= kdc_socket
->process(kdc_socket
->kdc
,
174 talloc_free(tmp_ctx
);
178 /* queue a pending reply */
179 rep
= talloc(kdc_socket
, struct kdc_reply
);
181 talloc_free(tmp_ctx
);
184 rep
->dest
= talloc_steal(rep
, src
);
186 talloc_steal(rep
, reply
.data
);
188 if (rep
->packet
.data
== NULL
) {
190 talloc_free(tmp_ctx
);
194 DLIST_ADD_END(kdc_socket
->send_queue
, rep
, struct kdc_reply
*);
195 EVENT_FD_WRITEABLE(kdc_socket
->fde
);
196 talloc_free(tmp_ctx
);
200 handle fd events on a KDC socket
202 static void kdc_socket_handler(struct tevent_context
*ev
, struct tevent_fd
*fde
,
203 uint16_t flags
, void *private_data
)
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
);
209 if (flags
& EVENT_FD_READ
) {
210 kdc_recv_handler(kdc_socket
);
214 static void kdc_tcp_terminate_connection(struct kdc_tcp_connection
*kdcconn
, const char *reason
)
216 stream_terminate_connection(kdcconn
->conn
, reason
);
220 receive a full packet on a KDC connection
222 static NTSTATUS
kdc_tcp_recv(void *private_data
, DATA_BLOB blob
)
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
);
229 DATA_BLOB input
, reply
;
230 struct socket_address
*src_addr
;
231 struct socket_address
*my_addr
;
233 talloc_steal(tmp_ctx
, blob
.data
);
235 src_addr
= socket_get_peer_addr(kdcconn
->conn
->socket
, tmp_ctx
);
237 talloc_free(tmp_ctx
);
238 return NT_STATUS_NO_MEMORY
;
241 my_addr
= socket_get_my_addr(kdcconn
->conn
->socket
, tmp_ctx
);
243 talloc_free(tmp_ctx
);
244 return NT_STATUS_NO_MEMORY
;
248 input
= data_blob_const(blob
.data
+ 4, blob
.length
- 4);
250 ret
= kdcconn
->process(kdcconn
->kdc
,
256 0 /* Not datagram */);
258 talloc_free(tmp_ctx
);
259 return NT_STATUS_INTERNAL_ERROR
;
262 /* and now encode the reply */
263 blob
= data_blob_talloc(kdcconn
, NULL
, reply
.length
+ 4);
265 talloc_free(tmp_ctx
);
266 return NT_STATUS_NO_MEMORY
;
269 RSIVAL(blob
.data
, 0, reply
.length
);
270 memcpy(blob
.data
+ 4, reply
.data
, reply
.length
);
272 status
= packet_send(kdcconn
->packet
, blob
);
273 if (!NT_STATUS_IS_OK(status
)) {
274 talloc_free(tmp_ctx
);
278 /* the call isn't needed any more */
279 talloc_free(tmp_ctx
);
284 receive some data on a KDC connection
286 static void kdc_tcp_recv_handler(struct stream_connection
*conn
, uint16_t flags
)
288 struct kdc_tcp_connection
*kdcconn
= talloc_get_type(conn
->private_data
,
289 struct kdc_tcp_connection
);
290 packet_recv(kdcconn
->packet
);
294 called on a tcp recv error
296 static void kdc_tcp_recv_error(void *private_data
, NTSTATUS status
)
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
));
304 called when we can write to a connection
306 static void kdc_tcp_send(struct stream_connection
*conn
, uint16_t flags
)
308 struct kdc_tcp_connection
*kdcconn
= talloc_get_type(conn
->private_data
,
309 struct kdc_tcp_connection
);
310 packet_queue_run(kdcconn
->packet
);
314 Wrapper for krb5_kdc_process_krb5_request, converting to/from Samba
318 static bool kdc_process(struct kdc_server
*kdc
,
322 struct socket_address
*peer_addr
,
323 struct socket_address
*my_addr
,
328 krb5_data_zero(&k5_reply
);
330 krb5_kdc_update_time(NULL
);
332 DEBUG(10,("Received KDC packet of length %lu from %s:%d\n",
333 (long)input
->length
- 4, peer_addr
->addr
, peer_addr
->port
));
335 ret
= krb5_kdc_process_krb5_request(kdc
->smb_krb5_context
->krb5_context
,
337 input
->data
, input
->length
,
343 *reply
= data_blob(NULL
, 0);
346 if (k5_reply
.length
) {
347 *reply
= data_blob_talloc(mem_ctx
, k5_reply
.data
, k5_reply
.length
);
348 krb5_data_free(&k5_reply
);
350 *reply
= data_blob(NULL
, 0);
356 called when we get a new connection
358 static void kdc_tcp_generic_accept(struct stream_connection
*conn
, kdc_process_fn_t process_fn
)
360 struct kdc_server
*kdc
= talloc_get_type(conn
->private_data
, struct kdc_server
);
361 struct kdc_tcp_connection
*kdcconn
;
363 kdcconn
= talloc_zero(conn
, struct kdc_tcp_connection
);
365 stream_terminate_connection(conn
, "kdc_tcp_accept: out of memory");
368 kdcconn
->conn
= conn
;
370 kdcconn
->process
= process_fn
;
371 conn
->private_data
= kdcconn
;
373 kdcconn
->packet
= packet_init(kdcconn
);
374 if (kdcconn
->packet
== NULL
) {
375 kdc_tcp_terminate_connection(kdcconn
, "kdc_tcp_accept: out of memory");
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
);
388 static void kdc_tcp_accept(struct stream_connection
*conn
)
390 kdc_tcp_generic_accept(conn
, kdc_process
);
393 static const struct stream_server_ops kdc_tcp_stream_ops
= {
395 .accept_connection
= kdc_tcp_accept
,
396 .recv_handler
= kdc_tcp_recv_handler
,
397 .send_handler
= kdc_tcp_send
400 static void kpasswdd_tcp_accept(struct stream_connection
*conn
)
402 kdc_tcp_generic_accept(conn
, kpasswdd_process
);
405 static 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
413 start listening on the given address
415 static NTSTATUS
kdc_add_kdc_socket(struct kdc_server
*kdc
,
416 const struct model_ops
*model_ops
,
420 struct kdc_socket
*kdc_socket
;
421 struct socket_address
*kdc_address
;
424 kdc_socket
= talloc(kdc
, struct kdc_socket
);
425 NT_STATUS_HAVE_NO_MEMORY(kdc_socket
);
427 status
= socket_create("ip", SOCKET_TYPE_DGRAM
, &kdc_socket
->sock
, 0);
428 if (!NT_STATUS_IS_OK(status
)) {
429 talloc_free(kdc_socket
);
433 kdc_socket
->kdc
= kdc
;
434 kdc_socket
->send_queue
= NULL
;
435 kdc_socket
->process
= kdc_process
;
437 talloc_steal(kdc_socket
, kdc_socket
->sock
);
439 kdc_socket
->fde
= event_add_fd(kdc
->task
->event_ctx
, kdc
,
440 socket_get_fd(kdc_socket
->sock
), EVENT_FD_READ
,
441 kdc_socket_handler
, kdc_socket
);
443 kdc_address
= socket_address_from_strings(kdc_socket
, kdc_socket
->sock
->backend_name
,
445 NT_STATUS_HAVE_NO_MEMORY(kdc_address
);
447 status
= socket_listen(kdc_socket
->sock
, kdc_address
, 0, 0);
448 if (!NT_STATUS_IS_OK(status
)) {
449 DEBUG(0,("Failed to bind to %s:%d UDP for kdc - %s\n",
450 address
, kdc_port
, nt_errstr(status
)));
451 talloc_free(kdc_socket
);
455 status
= stream_setup_socket(kdc
->task
->event_ctx
,
459 "ip", address
, &kdc_port
,
460 lp_socket_options(kdc
->task
->lp_ctx
),
462 if (!NT_STATUS_IS_OK(status
)) {
463 DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
464 address
, kdc_port
, nt_errstr(status
)));
465 talloc_free(kdc_socket
);
472 static NTSTATUS
kdc_add_kpasswd_socket(struct kdc_server
*kdc
,
473 const struct model_ops
*model_ops
,
475 uint16_t kpasswd_port
)
477 struct kdc_socket
*kpasswd_socket
;
478 struct socket_address
*kpasswd_address
;
481 kpasswd_socket
= talloc(kdc
, struct kdc_socket
);
482 NT_STATUS_HAVE_NO_MEMORY(kpasswd_socket
);
484 status
= socket_create("ip", SOCKET_TYPE_DGRAM
, &kpasswd_socket
->sock
, 0);
485 if (!NT_STATUS_IS_OK(status
)) {
486 talloc_free(kpasswd_socket
);
490 kpasswd_socket
->kdc
= kdc
;
491 kpasswd_socket
->send_queue
= NULL
;
492 kpasswd_socket
->process
= kpasswdd_process
;
494 talloc_steal(kpasswd_socket
, kpasswd_socket
->sock
);
496 kpasswd_socket
->fde
= event_add_fd(kdc
->task
->event_ctx
, kdc
,
497 socket_get_fd(kpasswd_socket
->sock
), EVENT_FD_READ
,
498 kdc_socket_handler
, kpasswd_socket
);
500 kpasswd_address
= socket_address_from_strings(kpasswd_socket
, kpasswd_socket
->sock
->backend_name
,
501 address
, kpasswd_port
);
502 NT_STATUS_HAVE_NO_MEMORY(kpasswd_address
);
504 status
= socket_listen(kpasswd_socket
->sock
, kpasswd_address
, 0, 0);
505 if (!NT_STATUS_IS_OK(status
)) {
506 DEBUG(0,("Failed to bind to %s:%d UDP for kpasswd - %s\n",
507 address
, kpasswd_port
, nt_errstr(status
)));
508 talloc_free(kpasswd_socket
);
512 status
= stream_setup_socket(kdc
->task
->event_ctx
,
515 &kpasswdd_tcp_stream_ops
,
516 "ip", address
, &kpasswd_port
,
517 lp_socket_options(kdc
->task
->lp_ctx
),
519 if (!NT_STATUS_IS_OK(status
)) {
520 DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
521 address
, kpasswd_port
, nt_errstr(status
)));
522 talloc_free(kpasswd_socket
);
531 setup our listening sockets on the configured network interfaces
533 static NTSTATUS
kdc_startup_interfaces(struct kdc_server
*kdc
, struct loadparm_context
*lp_ctx
,
534 struct interface
*ifaces
)
536 const struct model_ops
*model_ops
;
538 TALLOC_CTX
*tmp_ctx
= talloc_new(kdc
);
542 /* within the kdc task we want to be a single process, so
543 ask for the single process model ops and pass these to the
544 stream_setup_socket() call. */
545 model_ops
= process_model_startup(kdc
->task
->event_ctx
, "single");
547 DEBUG(0,("Can't find 'single' process model_ops\n"));
548 return NT_STATUS_INTERNAL_ERROR
;
551 num_interfaces
= iface_count(ifaces
);
553 for (i
=0; i
<num_interfaces
; i
++) {
554 const char *address
= talloc_strdup(tmp_ctx
, iface_n_ip(ifaces
, i
));
555 uint16_t kdc_port
= lp_krb5_port(lp_ctx
);
556 uint16_t kpasswd_port
= lp_kpasswd_port(lp_ctx
);
559 status
= kdc_add_kdc_socket(kdc
, model_ops
, address
, kdc_port
);
560 NT_STATUS_NOT_OK_RETURN(status
);
564 status
= kdc_add_kpasswd_socket(kdc
, model_ops
, address
, kpasswd_port
);
565 NT_STATUS_NOT_OK_RETURN(status
);
569 talloc_free(tmp_ctx
);
575 static NTSTATUS
kdc_check_generic_kerberos(struct irpc_message
*msg
,
576 struct kdc_check_generic_kerberos
*r
)
578 struct PAC_Validate pac_validate
;
580 struct PAC_SIGNATURE_DATA kdc_sig
;
581 struct kdc_server
*kdc
= talloc_get_type(msg
->private_data
, struct kdc_server
);
582 enum ndr_err_code ndr_err
;
586 krb5_principal principal
;
587 krb5_keyblock keyblock
;
590 /* There is no reply to this request */
591 r
->out
.generic_reply
= data_blob(NULL
, 0);
593 ndr_err
= ndr_pull_struct_blob(&r
->in
.generic_request
, msg
,
594 lp_iconv_convenience(kdc
->task
->lp_ctx
),
596 (ndr_pull_flags_fn_t
)ndr_pull_PAC_Validate
);
597 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
598 return NT_STATUS_INVALID_PARAMETER
;
601 if (pac_validate
.MessageType
!= 3) {
602 /* We don't implement any other message types - such as certificate validation - yet */
603 return NT_STATUS_INVALID_PARAMETER
;
606 if (pac_validate
.ChecksumAndSignature
.length
!= (pac_validate
.ChecksumLength
+ pac_validate
.SignatureLength
)
607 || pac_validate
.ChecksumAndSignature
.length
< pac_validate
.ChecksumLength
608 || pac_validate
.ChecksumAndSignature
.length
< pac_validate
.SignatureLength
) {
609 return NT_STATUS_INVALID_PARAMETER
;
612 srv_sig
= data_blob_const(pac_validate
.ChecksumAndSignature
.data
,
613 pac_validate
.ChecksumLength
);
615 if (pac_validate
.SignatureType
== CKSUMTYPE_HMAC_MD5
) {
616 etype
= ETYPE_ARCFOUR_HMAC_MD5
;
618 ret
= krb5_cksumtype_to_enctype(kdc
->smb_krb5_context
->krb5_context
, pac_validate
.SignatureType
,
621 return NT_STATUS_LOGON_FAILURE
;
625 ret
= krb5_make_principal(kdc
->smb_krb5_context
->krb5_context
, &principal
,
626 lp_realm(kdc
->task
->lp_ctx
),
627 "krbtgt", lp_realm(kdc
->task
->lp_ctx
),
631 return NT_STATUS_NO_MEMORY
;
634 ret
= kdc
->config
->db
[0]->hdb_fetch(kdc
->smb_krb5_context
->krb5_context
,
637 HDB_F_GET_KRBTGT
| HDB_F_DECRYPT
,
641 hdb_free_entry(kdc
->smb_krb5_context
->krb5_context
, &ent
);
642 krb5_free_principal(kdc
->smb_krb5_context
->krb5_context
, principal
);
644 return NT_STATUS_LOGON_FAILURE
;
647 ret
= hdb_enctype2key(kdc
->smb_krb5_context
->krb5_context
, &ent
.entry
, etype
, &key
);
650 hdb_free_entry(kdc
->smb_krb5_context
->krb5_context
, &ent
);
651 krb5_free_principal(kdc
->smb_krb5_context
->krb5_context
, principal
);
652 return NT_STATUS_LOGON_FAILURE
;
657 kdc_sig
.type
= pac_validate
.SignatureType
;
658 kdc_sig
.signature
= data_blob_const(&pac_validate
.ChecksumAndSignature
.data
[pac_validate
.ChecksumLength
],
659 pac_validate
.SignatureLength
);
660 ret
= check_pac_checksum(msg
, srv_sig
, &kdc_sig
,
661 kdc
->smb_krb5_context
->krb5_context
, &keyblock
);
663 hdb_free_entry(kdc
->smb_krb5_context
->krb5_context
, &ent
);
664 krb5_free_principal(kdc
->smb_krb5_context
->krb5_context
, principal
);
667 return NT_STATUS_LOGON_FAILURE
;
677 static void kdc_task_init(struct task_server
*task
)
679 struct kdc_server
*kdc
;
682 struct interface
*ifaces
;
684 switch (lp_server_role(task
->lp_ctx
)) {
685 case ROLE_STANDALONE
:
686 task_server_terminate(task
, "kdc: no KDC required in standalone configuration", false);
688 case ROLE_DOMAIN_MEMBER
:
689 task_server_terminate(task
, "kdc: no KDC required in member server configuration", false);
691 case ROLE_DOMAIN_CONTROLLER
:
692 /* Yes, we want a KDC */
696 load_interfaces(task
, lp_interfaces(task
->lp_ctx
), &ifaces
);
698 if (iface_count(ifaces
) == 0) {
699 task_server_terminate(task
, "kdc: no network interfaces configured", false);
703 task_server_set_title(task
, "task[kdc]");
705 kdc
= talloc(task
, struct kdc_server
);
707 task_server_terminate(task
, "kdc: out of memory", true);
713 initialize_krb5_error_table();
715 ret
= smb_krb5_init_context(kdc
, task
->event_ctx
, task
->lp_ctx
, &kdc
->smb_krb5_context
);
717 DEBUG(1,("kdc_task_init: krb5_init_context failed (%s)\n",
718 error_message(ret
)));
719 task_server_terminate(task
, "kdc: krb5_init_context failed", true);
723 krb5_add_et_list(kdc
->smb_krb5_context
->krb5_context
, initialize_hdb_error_table_r
);
725 ret
= krb5_kdc_get_config(kdc
->smb_krb5_context
->krb5_context
,
728 task_server_terminate(task
, "kdc: failed to get KDC configuration", true);
732 kdc
->config
->logf
= kdc
->smb_krb5_context
->logf
;
733 kdc
->config
->db
= talloc(kdc
, struct HDB
*);
734 if (!kdc
->config
->db
) {
735 task_server_terminate(task
, "kdc: out of memory", true);
738 kdc
->config
->num_db
= 1;
740 status
= hdb_samba4_create_kdc(kdc
, task
->event_ctx
, task
->lp_ctx
,
741 kdc
->smb_krb5_context
->krb5_context
,
742 &kdc
->config
->db
[0]);
743 if (!NT_STATUS_IS_OK(status
)) {
744 task_server_terminate(task
, "kdc: hdb_samba4_create_kdc (setup KDC database) failed", true);
748 /* Register hdb-samba4 hooks for use as a keytab */
750 kdc
->hdb_samba4_context
= talloc(kdc
, struct hdb_samba4_context
);
751 if (!kdc
->hdb_samba4_context
) {
752 task_server_terminate(task
, "kdc: out of memory", true);
756 kdc
->hdb_samba4_context
->ev_ctx
= task
->event_ctx
;
757 kdc
->hdb_samba4_context
->lp_ctx
= task
->lp_ctx
;
759 ret
= krb5_plugin_register(kdc
->smb_krb5_context
->krb5_context
,
760 PLUGIN_TYPE_DATA
, "hdb",
763 task_server_terminate(task
, "kdc: failed to register hdb keytab", true);
767 ret
= krb5_kt_register(kdc
->smb_krb5_context
->krb5_context
, &hdb_kt_ops
);
769 task_server_terminate(task
, "kdc: failed to register hdb keytab", true);
773 /* Registar WinDC hooks */
774 ret
= krb5_plugin_register(kdc
->smb_krb5_context
->krb5_context
,
775 PLUGIN_TYPE_DATA
, "windc",
776 &windc_plugin_table
);
778 task_server_terminate(task
, "kdc: failed to register hdb keytab", true);
782 krb5_kdc_windc_init(kdc
->smb_krb5_context
->krb5_context
);
784 /* start listening on the configured network interfaces */
785 status
= kdc_startup_interfaces(kdc
, task
->lp_ctx
, ifaces
);
786 if (!NT_STATUS_IS_OK(status
)) {
787 task_server_terminate(task
, "kdc failed to setup interfaces", true);
791 status
= IRPC_REGISTER(task
->msg_ctx
, irpc
, KDC_CHECK_GENERIC_KERBEROS
,
792 kdc_check_generic_kerberos
, kdc
);
793 if (!NT_STATUS_IS_OK(status
)) {
794 task_server_terminate(task
, "nbtd failed to setup monitoring", true);
798 irpc_add_name(task
->msg_ctx
, "kdc_server");
802 /* called at smbd startup - register ourselves as a server service */
803 NTSTATUS
server_service_kdc_init(void)
805 return register_server_service("kdc", kdc_task_init
);