2005-06-03 11:23:15 +00:00
/*
Unix SMB / CIFS implementation .
KDC Server startup
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2005
Copyright ( C ) Andrew Tridgell 2005
2005-10-14 06:12:05 +00:00
Copyright ( C ) Stefan Metzmacher 2005
2005-06-03 11:23:15 +00:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
# include "smbd/service_task.h"
2005-10-14 06:12:05 +00:00
# include "smbd/service_stream.h"
2005-06-03 11:23:15 +00:00
# include "lib/events/events.h"
# include "lib/socket/socket.h"
# include "kdc/kdc.h"
2005-06-03 14:32:10 +00:00
# include "system/network.h"
2005-06-04 05:35:27 +00:00
# include "dlinklist.h"
2005-07-19 09:27:20 +00:00
# include "lib/messaging/irpc.h"
2005-06-04 05:35:27 +00:00
2005-10-14 06:12:05 +00:00
/* hold all the info needed to send a reply */
struct kdc_reply {
struct kdc_reply * next , * prev ;
const char * dest_address ;
int dest_port ;
DATA_BLOB packet ;
} ;
2005-06-29 13:55:09 +00:00
2005-10-14 06:12:05 +00:00
/*
top level context structure for the kdc server
*/
struct kdc_server {
struct task_server * task ;
krb5_kdc_configuration * config ;
struct smb_krb5_context * smb_krb5_context ;
} ;
/* hold information about one kdc socket */
struct kdc_socket {
struct socket_context * sock ;
struct kdc_server * kdc ;
struct fd_event * fde ;
/* a queue of outgoing replies that have been deferred */
struct kdc_reply * send_queue ;
2005-10-17 01:01:59 +00:00
int ( * process ) ( krb5_context context ,
krb5_kdc_configuration * config ,
unsigned char * buf ,
size_t len ,
krb5_data * reply ,
const char * from ,
struct sockaddr * addr ) ;
2005-10-14 06:12:05 +00:00
} ;
/*
state of an open tcp connection
*/
struct kdc_tcp_connection {
/* stream connection we belong to */
struct stream_connection * conn ;
/* the kdc_server the connection belongs to */
struct kdc_server * kdc ;
/* the partial data we've receiced yet */
DATA_BLOB partial ;
/* the amount that we used yet from the partial buffer */
uint32_t partial_read ;
/* prevent loops when we use half async code, while processing a requuest */
BOOL processing ;
/* a queue of outgoing replies that have been deferred */
struct data_blob_list_item * send_queue ;
2005-10-17 01:01:59 +00:00
int ( * process ) ( krb5_context context ,
krb5_kdc_configuration * config ,
unsigned char * buf ,
size_t len ,
krb5_data * reply ,
const char * from ,
struct sockaddr * addr ) ;
2005-10-14 06:12:05 +00:00
} ;
2005-06-29 13:55:09 +00:00
2005-06-04 05:35:27 +00:00
/*
handle fd send events on a KDC socket
*/
static void kdc_send_handler ( struct kdc_socket * kdc_socket )
{
while ( kdc_socket - > send_queue ) {
struct kdc_reply * rep = kdc_socket - > send_queue ;
NTSTATUS status ;
size_t sendlen ;
status = socket_sendto ( kdc_socket - > sock , & rep - > packet , & sendlen , 0 ,
rep - > dest_address , rep - > dest_port ) ;
if ( NT_STATUS_EQUAL ( status , STATUS_MORE_ENTRIES ) ) {
break ;
}
DLIST_REMOVE ( kdc_socket - > send_queue , rep ) ;
talloc_free ( rep ) ;
}
if ( kdc_socket - > send_queue = = NULL ) {
EVENT_FD_NOT_WRITEABLE ( kdc_socket - > fde ) ;
}
}
2005-06-03 11:23:15 +00:00
2005-06-04 01:40:30 +00:00
2005-06-04 05:35:27 +00:00
/*
handle fd recv events on a KDC socket
*/
static void kdc_recv_handler ( struct kdc_socket * kdc_socket )
2005-06-04 01:40:30 +00:00
{
NTSTATUS status ;
2005-06-04 05:35:27 +00:00
TALLOC_CTX * tmp_ctx = talloc_new ( kdc_socket ) ;
2005-06-04 01:40:30 +00:00
DATA_BLOB blob ;
2005-06-04 05:35:27 +00:00
struct kdc_reply * rep ;
2005-06-04 01:40:30 +00:00
krb5_data reply ;
size_t nread , dsize ;
const char * src_addr ;
int src_port ;
struct sockaddr_in src_sock_addr ;
struct ipv4_addr addr ;
2005-06-05 07:40:17 +00:00
int ret ;
2005-06-04 05:35:27 +00:00
2005-06-04 01:40:30 +00:00
status = socket_pending ( kdc_socket - > sock , & dsize ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( tmp_ctx ) ;
return ;
}
2005-06-04 05:35:27 +00:00
blob = data_blob_talloc ( kdc_socket , NULL , dsize ) ;
2005-06-04 01:40:30 +00:00
if ( blob . data = = NULL ) {
2005-06-04 05:35:27 +00:00
/* hope this is a temporary low memory condition */
2005-06-04 01:40:30 +00:00
talloc_free ( tmp_ctx ) ;
return ;
}
2005-06-04 05:35:27 +00:00
2005-06-04 01:40:30 +00:00
status = socket_recvfrom ( kdc_socket - > sock , blob . data , blob . length , & nread , 0 ,
& src_addr , & src_port ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( tmp_ctx ) ;
return ;
}
talloc_steal ( tmp_ctx , src_addr ) ;
blob . length = nread ;
2005-10-14 06:12:05 +00:00
DEBUG ( 2 , ( " Received krb5 UDP packet of length %u from %s:%u \n " ,
blob . length , src_addr , ( uint16_t ) src_port ) ) ;
2005-06-04 01:40:30 +00:00
/* TODO: This really should be in a utility function somewhere */
ZERO_STRUCT ( src_sock_addr ) ;
# ifdef HAVE_SOCK_SIN_LEN
src_sock_addr . sin_len = sizeof ( src_sock_addr ) ;
# endif
addr = interpret_addr2 ( src_addr ) ;
src_sock_addr . sin_addr . s_addr = addr . addr ;
src_sock_addr . sin_port = htons ( src_port ) ;
src_sock_addr . sin_family = PF_INET ;
/* Call krb5 */
2005-10-17 01:01:59 +00:00
ret = kdc_socket - > process ( kdc_socket - > kdc - > smb_krb5_context - > krb5_context ,
kdc_socket - > kdc - > config ,
blob . data , blob . length ,
& reply ,
src_addr ,
( struct sockaddr * ) & src_sock_addr ) ;
2005-06-05 07:40:17 +00:00
if ( ret = = - 1 ) {
2005-06-04 05:35:27 +00:00
talloc_free ( tmp_ctx ) ;
return ;
}
2005-06-04 01:40:30 +00:00
2005-06-04 05:35:27 +00:00
/* queue a pending reply */
rep = talloc ( kdc_socket , struct kdc_reply ) ;
if ( rep = = NULL ) {
2005-06-12 11:31:57 +00:00
krb5_data_free ( & reply ) ;
2005-06-04 05:35:27 +00:00
talloc_free ( tmp_ctx ) ;
return ;
}
rep - > dest_address = talloc_steal ( rep , src_addr ) ;
rep - > dest_port = src_port ;
rep - > packet = data_blob_talloc ( rep , reply . data , reply . length ) ;
2005-06-12 11:31:57 +00:00
krb5_data_free ( & reply ) ;
2005-06-04 05:35:27 +00:00
if ( rep - > packet . data = = NULL ) {
talloc_free ( rep ) ;
talloc_free ( tmp_ctx ) ;
return ;
2005-06-04 01:40:30 +00:00
}
2005-06-04 05:35:27 +00:00
DLIST_ADD_END ( kdc_socket - > send_queue , rep , struct kdc_reply * ) ;
EVENT_FD_WRITEABLE ( kdc_socket - > fde ) ;
2005-06-04 01:40:30 +00:00
talloc_free ( tmp_ctx ) ;
}
2005-06-03 11:23:15 +00:00
/*
2005-06-03 14:32:10 +00:00
handle fd events on a KDC socket
2005-06-03 11:23:15 +00:00
*/
static void kdc_socket_handler ( struct event_context * ev , struct fd_event * fde ,
uint16_t flags , void * private )
{
struct kdc_socket * kdc_socket = talloc_get_type ( private , struct kdc_socket ) ;
if ( flags & EVENT_FD_WRITE ) {
2005-06-04 05:35:27 +00:00
kdc_send_handler ( kdc_socket ) ;
2005-06-11 03:55:40 +00:00
}
if ( flags & EVENT_FD_READ ) {
2005-06-04 05:35:27 +00:00
kdc_recv_handler ( kdc_socket ) ;
2005-06-03 11:23:15 +00:00
}
}
2005-10-14 06:12:05 +00:00
static void kdc_tcp_terminate_connection ( struct kdc_tcp_connection * kdcconn , const char * reason )
{
stream_terminate_connection ( kdcconn - > conn , reason ) ;
}
/*
called when we get a new connection
*/
static void kdc_tcp_accept ( struct stream_connection * conn )
{
struct kdc_server * kdc = talloc_get_type ( conn - > private , struct kdc_server ) ;
struct kdc_tcp_connection * kdcconn ;
kdcconn = talloc_zero ( conn , struct kdc_tcp_connection ) ;
if ( ! kdcconn ) {
stream_terminate_connection ( conn , " kdc_tcp_accept: out of memory " ) ;
return ;
}
2005-10-17 01:01:59 +00:00
kdcconn - > conn = conn ;
kdcconn - > kdc = kdc ;
kdcconn - > process = krb5_kdc_process_krb5_request ;
conn - > private = kdcconn ;
2005-10-14 06:12:05 +00:00
}
/*
2005-10-17 01:01:59 +00:00
receive some data on a KDC connection
2005-10-14 06:12:05 +00:00
*/
static void kdc_tcp_recv ( struct stream_connection * conn , uint16_t flags )
{
struct kdc_tcp_connection * kdcconn = talloc_get_type ( conn - > private , struct kdc_tcp_connection ) ;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
TALLOC_CTX * tmp_ctx = talloc_new ( kdcconn ) ;
struct data_blob_list_item * rep ;
krb5_data reply ;
size_t nread ;
const char * src_addr ;
int src_port ;
struct sockaddr_in src_sock_addr ;
struct ipv4_addr addr ;
int ret ;
/* avoid recursion, because of half async code */
if ( kdcconn - > processing ) {
EVENT_FD_NOT_READABLE ( conn - > event . fde ) ;
return ;
}
if ( kdcconn - > partial . length = = 0 ) {
kdcconn - > partial = data_blob_talloc ( kdcconn , NULL , 4 ) ;
if ( ! kdcconn - > partial . data ) goto nomem ;
kdcconn - > partial_read = 0 ;
}
/* read in the packet length */
if ( kdcconn - > partial_read < 4 ) {
uint32_t packet_length ;
status = socket_recv ( conn - > socket ,
kdcconn - > partial . data + kdcconn - > partial_read ,
4 - kdcconn - > partial_read ,
& nread , 0 ) ;
if ( NT_STATUS_IS_ERR ( status ) ) goto failed ;
if ( ! NT_STATUS_IS_OK ( status ) ) return ;
kdcconn - > partial_read + = nread ;
if ( kdcconn - > partial_read ! = 4 ) return ;
packet_length = RIVAL ( kdcconn - > partial . data , 0 ) + 4 ;
kdcconn - > partial . data = talloc_realloc ( kdcconn , kdcconn - > partial . data ,
uint8_t , packet_length ) ;
if ( ! kdcconn - > partial . data ) goto nomem ;
kdcconn - > partial . length = packet_length ;
}
/* read in the body */
status = socket_recv ( conn - > socket ,
kdcconn - > partial . data + kdcconn - > partial_read ,
kdcconn - > partial . length - kdcconn - > partial_read ,
& nread , 0 ) ;
if ( NT_STATUS_IS_ERR ( status ) ) goto failed ;
if ( ! NT_STATUS_IS_OK ( status ) ) return ;
kdcconn - > partial_read + = nread ;
if ( kdcconn - > partial_read ! = kdcconn - > partial . length ) return ;
/*
* we have parsed the request , so we can reset the kdcconn - > partial_read ,
* maybe we could also free kdcconn - > partial , but for now we keep it ,
* and overwrite it the next time
*/
kdcconn - > partial_read = 0 ;
src_addr = socket_get_peer_addr ( kdcconn - > conn - > socket , tmp_ctx ) ;
if ( ! src_addr ) goto nomem ;
src_port = socket_get_peer_port ( kdcconn - > conn - > socket ) ;
DEBUG ( 2 , ( " Received krb5 TCP packet of length %u from %s:%u \n " ,
kdcconn - > partial . length - 4 , src_addr , src_port ) ) ;
/* TODO: This really should be in a utility function somewhere */
ZERO_STRUCT ( src_sock_addr ) ;
# ifdef HAVE_SOCK_SIN_LEN
src_sock_addr . sin_len = sizeof ( src_sock_addr ) ;
# endif
addr = interpret_addr2 ( src_addr ) ;
src_sock_addr . sin_addr . s_addr = addr . addr ;
src_sock_addr . sin_port = htons ( src_port ) ;
src_sock_addr . sin_family = PF_INET ;
/* Call krb5 */
kdcconn - > processing = True ;
2005-10-17 01:01:59 +00:00
ret = kdcconn - > process ( kdcconn - > kdc - > smb_krb5_context - > krb5_context ,
kdcconn - > kdc - > config ,
kdcconn - > partial . data + 4 , kdcconn - > partial . length - 4 ,
& reply ,
src_addr ,
( struct sockaddr * ) & src_sock_addr ) ;
2005-10-14 06:12:05 +00:00
kdcconn - > processing = False ;
if ( ret = = - 1 ) {
status = NT_STATUS_INTERNAL_ERROR ;
goto failed ;
}
/* and now encode the reply */
rep = talloc ( kdcconn , struct data_blob_list_item ) ;
if ( ! rep ) {
krb5_data_free ( & reply ) ;
goto nomem ;
}
rep - > blob = data_blob_talloc ( rep , NULL , reply . length + 4 ) ;
if ( ! rep - > blob . data ) {
krb5_data_free ( & reply ) ;
goto nomem ;
}
RSIVAL ( rep - > blob . data , 0 , reply . length ) ;
memcpy ( rep - > blob . data + 4 , reply . data , reply . length ) ;
krb5_data_free ( & reply ) ;
if ( ! kdcconn - > send_queue ) {
EVENT_FD_WRITEABLE ( kdcconn - > conn - > event . fde ) ;
}
DLIST_ADD_END ( kdcconn - > send_queue , rep , struct data_blob_list_item * ) ;
EVENT_FD_READABLE ( kdcconn - > conn - > event . fde ) ;
/* the call isn't needed any more */
talloc_free ( tmp_ctx ) ;
return ;
nomem :
status = NT_STATUS_NO_MEMORY ;
failed :
kdc_tcp_terminate_connection ( kdcconn , nt_errstr ( status ) ) ;
}
/*
called when we can write to a connection
*/
static void kdc_tcp_send ( struct stream_connection * conn , uint16_t flags )
{
struct kdc_tcp_connection * kdcconn = talloc_get_type ( conn - > private , struct kdc_tcp_connection ) ;
NTSTATUS status ;
while ( kdcconn - > send_queue ) {
struct data_blob_list_item * q = kdcconn - > send_queue ;
size_t sendlen ;
status = socket_send ( conn - > socket , & q - > blob , & sendlen , 0 ) ;
if ( NT_STATUS_IS_ERR ( status ) ) goto failed ;
if ( ! NT_STATUS_IS_OK ( status ) ) return ;
q - > blob . length - = sendlen ;
q - > blob . data + = sendlen ;
if ( q - > blob . length = = 0 ) {
DLIST_REMOVE ( kdcconn - > send_queue , q ) ;
talloc_free ( q ) ;
}
}
EVENT_FD_NOT_WRITEABLE ( conn - > event . fde ) ;
return ;
failed :
kdc_tcp_terminate_connection ( kdcconn , nt_errstr ( status ) ) ;
}
static const struct stream_server_ops kdc_tcp_stream_ops = {
. name = " kdc_tcp " ,
. accept_connection = kdc_tcp_accept ,
. recv_handler = kdc_tcp_recv ,
. send_handler = kdc_tcp_send
} ;
2005-06-04 05:35:27 +00:00
2005-06-03 11:23:15 +00:00
/*
start listening on the given address
*/
static NTSTATUS kdc_add_socket ( struct kdc_server * kdc , const char * address )
{
2005-10-14 06:12:05 +00:00
const struct model_ops * model_ops ;
2005-06-04 11:17:05 +00:00
struct kdc_socket * kdc_socket ;
2005-06-03 11:23:15 +00:00
NTSTATUS status ;
2005-10-14 06:12:05 +00:00
uint16_t port = lp_krb5_port ( ) ;
2005-06-03 11:23:15 +00:00
kdc_socket = talloc ( kdc , struct kdc_socket ) ;
NT_STATUS_HAVE_NO_MEMORY ( kdc_socket ) ;
status = socket_create ( " ip " , SOCKET_TYPE_DGRAM , & kdc_socket - > sock , 0 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( kdc_socket ) ;
return status ;
}
kdc_socket - > kdc = kdc ;
2005-06-04 05:35:27 +00:00
kdc_socket - > send_queue = NULL ;
2005-10-17 01:01:59 +00:00
kdc_socket - > process = krb5_kdc_process_krb5_request ;
2005-06-03 11:23:15 +00:00
talloc_steal ( kdc_socket , kdc_socket - > sock ) ;
kdc_socket - > fde = event_add_fd ( kdc - > task - > event_ctx , kdc ,
2005-06-04 05:35:27 +00:00
socket_get_fd ( kdc_socket - > sock ) , EVENT_FD_READ ,
2005-06-03 11:23:15 +00:00
kdc_socket_handler , kdc_socket ) ;
2005-10-14 06:12:05 +00:00
status = socket_listen ( kdc_socket - > sock , address , port , 0 , 0 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to bind to %s:%d UDP - %s \n " ,
address , port , nt_errstr ( status ) ) ) ;
talloc_free ( kdc_socket ) ;
return status ;
}
/* within the kdc task we want to be a single process, so
ask for the single process model ops and pass these to the
stream_setup_socket ( ) call . */
model_ops = process_model_byname ( " single " ) ;
if ( ! model_ops ) {
DEBUG ( 0 , ( " Can't find 'single' process model_ops \n " ) ) ;
talloc_free ( kdc_socket ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
status = stream_setup_socket ( kdc - > task - > event_ctx , model_ops , & kdc_tcp_stream_ops ,
" ip " , address , & port , kdc ) ;
2005-06-03 11:23:15 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2005-10-14 06:12:05 +00:00
DEBUG ( 0 , ( " Failed to bind to %s:%u TCP - %s \n " ,
address , port , nt_errstr ( status ) ) ) ;
2005-06-03 11:23:15 +00:00
talloc_free ( kdc_socket ) ;
return status ;
}
return NT_STATUS_OK ;
}
/*
setup our listening sockets on the configured network interfaces
*/
2005-10-14 06:12:05 +00:00
static NTSTATUS kdc_startup_interfaces ( struct kdc_server * kdc )
2005-06-03 11:23:15 +00:00
{
int num_interfaces = iface_count ( ) ;
TALLOC_CTX * tmp_ctx = talloc_new ( kdc ) ;
NTSTATUS status ;
/* if we are allowing incoming packets from any address, then
we need to bind to the wildcard address */
if ( ! lp_bind_interfaces_only ( ) ) {
status = kdc_add_socket ( kdc , " 0.0.0.0 " ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
} else {
int i ;
for ( i = 0 ; i < num_interfaces ; i + + ) {
const char * address = talloc_strdup ( tmp_ctx , iface_n_ip ( i ) ) ;
status = kdc_add_socket ( kdc , address ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
}
}
talloc_free ( tmp_ctx ) ;
return NT_STATUS_OK ;
}
/*
startup the kdc task
*/
static void kdc_task_init ( struct task_server * task )
{
struct kdc_server * kdc ;
NTSTATUS status ;
2005-06-03 14:32:10 +00:00
krb5_error_code ret ;
2005-06-03 11:23:15 +00:00
if ( iface_count ( ) = = 0 ) {
2005-06-25 23:53:14 +00:00
task_server_terminate ( task , " kdc: no network interfaces configured " ) ;
2005-06-03 11:23:15 +00:00
return ;
}
kdc = talloc ( task , struct kdc_server ) ;
if ( kdc = = NULL ) {
2005-06-25 23:53:14 +00:00
task_server_terminate ( task , " kdc: out of memory " ) ;
2005-06-03 11:23:15 +00:00
return ;
}
kdc - > task = task ;
/* Setup the KDC configuration */
2005-07-05 10:05:40 +00:00
kdc - > config = talloc ( kdc , krb5_kdc_configuration ) ;
2005-06-03 11:23:15 +00:00
if ( ! kdc - > config ) {
2005-06-25 23:53:14 +00:00
task_server_terminate ( task , " kdc: out of memory " ) ;
2005-06-03 11:23:15 +00:00
return ;
}
krb5_kdc_default_config ( kdc - > config ) ;
2005-06-05 13:11:42 +00:00
/* NAT and the like make this pointless, and painful */
kdc - > config - > check_ticket_addresses = FALSE ;
2005-06-03 14:32:10 +00:00
initialize_krb5_error_table ( ) ;
2005-06-04 11:17:05 +00:00
ret = smb_krb5_init_context ( kdc , & kdc - > smb_krb5_context ) ;
2005-06-03 14:32:10 +00:00
if ( ret ) {
DEBUG ( 1 , ( " kdc_task_init: krb5_init_context failed (%s) \n " ,
error_message ( ret ) ) ) ;
2005-06-25 23:53:14 +00:00
task_server_terminate ( task , " kdc: krb5_init_context failed " ) ;
2005-06-03 14:32:10 +00:00
return ;
}
2005-09-28 02:22:31 +00:00
krb5_add_et_list ( kdc - > smb_krb5_context - > krb5_context , initialize_hdb_error_table_r ) ;
2005-06-04 11:17:05 +00:00
kdc - > config - > logf = kdc - > smb_krb5_context - > logf ;
2005-06-03 14:32:10 +00:00
kdc - > config - > db = talloc ( kdc - > config , struct HDB * ) ;
if ( ! kdc - > config - > db ) {
2005-06-25 23:53:14 +00:00
task_server_terminate ( task , " kdc: out of memory " ) ;
2005-06-03 14:32:10 +00:00
return ;
}
kdc - > config - > num_db = 1 ;
2005-06-29 13:55:09 +00:00
ret = hdb_ldb_create ( kdc , kdc - > smb_krb5_context - > krb5_context ,
2005-06-04 11:17:05 +00:00
& kdc - > config - > db [ 0 ] , lp_sam_url ( ) ) ;
2005-06-03 14:32:10 +00:00
if ( ret ! = 0 ) {
DEBUG ( 1 , ( " kdc_task_init: hdb_ldb_create fails: %s \n " ,
2005-06-04 11:17:05 +00:00
smb_get_krb5_error_message ( kdc - > smb_krb5_context - > krb5_context , ret , kdc ) ) ) ;
2005-06-25 23:53:14 +00:00
task_server_terminate ( task , " kdc: hdb_ldb_create failed " ) ;
2005-06-03 14:32:10 +00:00
return ;
}
2005-06-03 11:23:15 +00:00
/* start listening on the configured network interfaces */
status = kdc_startup_interfaces ( kdc ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2005-06-25 23:53:14 +00:00
task_server_terminate ( task , " kdc failed to setup interfaces " ) ;
2005-06-03 11:23:15 +00:00
return ;
}
2005-07-19 09:27:20 +00:00
irpc_add_name ( task - > msg_ctx , " kdc_server " ) ;
2005-06-03 11:23:15 +00:00
}
/*
called on startup of the KDC service
*/
static NTSTATUS kdc_init ( struct event_context * event_ctx ,
const struct model_ops * model_ops )
{
return task_server_startup ( event_ctx , model_ops , kdc_task_init ) ;
}
/* called at smbd startup - register ourselves as a server service */
NTSTATUS server_service_kdc_init ( void )
{
return register_server_service ( " kdc " , kdc_init ) ;
}