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/process_model.h"
26 #include "lib/tsocket/tsocket.h"
27 #include "libcli/util/tstream.h"
28 #include "lib/messaging/irpc.h"
29 #include "librpc/gen_ndr/ndr_irpc.h"
30 #include "librpc/gen_ndr/ndr_krb5pac.h"
31 #include "lib/stream/packet.h"
32 #include "lib/socket/netif.h"
33 #include "param/param.h"
34 #include "kdc/kdc-glue.h"
35 #include "dsdb/samdb/samdb.h"
36 #include "auth/session.h"
38 extern struct krb5plugin_windc_ftable windc_plugin_table
;
39 extern struct hdb_method hdb_samba4
;
41 static void kdc_tcp_terminate_connection(struct kdc_tcp_connection
*kdcconn
, const char *reason
)
43 stream_terminate_connection(kdcconn
->conn
, reason
);
46 static void kdc_tcp_recv(struct stream_connection
*conn
, uint16_t flags
)
48 struct kdc_tcp_connection
*kdcconn
= talloc_get_type(conn
->private_data
,
49 struct kdc_tcp_connection
);
50 /* this should never be triggered! */
51 kdc_tcp_terminate_connection(kdcconn
, "kdc_tcp_recv: called");
54 static void kdc_tcp_send(struct stream_connection
*conn
, uint16_t flags
)
56 struct kdc_tcp_connection
*kdcconn
= talloc_get_type(conn
->private_data
,
57 struct kdc_tcp_connection
);
58 /* this should never be triggered! */
59 kdc_tcp_terminate_connection(kdcconn
, "kdc_tcp_send: called");
63 Wrapper for krb5_kdc_process_krb5_request, converting to/from Samba
67 static enum kdc_process_ret
kdc_process(struct kdc_server
*kdc
,
71 struct tsocket_address
*peer_addr
,
72 struct tsocket_address
*my_addr
,
77 struct sockaddr_storage ss
;
79 krb5_data_zero(&k5_reply
);
81 krb5_kdc_update_time(NULL
);
83 ret
= tsocket_address_bsd_sockaddr(peer_addr
, (struct sockaddr
*) &ss
,
84 sizeof(struct sockaddr_storage
));
86 return KDC_PROCESS_FAILED
;
88 pa
= tsocket_address_string(peer_addr
, mem_ctx
);
90 return KDC_PROCESS_FAILED
;
93 DEBUG(10,("Received KDC packet of length %lu from %s\n",
94 (long)input
->length
- 4, pa
));
96 ret
= krb5_kdc_process_krb5_request(kdc
->smb_krb5_context
->krb5_context
,
98 input
->data
, input
->length
,
101 (struct sockaddr
*) &ss
,
104 *reply
= data_blob(NULL
, 0);
105 return KDC_PROCESS_FAILED
;
108 if (ret
== HDB_ERR_NOT_FOUND_HERE
) {
109 *reply
= data_blob(NULL
, 0);
110 return KDC_PROCESS_PROXY
;
113 if (k5_reply
.length
) {
114 *reply
= data_blob_talloc(mem_ctx
, k5_reply
.data
, k5_reply
.length
);
115 krb5_data_free(&k5_reply
);
117 *reply
= data_blob(NULL
, 0);
119 return KDC_PROCESS_OK
;
122 static void kdc_tcp_call_writev_done(struct tevent_req
*subreq
);
124 static void kdc_tcp_call_loop(struct tevent_req
*subreq
)
126 struct kdc_tcp_connection
*kdc_conn
= tevent_req_callback_data(subreq
,
127 struct kdc_tcp_connection
);
128 struct kdc_tcp_call
*call
;
130 enum kdc_process_ret ret
;
132 call
= talloc(kdc_conn
, struct kdc_tcp_call
);
134 kdc_tcp_terminate_connection(kdc_conn
, "kdc_tcp_call_loop: "
135 "no memory for kdc_tcp_call");
138 call
->kdc_conn
= kdc_conn
;
140 status
= tstream_read_pdu_blob_recv(subreq
,
144 if (!NT_STATUS_IS_OK(status
)) {
147 reason
= talloc_asprintf(call
, "kdc_tcp_call_loop: "
148 "tstream_read_pdu_blob_recv() - %s",
151 reason
= nt_errstr(status
);
154 kdc_tcp_terminate_connection(kdc_conn
, reason
);
158 DEBUG(10,("Received krb5 TCP packet of length %lu from %s\n",
159 (long) call
->in
.length
,
160 tsocket_address_string(kdc_conn
->conn
->remote_address
, call
)));
162 /* skip length header */
164 call
->in
.length
-= 4;
167 ret
= kdc_conn
->kdc_socket
->process(kdc_conn
->kdc_socket
->kdc
,
171 kdc_conn
->conn
->remote_address
,
172 kdc_conn
->conn
->local_address
,
174 if (ret
== KDC_PROCESS_FAILED
) {
175 kdc_tcp_terminate_connection(kdc_conn
,
176 "kdc_tcp_call_loop: process function failed");
180 if (ret
== KDC_PROCESS_PROXY
) {
181 if (!kdc_conn
->kdc_socket
->kdc
->am_rodc
) {
182 kdc_tcp_terminate_connection(kdc_conn
,
183 "kdc_tcp_call_loop: proxying requested when not RODC");
186 kdc_tcp_proxy(kdc_conn
->kdc_socket
->kdc
, kdc_conn
, call
,
187 tsocket_address_inet_port(kdc_conn
->conn
->local_address
));
191 /* First add the length of the out buffer */
192 RSIVAL(call
->out_hdr
, 0, call
->out
.length
);
193 call
->out_iov
[0].iov_base
= (char *) call
->out_hdr
;
194 call
->out_iov
[0].iov_len
= 4;
196 call
->out_iov
[1].iov_base
= (char *) call
->out
.data
;
197 call
->out_iov
[1].iov_len
= call
->out
.length
;
199 subreq
= tstream_writev_queue_send(call
,
200 kdc_conn
->conn
->event
.ctx
,
202 kdc_conn
->send_queue
,
204 if (subreq
== NULL
) {
205 kdc_tcp_terminate_connection(kdc_conn
, "kdc_tcp_call_loop: "
206 "no memory for tstream_writev_queue_send");
209 tevent_req_set_callback(subreq
, kdc_tcp_call_writev_done
, call
);
213 * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
214 * packet_full_request_u32 provides the pdu length then.
216 subreq
= tstream_read_pdu_blob_send(kdc_conn
,
217 kdc_conn
->conn
->event
.ctx
,
219 4, /* initial_read_size */
220 packet_full_request_u32
,
222 if (subreq
== NULL
) {
223 kdc_tcp_terminate_connection(kdc_conn
, "kdc_tcp_call_loop: "
224 "no memory for tstream_read_pdu_blob_send");
227 tevent_req_set_callback(subreq
, kdc_tcp_call_loop
, kdc_conn
);
230 static void kdc_tcp_call_writev_done(struct tevent_req
*subreq
)
232 struct kdc_tcp_call
*call
= tevent_req_callback_data(subreq
,
233 struct kdc_tcp_call
);
237 rc
= tstream_writev_queue_recv(subreq
, &sys_errno
);
242 reason
= talloc_asprintf(call
, "kdc_tcp_call_writev_done: "
243 "tstream_writev_queue_recv() - %d:%s",
244 sys_errno
, strerror(sys_errno
));
246 reason
= "kdc_tcp_call_writev_done: tstream_writev_queue_recv() failed";
249 kdc_tcp_terminate_connection(call
->kdc_conn
, reason
);
253 /* We don't care about errors */
259 called when we get a new connection
261 static void kdc_tcp_accept(struct stream_connection
*conn
)
263 struct kdc_socket
*kdc_socket
;
264 struct kdc_tcp_connection
*kdc_conn
;
265 struct tevent_req
*subreq
;
268 kdc_conn
= talloc_zero(conn
, struct kdc_tcp_connection
);
269 if (kdc_conn
== NULL
) {
270 stream_terminate_connection(conn
,
271 "kdc_tcp_accept: out of memory");
275 kdc_conn
->send_queue
= tevent_queue_create(conn
, "kdc_tcp_accept");
276 if (kdc_conn
->send_queue
== NULL
) {
277 stream_terminate_connection(conn
,
278 "kdc_tcp_accept: out of memory");
282 kdc_socket
= talloc_get_type(conn
->private_data
, struct kdc_socket
);
284 TALLOC_FREE(conn
->event
.fde
);
286 rc
= tstream_bsd_existing_socket(kdc_conn
,
287 socket_get_fd(conn
->socket
),
290 stream_terminate_connection(conn
,
291 "kdc_tcp_accept: out of memory");
295 kdc_conn
->conn
= conn
;
296 kdc_conn
->kdc_socket
= kdc_socket
;
297 conn
->private_data
= kdc_conn
;
300 * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
301 * packet_full_request_u32 provides the pdu length then.
303 subreq
= tstream_read_pdu_blob_send(kdc_conn
,
304 kdc_conn
->conn
->event
.ctx
,
306 4, /* initial_read_size */
307 packet_full_request_u32
,
309 if (subreq
== NULL
) {
310 kdc_tcp_terminate_connection(kdc_conn
, "kdc_tcp_accept: "
311 "no memory for tstream_read_pdu_blob_send");
314 tevent_req_set_callback(subreq
, kdc_tcp_call_loop
, kdc_conn
);
317 static const struct stream_server_ops kdc_tcp_stream_ops
= {
319 .accept_connection
= kdc_tcp_accept
,
320 .recv_handler
= kdc_tcp_recv
,
321 .send_handler
= kdc_tcp_send
324 static void kdc_udp_call_sendto_done(struct tevent_req
*subreq
);
326 static void kdc_udp_call_loop(struct tevent_req
*subreq
)
328 struct kdc_udp_socket
*sock
= tevent_req_callback_data(subreq
,
329 struct kdc_udp_socket
);
330 struct kdc_udp_call
*call
;
334 enum kdc_process_ret ret
;
336 call
= talloc(sock
, struct kdc_udp_call
);
342 len
= tdgram_recvfrom_recv(subreq
, &sys_errno
,
343 call
, &buf
, &call
->src
);
351 call
->in
.length
= len
;
353 DEBUG(10,("Received krb5 UDP packet of length %lu from %s\n",
354 (long)call
->in
.length
,
355 tsocket_address_string(call
->src
, call
)));
358 ret
= sock
->kdc_socket
->process(sock
->kdc_socket
->kdc
,
363 sock
->kdc_socket
->local_address
,
365 if (ret
== KDC_PROCESS_FAILED
) {
370 if (ret
== KDC_PROCESS_PROXY
) {
371 if (!sock
->kdc_socket
->kdc
->am_rodc
) {
372 DEBUG(0,("kdc_udp_call_loop: proxying requested when not RODC"));
376 kdc_udp_proxy(sock
->kdc_socket
->kdc
, sock
, call
,
377 tsocket_address_inet_port(sock
->kdc_socket
->local_address
));
381 subreq
= tdgram_sendto_queue_send(call
,
382 sock
->kdc_socket
->kdc
->task
->event_ctx
,
388 if (subreq
== NULL
) {
392 tevent_req_set_callback(subreq
, kdc_udp_call_sendto_done
, call
);
395 subreq
= tdgram_recvfrom_send(sock
,
396 sock
->kdc_socket
->kdc
->task
->event_ctx
,
398 if (subreq
== NULL
) {
399 task_server_terminate(sock
->kdc_socket
->kdc
->task
,
400 "no memory for tdgram_recvfrom_send",
404 tevent_req_set_callback(subreq
, kdc_udp_call_loop
, sock
);
407 static void kdc_udp_call_sendto_done(struct tevent_req
*subreq
)
409 struct kdc_udp_call
*call
= tevent_req_callback_data(subreq
,
410 struct kdc_udp_call
);
414 ret
= tdgram_sendto_queue_recv(subreq
, &sys_errno
);
416 /* We don't care about errors */
422 start listening on the given address
424 static NTSTATUS
kdc_add_socket(struct kdc_server
*kdc
,
425 const struct model_ops
*model_ops
,
429 kdc_process_fn_t process
,
432 struct kdc_socket
*kdc_socket
;
433 struct kdc_udp_socket
*kdc_udp_socket
;
434 struct tevent_req
*udpsubreq
;
438 kdc_socket
= talloc(kdc
, struct kdc_socket
);
439 NT_STATUS_HAVE_NO_MEMORY(kdc_socket
);
441 kdc_socket
->kdc
= kdc
;
442 kdc_socket
->process
= process
;
444 ret
= tsocket_address_inet_from_strings(kdc_socket
, "ip",
446 &kdc_socket
->local_address
);
448 status
= map_nt_error_from_unix(errno
);
453 status
= stream_setup_socket(kdc
->task
,
454 kdc
->task
->event_ctx
,
458 "ip", address
, &port
,
459 lpcfg_socket_options(kdc
->task
->lp_ctx
),
461 if (!NT_STATUS_IS_OK(status
)) {
462 DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
463 address
, port
, nt_errstr(status
)));
464 talloc_free(kdc_socket
);
469 kdc_udp_socket
= talloc(kdc_socket
, struct kdc_udp_socket
);
470 NT_STATUS_HAVE_NO_MEMORY(kdc_udp_socket
);
472 kdc_udp_socket
->kdc_socket
= kdc_socket
;
474 ret
= tdgram_inet_udp_socket(kdc_socket
->local_address
,
477 &kdc_udp_socket
->dgram
);
479 status
= map_nt_error_from_unix(errno
);
480 DEBUG(0,("Failed to bind to %s:%u UDP - %s\n",
481 address
, port
, nt_errstr(status
)));
485 kdc_udp_socket
->send_queue
= tevent_queue_create(kdc_udp_socket
,
486 "kdc_udp_send_queue");
487 NT_STATUS_HAVE_NO_MEMORY(kdc_udp_socket
->send_queue
);
489 udpsubreq
= tdgram_recvfrom_send(kdc_udp_socket
,
490 kdc
->task
->event_ctx
,
491 kdc_udp_socket
->dgram
);
492 NT_STATUS_HAVE_NO_MEMORY(udpsubreq
);
493 tevent_req_set_callback(udpsubreq
, kdc_udp_call_loop
, kdc_udp_socket
);
500 setup our listening sockets on the configured network interfaces
502 static NTSTATUS
kdc_startup_interfaces(struct kdc_server
*kdc
, struct loadparm_context
*lp_ctx
,
503 struct interface
*ifaces
)
505 const struct model_ops
*model_ops
;
507 TALLOC_CTX
*tmp_ctx
= talloc_new(kdc
);
510 uint16_t kdc_port
= lpcfg_krb5_port(lp_ctx
);
511 uint16_t kpasswd_port
= lpcfg_kpasswd_port(lp_ctx
);
512 bool done_wildcard
= false;
514 /* within the kdc task we want to be a single process, so
515 ask for the single process model ops and pass these to the
516 stream_setup_socket() call. */
517 model_ops
= process_model_startup("single");
519 DEBUG(0,("Can't find 'single' process model_ops\n"));
520 return NT_STATUS_INTERNAL_ERROR
;
523 num_interfaces
= iface_count(ifaces
);
525 /* if we are allowing incoming packets from any address, then
526 we need to bind to the wildcard address */
527 if (!lpcfg_bind_interfaces_only(lp_ctx
)) {
529 status
= kdc_add_socket(kdc
, model_ops
,
530 "kdc", "0.0.0.0", kdc_port
,
532 NT_STATUS_NOT_OK_RETURN(status
);
536 status
= kdc_add_socket(kdc
, model_ops
,
537 "kpasswd", "0.0.0.0", kpasswd_port
,
538 kpasswdd_process
, false);
539 NT_STATUS_NOT_OK_RETURN(status
);
541 done_wildcard
= true;
544 for (i
=0; i
<num_interfaces
; i
++) {
545 const char *address
= talloc_strdup(tmp_ctx
, iface_n_ip(ifaces
, i
));
548 status
= kdc_add_socket(kdc
, model_ops
,
549 "kdc", address
, kdc_port
,
550 kdc_process
, done_wildcard
);
551 NT_STATUS_NOT_OK_RETURN(status
);
555 status
= kdc_add_socket(kdc
, model_ops
,
556 "kpasswd", address
, kpasswd_port
,
557 kpasswdd_process
, done_wildcard
);
558 NT_STATUS_NOT_OK_RETURN(status
);
562 talloc_free(tmp_ctx
);
568 static NTSTATUS
kdc_check_generic_kerberos(struct irpc_message
*msg
,
569 struct kdc_check_generic_kerberos
*r
)
571 struct PAC_Validate pac_validate
;
573 struct PAC_SIGNATURE_DATA kdc_sig
;
574 struct kdc_server
*kdc
= talloc_get_type(msg
->private_data
, struct kdc_server
);
575 enum ndr_err_code ndr_err
;
579 krb5_principal principal
;
580 krb5_keyblock keyblock
;
583 /* There is no reply to this request */
584 r
->out
.generic_reply
= data_blob(NULL
, 0);
586 ndr_err
= ndr_pull_struct_blob(&r
->in
.generic_request
, msg
, &pac_validate
,
587 (ndr_pull_flags_fn_t
)ndr_pull_PAC_Validate
);
588 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
589 return NT_STATUS_INVALID_PARAMETER
;
592 if (pac_validate
.MessageType
!= 3) {
593 /* We don't implement any other message types - such as certificate validation - yet */
594 return NT_STATUS_INVALID_PARAMETER
;
597 if (pac_validate
.ChecksumAndSignature
.length
!= (pac_validate
.ChecksumLength
+ pac_validate
.SignatureLength
)
598 || pac_validate
.ChecksumAndSignature
.length
< pac_validate
.ChecksumLength
599 || pac_validate
.ChecksumAndSignature
.length
< pac_validate
.SignatureLength
) {
600 return NT_STATUS_INVALID_PARAMETER
;
603 srv_sig
= data_blob_const(pac_validate
.ChecksumAndSignature
.data
,
604 pac_validate
.ChecksumLength
);
606 if (pac_validate
.SignatureType
== CKSUMTYPE_HMAC_MD5
) {
607 etype
= ETYPE_ARCFOUR_HMAC_MD5
;
609 ret
= krb5_cksumtype_to_enctype(kdc
->smb_krb5_context
->krb5_context
, pac_validate
.SignatureType
,
612 return NT_STATUS_LOGON_FAILURE
;
616 ret
= krb5_make_principal(kdc
->smb_krb5_context
->krb5_context
, &principal
,
617 lpcfg_realm(kdc
->task
->lp_ctx
),
618 "krbtgt", lpcfg_realm(kdc
->task
->lp_ctx
),
622 return NT_STATUS_NO_MEMORY
;
625 ret
= kdc
->config
->db
[0]->hdb_fetch_kvno(kdc
->smb_krb5_context
->krb5_context
,
628 HDB_F_GET_KRBTGT
| HDB_F_DECRYPT
,
633 hdb_free_entry(kdc
->smb_krb5_context
->krb5_context
, &ent
);
634 krb5_free_principal(kdc
->smb_krb5_context
->krb5_context
, principal
);
636 return NT_STATUS_LOGON_FAILURE
;
639 ret
= hdb_enctype2key(kdc
->smb_krb5_context
->krb5_context
, &ent
.entry
, etype
, &key
);
642 hdb_free_entry(kdc
->smb_krb5_context
->krb5_context
, &ent
);
643 krb5_free_principal(kdc
->smb_krb5_context
->krb5_context
, principal
);
644 return NT_STATUS_LOGON_FAILURE
;
649 kdc_sig
.type
= pac_validate
.SignatureType
;
650 kdc_sig
.signature
= data_blob_const(&pac_validate
.ChecksumAndSignature
.data
[pac_validate
.ChecksumLength
],
651 pac_validate
.SignatureLength
);
652 ret
= check_pac_checksum(msg
, srv_sig
, &kdc_sig
,
653 kdc
->smb_krb5_context
->krb5_context
, &keyblock
);
655 hdb_free_entry(kdc
->smb_krb5_context
->krb5_context
, &ent
);
656 krb5_free_principal(kdc
->smb_krb5_context
->krb5_context
, principal
);
659 return NT_STATUS_LOGON_FAILURE
;
669 static void kdc_task_init(struct task_server
*task
)
671 struct kdc_server
*kdc
;
674 struct interface
*ifaces
;
677 switch (lpcfg_server_role(task
->lp_ctx
)) {
678 case ROLE_STANDALONE
:
679 task_server_terminate(task
, "kdc: no KDC required in standalone configuration", false);
681 case ROLE_DOMAIN_MEMBER
:
682 task_server_terminate(task
, "kdc: no KDC required in member server configuration", false);
684 case ROLE_DOMAIN_CONTROLLER
:
685 /* Yes, we want a KDC */
689 load_interfaces(task
, lpcfg_interfaces(task
->lp_ctx
), &ifaces
);
691 if (iface_count(ifaces
) == 0) {
692 task_server_terminate(task
, "kdc: no network interfaces configured", false);
696 task_server_set_title(task
, "task[kdc]");
698 kdc
= talloc_zero(task
, struct kdc_server
);
700 task_server_terminate(task
, "kdc: out of memory", true);
707 /* get a samdb connection */
708 kdc
->samdb
= samdb_connect(kdc
, kdc
->task
->event_ctx
, kdc
->task
->lp_ctx
,
709 system_session(kdc
->task
->lp_ctx
), 0);
711 DEBUG(1,("kdc_task_init: unable to connect to samdb\n"));
712 task_server_terminate(task
, "kdc: krb5_init_context samdb connect failed", true);
716 ldb_ret
= samdb_rodc(kdc
->samdb
, &kdc
->am_rodc
);
717 if (ldb_ret
!= LDB_SUCCESS
) {
718 DEBUG(1, ("kdc_task_init: Cannot determine if we are an RODC: %s\n",
719 ldb_errstring(kdc
->samdb
)));
720 task_server_terminate(task
, "kdc: krb5_init_context samdb RODC connect failed", true);
724 kdc
->proxy_timeout
= lpcfg_parm_int(kdc
->task
->lp_ctx
, NULL
, "kdc", "proxy timeout", 5);
726 initialize_krb5_error_table();
728 ret
= smb_krb5_init_context(kdc
, task
->event_ctx
, task
->lp_ctx
, &kdc
->smb_krb5_context
);
730 DEBUG(1,("kdc_task_init: krb5_init_context failed (%s)\n",
731 error_message(ret
)));
732 task_server_terminate(task
, "kdc: krb5_init_context failed", true);
736 krb5_add_et_list(kdc
->smb_krb5_context
->krb5_context
, initialize_hdb_error_table_r
);
738 ret
= krb5_kdc_get_config(kdc
->smb_krb5_context
->krb5_context
,
741 task_server_terminate(task
, "kdc: failed to get KDC configuration", true);
745 kdc
->config
->logf
= kdc
->smb_krb5_context
->logf
;
746 kdc
->config
->db
= talloc(kdc
, struct HDB
*);
747 if (!kdc
->config
->db
) {
748 task_server_terminate(task
, "kdc: out of memory", true);
751 kdc
->config
->num_db
= 1;
753 /* Register hdb-samba4 hooks for use as a keytab */
755 kdc
->base_ctx
= talloc_zero(kdc
, struct samba_kdc_base_context
);
756 if (!kdc
->base_ctx
) {
757 task_server_terminate(task
, "kdc: out of memory", true);
761 kdc
->base_ctx
->ev_ctx
= task
->event_ctx
;
762 kdc
->base_ctx
->lp_ctx
= task
->lp_ctx
;
764 status
= hdb_samba4_create_kdc(kdc
->base_ctx
,
765 kdc
->smb_krb5_context
->krb5_context
,
766 &kdc
->config
->db
[0]);
767 if (!NT_STATUS_IS_OK(status
)) {
768 task_server_terminate(task
, "kdc: hdb_samba4_create_kdc (setup KDC database) failed", true);
772 ret
= krb5_plugin_register(kdc
->smb_krb5_context
->krb5_context
,
773 PLUGIN_TYPE_DATA
, "hdb",
776 task_server_terminate(task
, "kdc: failed to register hdb plugin", true);
780 ret
= krb5_kt_register(kdc
->smb_krb5_context
->krb5_context
, &hdb_kt_ops
);
782 task_server_terminate(task
, "kdc: failed to register keytab plugin", true);
786 /* Register WinDC hooks */
787 ret
= krb5_plugin_register(kdc
->smb_krb5_context
->krb5_context
,
788 PLUGIN_TYPE_DATA
, "windc",
789 &windc_plugin_table
);
791 task_server_terminate(task
, "kdc: failed to register windc plugin", true);
795 ret
= krb5_kdc_windc_init(kdc
->smb_krb5_context
->krb5_context
);
798 task_server_terminate(task
, "kdc: failed to init windc plugin", true);
802 ret
= krb5_kdc_pkinit_config(kdc
->smb_krb5_context
->krb5_context
, kdc
->config
);
805 task_server_terminate(task
, "kdc: failed to init kdc pkinit subsystem", true);
809 /* start listening on the configured network interfaces */
810 status
= kdc_startup_interfaces(kdc
, task
->lp_ctx
, ifaces
);
811 if (!NT_STATUS_IS_OK(status
)) {
812 task_server_terminate(task
, "kdc failed to setup interfaces", true);
816 status
= IRPC_REGISTER(task
->msg_ctx
, irpc
, KDC_CHECK_GENERIC_KERBEROS
,
817 kdc_check_generic_kerberos
, kdc
);
818 if (!NT_STATUS_IS_OK(status
)) {
819 task_server_terminate(task
, "kdc failed to setup monitoring", true);
823 irpc_add_name(task
->msg_ctx
, "kdc_server");
827 /* called at smbd startup - register ourselves as a server service */
828 NTSTATUS
server_service_kdc_init(void)
830 return register_server_service("kdc", kdc_task_init
);