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 "messages.h"
# include "ntdomain.h"
2018-03-20 03:14:38 +03:00
# include "passdb.h"
2011-05-23 14:39:07 +04:00
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"
2019-02-26 15:48:33 +03:00
# include "librpc/rpc/dcesrv_core.h"
2011-05-23 14:39:07 +04:00
# include "rpc_server/rpc_server.h"
# include "rpc_server/rpc_ep_register.h"
# include "rpc_server/rpc_sock_helper.h"
2019-02-27 17:45:52 +03:00
# include "rpc_server/rpc_service_setup.h"
2011-05-23 14:39:07 +04:00
2019-03-15 11:40:21 +03:00
# include "rpc_server/lsasd.h"
2011-05-23 14:39:07 +04:00
2019-02-26 15:48:33 +03:00
# include "librpc/gen_ndr/ndr_lsa_scompat.h"
# include "librpc/gen_ndr/ndr_samr_scompat.h"
# include "librpc/gen_ndr/ndr_netlogon_scompat.h"
2021-01-03 23:53:49 +03:00
# include "lib/global_contexts.h"
2019-02-26 15:48:33 +03:00
2019-02-05 21:27:58 +03:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_RPC_SRV
2011-05-23 14:39:07 +04:00
# define DAEMON_NAME "lsasd"
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
2020-12-26 12:04:42 +03:00
static const struct pf_daemon_config default_pf_lsasd_cfg = {
2011-08-13 01:21:50 +04:00
. 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
static void lsasd_reopen_logs ( int child_id )
{
2019-11-05 12:34:11 +03:00
const struct loadparm_substitution * lp_sub =
loadparm_s3_global_substitution ( ) ;
char * lfile = lp_logfile ( talloc_tos ( ) , lp_sub ) ;
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 " ,
2019-11-05 12:34:11 +03:00
lp_logfile ( talloc_tos ( ) , lp_sub ) ,
2011-05-23 14:39:07 +04:00
child_id ) ;
} else {
rc = asprintf ( & lfile , " %s.%s " ,
2019-11-05 12:34:11 +03:00
lp_logfile ( talloc_tos ( ) , lp_sub ) ,
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 ( ) ;
2014-07-30 18:43:05 +04:00
lp_load_global ( get_dyn_CONFIGFILE ( ) ) ;
2011-05-23 14:39:07 +04:00
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 )
{
2019-02-26 15:24:33 +03:00
exit_server_cleanly ( " termination signal " ) ;
2011-05-23 14:39:07 +04:00
}
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 ) {
2019-02-26 15:24:33 +03:00
exit_server ( " failed to setup SIGTERM handler " ) ;
2011-05-23 14:39:07 +04:00
}
}
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 ( ) ;
2014-07-30 18:43:05 +04:00
lp_load_global ( get_dyn_CONFIGFILE ( ) ) ;
2011-05-23 14:39:07 +04:00
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 ;
2018-08-21 21:09:16 +03:00
struct messaging_context * msg_ctx = global_messaging_context ( ) ;
2011-05-23 14:39:07 +04:00
bool ok ;
status = reinit_after_fork ( msg_ctx , ev_ctx ,
2015-09-23 21:14:05 +03:00
true , " lsasd-child " ) ;
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 " ) ;
}
2018-03-20 03:14:38 +03:00
initialize_password_db ( true , ev_ctx ) ;
2011-05-23 14:39:07 +04:00
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 ;
}
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
return true ;
}
struct lsasd_children_data {
struct tevent_context * ev_ctx ;
struct messaging_context * msg_ctx ;
2019-02-27 22:21:44 +03:00
struct dcesrv_context * dce_ctx ;
2011-05-23 14:39:07 +04:00
struct pf_worker_data * pf ;
int listen_fd_size ;
2019-01-28 12:57:53 +03:00
struct pf_listen_fd * listen_fds ;
2011-05-23 14:39:07 +04:00
} ;
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 ,
2019-01-28 12:57:53 +03:00
struct pf_listen_fd * listen_fds ,
2011-05-23 14:39:07 +04:00
void * private_data )
{
struct lsasd_children_data * data ;
bool ok ;
2011-08-24 03:02:38 +04:00
int ret = 0 ;
2019-02-27 22:21:44 +03:00
struct dcesrv_context * dce_ctx = NULL ;
dce_ctx = talloc_get_type_abort ( private_data , struct dcesrv_context ) ;
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 ;
2019-02-27 22:21:44 +03:00
data - > dce_ctx = dce_ctx ;
2011-05-23 14:39:07 +04:00
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 ;
}
2019-12-05 13:45:54 +03:00
static void lsasd_client_terminated ( struct dcesrv_connection * conn , void * pvt )
2011-05-23 14:39:07 +04:00
{
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 ;
2019-02-27 22:21:44 +03:00
void * listen_fd_data = NULL ;
struct dcesrv_endpoint * ep = NULL ;
enum dcerpc_transport_t transport ;
dcerpc_ncacn_termination_fn term_fn = NULL ;
void * term_fn_data = NULL ;
2011-05-23 14:39:07 +04:00
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 ,
2019-02-27 22:21:44 +03:00
& listen_fd_data ,
2011-05-23 14:39:07 +04:00
& 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
}
2019-02-27 22:21:44 +03:00
ep = talloc_get_type_abort ( listen_fd_data , struct dcesrv_endpoint ) ;
transport = dcerpc_binding_get_transport ( ep - > ep_description ) ;
if ( transport = = NCACN_NP ) {
term_fn = lsasd_client_terminated ;
term_fn_data = data ;
}
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 ) ;
2019-02-27 22:21:44 +03:00
DBG_INFO ( " LSASD preforked child %d got client connection on '%s' \n " ,
( int ) ( data - > pf - > pid ) , dcerpc_binding_string ( tmp_ctx ,
ep - > ep_description ) ) ;
2011-05-23 14:39:07 +04:00
2019-02-27 22:21:44 +03:00
dcerpc_ncacn_accept ( data - > ev_ctx ,
data - > msg_ctx ,
data - > dce_ctx ,
ep ,
2021-01-12 11:26:24 +03:00
& cli_addr ,
& srv_addr ,
2019-02-27 22:21:44 +03:00
sd ,
term_fn ,
term_fn_data ) ;
2011-05-23 14:39:07 +04:00
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
*/
2019-02-27 17:45:52 +03:00
static NTSTATUS lsasd_create_sockets ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
struct dcesrv_context * dce_ctx ,
2020-12-31 17:10:10 +03:00
TALLOC_CTX * mem_ctx ,
struct pf_listen_fd * * plisten_fds ,
size_t * pnum_listen_fds )
2011-05-23 14:39:07 +04:00
{
NTSTATUS status ;
2020-12-31 17:10:10 +03:00
size_t i , num_fds ;
struct pf_listen_fd * fds = NULL ;
2011-05-23 14:39:07 +04:00
int rc ;
2020-12-31 17:10:10 +03:00
struct dcesrv_endpoint * e = dce_ctx - > endpoint_list ;
2011-05-23 14:39:07 +04:00
2019-02-27 17:45:52 +03:00
DBG_INFO ( " Initializing DCE/RPC connection endpoints \n " ) ;
2020-12-31 17:10:10 +03:00
status = dcesrv_create_endpoint_list_pf_listen_fds (
ev_ctx , msg_ctx , dce_ctx , e , mem_ctx , & num_fds , & fds ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2019-02-27 17:45:52 +03:00
}
2020-12-31 17:10:10 +03:00
for ( i = 0 ; i < num_fds ; i + + ) {
rc = listen ( fds [ i ] . fd , pf_lsasd_cfg . max_allowed_clients ) ;
2019-02-27 17:45:52 +03:00
if ( rc = = - 1 ) {
2020-11-25 14:55:24 +03:00
char * ep_string = NULL ;
2020-12-31 17:10:10 +03:00
e = fds [ i ] . fd_data ;
2020-11-25 14:55:24 +03:00
ep_string = dcerpc_binding_string ( dce_ctx ,
e - > ep_description ) ;
2019-02-27 17:45:52 +03:00
DBG_ERR ( " Failed to listen on endpoint '%s': %s \n " ,
ep_string , strerror ( errno ) ) ;
status = map_nt_error_from_unix ( errno ) ;
TALLOC_FREE ( ep_string ) ;
goto done ;
}
}
2019-02-27 21:32:26 +03:00
for ( e = dce_ctx - > endpoint_list ; e ; e = e - > next ) {
struct dcesrv_if_list * ifl = NULL ;
for ( ifl = e - > interface_list ; ifl ; ifl = ifl - > next ) {
status = rpc_ep_register ( ev_ctx ,
msg_ctx ,
dce_ctx ,
ifl - > iface ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " Failed to register interface in "
" endpoint mapper: %s " ,
nt_errstr ( status ) ) ;
goto done ;
}
}
2011-05-23 14:39:07 +04:00
}
2020-12-31 17:10:10 +03:00
* plisten_fds = fds ;
* pnum_listen_fds = num_fds ;
2019-02-27 17:45:52 +03:00
status = NT_STATUS_OK ;
2011-05-23 14:39:07 +04:00
done :
2019-02-27 17:45:52 +03:00
return status ;
2011-05-23 14:39:07 +04:00
}
void start_lsasd ( struct tevent_context * ev_ctx ,
2019-02-26 18:56:42 +03:00
struct messaging_context * msg_ctx ,
struct dcesrv_context * dce_ctx )
2011-05-23 14:39:07 +04:00
{
NTSTATUS status ;
2020-12-31 17:10:10 +03:00
struct pf_listen_fd * listen_fd = NULL ;
size_t listen_fd_size = 0 ;
2011-05-23 14:39:07 +04:00
pid_t pid ;
int rc ;
bool ok ;
2019-02-26 15:48:33 +03:00
const struct dcesrv_endpoint_server * ep_server = NULL ;
2019-02-26 19:57:58 +03:00
const char * ep_servers [ ] = { " lsarpc " , " samr " , " netlogon " , NULL } ;
2011-05-23 14:39:07 +04:00
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 ;
}
2015-09-23 21:14:05 +03:00
status = smbd_reinit_after_fork ( msg_ctx , ev_ctx , true , " lsasd-master " ) ;
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 " ) ;
}
2018-03-20 03:14:38 +03:00
initialize_password_db ( true , ev_ctx ) ;
2011-05-23 14:39:07 +04:00
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 ) ;
2019-02-26 15:48:33 +03:00
DBG_INFO ( " Registering DCE/RPC endpoint servers \n " ) ;
ep_server = lsarpc_get_ep_server ( ) ;
if ( ep_server = = NULL ) {
DBG_ERR ( " Failed to get 'lsarpc' endpoint server \n " ) ;
exit ( 1 ) ;
}
status = dcerpc_register_ep_server ( ep_server ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " Failed to register 'lsarpc' endpoint server: %s \n " ,
nt_errstr ( status ) ) ;
exit ( 1 ) ;
}
ep_server = samr_get_ep_server ( ) ;
if ( ep_server = = NULL ) {
DBG_ERR ( " Failed to get 'samr' endpoint server \n " ) ;
exit ( 1 ) ;
}
status = dcerpc_register_ep_server ( ep_server ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " Failed to register 'samr' endpoint server: %s \n " ,
nt_errstr ( status ) ) ;
exit ( 1 ) ;
}
ep_server = netlogon_get_ep_server ( ) ;
if ( ep_server = = NULL ) {
DBG_ERR ( " Failed to get 'netlogon' endpoint server \n " ) ;
exit ( 1 ) ;
}
status = dcerpc_register_ep_server ( ep_server ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " Failed to register 'netlogon' endpoint server: %s \n " ,
nt_errstr ( status ) ) ;
exit ( 1 ) ;
}
2019-02-26 18:56:42 +03:00
DBG_INFO ( " Reinitializing DCE/RPC server context \n " ) ;
status = dcesrv_reinit_context ( dce_ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " Failed to reinit DCE/RPC context: %s \n " ,
nt_errstr ( status ) ) ;
exit ( 1 ) ;
}
2019-02-26 19:57:58 +03:00
DBG_INFO ( " Initializing DCE/RPC registered endpoint servers \n " ) ;
/* Init ep servers */
status = dcesrv_init_ep_servers ( dce_ctx , ep_servers ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " Failed to init DCE/RPC endpoint server: %s \n " ,
nt_errstr ( status ) ) ;
exit ( 1 ) ;
}
2019-02-27 17:45:52 +03:00
status = lsasd_create_sockets ( ev_ctx ,
msg_ctx ,
dce_ctx ,
2020-12-31 17:10:10 +03:00
dce_ctx ,
& listen_fd ,
2019-02-27 17:45:52 +03:00
& listen_fd_size ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-05-23 14:39:07 +04:00
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 ,
2019-02-27 22:21:44 +03:00
dce_ctx ,
2011-08-11 22:24:05 +04:00
& lsasd_pool ) ;
2020-12-31 17:10:10 +03:00
TALLOC_FREE ( listen_fd ) ;
2011-05-23 14:39:07 +04:00
if ( ! ok ) {
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
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 ) ;
}
2013-03-15 03:06:10 +04:00
DEBUG ( 1 , ( " LSASD Daemon Started (%u) \n " , ( unsigned int ) getpid ( ) ) ) ;
2011-05-23 14:39:07 +04:00
/* 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 ) ;
}