struct imessaging_context *winbind_imessaging_context(void) { static struct imessaging_context *msg = NULL; struct messaging_context *msg_ctx; struct server_id myself; struct loadparm_context *lp_ctx; if (msg != NULL) { return msg; } msg_ctx = server_messaging_context(); if (msg_ctx == NULL) { smb_panic("server_messaging_context failed\n"); } myself = messaging_server_id(msg_ctx); lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers()); if (lp_ctx == NULL) { smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n"); } /* * Note we MUST use the NULL context here, not the autofree context, * to avoid side effects in forked children exiting. */ msg = imessaging_init(NULL, lp_ctx, myself, winbind_event_context()); talloc_unlink(NULL, lp_ctx); if (msg == NULL) { smb_panic("Could not init winbindd's messaging context.\n"); } return msg; }
static bool locking_init_internal(bool read_only) { brl_init(read_only); if (lock_db) return True; lock_db = db_open(NULL, lock_path("locking.tdb"), SMB_OPEN_DATABASE_TDB_HASH_SIZE, TDB_DEFAULT|TDB_VOLATILE|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, read_only?O_RDONLY:O_RDWR|O_CREAT, 0644, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (!lock_db) { DEBUG(0,("ERROR: Failed to initialise locking database\n")); return False; } if (!posix_locking_init(read_only)) return False; dbwrap_watch_db(lock_db, server_messaging_context()); return True; }
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, true); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("reinit_after_fork() failed\n")); smb_panic("reinit_after_fork() failed"); } prctl_set_comment("lsasd-child"); lsasd_child_id = child_id; lsasd_reopen_logs(child_id); ok = lsasd_setup_chld_hup_handler(ev_ctx); if (!ok) { return false; } if (!serverid_register(messaging_server_id(msg_ctx), FLAG_MSG_GENERAL)) { return false; } messaging_register(msg_ctx, ev_ctx, MSG_SMB_CONF_UPDATED, lsasd_smb_conf_updated); messaging_register(msg_ctx, ev_ctx, MSG_PREFORK_PARENT_EVENT, parent_ping); id_cache_register_msgs(msg_ctx); 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 messaging_context *winbind_messaging_context(void) { struct messaging_context *msg_ctx = server_messaging_context(); if (likely(msg_ctx != NULL)) { return msg_ctx; } smb_panic("Could not init winbindd's messaging context.\n"); return NULL; }
NTSTATUS smbXsrv_session_global_init(struct messaging_context *msg_ctx) { char *global_path = NULL; struct db_context *backend = NULL; struct db_context *db_ctx = NULL; if (smbXsrv_session_global_db_ctx != NULL) { return NT_STATUS_OK; } /* * This contains secret information like session keys! */ global_path = lock_path("smbXsrv_session_global.tdb"); if (global_path == NULL) { return NT_STATUS_NO_MEMORY; } backend = db_open(NULL, global_path, 0, /* hash_size */ TDB_DEFAULT | TDB_CLEAR_IF_FIRST | TDB_INCOMPATIBLE_HASH, O_RDWR | O_CREAT, 0600, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); TALLOC_FREE(global_path); if (backend == NULL) { NTSTATUS status; status = map_nt_error_from_unix_common(errno); return status; } db_ctx = db_open_watched(NULL, backend, server_messaging_context()); if (db_ctx == NULL) { TALLOC_FREE(backend); return NT_STATUS_NO_MEMORY; } smbXsrv_session_global_db_ctx = db_ctx; return NT_STATUS_OK; }
static bool mdssd_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, true, "mdssd-child"); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("reinit_after_fork() failed\n")); smb_panic("reinit_after_fork() failed"); } mdssd_child_id = child_id; reopen_logs(); ok = mdssd_setup_chld_hup_handler(ev_ctx); if (!ok) { return false; } if (!serverid_register(messaging_server_id(msg_ctx), FLAG_MSG_GENERAL)) { return false; } messaging_register(msg_ctx, ev_ctx, MSG_SMB_CONF_UPDATED, mdssd_smb_conf_updated); messaging_register(msg_ctx, ev_ctx, MSG_PREFORK_PARENT_EVENT, parent_ping); status = rpc_mdssvc_init(NULL); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to intialize RPC: %s\n", nt_errstr(status))); return false; } return true; }
/* Return a server_id with a unique task_id element. Free the * returned pointer to de-allocate the task_id via a talloc destructor * (ie, use talloc_free()) */ static struct server_id *new_server_id_task(TALLOC_CTX *mem_ctx) { struct messaging_context *msg_ctx; struct server_id *server_id; int task_id; if (!task_id_tree) { task_id_tree = idr_init(NULL); if (!task_id_tree) { return NULL; } } msg_ctx = server_messaging_context(); if (msg_ctx == NULL) { return NULL; } server_id = talloc(mem_ctx, struct server_id); if (!server_id) { return NULL; } *server_id = messaging_server_id(msg_ctx); /* 0 is the default server_id, so we need to start with 1 */ task_id = idr_get_new_above(task_id_tree, server_id, 1, INT32_MAX); if (task_id == -1) { talloc_free(server_id); return NULL; } talloc_set_destructor(server_id, free_task_id); server_id->task_id = task_id; return server_id; }
static void exit_server_common(enum server_exit_reason how, const char *reason) { struct smbXsrv_connection *conn = global_smbXsrv_connection; struct smbd_server_connection *sconn = NULL; struct messaging_context *msg_ctx = server_messaging_context(); if (conn != NULL) { sconn = conn->sconn; } if (!exit_firsttime) exit(0); exit_firsttime = false; change_to_root_user(); if (sconn) { NTSTATUS status; if (NT_STATUS_IS_OK(sconn->status)) { switch (how) { case SERVER_EXIT_ABNORMAL: sconn->status = NT_STATUS_INTERNAL_ERROR; break; case SERVER_EXIT_NORMAL: sconn->status = NT_STATUS_LOCAL_DISCONNECT; break; } } TALLOC_FREE(sconn->smb1.negprot.auth_context); if (lp_log_writeable_files_on_exit()) { bool found = false; files_forall(sconn, log_writeable_file_fn, &found); } /* * Note: this is a no-op for smb2 as * conn->tcon_table is empty */ status = smb1srv_tcon_disconnect_all(conn); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Server exit (%s)\n", (reason ? reason : "normal exit"))); DEBUG(0, ("exit_server_common: " "smb1srv_tcon_disconnect_all() failed (%s) - " "triggering cleanup\n", nt_errstr(status))); how = SERVER_EXIT_ABNORMAL; reason = "smb1srv_tcon_disconnect_all failed"; } status = smbXsrv_session_logoff_all(conn); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Server exit (%s)\n", (reason ? reason : "normal exit"))); DEBUG(0, ("exit_server_common: " "smbXsrv_session_logoff_all() failed (%s) - " "triggering cleanup\n", nt_errstr(status))); how = SERVER_EXIT_ABNORMAL; reason = "smbXsrv_session_logoff_all failed"; } change_to_root_user(); } /* 3 second timeout. */ print_notify_send_messages(msg_ctx, 3); /* delete our entry in the serverid database. */ if (am_parent) { /* * For children the parent takes care of cleaning up */ serverid_deregister(messaging_server_id(msg_ctx)); } #ifdef WITH_DFS if (dcelogin_atmost_once) { dfs_unlogin(); } #endif #ifdef USE_DMAPI /* Destroy Samba DMAPI session only if we are master smbd process */ if (am_parent) { if (!dmapi_destroy_session()) { DEBUG(0,("Unable to close Samba DMAPI session\n")); } } #endif if (am_parent) { rpc_wkssvc_shutdown(); rpc_dssetup_shutdown(); #ifdef DEVELOPER rpc_rpcecho_shutdown(); #endif rpc_netdfs_shutdown(); rpc_initshutdown_shutdown(); rpc_eventlog_shutdown(); rpc_ntsvcs_shutdown(); rpc_svcctl_shutdown(); rpc_spoolss_shutdown(); rpc_srvsvc_shutdown(); rpc_winreg_shutdown(); rpc_netlogon_shutdown(); rpc_samr_shutdown(); rpc_lsarpc_shutdown(); } /* * we need to force the order of freeing the following, * because smbd_msg_ctx is not a talloc child of smbd_server_conn. */ sconn = NULL; conn = NULL; TALLOC_FREE(global_smbXsrv_connection); server_messaging_context_free(); server_event_context_free(); TALLOC_FREE(smbd_memcache_ctx); locking_end(); printing_end(); if (how != SERVER_EXIT_NORMAL) { smb_panic(reason); /* Notreached. */ exit(1); } else { DEBUG(3,("Server exit (%s)\n", (reason ? reason : "normal exit"))); if (am_parent) { pidfile_unlink(lp_pid_directory(), "smbd"); } gencache_stabilize(); } exit(0); }
int main(int argc,const char *argv[]) { /* shall I run as a daemon */ bool is_daemon = false; bool interactive = false; bool Fork = true; bool no_process_group = false; bool log_stdout = false; char *ports = NULL; char *profile_level = NULL; int opt; poptContext pc; bool print_build_options = False; enum { OPT_DAEMON = 1000, OPT_INTERACTIVE, OPT_FORK, OPT_NO_PROCESS_GROUP, OPT_LOG_STDOUT }; struct poptOption long_options[] = { POPT_AUTOHELP {"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" }, {"interactive", 'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE, "Run interactive (not a daemon)"}, {"foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Run daemon in foreground (for daemontools, etc.)" }, {"no-process-group", '\0', POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" }, {"log-stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" }, {"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" }, {"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"}, {"profiling-level", 'P', POPT_ARG_STRING, &profile_level, 0, "Set profiling level","PROFILE_LEVEL"}, POPT_COMMON_SAMBA POPT_COMMON_DYNCONFIG POPT_TABLEEND }; struct smbd_parent_context *parent = NULL; TALLOC_CTX *frame; NTSTATUS status; uint64_t unique_id; struct tevent_context *ev_ctx; struct messaging_context *msg_ctx; /* * Do this before any other talloc operation */ talloc_enable_null_tracking(); frame = talloc_stackframe(); setup_logging(argv[0], DEBUG_DEFAULT_STDOUT); load_case_tables(); smbd_init_globals(); TimeInit(); #ifdef HAVE_SET_AUTH_PARAMETERS set_auth_parameters(argc,argv); #endif pc = poptGetContext("smbd", argc, argv, long_options, 0); while((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_DAEMON: is_daemon = true; break; case OPT_INTERACTIVE: interactive = true; break; case OPT_FORK: Fork = false; break; case OPT_NO_PROCESS_GROUP: no_process_group = true; break; case OPT_LOG_STDOUT: log_stdout = true; break; case 'b': print_build_options = True; break; default: d_fprintf(stderr, "\nInvalid option %s: %s\n\n", poptBadOption(pc, 0), poptStrerror(opt)); poptPrintUsage(pc, stderr, 0); exit(1); } } poptFreeContext(pc); if (interactive) { Fork = False; log_stdout = True; } if (log_stdout) { setup_logging(argv[0], DEBUG_STDOUT); } else { setup_logging(argv[0], DEBUG_FILE); } if (print_build_options) { build_options(True); /* Display output to screen as well as debug */ exit(0); } #ifdef HAVE_SETLUID /* needed for SecureWare on SCO */ setluid(0); #endif set_remote_machine_name("smbd", False); if (interactive && (DEBUGLEVEL >= 9)) { talloc_enable_leak_report(); } if (log_stdout && Fork) { DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n")); exit(1); } /* we want to re-seed early to prevent time delays causing client problems at a later date. (tridge) */ generate_random_buffer(NULL, 0); /* get initial effective uid and gid */ sec_init(); /* make absolutely sure we run as root - to handle cases where people are crazy enough to have it setuid */ gain_root_privilege(); gain_root_group_privilege(); fault_setup(); dump_core_setup("smbd", lp_logfile()); /* we are never interested in SIGPIPE */ BlockSignals(True,SIGPIPE); #if defined(SIGFPE) /* we are never interested in SIGFPE */ BlockSignals(True,SIGFPE); #endif #if defined(SIGUSR2) /* We are no longer interested in USR2 */ BlockSignals(True,SIGUSR2); #endif /* POSIX demands that signals are inherited. If the invoking process has * these signals masked, we will have problems, as we won't recieve them. */ BlockSignals(False, SIGHUP); BlockSignals(False, SIGUSR1); BlockSignals(False, SIGTERM); /* Ensure we leave no zombies until we * correctly set up child handling below. */ CatchChild(); /* we want total control over the permissions on created files, so set our umask to 0 */ umask(0); reopen_logs(); DEBUG(0,("smbd version %s started.\n", samba_version_string())); DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE)); DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); /* Output the build options to the debug log */ build_options(False); if (sizeof(uint16) < 2 || sizeof(uint32) < 4) { DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n")); exit(1); } if (!lp_load_initial_only(get_dyn_CONFIGFILE())) { DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE())); exit(1); } /* Init the security context and global current_user */ init_sec_ctx(); /* * Initialize the event context. The event context needs to be * initialized before the messaging context, cause the messaging * context holds an event context. * FIXME: This should be s3_tevent_context_init() */ ev_ctx = server_event_context(); if (ev_ctx == NULL) { exit(1); } /* * Init the messaging context * FIXME: This should only call messaging_init() */ msg_ctx = server_messaging_context(); if (msg_ctx == NULL) { exit(1); } /* * Reloading of the printers will not work here as we don't have a * server info and rpc services set up. It will be called later. */ if (!reload_services(NULL, -1, False)) { exit(1); } /* ...NOTE... Log files are working from this point! */ DEBUG(3,("loaded services\n")); init_structs(); #ifdef WITH_PROFILE if (!profile_setup(msg_ctx, False)) { DEBUG(0,("ERROR: failed to setup profiling\n")); return -1; } if (profile_level != NULL) { int pl = atoi(profile_level); struct server_id src; DEBUG(1, ("setting profiling level: %s\n",profile_level)); src.pid = getpid(); set_profile_level(pl, src); } #endif if (!is_daemon && !is_a_socket(0)) { if (!interactive) DEBUG(0,("standard input is not a socket, assuming -D option\n")); /* * Setting is_daemon here prevents us from eventually calling * the open_sockets_inetd() */ is_daemon = True; } if (is_daemon && !interactive) { DEBUG( 3, ( "Becoming a daemon.\n" ) ); become_daemon(Fork, no_process_group, log_stdout); } generate_random_buffer((uint8_t *)&unique_id, sizeof(unique_id)); set_my_unique_id(unique_id); #if HAVE_SETPGID /* * If we're interactive we want to set our own process group for * signal management. */ if (interactive && !no_process_group) setpgid( (pid_t)0, (pid_t)0); #endif if (!directory_exist(lp_lockdir())) mkdir(lp_lockdir(), 0755); if (is_daemon) pidfile_create("smbd"); status = reinit_after_fork(msg_ctx, ev_ctx, procid_self(), false); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("reinit_after_fork() failed\n")); exit(1); } smbd_server_conn->msg_ctx = msg_ctx; smbd_setup_sig_term_handler(); smbd_setup_sig_hup_handler(ev_ctx, msg_ctx); /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */ if (smbd_memcache() == NULL) { exit(1); } memcache_set_global(smbd_memcache()); /* Initialise the password backed before the global_sam_sid to ensure that we fetch from ldap before we make a domain sid up */ if(!initialize_password_db(false, ev_ctx)) exit(1); if (!secrets_init()) { DEBUG(0, ("ERROR: smbd can not open secrets.tdb\n")); exit(1); } if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) { struct loadparm_context *lp_ctx = loadparm_init_s3(NULL, loadparm_s3_context()); if (!open_schannel_session_store(NULL, lp_ctx)) { DEBUG(0,("ERROR: Samba cannot open schannel store for secured NETLOGON operations.\n")); exit(1); } TALLOC_FREE(lp_ctx); } if(!get_global_sam_sid()) { DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); exit(1); } if (!sessionid_init()) { exit(1); } if (!connections_init(True)) exit(1); if (!locking_init()) exit(1); if (!messaging_tdb_parent_init(ev_ctx)) { exit(1); } if (!notify_internal_parent_init(ev_ctx)) { exit(1); } if (!serverid_parent_init(ev_ctx)) { exit(1); } if (!W_ERROR_IS_OK(registry_init_full())) exit(1); /* Open the share_info.tdb here, so we don't have to open after the fork on every single connection. This is a small performance improvment and reduces the total number of system fds used. */ if (!share_info_db_init()) { DEBUG(0,("ERROR: failed to load share info db.\n")); exit(1); } status = init_system_info(); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("ERROR: failed to setup system user info: %s.\n", nt_errstr(status))); return -1; } if (!init_guest_info()) { DEBUG(0,("ERROR: failed to setup guest info.\n")); return -1; } if (!file_init(smbd_server_conn)) { DEBUG(0, ("ERROR: file_init failed\n")); return -1; } /* This MUST be done before start_epmd() because otherwise * start_epmd() forks and races against dcesrv_ep_setup() to * call directory_create_or_exist() */ if (!directory_create_or_exist(lp_ncalrpc_dir(), geteuid(), 0755)) { DEBUG(0, ("Failed to create pipe directory %s - %s\n", lp_ncalrpc_dir(), strerror(errno))); return -1; } if (is_daemon && !interactive) { if (rpc_epmapper_daemon() == RPC_DAEMON_FORK) { start_epmd(ev_ctx, msg_ctx); } } if (!dcesrv_ep_setup(ev_ctx, msg_ctx)) { exit(1); } /* only start other daemons if we are running as a daemon * -- bad things will happen if smbd is launched via inetd * and we fork a copy of ourselves here */ if (is_daemon && !interactive) { if (rpc_lsasd_daemon() == RPC_DAEMON_FORK) { start_lsasd(ev_ctx, msg_ctx); } if (!_lp_disable_spoolss() && (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) { bool bgq = lp_parm_bool(-1, "smbd", "backgroundqueue", true); if (!printing_subsystem_init(ev_ctx, msg_ctx, true, bgq)) { exit(1); } } } else if (!_lp_disable_spoolss() && (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) { if (!printing_subsystem_init(ev_ctx, msg_ctx, false, false)) { exit(1); } } if (!is_daemon) { /* inetd mode */ TALLOC_FREE(frame); /* Started from inetd. fd 0 is the socket. */ /* We will abort gracefully when the client or remote system goes away */ smbd_server_conn->sock = dup(0); /* close our standard file descriptors */ if (!debug_get_output_is_stdout()) { close_low_fds(False); /* Don't close stderr */ } #ifdef HAVE_ATEXIT atexit(killkids); #endif /* Stop zombies */ smbd_setup_sig_chld_handler(ev_ctx); smbd_process(ev_ctx, smbd_server_conn); exit_server_cleanly(NULL); return(0); } parent = talloc_zero(ev_ctx, struct smbd_parent_context); if (!parent) { exit_server("talloc(struct smbd_parent_context) failed"); } parent->interactive = interactive; if (!open_sockets_smbd(parent, ev_ctx, msg_ctx, ports)) exit_server("open_sockets_smbd() failed"); /* do a printer update now that all messaging has been set up, * before we allow clients to start connecting */ printing_subsystem_update(ev_ctx, msg_ctx, false); TALLOC_FREE(frame); /* make sure we always have a valid stackframe */ frame = talloc_stackframe(); smbd_parent_loop(ev_ctx, parent); exit_server_cleanly(NULL); TALLOC_FREE(frame); return(0); }
static void exit_server_common(enum server_exit_reason how, const char *reason) { struct smbXsrv_client *client = global_smbXsrv_client; struct smbXsrv_connection *xconn = NULL; struct smbd_server_connection *sconn = NULL; struct messaging_context *msg_ctx = server_messaging_context(); if (client != NULL) { sconn = client->sconn; /* * Here we typically have just one connection */ xconn = client->connections; } if (!exit_firsttime) exit(0); exit_firsttime = false; change_to_root_user(); if (xconn != NULL) { /* * This is typically the disconnect for the only * (or with multi-channel last) connection of the client */ if (NT_STATUS_IS_OK(xconn->transport.status)) { switch (how) { case SERVER_EXIT_ABNORMAL: xconn->transport.status = NT_STATUS_INTERNAL_ERROR; break; case SERVER_EXIT_NORMAL: xconn->transport.status = NT_STATUS_LOCAL_DISCONNECT; break; } } TALLOC_FREE(xconn->smb1.negprot.auth_context); } change_to_root_user(); if (sconn != NULL) { if (lp_log_writeable_files_on_exit()) { bool found = false; files_forall(sconn, log_writeable_file_fn, &found); } } change_to_root_user(); if (xconn != NULL) { NTSTATUS status; /* * Note: this is a no-op for smb2 as * conn->tcon_table is empty */ status = smb1srv_tcon_disconnect_all(xconn); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Server exit (%s)\n", (reason ? reason : "normal exit"))); DEBUG(0, ("exit_server_common: " "smb1srv_tcon_disconnect_all() failed (%s) - " "triggering cleanup\n", nt_errstr(status))); } status = smbXsrv_session_logoff_all(xconn); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Server exit (%s)\n", (reason ? reason : "normal exit"))); DEBUG(0, ("exit_server_common: " "smbXsrv_session_logoff_all() failed (%s) - " "triggering cleanup\n", nt_errstr(status))); } } change_to_root_user(); /* 3 second timeout. */ print_notify_send_messages(msg_ctx, 3); #ifdef USE_DMAPI /* Destroy Samba DMAPI session only if we are master smbd process */ if (am_parent) { if (!dmapi_destroy_session()) { DEBUG(0,("Unable to close Samba DMAPI session\n")); } } #endif if (am_parent) { rpc_wkssvc_shutdown(); rpc_dssetup_shutdown(); #ifdef DEVELOPER rpc_rpcecho_shutdown(); #endif rpc_netdfs_shutdown(); rpc_initshutdown_shutdown(); rpc_eventlog_shutdown(); rpc_ntsvcs_shutdown(); rpc_svcctl_shutdown(); rpc_spoolss_shutdown(); rpc_srvsvc_shutdown(); rpc_winreg_shutdown(); rpc_netlogon_shutdown(); rpc_samr_shutdown(); rpc_lsarpc_shutdown(); } /* * we need to force the order of freeing the following, * because smbd_msg_ctx is not a talloc child of smbd_server_conn. */ if (client != NULL) { struct smbXsrv_connection *next; for (; xconn != NULL; xconn = next) { next = xconn->next; DLIST_REMOVE(client->connections, xconn); talloc_free(xconn); DO_PROFILE_INC(disconnect); } TALLOC_FREE(client->sconn); } sconn = NULL; xconn = NULL; client = NULL; netlogon_creds_cli_close_global_db(); TALLOC_FREE(global_smbXsrv_client); smbprofile_dump(); server_messaging_context_free(); server_event_context_free(); TALLOC_FREE(smbd_memcache_ctx); locking_end(); printing_end(); if (how != SERVER_EXIT_NORMAL) { smb_panic(reason); /* Notreached. */ exit(1); } else { DEBUG(3,("Server exit (%s)\n", (reason ? reason : "normal exit"))); if (am_parent) { pidfile_unlink(lp_pid_directory(), "smbd"); } gencache_stabilize(); } exit(0); }
/** * open a database */ struct db_context *db_open(TALLOC_CTX *mem_ctx, const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode, enum dbwrap_lock_order lock_order, uint64_t dbwrap_flags) { struct db_context *result = NULL; const char *sockname; if (!DBWRAP_LOCK_ORDER_VALID(lock_order)) { errno = EINVAL; return NULL; } if (tdb_flags & TDB_CLEAR_IF_FIRST) { const char *base; bool try_readonly = false; base = strrchr_m(name, '/'); if (base != NULL) { base += 1; } else { base = name; } if (dbwrap_flags & DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS) { try_readonly = true; } try_readonly = lp_parm_bool(-1, "dbwrap_optimize_readonly", "*", try_readonly); try_readonly = lp_parm_bool(-1, "dbwrap_optimize_readonly", base, try_readonly); if (try_readonly) { dbwrap_flags |= DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS; } else { dbwrap_flags &= ~DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS; } } if (tdb_flags & TDB_CLEAR_IF_FIRST) { const char *base; bool try_mutex = true; bool require_mutex = false; base = strrchr_m(name, '/'); if (base != NULL) { base += 1; } else { base = name; } try_mutex = lp_parm_bool(-1, "dbwrap_tdb_mutexes", "*", try_mutex); try_mutex = lp_parm_bool(-1, "dbwrap_tdb_mutexes", base, try_mutex); if (!lp_use_mmap()) { /* * Mutexes require mmap. "use mmap = no" can * be a debugging tool, so let it override the * mutex parameters */ try_mutex = false; } if (try_mutex && tdb_runtime_check_for_robust_mutexes()) { tdb_flags |= TDB_MUTEX_LOCKING; } require_mutex = lp_parm_bool(-1, "dbwrap_tdb_require_mutexes", "*", require_mutex); require_mutex = lp_parm_bool(-1, "dbwrap_tdb_require_mutexes", base, require_mutex); if (require_mutex) { tdb_flags |= TDB_MUTEX_LOCKING; } } sockname = lp_ctdbd_socket(); if (lp_clustering()) { const char *partname; if (!socket_exist(sockname)) { DEBUG(1, ("ctdb socket does not exist - is ctdb not " "running?\n")); return NULL; } /* ctdb only wants the file part of the name */ partname = strrchr(name, '/'); if (partname) { partname++; } else { partname = name; } /* allow ctdb for individual databases to be disabled */ if (lp_parm_bool(-1, "ctdb", partname, True)) { struct messaging_context *msg_ctx; struct ctdbd_connection *conn; conn = messaging_ctdb_connection(); if (conn == NULL) { DBG_WARNING("No ctdb connection\n"); errno = EIO; return NULL; } msg_ctx = server_messaging_context(); result = db_open_ctdb(mem_ctx, msg_ctx, partname, hash_size, tdb_flags, open_flags, mode, lock_order, dbwrap_flags); if (result == NULL) { DEBUG(0,("failed to attach to ctdb %s\n", partname)); if (errno == 0) { errno = EIO; } return NULL; } } } if (result == NULL) { struct loadparm_context *lp_ctx = loadparm_init_s3(mem_ctx, loadparm_s3_helpers()); if (hash_size == 0) { hash_size = lpcfg_tdb_hash_size(lp_ctx, name); } tdb_flags = lpcfg_tdb_flags(lp_ctx, tdb_flags); result = dbwrap_local_open( mem_ctx, name, hash_size, tdb_flags, open_flags, mode, lock_order, dbwrap_flags); talloc_unlink(mem_ctx, lp_ctx); } return result; }
static NTSTATUS ep_register(TALLOC_CTX *mem_ctx, const struct ndr_interface_table *iface, const struct dcerpc_binding_vector *bind_vec, const struct GUID *object_guid, const char *annotation, uint32_t replace, uint32_t unregister, struct dcerpc_binding_handle **pbh) { struct rpc_pipe_client *cli = NULL; struct dcerpc_binding_handle *h; struct pipe_auth_data *auth; const char *ncalrpc_sock; const char *rpcsrv_type; struct epm_entry_t *entries; uint32_t num_ents, i; TALLOC_CTX *tmp_ctx; uint32_t result = EPMAPPER_STATUS_OK; NTSTATUS status; if (iface == NULL) { return NT_STATUS_INVALID_PARAMETER; } if (bind_vec == NULL || bind_vec->count == 0) { return NT_STATUS_INVALID_PARAMETER; } tmp_ctx = talloc_stackframe(); if (tmp_ctx == NULL) { return NT_STATUS_NO_MEMORY; } rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM, "rpc_server", "epmapper", "none"); if (strcasecmp_m(rpcsrv_type, "embedded") == 0) { struct tsocket_address *local; int rc; rc = tsocket_address_inet_from_strings(tmp_ctx, "ip", "127.0.0.1", 0, &local); if (rc < 0) { return NT_STATUS_NO_MEMORY; } status = rpcint_binding_handle(tmp_ctx, &ndr_table_epmapper, local, get_session_info_system(), server_messaging_context(), &h); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("dcerpc_ep_register: Could not connect to " "epmapper (%s)", nt_errstr(status))); goto done; } } else if (strcasecmp_m(rpcsrv_type, "daemon") == 0) { /* Connect to the endpoint mapper locally */ ncalrpc_sock = talloc_asprintf(tmp_ctx, "%s/%s", lp_ncalrpc_dir(), "EPMAPPER"); if (ncalrpc_sock == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } status = rpc_pipe_open_ncalrpc(tmp_ctx, ncalrpc_sock, &ndr_table_epmapper.syntax_id, &cli); if (!NT_STATUS_IS_OK(status)) { goto done; } status = rpccli_ncalrpc_bind_data(cli, &auth); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to initialize anonymous bind.\n")); goto done; } status = rpc_pipe_bind(cli, auth); if (!NT_STATUS_IS_OK(status)) { DEBUG(2, ("Failed to bind ncalrpc socket.\n")); goto done; } h = cli->binding_handle; } else { status = NT_STATUS_INVALID_PARAMETER; goto done; } num_ents = bind_vec->count; entries = talloc_array(tmp_ctx, struct epm_entry_t, num_ents); for (i = 0; i < num_ents; i++) { struct dcerpc_binding *map_binding = &bind_vec->bindings[i]; struct epm_twr_t *map_tower; map_tower = talloc_zero(entries, struct epm_twr_t); if (map_tower == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } status = dcerpc_binding_build_tower(entries, map_binding, &map_tower->tower); if (!NT_STATUS_IS_OK(status)) { goto done; } entries[i].tower = map_tower; if (annotation == NULL) { entries[i].annotation = talloc_strdup(entries, ""); } else { entries[i].annotation = talloc_strndup(entries, annotation, EPM_MAX_ANNOTATION_SIZE); } if (entries[i].annotation == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } if (object_guid != NULL) { entries[i].object = *object_guid; } else { entries[i].object = map_binding->object.uuid; } } if (unregister) { status = dcerpc_epm_Delete(h, tmp_ctx, num_ents, entries, &result); } else { status = dcerpc_epm_Insert(h, tmp_ctx, num_ents, entries, replace, &result); } if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("dcerpc_ep_register: Could not insert tower (%s)\n", nt_errstr(status))); goto done; } if (result != EPMAPPER_STATUS_OK) { DEBUG(0, ("dcerpc_ep_register: Could not insert tower (0x%.8x)\n", result)); status = NT_STATUS_UNSUCCESSFUL; goto done; } if (pbh != NULL) { *pbh = talloc_move(mem_ctx, &h); talloc_steal(*pbh, cli); } done: talloc_free(tmp_ctx); return status; }
static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret, const char *domain, const char *dc_name, const struct sockaddr_storage *dc_ss, struct rpc_pipe_client **pipe_ret, TALLOC_CTX *mem_ctx, struct netlogon_creds_cli_context **creds_ret) { TALLOC_CTX *frame = talloc_stackframe(); struct messaging_context *msg_ctx = server_messaging_context(); NTSTATUS result; struct cli_state *cli = NULL; struct rpc_pipe_client *netlogon_pipe = NULL; struct netlogon_creds_cli_context *netlogon_creds = NULL; struct netlogon_creds_CredentialState *creds = NULL; uint32_t netlogon_flags = 0; enum netr_SchannelType sec_chan_type = 0; const char *_account_name = NULL; const char *account_name = NULL; struct samr_Password current_nt_hash; struct samr_Password *previous_nt_hash = NULL; bool ok; *cli_ret = NULL; *pipe_ret = NULL; *creds_ret = NULL; /* TODO: Send a SAMLOGON request to determine whether this is a valid logonserver. We can avoid a 30-second timeout if the DC is down if the SAMLOGON request fails as it is only over UDP. */ /* we use a mutex to prevent two connections at once - when a Win2k PDC get two connections where one hasn't completed a session setup yet it will send a TCP reset to the first connection (tridge) */ /* * With NT4.x DC's *all* authentication must be serialized to avoid * ACCESS_DENIED errors if 2 auths are done from the same machine. JRA. */ mutex = grab_named_mutex(NULL, dc_name, 10); if (mutex == NULL) { TALLOC_FREE(frame); return NT_STATUS_NO_LOGON_SERVERS; } /* Attempt connection */ result = cli_full_connection(&cli, lp_netbios_name(), dc_name, dc_ss, 0, "IPC$", "IPC", "", "", "", 0, SMB_SIGNING_DEFAULT); if (!NT_STATUS_IS_OK(result)) { /* map to something more useful */ if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { result = NT_STATUS_NO_LOGON_SERVERS; } TALLOC_FREE(mutex); TALLOC_FREE(frame); return result; } /* * We now have an anonymous connection to IPC$ on the domain password server. */ ok = get_trust_pw_hash(domain, current_nt_hash.hash, &_account_name, &sec_chan_type); if (!ok) { cli_shutdown(cli); TALLOC_FREE(mutex); TALLOC_FREE(frame); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } account_name = talloc_asprintf(talloc_tos(), "%s$", _account_name); if (account_name == NULL) { cli_shutdown(cli); TALLOC_FREE(mutex); TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } result = rpccli_create_netlogon_creds(dc_name, domain, account_name, sec_chan_type, msg_ctx, talloc_tos(), &netlogon_creds); if (!NT_STATUS_IS_OK(result)) { cli_shutdown(cli); TALLOC_FREE(mutex); TALLOC_FREE(frame); SAFE_FREE(previous_nt_hash); return result; } result = rpccli_setup_netlogon_creds(cli, netlogon_creds, false, /* force_reauth */ current_nt_hash, previous_nt_hash); SAFE_FREE(previous_nt_hash); if (!NT_STATUS_IS_OK(result)) { cli_shutdown(cli); TALLOC_FREE(mutex); TALLOC_FREE(frame); return result; } result = netlogon_creds_cli_get(netlogon_creds, talloc_tos(), &creds); if (!NT_STATUS_IS_OK(result)) { cli_shutdown(cli); TALLOC_FREE(mutex); TALLOC_FREE(frame); return result; } netlogon_flags = creds->negotiate_flags; TALLOC_FREE(creds); if (netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC) { result = cli_rpc_pipe_open_schannel_with_key( cli, &ndr_table_netlogon, NCACN_NP, domain, netlogon_creds, &netlogon_pipe); } else { result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, &netlogon_pipe); } if (!NT_STATUS_IS_OK(result)) { DEBUG(0,("connect_to_domain_password_server: " "unable to open the domain client session to " "machine %s. Flags[0x%08X] Error was : %s.\n", dc_name, (unsigned)netlogon_flags, nt_errstr(result))); cli_shutdown(cli); TALLOC_FREE(mutex); TALLOC_FREE(frame); return result; } if(!netlogon_pipe) { DEBUG(0, ("connect_to_domain_password_server: unable to open " "the domain client session to machine %s. Error " "was : %s.\n", dc_name, nt_errstr(result))); cli_shutdown(cli); TALLOC_FREE(mutex); TALLOC_FREE(frame); return NT_STATUS_NO_LOGON_SERVERS; } /* We exit here with the mutex *locked*. JRA */ *cli_ret = cli; *pipe_ret = netlogon_pipe; *creds_ret = talloc_move(mem_ctx, &netlogon_creds); TALLOC_FREE(frame); return NT_STATUS_OK; }
bool run_dbwrap_do_locked1(int dummy) { struct tevent_context *ev; struct messaging_context *msg; struct db_context *backend; struct db_context *db; const char *dbname = "test_do_locked.tdb"; const char *keystr = "key"; TDB_DATA key = string_term_tdb_data(keystr); const char *valuestr = "value"; TDB_DATA value = string_term_tdb_data(valuestr); struct do_locked1_state state = { .value = value }; int ret = false; NTSTATUS status; ev = server_event_context(); if (ev == NULL) { fprintf(stderr, "server_event_context() failed\n"); return false; } msg = server_messaging_context(); if (msg == NULL) { fprintf(stderr, "server_messaging_context() failed\n"); return false; } backend = db_open(talloc_tos(), dbname, 0, TDB_CLEAR_IF_FIRST, O_CREAT|O_RDWR, 0644, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (backend == NULL) { fprintf(stderr, "db_open failed: %s\n", strerror(errno)); return false; } db = db_open_watched(talloc_tos(), backend, msg); if (db == NULL) { fprintf(stderr, "db_open_watched failed: %s\n", strerror(errno)); return false; } status = dbwrap_do_locked(db, key, do_locked1_cb, &state); if (!NT_STATUS_IS_OK(status)) { fprintf(stderr, "dbwrap_do_locked failed: %s\n", nt_errstr(status)); goto fail; } if (!NT_STATUS_IS_OK(state.status)) { fprintf(stderr, "store returned %s\n", nt_errstr(state.status)); goto fail; } status = dbwrap_parse_record(db, key, do_locked1_check, &state); if (!NT_STATUS_IS_OK(status)) { fprintf(stderr, "dbwrap_parse_record failed: %s\n", nt_errstr(status)); goto fail; } if (!NT_STATUS_IS_OK(state.status)) { fprintf(stderr, "data compare returned %s\n", nt_errstr(status)); goto fail; } status = dbwrap_do_locked(db, key, do_locked1_del, &state); if (!NT_STATUS_IS_OK(status)) { fprintf(stderr, "dbwrap_do_locked failed: %s\n", nt_errstr(status)); goto fail; } if (!NT_STATUS_IS_OK(state.status)) { fprintf(stderr, "delete returned %s\n", nt_errstr(status)); goto fail; } status = dbwrap_parse_record(db, key, do_locked1_check, &state); if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { fprintf(stderr, "parse_record returned %s, " "expected NOT_FOUND\n", nt_errstr(status)); goto fail; } ret = true; fail: TALLOC_FREE(db); unlink(dbname); return ret; }
static bool spoolss_child_init(struct tevent_context *ev_ctx, int child_id, struct pf_worker_data *pf) { NTSTATUS status; struct rpc_srv_callbacks spoolss_cb; struct messaging_context *msg_ctx = server_messaging_context(); bool ok; status = reinit_after_fork(msg_ctx, ev_ctx, true, "spoolssd-child"); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("reinit_after_fork() failed\n")); smb_panic("reinit_after_fork() failed"); } spoolss_child_id = child_id; spoolss_reopen_logs(child_id); ok = spoolss_setup_chld_hup_handler(ev_ctx, msg_ctx, pf); if (!ok) { return false; } if (!serverid_register(messaging_server_id(msg_ctx), FLAG_MSG_GENERAL | FLAG_MSG_PRINT_GENERAL)) { return false; } if (!locking_init()) { return false; } messaging_register(msg_ctx, ev_ctx, MSG_SMB_CONF_UPDATED, smb_conf_updated); messaging_register(msg_ctx, ev_ctx, MSG_PREFORK_PARENT_EVENT, parent_ping); /* As soon as messaging is up check if pcap has been loaded already. * If so then we probably missed a message and should load_printers() * ourselves. If pcap has not been loaded yet, then ignore, we will get * a message as soon as the bq process completes the reload. */ if (pcap_cache_loaded(NULL)) { load_printers(ev_ctx, msg_ctx); } /* try to reinit rpc queues */ spoolss_cb.init = spoolss_init_cb; spoolss_cb.shutdown = spoolss_shutdown_cb; spoolss_cb.private_data = msg_ctx; status = rpc_winreg_init(NULL); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to register winreg rpc interface! (%s)\n", nt_errstr(status))); return false; } status = rpc_spoolss_init(&spoolss_cb); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to register spoolss rpc interface! (%s)\n", nt_errstr(status))); return false; } return true; }