2011-05-23 14:39:07 +04:00
/*
* Unix SMB / CIFS implementation .
*
* LSA service daemon
*
* Copyright ( c ) 2011 Andreas Schneider < asn @ samba . org >
*
* 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 3 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 , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "serverid.h"
# include "messages.h"
# include "ntdomain.h"
2011-08-19 19:36:53 +04:00
# include "lib/id_cache.h"
2011-05-23 14:39:07 +04:00
# include "../lib/tsocket/tsocket.h"
# include "lib/server_prefork.h"
2011-08-13 01:21:50 +04:00
# include "lib/server_prefork_util.h"
2011-05-23 14:39:07 +04:00
# include "librpc/rpc/dcerpc_ep.h"
# include "rpc_server/rpc_server.h"
# include "rpc_server/rpc_ep_register.h"
# include "rpc_server/rpc_sock_helper.h"
# include "librpc/gen_ndr/srv_lsa.h"
# include "librpc/gen_ndr/srv_samr.h"
# include "librpc/gen_ndr/srv_netlogon.h"
# define DAEMON_NAME "lsasd"
# define LSASD_MAX_SOCKETS 64
2011-08-17 01:34:30 +04:00
static struct server_id parent_id ;
2011-08-11 22:24:05 +04:00
static struct prefork_pool * lsasd_pool = NULL ;
static int lsasd_child_id = 0 ;
2011-05-23 14:39:07 +04:00
2011-08-13 01:21:50 +04:00
static struct pf_daemon_config default_pf_lsasd_cfg = {
. prefork_status = PFH_INIT ,
. min_children = 5 ,
. max_children = 25 ,
. spawn_rate = 5 ,
. max_allowed_clients = 100 ,
. child_min_life = 60 /* 1 minute minimum life time */
} ;
static struct pf_daemon_config pf_lsasd_cfg = { 0 } ;
2011-05-23 14:39:07 +04:00
void start_lsasd ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ) ;
static void lsasd_reopen_logs ( int child_id )
{
2012-07-18 09:37:23 +04:00
char * lfile = lp_logfile ( talloc_tos ( ) ) ;
2011-05-23 14:39:07 +04:00
char * extension ;
int rc ;
if ( child_id ) {
rc = asprintf ( & extension , " %s.%d " , DAEMON_NAME , child_id ) ;
} else {
rc = asprintf ( & extension , " %s " , DAEMON_NAME ) ;
}
if ( rc = = - 1 ) {
return ;
}
rc = 0 ;
if ( lfile = = NULL | | lfile [ 0 ] = = ' \0 ' ) {
rc = asprintf ( & lfile , " %s/log.%s " ,
get_dyn_LOGFILEBASE ( ) , extension ) ;
} else {
if ( strstr ( lfile , extension ) = = NULL ) {
if ( child_id ) {
rc = asprintf ( & lfile , " %s.%d " ,
2012-07-18 09:37:23 +04:00
lp_logfile ( talloc_tos ( ) ) ,
2011-05-23 14:39:07 +04:00
child_id ) ;
} else {
rc = asprintf ( & lfile , " %s.%s " ,
2012-07-18 09:37:23 +04:00
lp_logfile ( talloc_tos ( ) ) ,
2011-05-23 14:39:07 +04:00
extension ) ;
}
}
}
if ( rc > 0 ) {
lp_set_logfile ( lfile ) ;
SAFE_FREE ( lfile ) ;
}
SAFE_FREE ( extension ) ;
reopen_logs ( ) ;
}
static void lsasd_smb_conf_updated ( struct messaging_context * msg ,
void * private_data ,
uint32_t msg_type ,
struct server_id server_id ,
DATA_BLOB * data )
{
2011-08-13 01:21:50 +04:00
struct tevent_context * ev_ctx ;
2011-05-23 14:39:07 +04:00
DEBUG ( 10 , ( " Got message saying smb.conf was updated. Reloading. \n " ) ) ;
2011-08-13 01:21:50 +04:00
ev_ctx = talloc_get_type_abort ( private_data , struct tevent_context ) ;
2011-05-23 14:39:07 +04:00
change_to_root_user ( ) ;
lp_load ( get_dyn_CONFIGFILE ( ) , true , false , false , true ) ;
2011-08-11 22:24:05 +04:00
lsasd_reopen_logs ( lsasd_child_id ) ;
if ( lsasd_child_id = = 0 ) {
2011-08-13 01:21:50 +04:00
pfh_daemon_config ( DAEMON_NAME ,
& pf_lsasd_cfg ,
& default_pf_lsasd_cfg ) ;
pfh_manage_pool ( ev_ctx , msg , & pf_lsasd_cfg , lsasd_pool ) ;
2011-08-11 22:24:05 +04:00
}
2011-05-23 14:39:07 +04:00
}
static void lsasd_sig_term_handler ( struct tevent_context * ev ,
struct tevent_signal * se ,
int signum ,
int count ,
void * siginfo ,
void * private_data )
{
rpc_netlogon_shutdown ( ) ;
rpc_samr_shutdown ( ) ;
rpc_lsarpc_shutdown ( ) ;
DEBUG ( 0 , ( " termination signal \n " ) ) ;
exit ( 0 ) ;
}
static void lsasd_setup_sig_term_handler ( struct tevent_context * ev_ctx )
{
struct tevent_signal * se ;
se = tevent_add_signal ( ev_ctx ,
ev_ctx ,
SIGTERM , 0 ,
lsasd_sig_term_handler ,
NULL ) ;
if ( ! se ) {
DEBUG ( 0 , ( " failed to setup SIGTERM handler \n " ) ) ;
exit ( 1 ) ;
}
}
static void lsasd_sig_hup_handler ( struct tevent_context * ev ,
struct tevent_signal * se ,
int signum ,
int count ,
void * siginfo ,
void * pvt )
{
change_to_root_user ( ) ;
lp_load ( get_dyn_CONFIGFILE ( ) , true , false , false , true ) ;
2011-08-11 22:24:05 +04:00
lsasd_reopen_logs ( lsasd_child_id ) ;
2011-08-13 01:21:50 +04:00
pfh_daemon_config ( DAEMON_NAME ,
& pf_lsasd_cfg ,
& default_pf_lsasd_cfg ) ;
2011-05-23 14:39:07 +04:00
/* relay to all children */
2011-08-11 22:24:05 +04:00
prefork_send_signal_to_all ( lsasd_pool , SIGHUP ) ;
2011-05-23 14:39:07 +04:00
}
2011-08-11 22:24:05 +04:00
static void lsasd_setup_sig_hup_handler ( struct tevent_context * ev_ctx )
2011-05-23 14:39:07 +04:00
{
struct tevent_signal * se ;
se = tevent_add_signal ( ev_ctx ,
ev_ctx ,
SIGHUP , 0 ,
lsasd_sig_hup_handler ,
2011-08-11 22:24:05 +04:00
NULL ) ;
2011-05-23 14:39:07 +04:00
if ( ! se ) {
DEBUG ( 0 , ( " failed to setup SIGHUP handler \n " ) ) ;
exit ( 1 ) ;
}
}
/**********************************************************
* Children
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void lsasd_chld_sig_hup_handler ( struct tevent_context * ev ,
struct tevent_signal * se ,
int signum ,
int count ,
void * siginfo ,
void * pvt )
{
change_to_root_user ( ) ;
2011-08-11 22:24:05 +04:00
lsasd_reopen_logs ( lsasd_child_id ) ;
2011-05-23 14:39:07 +04:00
}
2011-08-18 18:35:19 +04:00
static bool lsasd_setup_chld_hup_handler ( struct tevent_context * ev_ctx )
2011-05-23 14:39:07 +04:00
{
struct tevent_signal * se ;
se = tevent_add_signal ( ev_ctx ,
ev_ctx ,
SIGHUP , 0 ,
lsasd_chld_sig_hup_handler ,
2011-08-18 18:35:19 +04:00
NULL ) ;
2011-05-23 14:39:07 +04:00
if ( ! se ) {
DEBUG ( 1 , ( " failed to setup SIGHUP handler " ) ) ;
return false ;
}
return true ;
}
2011-08-17 23:21:52 +04:00
static void parent_ping ( struct messaging_context * msg_ctx ,
void * private_data ,
uint32_t msg_type ,
struct server_id server_id ,
DATA_BLOB * data )
{
/* The fact we received this message is enough to let make the event
* loop if it was idle . lsasd_children_main will cycle through
* lsasd_next_client at least once . That function will take whatever
* action is necessary */
DEBUG ( 10 , ( " Got message that the parent changed status. \n " ) ) ;
return ;
}
2011-05-23 14:39:07 +04:00
static bool lsasd_child_init ( struct tevent_context * ev_ctx ,
int child_id ,
struct pf_worker_data * pf )
{
NTSTATUS status ;
struct messaging_context * msg_ctx = server_messaging_context ( ) ;
bool ok ;
status = reinit_after_fork ( msg_ctx , ev_ctx ,
2011-12-12 17:55:54 +04:00
true ) ;
2011-05-23 14:39:07 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " reinit_after_fork() failed \n " ) ) ;
smb_panic ( " reinit_after_fork() failed " ) ;
}
2011-08-11 22:24:05 +04:00
lsasd_child_id = child_id ;
2011-05-23 14:39:07 +04:00
lsasd_reopen_logs ( child_id ) ;
2011-08-18 18:35:19 +04:00
ok = lsasd_setup_chld_hup_handler ( ev_ctx ) ;
2011-05-23 14:39:07 +04:00
if ( ! ok ) {
return false ;
}
2012-10-19 09:15:31 +04:00
if ( ! serverid_register ( messaging_server_id ( msg_ctx ) ,
FLAG_MSG_GENERAL ) ) {
2011-05-23 14:39:07 +04:00
return false ;
}
messaging_register ( msg_ctx , ev_ctx ,
MSG_SMB_CONF_UPDATED , lsasd_smb_conf_updated ) ;
2011-08-17 23:21:52 +04:00
messaging_register ( msg_ctx , ev_ctx ,
MSG_PREFORK_PARENT_EVENT , parent_ping ) ;
2011-08-19 19:36:53 +04:00
id_cache_register_msgs ( msg_ctx ) ;
2011-05-23 14:39:07 +04:00
status = rpc_lsarpc_init ( NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to register lsarpc rpc inteface! (%s) \n " ,
nt_errstr ( status ) ) ) ;
return false ;
}
status = rpc_samr_init ( NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to register samr rpc inteface! (%s) \n " ,
nt_errstr ( status ) ) ) ;
return false ;
}
status = rpc_netlogon_init ( NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to register netlogon rpc inteface! (%s) \n " ,
nt_errstr ( status ) ) ) ;
return false ;
}
return true ;
}
struct lsasd_children_data {
struct tevent_context * ev_ctx ;
struct messaging_context * msg_ctx ;
struct pf_worker_data * pf ;
int listen_fd_size ;
int * listen_fds ;
} ;
static void lsasd_next_client ( void * pvt ) ;
static int lsasd_children_main ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
struct pf_worker_data * pf ,
int child_id ,
int listen_fd_size ,
int * listen_fds ,
void * private_data )
{
struct lsasd_children_data * data ;
bool ok ;
2011-08-24 03:02:38 +04:00
int ret = 0 ;
2011-05-23 14:39:07 +04:00
ok = lsasd_child_init ( ev_ctx , child_id , pf ) ;
if ( ! ok ) {
return 1 ;
}
data = talloc ( ev_ctx , struct lsasd_children_data ) ;
if ( ! data ) {
return 1 ;
}
data - > pf = pf ;
data - > ev_ctx = ev_ctx ;
data - > msg_ctx = msg_ctx ;
data - > listen_fd_size = listen_fd_size ;
data - > listen_fds = listen_fds ;
/* loop until it is time to exit */
while ( pf - > status ! = PF_WORKER_EXITING ) {
/* try to see if it is time to schedule the next client */
lsasd_next_client ( data ) ;
ret = tevent_loop_once ( ev_ctx ) ;
if ( ret ! = 0 ) {
DEBUG ( 0 , ( " tevent_loop_once() exited with %d: %s \n " ,
ret , strerror ( errno ) ) ) ;
pf - > status = PF_WORKER_EXITING ;
}
}
return ret ;
}
static void lsasd_client_terminated ( void * pvt )
{
struct lsasd_children_data * data ;
data = talloc_get_type_abort ( pvt , struct lsasd_children_data ) ;
2011-08-16 20:01:02 +04:00
pfh_client_terminated ( data - > pf ) ;
2011-05-23 14:39:07 +04:00
lsasd_next_client ( pvt ) ;
}
struct lsasd_new_client {
struct lsasd_children_data * data ;
} ;
static void lsasd_handle_client ( struct tevent_req * req ) ;
static void lsasd_next_client ( void * pvt )
{
struct tevent_req * req ;
struct lsasd_children_data * data ;
struct lsasd_new_client * next ;
data = talloc_get_type_abort ( pvt , struct lsasd_children_data ) ;
2011-08-16 20:01:02 +04:00
if ( ! pfh_child_allowed_to_accept ( data - > pf ) ) {
2011-05-23 14:39:07 +04:00
/* nothing to do for now we are already listening
2011-08-16 20:01:02 +04:00
* or we are not allowed to listen further */
2011-05-23 14:39:07 +04:00
return ;
}
next = talloc_zero ( data , struct lsasd_new_client ) ;
if ( ! next ) {
DEBUG ( 1 , ( " Out of memory!? \n " ) ) ;
return ;
}
next - > data = data ;
req = prefork_listen_send ( next ,
data - > ev_ctx ,
data - > pf ,
data - > listen_fd_size ,
2011-08-16 17:30:28 +04:00
data - > listen_fds ) ;
2011-05-23 14:39:07 +04:00
if ( ! req ) {
DEBUG ( 1 , ( " Failed to make listening request!? \n " ) ) ;
talloc_free ( next ) ;
return ;
}
tevent_req_set_callback ( req , lsasd_handle_client , next ) ;
}
static void lsasd_handle_client ( struct tevent_req * req )
{
struct lsasd_children_data * data ;
struct lsasd_new_client * client ;
2011-08-17 01:34:30 +04:00
const DATA_BLOB ping = data_blob_null ;
2011-05-23 14:39:07 +04:00
int rc ;
int sd ;
TALLOC_CTX * tmp_ctx ;
struct tsocket_address * srv_addr ;
struct tsocket_address * cli_addr ;
client = tevent_req_callback_data ( req , struct lsasd_new_client ) ;
data = client - > data ;
tmp_ctx = talloc_stackframe ( ) ;
if ( tmp_ctx = = NULL ) {
DEBUG ( 1 , ( " Failed to allocate stackframe! \n " ) ) ;
return ;
}
rc = prefork_listen_recv ( req ,
tmp_ctx ,
& sd ,
& srv_addr ,
& cli_addr ) ;
/* this will free the request too */
talloc_free ( client ) ;
2011-08-16 17:30:28 +04:00
if ( rc ! = 0 ) {
DEBUG ( 6 , ( " No client connection was available after all! \n " ) ) ;
goto done ;
2011-05-23 14:39:07 +04:00
}
2011-08-17 01:34:30 +04:00
/* Warn parent that our status changed */
messaging_send ( data - > msg_ctx , parent_id ,
MSG_PREFORK_CHILD_EVENT , & ping ) ;
2011-05-23 14:39:07 +04:00
DEBUG ( 2 , ( " LSASD preforked child %d got client connection! \n " ,
( int ) ( data - > pf - > pid ) ) ) ;
if ( tsocket_address_is_inet ( srv_addr , " ip " ) ) {
DEBUG ( 3 , ( " Got a tcpip client connection from %s on inteface %s \n " ,
tsocket_address_string ( cli_addr , tmp_ctx ) ,
tsocket_address_string ( srv_addr , tmp_ctx ) ) ) ;
dcerpc_ncacn_accept ( data - > ev_ctx ,
data - > msg_ctx ,
NCACN_IP_TCP ,
" IP " ,
cli_addr ,
srv_addr ,
sd ,
NULL ) ;
} else if ( tsocket_address_is_unix ( srv_addr ) ) {
2012-06-19 13:33:12 +04:00
const char * p ;
const char * b ;
2011-05-23 14:39:07 +04:00
p = tsocket_address_unix_path ( srv_addr , tmp_ctx ) ;
if ( p = = NULL ) {
talloc_free ( tmp_ctx ) ;
return ;
}
2012-06-19 13:33:12 +04:00
b = strrchr ( p , ' / ' ) ;
if ( b ! = NULL ) {
b + + ;
} else {
b = p ;
}
2011-05-23 14:39:07 +04:00
2012-06-19 13:33:12 +04:00
if ( strstr ( p , " /np/ " ) ) {
2011-05-23 14:39:07 +04:00
named_pipe_accept_function ( data - > ev_ctx ,
data - > msg_ctx ,
2012-06-19 13:33:12 +04:00
b ,
2011-05-23 14:39:07 +04:00
sd ,
lsasd_client_terminated ,
data ) ;
} else {
dcerpc_ncacn_accept ( data - > ev_ctx ,
data - > msg_ctx ,
NCALRPC ,
2012-06-19 13:33:12 +04:00
b ,
2011-05-23 14:39:07 +04:00
cli_addr ,
srv_addr ,
sd ,
NULL ) ;
}
} else {
DEBUG ( 0 , ( " ERROR: Unsupported socket! \n " ) ) ;
}
2011-08-16 17:30:28 +04:00
done :
2011-05-23 14:39:07 +04:00
talloc_free ( tmp_ctx ) ;
}
/*
* MAIN
*/
2011-08-17 01:34:30 +04:00
static void child_ping ( struct messaging_context * msg_ctx ,
void * private_data ,
uint32_t msg_type ,
struct server_id server_id ,
DATA_BLOB * data )
{
struct tevent_context * ev_ctx ;
ev_ctx = talloc_get_type_abort ( private_data , struct tevent_context ) ;
DEBUG ( 10 , ( " Got message that a child changed status. \n " ) ) ;
pfh_manage_pool ( ev_ctx , msg_ctx , & pf_lsasd_cfg , lsasd_pool ) ;
}
2011-05-23 14:39:07 +04:00
static bool lsasd_schedule_check ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
struct timeval current_time ) ;
static void lsasd_check_children ( struct tevent_context * ev_ctx ,
struct tevent_timer * te ,
struct timeval current_time ,
void * pvt ) ;
static void lsasd_sigchld_handler ( struct tevent_context * ev_ctx ,
struct prefork_pool * pfp ,
void * pvt )
{
struct messaging_context * msg_ctx ;
msg_ctx = talloc_get_type_abort ( pvt , struct messaging_context ) ;
2011-08-13 01:21:50 +04:00
/* run pool management so we can fork/retire or increase
* the allowed connections per child based on load */
pfh_manage_pool ( ev_ctx , msg_ctx , & pf_lsasd_cfg , lsasd_pool ) ;
2011-05-23 14:39:07 +04:00
}
static bool lsasd_setup_children_monitor ( struct tevent_context * ev_ctx ,
2011-08-11 22:24:05 +04:00
struct messaging_context * msg_ctx )
2011-05-23 14:39:07 +04:00
{
bool ok ;
/* add our oun sigchld callback */
2011-08-11 22:24:05 +04:00
prefork_set_sigchld_callback ( lsasd_pool , lsasd_sigchld_handler , msg_ctx ) ;
2011-05-23 14:39:07 +04:00
2011-08-11 22:24:05 +04:00
ok = lsasd_schedule_check ( ev_ctx , msg_ctx , tevent_timeval_current ( ) ) ;
2011-05-23 14:39:07 +04:00
return ok ;
}
static bool lsasd_schedule_check ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
struct timeval current_time )
{
struct tevent_timer * te ;
struct timeval next_event ;
/* check situation again in 10 seconds */
next_event = tevent_timeval_current_ofs ( 10 , 0 ) ;
/* TODO: check when the socket becomes readable, so that children
* are checked only when there is some activity ? */
2011-08-11 22:24:05 +04:00
te = tevent_add_timer ( ev_ctx , lsasd_pool , next_event ,
lsasd_check_children , msg_ctx ) ;
2011-05-23 14:39:07 +04:00
if ( ! te ) {
DEBUG ( 2 , ( " Failed to set up children monitoring! \n " ) ) ;
return false ;
}
return true ;
}
static void lsasd_check_children ( struct tevent_context * ev_ctx ,
struct tevent_timer * te ,
struct timeval current_time ,
void * pvt )
{
2011-08-11 22:24:05 +04:00
struct messaging_context * msg_ctx ;
2011-05-23 14:39:07 +04:00
2011-08-11 22:24:05 +04:00
msg_ctx = talloc_get_type_abort ( pvt , struct messaging_context ) ;
2011-05-23 14:39:07 +04:00
2011-08-13 01:21:50 +04:00
pfh_manage_pool ( ev_ctx , msg_ctx , & pf_lsasd_cfg , lsasd_pool ) ;
2011-05-23 14:39:07 +04:00
2011-08-13 01:21:50 +04:00
lsasd_schedule_check ( ev_ctx , msg_ctx , current_time ) ;
2011-05-23 14:39:07 +04:00
}
/*
* start it up
*/
static bool lsasd_create_sockets ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
int * listen_fd ,
int * listen_fd_size )
{
struct dcerpc_binding_vector * v , * v_orig ;
TALLOC_CTX * tmp_ctx ;
NTSTATUS status ;
uint32_t i ;
int fd ;
int rc ;
bool ok = true ;
tmp_ctx = talloc_stackframe ( ) ;
if ( tmp_ctx = = NULL ) {
return false ;
}
status = dcerpc_binding_vector_new ( tmp_ctx , & v_orig ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ok = false ;
goto done ;
}
/* Create only one tcpip listener for all services */
status = rpc_create_tcpip_sockets ( & ndr_table_lsarpc ,
v_orig ,
0 ,
listen_fd ,
listen_fd_size ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ok = false ;
goto done ;
}
/* Start to listen on tcpip sockets */
for ( i = 0 ; i < * listen_fd_size ; i + + ) {
2011-08-13 01:21:50 +04:00
rc = listen ( listen_fd [ i ] , pf_lsasd_cfg . max_allowed_clients ) ;
2011-05-23 14:39:07 +04:00
if ( rc = = - 1 ) {
DEBUG ( 0 , ( " Failed to listen on tcpip socket - %s \n " ,
strerror ( errno ) ) ) ;
ok = false ;
goto done ;
}
}
/* LSARPC */
fd = create_named_pipe_socket ( " lsarpc " ) ;
if ( fd < 0 ) {
ok = false ;
goto done ;
}
listen_fd [ * listen_fd_size ] = fd ;
( * listen_fd_size ) + + ;
2011-08-13 01:21:50 +04:00
rc = listen ( fd , pf_lsasd_cfg . max_allowed_clients ) ;
2011-05-23 14:39:07 +04:00
if ( rc = = - 1 ) {
DEBUG ( 0 , ( " Failed to listen on lsarpc pipe - %s \n " ,
strerror ( errno ) ) ) ;
ok = false ;
goto done ;
}
2011-08-21 13:58:36 +04:00
fd = create_named_pipe_socket ( " lsass " ) ;
if ( fd < 0 ) {
ok = false ;
goto done ;
}
listen_fd [ * listen_fd_size ] = fd ;
( * listen_fd_size ) + + ;
rc = listen ( fd , pf_lsasd_cfg . max_allowed_clients ) ;
if ( rc = = - 1 ) {
DEBUG ( 0 , ( " Failed to listen on lsass pipe - %s \n " ,
strerror ( errno ) ) ) ;
ok = false ;
goto done ;
}
2011-08-18 21:05:27 +04:00
fd = create_dcerpc_ncalrpc_socket ( " lsarpc " ) ;
if ( fd < 0 ) {
ok = false ;
goto done ;
}
listen_fd [ * listen_fd_size ] = fd ;
( * listen_fd_size ) + + ;
rc = listen ( fd , pf_lsasd_cfg . max_allowed_clients ) ;
if ( rc = = - 1 ) {
DEBUG ( 0 , ( " Failed to listen on lsarpc ncalrpc - %s \n " ,
strerror ( errno ) ) ) ;
ok = false ;
goto done ;
}
2011-05-23 14:39:07 +04:00
v = dcerpc_binding_vector_dup ( tmp_ctx , v_orig ) ;
if ( v = = NULL ) {
ok = false ;
goto done ;
}
status = dcerpc_binding_vector_replace_iface ( & ndr_table_lsarpc , v ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return false ;
}
status = dcerpc_binding_vector_add_np_default ( & ndr_table_lsarpc , v ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ok = false ;
goto done ;
}
2011-08-18 21:05:27 +04:00
status = dcerpc_binding_vector_add_unix ( & ndr_table_lsarpc , v , " lsarpc " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ok = false ;
goto done ;
}
2011-05-23 14:39:07 +04:00
status = rpc_ep_register ( ev_ctx , msg_ctx , & ndr_table_lsarpc , v ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ok = false ;
goto done ;
}
/* SAMR */
fd = create_named_pipe_socket ( " samr " ) ;
if ( fd < 0 ) {
ok = false ;
goto done ;
}
2011-08-13 01:21:50 +04:00
rc = listen ( fd , pf_lsasd_cfg . max_allowed_clients ) ;
2011-05-23 14:39:07 +04:00
if ( rc = = - 1 ) {
DEBUG ( 0 , ( " Failed to listen on samr pipe - %s \n " ,
strerror ( errno ) ) ) ;
ok = false ;
goto done ;
}
listen_fd [ * listen_fd_size ] = fd ;
( * listen_fd_size ) + + ;
2011-08-18 21:05:27 +04:00
fd = create_dcerpc_ncalrpc_socket ( " samr " ) ;
if ( fd < 0 ) {
ok = false ;
goto done ;
}
listen_fd [ * listen_fd_size ] = fd ;
( * listen_fd_size ) + + ;
rc = listen ( fd , pf_lsasd_cfg . max_allowed_clients ) ;
if ( rc = = - 1 ) {
DEBUG ( 0 , ( " Failed to listen on samr ncalrpc - %s \n " ,
strerror ( errno ) ) ) ;
ok = false ;
goto done ;
}
2011-05-23 14:39:07 +04:00
v = dcerpc_binding_vector_dup ( tmp_ctx , v_orig ) ;
if ( v = = NULL ) {
ok = false ;
goto done ;
}
status = dcerpc_binding_vector_replace_iface ( & ndr_table_samr , v ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return false ;
}
status = dcerpc_binding_vector_add_np_default ( & ndr_table_samr , v ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ok = false ;
goto done ;
}
2011-08-18 21:05:27 +04:00
status = dcerpc_binding_vector_add_unix ( & ndr_table_lsarpc , v , " samr " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ok = false ;
goto done ;
}
2011-05-23 14:39:07 +04:00
status = rpc_ep_register ( ev_ctx , msg_ctx , & ndr_table_samr , v ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ok = false ;
goto done ;
}
/* NETLOGON */
fd = create_named_pipe_socket ( " netlogon " ) ;
if ( fd < 0 ) {
ok = false ;
goto done ;
}
2011-08-13 01:21:50 +04:00
rc = listen ( fd , pf_lsasd_cfg . max_allowed_clients ) ;
2011-05-23 14:39:07 +04:00
if ( rc = = - 1 ) {
DEBUG ( 0 , ( " Failed to listen on samr pipe - %s \n " ,
strerror ( errno ) ) ) ;
ok = false ;
goto done ;
}
listen_fd [ * listen_fd_size ] = fd ;
( * listen_fd_size ) + + ;
2011-08-18 21:05:27 +04:00
fd = create_dcerpc_ncalrpc_socket ( " netlogon " ) ;
if ( fd < 0 ) {
ok = false ;
goto done ;
}
listen_fd [ * listen_fd_size ] = fd ;
( * listen_fd_size ) + + ;
rc = listen ( fd , pf_lsasd_cfg . max_allowed_clients ) ;
if ( rc = = - 1 ) {
DEBUG ( 0 , ( " Failed to listen on netlogon ncalrpc - %s \n " ,
strerror ( errno ) ) ) ;
ok = false ;
goto done ;
}
2011-05-23 14:39:07 +04:00
v = dcerpc_binding_vector_dup ( tmp_ctx , v_orig ) ;
if ( v = = NULL ) {
ok = false ;
goto done ;
}
status = dcerpc_binding_vector_replace_iface ( & ndr_table_netlogon , v ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return false ;
}
status = dcerpc_binding_vector_add_np_default ( & ndr_table_netlogon , v ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ok = false ;
goto done ;
}
2011-08-18 21:05:27 +04:00
status = dcerpc_binding_vector_add_unix ( & ndr_table_lsarpc , v , " netlogon " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ok = false ;
goto done ;
}
2011-05-23 14:39:07 +04:00
status = rpc_ep_register ( ev_ctx , msg_ctx , & ndr_table_netlogon , v ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ok = false ;
goto done ;
}
done :
talloc_free ( tmp_ctx ) ;
return ok ;
}
void start_lsasd ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx )
{
NTSTATUS status ;
int listen_fd [ LSASD_MAX_SOCKETS ] ;
int listen_fd_size = 0 ;
pid_t pid ;
int rc ;
bool ok ;
DEBUG ( 1 , ( " Forking LSA Service Daemon \n " ) ) ;
/*
* Block signals before forking child as it will have to
* set its own handlers . Child will re - enable SIGHUP as
* soon as the handlers are set up .
*/
BlockSignals ( true , SIGTERM ) ;
BlockSignals ( true , SIGHUP ) ;
2012-03-24 23:17:08 +04:00
pid = fork ( ) ;
2011-05-23 14:39:07 +04:00
if ( pid = = - 1 ) {
DEBUG ( 0 , ( " Failed to fork LSASD [%s], aborting ... \n " ,
strerror ( errno ) ) ) ;
exit ( 1 ) ;
}
/* parent or error */
if ( pid ! = 0 ) {
/* Re-enable SIGHUP before returnig */
BlockSignals ( false , SIGTERM ) ;
BlockSignals ( false , SIGHUP ) ;
return ;
}
status = reinit_after_fork ( msg_ctx ,
ev_ctx ,
2011-12-12 17:55:54 +04:00
true ) ;
2011-05-23 14:39:07 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " reinit_after_fork() failed \n " ) ) ;
smb_panic ( " reinit_after_fork() failed " ) ;
}
2012-10-19 09:15:31 +04:00
/* save the parent process id so the children can use it later */
parent_id = messaging_server_id ( msg_ctx ) ;
2011-05-23 14:39:07 +04:00
lsasd_reopen_logs ( 0 ) ;
2011-08-13 01:21:50 +04:00
pfh_daemon_config ( DAEMON_NAME ,
& pf_lsasd_cfg ,
& default_pf_lsasd_cfg ) ;
2011-05-23 14:39:07 +04:00
lsasd_setup_sig_term_handler ( ev_ctx ) ;
2011-08-11 22:24:05 +04:00
lsasd_setup_sig_hup_handler ( ev_ctx ) ;
2011-05-23 14:39:07 +04:00
BlockSignals ( false , SIGTERM ) ;
BlockSignals ( false , SIGHUP ) ;
ok = lsasd_create_sockets ( ev_ctx , msg_ctx , listen_fd , & listen_fd_size ) ;
if ( ! ok ) {
exit ( 1 ) ;
}
/* start children before any more initialization is done */
ok = prefork_create_pool ( ev_ctx , /* mem_ctx */
ev_ctx ,
msg_ctx ,
listen_fd_size ,
listen_fd ,
2011-08-13 01:21:50 +04:00
pf_lsasd_cfg . min_children ,
pf_lsasd_cfg . max_children ,
2011-05-23 14:39:07 +04:00
& lsasd_children_main ,
NULL ,
2011-08-11 22:24:05 +04:00
& lsasd_pool ) ;
2011-05-23 14:39:07 +04:00
if ( ! ok ) {
exit ( 1 ) ;
}
2012-10-19 09:15:31 +04:00
if ( ! serverid_register ( messaging_server_id ( msg_ctx ) ,
FLAG_MSG_GENERAL ) ) {
2011-05-23 14:39:07 +04:00
exit ( 1 ) ;
}
messaging_register ( msg_ctx ,
ev_ctx ,
MSG_SMB_CONF_UPDATED ,
lsasd_smb_conf_updated ) ;
2011-08-17 01:34:30 +04:00
messaging_register ( msg_ctx , ev_ctx ,
MSG_PREFORK_CHILD_EVENT , child_ping ) ;
2011-05-23 14:39:07 +04:00
status = rpc_lsarpc_init ( NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-03-03 05:18:21 +04:00
DEBUG ( 0 , ( " Failed to register lsarpc rpc inteface in lsasd! (%s) \n " ,
2011-05-23 14:39:07 +04:00
nt_errstr ( status ) ) ) ;
exit ( 1 ) ;
}
status = rpc_samr_init ( NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-03-03 05:18:21 +04:00
DEBUG ( 0 , ( " Failed to register samr rpc inteface in lsasd! (%s) \n " ,
2011-05-23 14:39:07 +04:00
nt_errstr ( status ) ) ) ;
exit ( 1 ) ;
}
status = rpc_netlogon_init ( NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-03-03 05:18:21 +04:00
DEBUG ( 0 , ( " Failed to register netlogon rpc inteface in lsasd! (%s) \n " ,
2011-05-23 14:39:07 +04:00
nt_errstr ( status ) ) ) ;
exit ( 1 ) ;
}
2011-08-11 22:24:05 +04:00
ok = lsasd_setup_children_monitor ( ev_ctx , msg_ctx ) ;
2011-05-23 14:39:07 +04:00
if ( ! ok ) {
DEBUG ( 0 , ( " Failed to setup children monitoring! \n " ) ) ;
exit ( 1 ) ;
}
DEBUG ( 1 , ( " LSASD Daemon Started (%d) \n " , getpid ( ) ) ) ;
/* loop forever */
rc = tevent_loop_wait ( ev_ctx ) ;
/* should not be reached */
2011-08-11 22:24:05 +04:00
DEBUG ( 0 , ( " lsasd: tevent_loop_wait() exited with %d - %s \n " ,
2011-05-23 14:39:07 +04:00
rc , ( rc = = 0 ) ? " out of events " : strerror ( errno ) ) ) ;
exit ( 1 ) ;
}