const char *get_global_sam_name(void) { if ((lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC)) { return lp_workgroup(); } return global_myname(); }
enum netr_SchannelType get_default_sec_channel(void) { if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) { return SEC_CHAN_BDC; } else { return SEC_CHAN_WKSTA; } }
NTSTATUS make_auth3_context_for_ntlm(TALLOC_CTX *mem_ctx, struct auth_context **auth_context) { const char *methods = NULL; NTSTATUS nt_status; switch (lp_server_role()) { case ROLE_ACTIVE_DIRECTORY_DC: DEBUG(5,("Making default auth method list for server role = " "'active directory domain controller'\n")); return make_auth_context_specific(mem_ctx, auth_context, "samba4"); default: break; } if (lp_auth_methods()) { DEBUG(5,("Using specified auth order\n")); nt_status = make_auth_context_text_list( mem_ctx, auth_context, discard_const_p(char *, lp_auth_methods())); return nt_status; } switch (lp_server_role()) { case ROLE_DOMAIN_MEMBER: DEBUG(5,("Making default auth method list for server role = 'domain member'\n")); methods = "guest sam winbind:ntdomain sam_ignoredomain"; break; case ROLE_DOMAIN_BDC: case ROLE_DOMAIN_PDC: DEBUG(5,("Making default auth method list for DC\n")); methods = "guest sam winbind:trustdomain sam_ignoredomain"; break; case ROLE_STANDALONE: DEBUG(5,("Making default auth method list for server role = 'standalone server', encrypt passwords = yes\n")); if (lp_encrypt_passwords()) { methods = "guest sam_ignoredomain"; } else { DEBUG(5,("Making default auth method list for server role = 'standalone server', encrypt passwords = no\n")); methods = "guest unix"; } break; default: DEBUG(5,("Unknown auth method!\n")); return NT_STATUS_UNSUCCESSFUL; } return make_auth_context_specific(mem_ctx, auth_context, methods); }
NTSTATUS auth_ntlmssp_start(AUTH_NTLMSSP_STATE **auth_ntlmssp_state) { NTSTATUS nt_status; TALLOC_CTX *mem_ctx; mem_ctx = talloc_init("AUTH NTLMSSP context"); *auth_ntlmssp_state = TALLOC_ZERO_P(mem_ctx, AUTH_NTLMSSP_STATE); if (!*auth_ntlmssp_state) { DEBUG(0,("auth_ntlmssp_start: talloc failed!\n")); talloc_destroy(mem_ctx); return NT_STATUS_NO_MEMORY; } ZERO_STRUCTP(*auth_ntlmssp_state); (*auth_ntlmssp_state)->mem_ctx = mem_ctx; if (!NT_STATUS_IS_OK(nt_status = ntlmssp_server_start(&(*auth_ntlmssp_state)->ntlmssp_state))) { return nt_status; } if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&(*auth_ntlmssp_state)->auth_context))) { return nt_status; } (*auth_ntlmssp_state)->ntlmssp_state->auth_context = (*auth_ntlmssp_state); (*auth_ntlmssp_state)->ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge; (*auth_ntlmssp_state)->ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge; (*auth_ntlmssp_state)->ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge; (*auth_ntlmssp_state)->ntlmssp_state->check_password = auth_ntlmssp_check_password; (*auth_ntlmssp_state)->ntlmssp_state->server_role = (enum server_types)lp_server_role(); return NT_STATUS_OK; }
NTSTATUS _net_logon_ctrl2(pipes_struct *p, NET_Q_LOGON_CTRL2 *q_u, NET_R_LOGON_CTRL2 *r_u) { uint32 flags = 0x0; uint32 pdc_connection_status = 0x0; uint32 logon_attempts = 0x0; uint32 tc_status = ERROR_NO_LOGON_SERVERS; const char *trusted_domain = "test_domain"; DEBUG(0, ("*** net long ctrl2 %d, %d, %d\n", q_u->function_code, q_u->query_level, q_u->switch_value)); DEBUG(6,("_net_logon_ctrl2: %d\n", __LINE__)); /* set up the Logon Control2 response */ init_net_r_logon_ctrl2(r_u, q_u->query_level, flags, pdc_connection_status, logon_attempts, tc_status, trusted_domain); if (lp_server_role() == ROLE_DOMAIN_BDC) send_sync_message(); DEBUG(6,("_net_logon_ctrl2: %d\n", __LINE__)); return r_u->status; }
static int prod_options_fetch_values(const char *key, REGVAL_CTR *regvals) { const char *value_ascii = ""; fstring value; int value_length; switch (lp_server_role()) { case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: value_ascii = "LanmanNT"; break; case ROLE_STANDALONE: value_ascii = "ServerNT"; break; case ROLE_DOMAIN_MEMBER: value_ascii = "WinNT"; break; } value_length = push_ucs2(value, value, value_ascii, sizeof(value), STR_TERMINATE|STR_NOALIGN ); regval_ctr_addvalue(regvals, "ProductType", REG_SZ, value, value_length); return regval_ctr_numvals( regvals ); }
BOOL secrets_fetch_domain_guid(const char *domain, GUID *guid) { GUID *dyn_guid; fstring key; size_t size; GUID new_guid; slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain); strupper_m(key); dyn_guid = (GUID *)secrets_fetch(key, &size); DEBUG(6,("key is %s, size is %d\n", key, (int)size)); if ((NULL == dyn_guid) && (ROLE_DOMAIN_PDC == lp_server_role())) { smb_uuid_generate_random(&new_guid); if (!secrets_store_domain_guid(domain, &new_guid)) return False; dyn_guid = (GUID *)secrets_fetch(key, &size); if (dyn_guid == NULL) return False; } if (size != sizeof(GUID)) { SAFE_FREE(dyn_guid); return False; } *guid = *dyn_guid; SAFE_FREE(dyn_guid); return True; }
NTSTATUS make_auth3_context_for_netlogon(TALLOC_CTX *mem_ctx, struct auth_context **auth_context) { const char *methods = NULL; NTSTATUS nt_status; /* * We do the lp_auth_methods check before * the lp_server_role check in order to * backward compatible. The "auth methods" option * is deprecated now, so this will go away in a future * release. */ if (lp_auth_methods()) { DBG_INFO("Using specified auth order for netlogon\n"); nt_status = make_auth_context_text_list( mem_ctx, auth_context, discard_const_p(char *, lp_auth_methods())); return nt_status; } switch (lp_server_role()) { case ROLE_DOMAIN_BDC: case ROLE_DOMAIN_PDC: methods = "sam_netlogon3 winbind:trustdomain"; break; default: DBG_ERR("Invalid server role!\n"); return NT_STATUS_INVALID_SERVER_STATE; } return make_auth_context_specific(mem_ctx, auth_context, methods); }
bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid) { struct GUID *dyn_guid; fstring key; size_t size = 0; struct GUID new_guid; slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain); strupper_m(key); dyn_guid = (struct GUID *)secrets_fetch(key, &size); if (!dyn_guid) { if (lp_server_role() == ROLE_DOMAIN_PDC) { smb_uuid_generate_random(&new_guid); if (!secrets_store_domain_guid(domain, &new_guid)) return False; dyn_guid = (struct GUID *)secrets_fetch(key, &size); } if (dyn_guid == NULL) { return False; } } if (size != sizeof(struct GUID)) { DEBUG(1,("UUID size %d is wrong!\n", (int)size)); SAFE_FREE(dyn_guid); return False; } *guid = *dyn_guid; SAFE_FREE(dyn_guid); return True; }
WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx, struct NetGetJoinInformation *r) { if ((lp_security() == SEC_ADS) && lp_realm()) { *r->out.name_buffer = talloc_strdup(ctx, lp_realm()); } else { *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup()); } if (!*r->out.name_buffer) { return WERR_NOMEM; } switch (lp_server_role()) { case ROLE_DOMAIN_MEMBER: case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: *r->out.name_type = NetSetupDomainName; break; case ROLE_STANDALONE: default: *r->out.name_type = NetSetupWorkgroupName; break; } return WERR_OK; }
BOOL lookup_name(const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) { extern pstring global_myname; extern fstring global_myworkgroup; fstring sid; char *sep = lp_winbind_separator(); *name_type = SID_NAME_UNKNOWN; if (!winbind_lookup_name(NULL, name, psid, name_type) || (*name_type != SID_NAME_USER) ) { BOOL ret = False; DEBUG(10, ("lookup_name: winbind lookup for %s failed - trying local\n", name)); /* If we are looking up a domain user, make sure it is for the local machine only */ if (strchr(name, sep[0]) || strchr(name, '\\')) { fstring domain, username; split_domain_name(name, domain, username); switch (lp_server_role()) { case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: if (strequal(domain, global_myworkgroup)) { fstrcpy(domain, global_myname); ret = local_lookup_name(domain, username, psid, name_type); } /* No break is deliberate here. JRA. */ default: if (strcasecmp(global_myname, domain) != 0) { DEBUG(5, ("lookup_name: domain %s is not local\n", domain)); ret = local_lookup_name(global_myname, username, psid, name_type); } } } else { ret = local_lookup_name(global_myname, name, psid, name_type); } if (ret) { DEBUG(10, ("lookup_name: (local) %s -> SID %s (type %u)\n", name, sid_to_string(sid,psid), (unsigned int)*name_type )); } else { DEBUG(10,("lookup name: (local) %s failed.\n", name)); } return ret; } DEBUG(10,("lookup_name (winbindd): %s -> SID %s (type %u)\n", name, sid_to_string(sid, psid), (unsigned int)*name_type)); return True; }
static NTSTATUS auth_samstrict_auth(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **server_info) { bool is_local_name, is_my_domain; if (!user_info || !auth_context) { return NT_STATUS_LOGON_FAILURE; } DEBUG(10, ("Check auth for: [%s]\n", user_info->mapped.account_name)); is_local_name = is_myname(user_info->mapped.domain_name); is_my_domain = strequal(user_info->mapped.domain_name, lp_workgroup()); /* check whether or not we service this domain/workgroup name */ switch ( lp_server_role() ) { case ROLE_STANDALONE: case ROLE_DOMAIN_MEMBER: if ( !is_local_name ) { DEBUG(6,("check_samstrict_security: %s is not one of my local names (%s)\n", user_info->mapped.domain_name, (lp_server_role() == ROLE_DOMAIN_MEMBER ? "ROLE_DOMAIN_MEMBER" : "ROLE_STANDALONE") )); return NT_STATUS_NOT_IMPLEMENTED; } case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: if ( !is_local_name && !is_my_domain ) { DEBUG(6,("check_samstrict_security: %s is not one of my local names or domain name (DC)\n", user_info->mapped.domain_name)); return NT_STATUS_NOT_IMPLEMENTED; } default: /* name is ok */ break; } return check_sam_security(&auth_context->challenge, mem_ctx, user_info, server_info); }
static BOOL is_our_primary_domain(const char *domain) { int role = lp_server_role(); if ((role == ROLE_DOMAIN_MEMBER) && strequal(lp_workgroup(), domain)) { return True; } else if (strequal(get_global_sam_name(), domain)) { return True; } return False; }
static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; const char *domain = lp_workgroup(); fstring dc_name; struct sockaddr_storage dc_ss; if ( lp_server_role() != ROLE_DOMAIN_MEMBER ) { DEBUG(0,("check_ntdomain_security: Configuration error! Cannot use " "ntdomain auth method when not a member of a domain.\n")); return NT_STATUS_NOT_IMPLEMENTED; } if (!user_info || !server_info || !auth_context) { DEBUG(1,("check_ntdomain_security: Critical variables not present. Failing.\n")); return NT_STATUS_INVALID_PARAMETER; } DEBUG(10, ("Check auth for: [%s]\n", user_info->mapped.account_name)); /* * Check that the requested domain is not our own machine name. * If it is, we should never check the PDC here, we use our own local * password file. */ if(strequal(get_global_sam_name(), user_info->mapped.domain_name)) { DEBUG(3,("check_ntdomain_security: Requested domain was for this machine.\n")); return NT_STATUS_NOT_IMPLEMENTED; } /* we need our DC to send the net_sam_logon() request to */ if ( !get_dc_name(domain, NULL, dc_name, &dc_ss) ) { DEBUG(5,("check_ntdomain_security: unable to locate a DC for domain %s\n", user_info->mapped.domain_name)); return NT_STATUS_NO_LOGON_SERVERS; } nt_status = domain_client_validate(mem_ctx, user_info, domain, (uchar *)auth_context->challenge.data, server_info, dc_name, &dc_ss); return nt_status; }
bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid) { struct GUID *dyn_guid; fstring key; size_t size = 0; struct GUID new_guid; #if _SAMBA_BUILD_ == 4 if (strequal(domain, get_global_sam_name()) && (pdb_capabilities() & PDB_CAP_ADS)) { struct pdb_domain_info *domain_info; domain_info = pdb_get_domain_info(talloc_tos()); if (!domain_info) { /* If we have a ADS-capable passdb backend, we * must never make up our own SID, it will * already be in the directory */ DEBUG(0, ("Unable to fetch a Domain GUID from the directory!\n")); return false; } *guid = domain_info->guid; return true; } #endif slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain); strupper_m(key); dyn_guid = (struct GUID *)secrets_fetch(key, &size); if (!dyn_guid) { if (lp_server_role() == ROLE_DOMAIN_PDC) { new_guid = GUID_random(); if (!secrets_store_domain_guid(domain, &new_guid)) return False; dyn_guid = (struct GUID *)secrets_fetch(key, &size); } if (dyn_guid == NULL) { return False; } } if (size != sizeof(struct GUID)) { DEBUG(1,("UUID size %d is wrong!\n", (int)size)); SAFE_FREE(dyn_guid); return False; } *guid = *dyn_guid; SAFE_FREE(dyn_guid); return True; }
static int count_fns(void) { int funcs = sizeof(api_lsa_cmds) / sizeof(struct api_struct); /* * NOTE: Certain calls can not be enabled if we aren't an ADS DC. Make sure * these calls are always last and that you decrement by the amount of calls * to disable. */ if (!(SEC_ADS == lp_security() && ROLE_DOMAIN_PDC == lp_server_role())) { funcs -= 1; } return funcs; }
/** * Iterator for winbindd's domain list. * To be used (e.g.) in tevent based loops. */ struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain) { if (domain == NULL) { domain = domain_list(); } else { domain = domain->next; } if ((domain != NULL) && (lp_server_role() != ROLE_ACTIVE_DIRECTORY_DC) && sid_check_is_our_sam(&domain->sid)) { domain = domain->next; } return domain; }
NTSTATUS create_builtin_administrators(const struct dom_sid *dom_sid) { NTSTATUS status; struct dom_sid dom_admins, root_sid; fstring root_name; enum lsa_SidType type; TALLOC_CTX *ctx; bool ret; status = create_builtin(BUILTIN_RID_ADMINISTRATORS); if ( !NT_STATUS_IS_OK(status) ) { DEBUG(5,("create_builtin_administrators: Failed to create Administrators\n")); return status; } /* add domain admins */ if ((IS_DC || (lp_server_role() == ROLE_DOMAIN_MEMBER)) && sid_compose(&dom_admins, dom_sid, DOMAIN_RID_ADMINS)) { status = add_sid_to_builtin(&global_sid_Builtin_Administrators, &dom_admins); if (!NT_STATUS_IS_OK(status)) { return status; } } /* add root */ if ( (ctx = talloc_init("create_builtin_administrators")) == NULL ) { return NT_STATUS_NO_MEMORY; } fstr_sprintf( root_name, "%s\\root", get_global_sam_name() ); ret = lookup_name(ctx, root_name, LOOKUP_NAME_DOMAIN, NULL, NULL, &root_sid, &type); TALLOC_FREE( ctx ); if ( ret ) { status = add_sid_to_builtin(&global_sid_Builtin_Administrators, &root_sid); } return status; }
/* module initialisation */ static NTSTATUS auth_init_sam(struct auth_context *auth_context, const char *param, auth_methods **auth_method) { struct auth_methods *result; if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC && !lp_parm_bool(-1, "server role check", "inhibit", false)) { DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the auth_sam module. \n")); DEBUGADD(0, ("You should not set 'auth methods' when running the AD DC.\n")); exit(1); } result = talloc_zero(auth_context, struct auth_methods); if (result == NULL) { return NT_STATUS_NO_MEMORY; } result->auth = auth_samstrict_auth; result->name = "sam"; *auth_method = result; return NT_STATUS_OK; }
static int prod_options_fetch_values(const char *key, struct regval_ctr *regvals) { const char *value_ascii = ""; switch (lp_server_role()) { case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: value_ascii = "LanmanNT"; break; case ROLE_STANDALONE: value_ascii = "ServerNT"; break; case ROLE_DOMAIN_MEMBER: value_ascii = "WinNT"; break; } regval_ctr_addvalue_sz(regvals, "ProductType", value_ascii); return regval_ctr_numvals( regvals ); }
NTSTATUS create_builtin_users(const struct dom_sid *dom_sid) { NTSTATUS status; struct dom_sid dom_users; status = create_builtin(BUILTIN_RID_USERS); if ( !NT_STATUS_IS_OK(status) ) { DEBUG(5,("create_builtin_users: Failed to create Users\n")); return status; } /* add domain users */ if ((IS_DC || (lp_server_role() == ROLE_DOMAIN_MEMBER)) && sid_compose(&dom_users, dom_sid, DOMAIN_RID_USERS)) { status = add_sid_to_builtin(&global_sid_Builtin_Users, &dom_users); } return status; }
/**************************************************************************** Check SAM security (above) but with a few extra checks. ****************************************************************************/ static NTSTATUS authsam_want_check(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info) { bool is_local_name, is_my_domain; if (!user_info->mapped.account_name || !*user_info->mapped.account_name) { return NT_STATUS_NOT_IMPLEMENTED; } is_local_name = lp_is_myname(ctx->auth_ctx->lp_ctx, user_info->mapped.domain_name); is_my_domain = lp_is_mydomain(ctx->auth_ctx->lp_ctx, user_info->mapped.domain_name); /* check whether or not we service this domain/workgroup name */ switch (lp_server_role(ctx->auth_ctx->lp_ctx)) { case ROLE_STANDALONE: return NT_STATUS_OK; case ROLE_DOMAIN_MEMBER: if (!is_local_name) { DEBUG(6,("authsam_check_password: %s is not one of my local names (DOMAIN_MEMBER)\n", user_info->mapped.domain_name)); return NT_STATUS_NOT_IMPLEMENTED; } return NT_STATUS_OK; case ROLE_DOMAIN_CONTROLLER: if (!is_local_name && !is_my_domain) { DEBUG(6,("authsam_check_password: %s is not one of my local names or domain name (DC)\n", user_info->mapped.domain_name)); return NT_STATUS_NOT_IMPLEMENTED; } return NT_STATUS_OK; } DEBUG(6,("authsam_check_password: lp_server_role() has an undefined value\n")); return NT_STATUS_NOT_IMPLEMENTED; }
NTSTATUS make_auth3_context_for_winbind(TALLOC_CTX *mem_ctx, struct auth_context **auth_context) { const char *methods = NULL; switch (lp_server_role()) { case ROLE_STANDALONE: case ROLE_DOMAIN_MEMBER: case ROLE_DOMAIN_BDC: case ROLE_DOMAIN_PDC: methods = "sam"; break; case ROLE_ACTIVE_DIRECTORY_DC: methods = "samba4:sam"; break; default: DEBUG(5,("Unknown auth method!\n")); return NT_STATUS_UNSUCCESSFUL; } return make_auth_context_specific(mem_ctx, auth_context, methods); }
int main(int argc, const char *argv[]) { bool is_daemon = false; bool opt_interactive = false; bool Fork = true; bool no_process_group = false; bool log_stdout = false; poptContext pc; char *p_lmhosts = NULL; int opt; struct messaging_context *msg; 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" }, {"hosts", 'H', POPT_ARG_STRING, &p_lmhosts, 0, "Load a netbios hosts file"}, {"port", 'p', POPT_ARG_INT, &global_nmb_port, 0, "Listen on the specified port" }, POPT_COMMON_SAMBA POPT_COMMON_DYNCONFIG POPT_TABLEEND }; TALLOC_CTX *frame; NTSTATUS status; bool ok; /* * Do this before any other talloc operation */ talloc_enable_null_tracking(); frame = talloc_stackframe(); /* * We want total control over the permissions on created files, * so set our umask to 0. */ umask(0); setup_logging(argv[0], DEBUG_DEFAULT_STDOUT); load_case_tables(); global_nmb_port = NMB_PORT; pc = poptGetContext("nmbd", argc, argv, long_options, 0); while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_DAEMON: is_daemon = true; break; case OPT_INTERACTIVE: opt_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; default: d_fprintf(stderr, "\nInvalid option %s: %s\n\n", poptBadOption(pc, 0), poptStrerror(opt)); poptPrintUsage(pc, stderr, 0); exit(1); } }; poptFreeContext(pc); global_in_nmbd = true; StartupTime = time(NULL); sys_srandom(time(NULL) ^ getpid()); if (!override_logfile) { char *lfile = NULL; if (asprintf(&lfile, "%s/log.nmbd", get_dyn_LOGFILEBASE()) < 0) { exit(1); } lp_set_logfile(lfile); SAFE_FREE(lfile); } fault_setup(); dump_core_setup("nmbd", lp_logfile(talloc_tos())); /* POSIX demands that signals are inherited. If the invoking process has * these signals masked, we will have problems, as we won't receive them. */ BlockSignals(False, SIGHUP); BlockSignals(False, SIGUSR1); BlockSignals(False, SIGTERM); #if defined(SIGFPE) /* we are never interested in SIGFPE */ BlockSignals(True,SIGFPE); #endif /* We no longer use USR2... */ #if defined(SIGUSR2) BlockSignals(True, SIGUSR2); #endif /* Ignore children - no zombies. */ CatchChild(); if ( opt_interactive ) { Fork = False; log_stdout = True; } 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); } if (log_stdout) { setup_logging(argv[0], DEBUG_STDOUT); } else { setup_logging( argv[0], DEBUG_FILE); } reopen_logs(); DEBUG(0,("nmbd version %s started.\n", samba_version_string())); DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE)); if (!lp_load_initial_only(get_dyn_CONFIGFILE())) { DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE())); exit(1); } reopen_logs(); if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC && !lp_parm_bool(-1, "server role check", "inhibit", false)) { /* TODO: when we have a merged set of defaults for * loadparm, we could possibly check if the internal * nbt server is in the list, and allow a startup if disabled */ DEBUG(0, ("server role = 'active directory domain controller' not compatible with running nmbd standalone. \n")); DEBUGADD(0, ("You should start 'samba' instead, and it will control starting the internal nbt server\n")); exit(1); } msg = messaging_init(NULL, server_event_context()); if (msg == NULL) { return 1; } if ( !reload_nmbd_services(False) ) return(-1); if(!init_names()) return -1; reload_nmbd_services( True ); if (strequal(lp_workgroup(),"*")) { DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n")); exit(1); } set_samba_nb_type(); if (!is_daemon && !is_a_socket(0)) { DEBUG(0,("standard input is not a socket, assuming -D option\n")); is_daemon = True; } if (is_daemon && !opt_interactive) { DEBUG( 2, ( "Becoming a daemon.\n" ) ); become_daemon(Fork, no_process_group, log_stdout); } #if HAVE_SETPGID /* * If we're interactive we want to set our own process group for * signal management. */ if (opt_interactive && !no_process_group) setpgid( (pid_t)0, (pid_t)0 ); #endif #ifndef SYNC_DNS /* Setup the async dns. We do it here so it doesn't have all the other stuff initialised and thus chewing memory and sockets */ if(lp_we_are_a_wins_server() && lp_wins_dns_proxy()) { start_async_dns(msg); } #endif ok = directory_create_or_exist(lp_lockdir(), geteuid(), 0755); if (!ok) { exit_daemon("Failed to create directory for lock files, check 'lock directory'", errno); } ok = directory_create_or_exist(lp_piddir(), geteuid(), 0755); if (!ok) { exit_daemon("Failed to create directory for pid files, check 'pid directory'", errno); } pidfile_create(lp_piddir(), "nmbd"); status = reinit_after_fork(msg, nmbd_event_context(), false); if (!NT_STATUS_IS_OK(status)) { exit_daemon("reinit_after_fork() failed", map_errno_from_nt_status(status)); } /* * Do not initialize the parent-child-pipe before becoming * a daemon: this is used to detect a died parent in the child * process. */ status = init_before_fork(); if (!NT_STATUS_IS_OK(status)) { exit_daemon(nt_errstr(status), map_errno_from_nt_status(status)); } if (!nmbd_setup_sig_term_handler(msg)) exit_daemon("NMBD failed to setup signal handler", EINVAL); if (!nmbd_setup_stdin_handler(msg, !Fork)) exit_daemon("NMBD failed to setup stdin handler", EINVAL); if (!nmbd_setup_sig_hup_handler(msg)) exit_daemon("NMBD failed to setup SIGHUP handler", EINVAL); /* get broadcast messages */ if (!serverid_register(messaging_server_id(msg), FLAG_MSG_GENERAL | FLAG_MSG_NMBD | FLAG_MSG_DBWRAP)) { exit_daemon("Could not register NMBD process in serverid.tdb", EACCES); } messaging_register(msg, NULL, MSG_FORCE_ELECTION, nmbd_message_election); #if 0 /* Until winsrepl is done. */ messaging_register(msg, NULL, MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry); #endif messaging_register(msg, NULL, MSG_SHUTDOWN, nmbd_terminate); messaging_register(msg, NULL, MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services); messaging_register(msg, NULL, MSG_SEND_PACKET, msg_nmbd_send_packet); TimeInit(); DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) ); if ( !open_sockets( is_daemon, global_nmb_port ) ) { kill_async_dns_child(); return 1; } /* Determine all the IP addresses we have. */ load_interfaces(); /* Create an nmbd subnet record for each of the above. */ if( False == create_subnets() ) { kill_async_dns_child(); exit_daemon("NMBD failed when creating subnet lists", EACCES); } /* Load in any static local names. */ if (p_lmhosts) { set_dyn_LMHOSTSFILE(p_lmhosts); } load_lmhosts_file(get_dyn_LMHOSTSFILE()); DEBUG(3,("Loaded hosts file %s\n", get_dyn_LMHOSTSFILE())); /* If we are acting as a WINS server, initialise data structures. */ if( !initialise_wins() ) { kill_async_dns_child(); exit_daemon( "NMBD failed when initialising WINS server.", EACCES); } /* * Register nmbd primary workgroup and nmbd names on all * the broadcast subnets, and on the WINS server (if specified). * Also initiate the startup of our primary workgroup (start * elections if we are setup as being able to be a local * master browser. */ if( False == register_my_workgroup_and_names() ) { kill_async_dns_child(); exit_daemon( "NMBD failed when creating my workgroup.", EACCES); } if (!initialize_nmbd_proxy_logon()) { kill_async_dns_child(); exit_daemon( "NMBD failed to setup nmbd_proxy_logon.", EACCES); } if (!nmbd_init_packet_server()) { kill_async_dns_child(); exit_daemon( "NMBD failed to setup packet server.", EACCES); } if (is_daemon && !opt_interactive) { daemon_ready("nmbd"); } TALLOC_FREE(frame); process(msg); kill_async_dns_child(); return(0); }
NTSTATUS make_auth_context_subsystem(TALLOC_CTX *mem_ctx, struct auth_context **auth_context) { char **auth_method_list = NULL; NTSTATUS nt_status; if (lp_auth_methods() && !(auth_method_list = str_list_copy(talloc_tos(), lp_auth_methods()))) { return NT_STATUS_NO_MEMORY; } if (auth_method_list == NULL) { switch (lp_security()) { case SEC_DOMAIN: DEBUG(5,("Making default auth method list for security=domain\n")); auth_method_list = str_list_make_v3( talloc_tos(), "guest sam winbind:ntdomain", NULL); break; case SEC_SERVER: DEBUG(5,("Making default auth method list for security=server\n")); auth_method_list = str_list_make_v3( talloc_tos(), "guest sam smbserver", NULL); break; case SEC_USER: if (lp_encrypted_passwords()) { if ((lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC)) { DEBUG(5,("Making default auth method list for DC, security=user, encrypt passwords = yes\n")); auth_method_list = str_list_make_v3( talloc_tos(), "guest sam winbind:trustdomain", NULL); } else { DEBUG(5,("Making default auth method list for standalone security=user, encrypt passwords = yes\n")); auth_method_list = str_list_make_v3( talloc_tos(), "guest sam", NULL); } } else { DEBUG(5,("Making default auth method list for security=user, encrypt passwords = no\n")); auth_method_list = str_list_make_v3( talloc_tos(), "guest unix", NULL); } break; case SEC_ADS: DEBUG(5,("Making default auth method list for security=ADS\n")); auth_method_list = str_list_make_v3( talloc_tos(), "guest sam winbind:ntdomain", NULL); break; default: DEBUG(5,("Unknown auth method!\n")); return NT_STATUS_UNSUCCESSFUL; } } else { DEBUG(5,("Using specified auth order\n")); } nt_status = make_auth_context_text_list(mem_ctx, auth_context, auth_method_list); TALLOC_FREE(auth_method_list); return nt_status; }
static NTSTATUS _idmap_adex_init(struct idmap_domain *dom) { ADS_STRUCT *ads = NULL; ADS_STATUS status; static NTSTATUS init_status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; struct dom_sid domain_sid; fstring dcname; struct sockaddr_storage ip; struct likewise_cell *lwcell; if (NT_STATUS_IS_OK(init_status)) return NT_STATUS_OK; /* Silently fail if we are not a member server in security = ads */ if ((lp_server_role() != ROLE_DOMAIN_MEMBER) || (lp_security() != SEC_ADS)) { init_status = NT_STATUS_INVALID_SERVER_STATE; BAIL_ON_NTSTATUS_ERROR(init_status); } /* fetch our domain SID first */ if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) { init_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; BAIL_ON_NTSTATUS_ERROR(init_status); } /* reuse the same ticket cache as winbindd */ setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1); /* Establish a connection to a DC */ if ((ads = ads_init(lp_realm(), lp_workgroup(), NULL)) == NULL) { init_status = NT_STATUS_NO_MEMORY; BAIL_ON_NTSTATUS_ERROR(init_status); } ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); ads->auth.realm = SMB_STRDUP(lp_realm()); /* get the DC name here to setup the server affinity cache and local krb5.conf */ get_dc_name(lp_workgroup(), lp_realm(), dcname, &ip); status = ads_connect(ads); if (!ADS_ERR_OK(status)) { DEBUG(0, ("_idmap_adex_init: ads_connect() failed! (%s)\n", ads_errstr(status))); } init_status = ads_ntstatus(status); BAIL_ON_NTSTATUS_ERROR(init_status); /* Find out cell membership */ init_status = cell_locate_membership(ads); if (!NT_STATUS_IS_OK(init_status)) { DEBUG(0,("LWI: Fail to locate cell membership (%s).", nt_errstr(init_status))); goto done; } /* Fill in the cell information */ lwcell = cell_list_head(); init_status = cell_lookup_settings(lwcell); BAIL_ON_NTSTATUS_ERROR(init_status); /* Miscellaneous setup. E.g. set up the list of GC servers and domain list for our forest (does not actually connect). */ init_status = gc_init_list(); BAIL_ON_NTSTATUS_ERROR(init_status); init_status = domain_init_list(); BAIL_ON_NTSTATUS_ERROR(init_status); done: if (!NT_STATUS_IS_OK(init_status)) { DEBUG(1,("Likewise initialization failed (%s)\n", nt_errstr(init_status))); } /* cleanup */ if (!NT_STATUS_IS_OK(init_status)) { cell_list_destroy(); /* init_status stores the failure reason but we need to return success or else idmap_init() will drop us from the backend list */ return NT_STATUS_OK; } init_status = NT_STATUS_OK; return init_status; }
NTSTATUS create_local_token(struct auth_serversupplied_info *server_info) { struct security_token *t; NTSTATUS status; size_t i; struct dom_sid tmp_sid; struct wbcUnixId *ids; /* * If winbind is not around, we can not make much use of the SIDs the * domain controller provided us with. Likewise if the user name was * mapped to some local unix user. */ if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) || (server_info->nss_token)) { status = create_token_from_username(server_info, server_info->unix_name, server_info->guest, &server_info->utok.uid, &server_info->utok.gid, &server_info->unix_name, &server_info->security_token); } else { status = create_local_nt_token_from_info3(server_info, server_info->guest, server_info->info3, &server_info->extra, &server_info->security_token); } if (!NT_STATUS_IS_OK(status)) { return status; } /* Convert the SIDs to gids. */ server_info->utok.ngroups = 0; server_info->utok.groups = NULL; t = server_info->security_token; ids = TALLOC_ARRAY(talloc_tos(), struct wbcUnixId, t->num_sids); if (ids == NULL) { return NT_STATUS_NO_MEMORY; } if (!sids_to_unix_ids(t->sids, t->num_sids, ids)) { TALLOC_FREE(ids); return NT_STATUS_NO_MEMORY; } /* Start at index 1, where the groups start. */ for (i=1; i<t->num_sids; i++) { if (ids[i].type != WBC_ID_TYPE_GID) { DEBUG(10, ("Could not convert SID %s to gid, " "ignoring it\n", sid_string_dbg(&t->sids[i]))); continue; } if (!add_gid_to_array_unique(server_info, ids[i].id.gid, &server_info->utok.groups, &server_info->utok.ngroups)) { return NT_STATUS_NO_MEMORY; } } /* * Add the "Unix Group" SID for each gid to catch mapped groups * and their Unix equivalent. This is to solve the backwards * compatibility problem of 'valid users = +ntadmin' where * ntadmin has been paired with "Domain Admins" in the group * mapping table. Otherwise smb.conf would need to be changed * to 'valid user = "******"'. --jerry * * For consistency we also add the "Unix User" SID, * so that the complete unix token is represented within * the nt token. */ uid_to_unix_users_sid(server_info->utok.uid, &tmp_sid); add_sid_to_array_unique(server_info->security_token, &tmp_sid, &server_info->security_token->sids, &server_info->security_token->num_sids); for ( i=0; i<server_info->utok.ngroups; i++ ) { gid_to_unix_groups_sid(server_info->utok.groups[i], &tmp_sid); add_sid_to_array_unique(server_info->security_token, &tmp_sid, &server_info->security_token->sids, &server_info->security_token->num_sids); } security_token_debug(DBGC_AUTH, 10, server_info->security_token); debug_unix_user_token(DBGC_AUTH, 10, server_info->utok.uid, server_info->utok.gid, server_info->utok.ngroups, server_info->utok.groups); status = log_nt_token(server_info->security_token); return status; }
bool is_trusted_domain(const char* dom_name) { struct dom_sid trustdom_sid; bool ret; /* no trusted domains for a standalone server */ if ( lp_server_role() == ROLE_STANDALONE ) return False; if (dom_name == NULL || dom_name[0] == '\0') { return false; } if (strequal(dom_name, get_global_sam_name())) { return false; } /* if we are a DC, then check for a direct trust relationships */ if ( IS_DC ) { become_root(); DEBUG (5,("is_trusted_domain: Checking for domain trust with " "[%s]\n", dom_name )); ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL); unbecome_root(); if (ret) return True; } else { wbcErr result; /* If winbind is around, ask it */ result = wb_is_trusted_domain(dom_name); if (result == WBC_ERR_SUCCESS) { return True; } if (result == WBC_ERR_DOMAIN_NOT_FOUND) { /* winbind could not find the domain */ return False; } /* The only other possible result is that winbind is not up and running. We need to update the trustdom_cache ourselves */ update_trustdom_cache(); } /* now the trustdom cache should be available a DC could still * have a transitive trust so fall back to the cache of trusted * domains (like a domain member would use */ if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) { return True; } return False; }
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); }
/* startup the dsdb replicator service task */ static void dreplsrv_task_init(struct task_server *task) { WERROR status; struct dreplsrv_service *service; uint32_t periodic_startup_interval; switch (lp_server_role(task->lp_ctx)) { case ROLE_STANDALONE: task_server_terminate(task, "dreplsrv: no DSDB replication required in standalone configuration"); return; case ROLE_DOMAIN_MEMBER: task_server_terminate(task, "dreplsrv: no DSDB replication required in domain member configuration"); return; case ROLE_DOMAIN_CONTROLLER: /* Yes, we want DSDB replication */ break; } task_server_set_title(task, "task[dreplsrv]"); service = talloc_zero(task, struct dreplsrv_service); if (!service) { task_server_terminate(task, "dreplsrv_task_init: out of memory"); return; } service->task = task; service->startup_time = timeval_current(); task->private_data = service; status = dreplsrv_init_creds(service); if (!W_ERROR_IS_OK(status)) { task_server_terminate(task, talloc_asprintf(task, "dreplsrv: Failed to obtain server credentials: %s\n", win_errstr(status))); return; } status = dreplsrv_connect_samdb(service, task->lp_ctx); if (!W_ERROR_IS_OK(status)) { task_server_terminate(task, talloc_asprintf(task, "dreplsrv: Failed to connect to local samdb: %s\n", win_errstr(status))); return; } status = dreplsrv_load_partitions(service); if (!W_ERROR_IS_OK(status)) { task_server_terminate(task, talloc_asprintf(task, "dreplsrv: Failed to load partitions: %s\n", win_errstr(status))); return; } periodic_startup_interval = lp_parm_int(task->lp_ctx, NULL, "dreplsrv", "periodic_startup_interval", 15); /* in seconds */ service->periodic.interval = lp_parm_int(task->lp_ctx, NULL, "dreplsrv", "periodic_interval", 300); /* in seconds */ status = dreplsrv_periodic_schedule(service, periodic_startup_interval); if (!W_ERROR_IS_OK(status)) { task_server_terminate(task, talloc_asprintf(task, "dreplsrv: Failed to periodic schedule: %s\n", win_errstr(status))); return; } irpc_add_name(task->msg_ctx, "dreplsrv"); }