/* initialise the mangling code */ NTSTATUS pvfs_mangle_init(struct pvfs_state *pvfs) { struct pvfs_mangle_context *ctx; ctx = talloc(pvfs, struct pvfs_mangle_context); if (ctx == NULL) { return NT_STATUS_NO_MEMORY; } /* by default have a max of 512 entries in the cache. */ ctx->cache_size = lpcfg_parm_int(pvfs->ntvfs->ctx->lp_ctx, NULL, "mangle", "cachesize", 512); ctx->prefix_cache = talloc_array(ctx, char *, ctx->cache_size); if (ctx->prefix_cache == NULL) { return NT_STATUS_NO_MEMORY; } ctx->prefix_cache_hashes = talloc_array(ctx, uint32_t, ctx->cache_size); if (ctx->prefix_cache_hashes == NULL) { return NT_STATUS_NO_MEMORY; } memset(ctx->prefix_cache, 0, sizeof(char *) * ctx->cache_size); memset(ctx->prefix_cache_hashes, 0, sizeof(uint32_t) * ctx->cache_size); ctx->mangle_prefix = lpcfg_parm_int(pvfs->ntvfs->ctx->lp_ctx, NULL, "mangle", "prefix", -1); if (ctx->mangle_prefix < 0 || ctx->mangle_prefix > 6) { ctx->mangle_prefix = DEFAULT_MANGLE_PREFIX; } init_tables(ctx); pvfs->mangle_ctx = ctx; return NT_STATUS_OK; }
static bool test_lp_parm_int(struct torture_context *tctx) { struct loadparm_context *lp_ctx = loadparm_init(tctx); torture_assert(tctx, lpcfg_set_option(lp_ctx, "some:thing=34"), "lpcfg_set_option failed"); torture_assert_int_equal(tctx, lpcfg_parm_int(lp_ctx, NULL, "some", "thing", 20), 34, "invalid parametric option"); torture_assert_int_equal(tctx, lpcfg_parm_int(lp_ctx, NULL, "some", "bla", 42), 42, "invalid parametric option"); return true; }
/* This hardcoded value should go into a ldb database! */ enum srvsvc_PlatformId dcesrv_common_get_platform_id(TALLOC_CTX *mem_ctx, struct dcesrv_context *dce_ctx) { enum srvsvc_PlatformId id; id = lpcfg_parm_int(dce_ctx->lp_ctx, NULL, "server_info", "platform_id", PLATFORM_ID_NT); return id; }
/* start a timer to refresh this name */ static void nbtd_wins_start_refresh_timer(struct nbtd_iface_name *iname) { uint32_t refresh_time; uint32_t max_refresh_time = lpcfg_parm_int(iname->iface->nbtsrv->task->lp_ctx, NULL, "nbtd", "max_refresh_time", 7200); refresh_time = MIN(max_refresh_time, iname->ttl/2); tevent_add_timer(iname->iface->nbtsrv->task->event_ctx, iname, timeval_add(&iname->registration_time, refresh_time, 0), nbtd_wins_refresh, iname); }
static struct tdb_wrap_private *tdb_wrap_private_open(TALLOC_CTX *mem_ctx, const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode, struct loadparm_context *lp_ctx) { struct tdb_wrap_private *result; struct tdb_logging_context lctx; result = talloc(mem_ctx, struct tdb_wrap_private); if (result == NULL) { return NULL; } result->name = talloc_strdup(result, name); if (result->name == NULL) { goto fail; } if (!lpcfg_use_mmap(lp_ctx)) { tdb_flags |= TDB_NOMMAP; } if ((hash_size == 0) && (name != NULL)) { const char *base; base = strrchr_m(name, '/'); if (base != NULL) { base += 1; } else { base = name; } hash_size = lpcfg_parm_int(lp_ctx, NULL, "tdb_hashsize", base, 0); } lctx.log_fn = tdb_wrap_log; lctx.log_private = NULL; result->tdb = tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, &lctx, NULL); if (result->tdb == NULL) { goto fail; } talloc_set_destructor(result, tdb_wrap_private_destructor); DLIST_ADD(tdb_list, result); return result; fail: TALLOC_FREE(result); return NULL; }
/* startup the WINS server, if configured */ NTSTATUS nbtd_winsserver_init(struct nbtd_server *nbtsrv) { uint32_t tmp; const char *owner; if (!lpcfg_we_are_a_wins_server(nbtsrv->task->lp_ctx)) { nbtsrv->winssrv = NULL; return NT_STATUS_OK; } nbtsrv->winssrv = talloc_zero(nbtsrv, struct wins_server); NT_STATUS_HAVE_NO_MEMORY(nbtsrv->winssrv); nbtsrv->winssrv->config.max_renew_interval = lpcfg_max_wins_ttl(nbtsrv->task->lp_ctx); nbtsrv->winssrv->config.min_renew_interval = lpcfg_min_wins_ttl(nbtsrv->task->lp_ctx); tmp = lpcfg_parm_int(nbtsrv->task->lp_ctx, NULL, "wreplsrv", "tombstone_interval", 6*24*60*60); nbtsrv->winssrv->config.tombstone_interval = tmp; tmp = lpcfg_parm_int(nbtsrv->task->lp_ctx, NULL, "wreplsrv"," tombstone_timeout", 1*24*60*60); nbtsrv->winssrv->config.tombstone_timeout = tmp; owner = lpcfg_parm_string(nbtsrv->task->lp_ctx, NULL, "winsdb", "local_owner"); if (owner == NULL) { struct interface *ifaces; load_interface_list(nbtsrv->task, nbtsrv->task->lp_ctx, &ifaces); owner = iface_list_first_v4(ifaces); } nbtsrv->winssrv->wins_db = winsdb_connect(nbtsrv->winssrv, nbtsrv->task->event_ctx, nbtsrv->task->lp_ctx, owner, WINSDB_HANDLE_CALLER_NBTD); if (!nbtsrv->winssrv->wins_db) { return NT_STATUS_INTERNAL_DB_ERROR; } irpc_add_name(nbtsrv->task->msg_ctx, "wins_server"); return NT_STATUS_OK; }
/** \details Retrieve MySQL backend parametric options from configuration file and store them into a data structure. \param lp_ctx Pointer to the loadparm context \param p pointer to the structure with individual parameters to return \return MAPISTORE_SUCCES on success, otherwise MAPISTORE error */ enum mapistore_error mapistore_namedprops_mysql_parameters(struct loadparm_context *lp_ctx, struct namedprops_mysql_params *p) { /* Sanity checks */ MAPISTORE_RETVAL_IF(!lp_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL); MAPISTORE_RETVAL_IF(!p, MAPISTORE_ERR_INVALID_PARAMETER, NULL); /* Retrieve parametric options */ p->data = lpcfg_parm_string(lp_ctx, NULL, "namedproperties", "mysql_data"); p->sock = lpcfg_parm_string(lp_ctx, NULL, "namedproperties", "mysql_sock"); p->user = lpcfg_parm_string(lp_ctx, NULL, "namedproperties", "mysql_user"); p->pass = lpcfg_parm_string(lp_ctx, NULL, "namedproperties", "mysql_pass"); p->host = lpcfg_parm_string(lp_ctx, NULL, "namedproperties", "mysql_host"); p->port = lpcfg_parm_int(lp_ctx, NULL, "namedproperties", "mysql_port", 3306); p->db = lpcfg_parm_string(lp_ctx, NULL, "namedproperties", "mysql_db"); /* Enforce the logic */ MAPISTORE_RETVAL_IF(!p->user, MAPISTORE_ERR_BACKEND_INIT, NULL); MAPISTORE_RETVAL_IF(!p->db, MAPISTORE_ERR_BACKEND_INIT, NULL); MAPISTORE_RETVAL_IF(!p->host && !p->sock, MAPISTORE_ERR_BACKEND_INIT, NULL); return MAPISTORE_SUCCESS; }
/* startup the kdc task */ static void kdc_task_init(struct task_server *task) { struct kdc_server *kdc; krb5_kdc_configuration *kdc_config = NULL; NTSTATUS status; krb5_error_code ret; struct interface *ifaces; int ldb_ret; switch (lpcfg_server_role(task->lp_ctx)) { case ROLE_STANDALONE: task_server_terminate(task, "kdc: no KDC required in standalone configuration", false); return; case ROLE_DOMAIN_MEMBER: task_server_terminate(task, "kdc: no KDC required in member server configuration", false); return; case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: task_server_terminate(task, "Cannot start KDC as a 'classic Samba' DC", true); return; case ROLE_ACTIVE_DIRECTORY_DC: /* Yes, we want a KDC */ break; } load_interface_list(task, task->lp_ctx, &ifaces); if (iface_list_count(ifaces) == 0) { task_server_terminate(task, "kdc: no network interfaces configured", false); return; } task_server_set_title(task, "task[kdc]"); kdc = talloc_zero(task, struct kdc_server); if (kdc == NULL) { task_server_terminate(task, "kdc: out of memory", true); return; } kdc->task = task; /* get a samdb connection */ kdc->samdb = samdb_connect(kdc, kdc->task->event_ctx, kdc->task->lp_ctx, system_session(kdc->task->lp_ctx), NULL, 0); if (!kdc->samdb) { DEBUG(1,("kdc_task_init: unable to connect to samdb\n")); task_server_terminate(task, "kdc: krb5_init_context samdb connect failed", true); return; } ldb_ret = samdb_rodc(kdc->samdb, &kdc->am_rodc); if (ldb_ret != LDB_SUCCESS) { DEBUG(1, ("kdc_task_init: Cannot determine if we are an RODC: %s\n", ldb_errstring(kdc->samdb))); task_server_terminate(task, "kdc: krb5_init_context samdb RODC connect failed", true); return; } kdc->proxy_timeout = lpcfg_parm_int(kdc->task->lp_ctx, NULL, "kdc", "proxy timeout", 5); initialize_krb5_error_table(); ret = smb_krb5_init_context(kdc, task->lp_ctx, &kdc->smb_krb5_context); if (ret) { DEBUG(1,("kdc_task_init: krb5_init_context failed (%s)\n", error_message(ret))); task_server_terminate(task, "kdc: krb5_init_context failed", true); return; } krb5_add_et_list(kdc->smb_krb5_context->krb5_context, initialize_hdb_error_table_r); ret = krb5_kdc_get_config(kdc->smb_krb5_context->krb5_context, &kdc_config); if(ret) { task_server_terminate(task, "kdc: failed to get KDC configuration", true); return; } kdc_config->logf = (krb5_log_facility *)kdc->smb_krb5_context->pvt_log_data; kdc_config->db = talloc(kdc, struct HDB *); if (!kdc_config->db) { task_server_terminate(task, "kdc: out of memory", true); return; } kdc_config->num_db = 1; /* * This restores the behavior before * commit 255e3e18e00f717d99f3bc57c8a8895ff624f3c3 * s4:heimdal: import lorikeet-heimdal-201107150856 * (commit 48936803fae4a2fb362c79365d31f420c917b85b) * * as_use_strongest_session_key,preauth_use_strongest_session_key * and tgs_use_strongest_session_key are input to the * _kdc_find_etype() function. The old bahavior is in * the use_strongest_session_key=FALSE code path. * (The only remaining difference in _kdc_find_etype() * is the is_preauth parameter.) * * The old behavior in the _kdc_get_preferred_key() * function is use_strongest_server_key=TRUE. */ kdc_config->as_use_strongest_session_key = false; kdc_config->preauth_use_strongest_session_key = false; kdc_config->tgs_use_strongest_session_key = false; kdc_config->use_strongest_server_key = true; kdc_config->autodetect_referrals = false; /* Register hdb-samba4 hooks for use as a keytab */ kdc->base_ctx = talloc_zero(kdc, struct samba_kdc_base_context); if (!kdc->base_ctx) { task_server_terminate(task, "kdc: out of memory", true); return; } kdc->base_ctx->ev_ctx = task->event_ctx; kdc->base_ctx->lp_ctx = task->lp_ctx; kdc->base_ctx->msg_ctx = task->msg_ctx; status = hdb_samba4_create_kdc(kdc->base_ctx, kdc->smb_krb5_context->krb5_context, &kdc_config->db[0]); if (!NT_STATUS_IS_OK(status)) { task_server_terminate(task, "kdc: hdb_samba4_create_kdc (setup KDC database) failed", true); return; } ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context, PLUGIN_TYPE_DATA, "hdb", &hdb_samba4_interface); if(ret) { task_server_terminate(task, "kdc: failed to register hdb plugin", true); return; } ret = krb5_kt_register(kdc->smb_krb5_context->krb5_context, &hdb_kt_ops); if(ret) { task_server_terminate(task, "kdc: failed to register keytab plugin", true); return; } kdc->keytab_name = talloc_asprintf(kdc, "HDB:samba4&%p", kdc->base_ctx); if (kdc->keytab_name == NULL) { task_server_terminate(task, "kdc: Failed to set keytab name", true); return; } /* Register WinDC hooks */ ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context, PLUGIN_TYPE_DATA, "windc", &windc_plugin_table); if(ret) { task_server_terminate(task, "kdc: failed to register windc plugin", true); return; } ret = krb5_kdc_windc_init(kdc->smb_krb5_context->krb5_context); if(ret) { task_server_terminate(task, "kdc: failed to init windc plugin", true); return; } ret = krb5_kdc_pkinit_config(kdc->smb_krb5_context->krb5_context, kdc_config); if(ret) { task_server_terminate(task, "kdc: failed to init kdc pkinit subsystem", true); return; } kdc->private_data = kdc_config; /* start listening on the configured network interfaces */ status = kdc_startup_interfaces(kdc, task->lp_ctx, ifaces, task->model_ops); if (!NT_STATUS_IS_OK(status)) { task_server_terminate(task, "kdc failed to setup interfaces", true); return; } status = IRPC_REGISTER(task->msg_ctx, irpc, KDC_CHECK_GENERIC_KERBEROS, kdc_check_generic_kerberos, kdc); if (!NT_STATUS_IS_OK(status)) { task_server_terminate(task, "kdc failed to setup monitoring", true); return; } irpc_add_name(task->msg_ctx, "kdc_server"); }
int torture_setting_int(struct torture_context *test, const char *name, int default_value) { return lpcfg_parm_int(test->lp_ctx, NULL, "torture", name, default_value); }
static bool test_fsrvp_sc_create(struct torture_context *tctx, struct dcerpc_pipe *p, const char *share, enum test_fsrvp_inject inject, struct fssagent_share_mapping_1 **sc_map) { struct fss_IsPathSupported r_pathsupport_get; struct fss_GetSupportedVersion r_version_get; struct fss_SetContext r_context_set; struct fss_StartShadowCopySet r_scset_start; struct fss_AddToShadowCopySet r_scset_add1; struct fss_AddToShadowCopySet r_scset_add2; struct fss_PrepareShadowCopySet r_scset_prep; struct fss_CommitShadowCopySet r_scset_commit; struct fss_ExposeShadowCopySet r_scset_expose; struct fss_GetShareMapping r_sharemap_get; struct dcerpc_binding_handle *b = p->binding_handle; NTSTATUS status; time_t start_time; TALLOC_CTX *tmp_ctx = talloc_new(tctx); struct fssagent_share_mapping_1 *map = NULL; int sleep_time; /* * PrepareShadowCopySet & CommitShadowCopySet often exceed the default * 60 second dcerpc request timeout against Windows Server "8" Beta. */ dcerpc_binding_handle_set_timeout(b, 240); ZERO_STRUCT(r_pathsupport_get); r_pathsupport_get.in.ShareName = share; status = dcerpc_fss_IsPathSupported_r(b, tmp_ctx, &r_pathsupport_get); torture_assert_ntstatus_ok(tctx, status, "IsPathSupported failed"); torture_assert_int_equal(tctx, r_pathsupport_get.out.result, 0, "failed IsPathSupported response"); torture_assert(tctx, r_pathsupport_get.out.SupportedByThisProvider, "path not supported"); ZERO_STRUCT(r_version_get); status = dcerpc_fss_GetSupportedVersion_r(b, tmp_ctx, &r_version_get); torture_assert_ntstatus_ok(tctx, status, "GetSupportedVersion failed"); torture_assert_int_equal(tctx, r_version_get.out.result, 0, "failed GetSupportedVersion response"); ZERO_STRUCT(r_context_set); r_context_set.in.Context = FSRVP_CTX_BACKUP; status = dcerpc_fss_SetContext_r(b, tmp_ctx, &r_context_set); torture_assert_ntstatus_ok(tctx, status, "SetContext failed"); torture_assert_int_equal(tctx, r_context_set.out.result, 0, "failed SetContext response"); if (inject == TEST_FSRVP_TOUT_SET_CTX) { sleep_time = lpcfg_parm_int(tctx->lp_ctx, NULL, "fss", "sequence timeout", 180); torture_comment(tctx, "sleeping for %d\n", sleep_time); smb_msleep((sleep_time * 1000) + 500); } ZERO_STRUCT(r_scset_start); r_scset_start.in.ClientShadowCopySetId = GUID_random(); status = dcerpc_fss_StartShadowCopySet_r(b, tmp_ctx, &r_scset_start); torture_assert_ntstatus_ok(tctx, status, "StartShadowCopySet failed"); if (inject == TEST_FSRVP_TOUT_SET_CTX) { /* expect error due to message sequence timeout after set_ctx */ torture_assert_int_equal(tctx, r_scset_start.out.result, FSRVP_E_BAD_STATE, "StartShadowCopySet timeout response"); goto done; } torture_assert_int_equal(tctx, r_scset_start.out.result, 0, "failed StartShadowCopySet response"); torture_comment(tctx, "%s: shadow-copy set created\n", GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId)); if (inject == TEST_FSRVP_TOUT_START_SET) { sleep_time = lpcfg_parm_int(tctx->lp_ctx, NULL, "fss", "sequence timeout", 180); torture_comment(tctx, "sleeping for %d\n", sleep_time); smb_msleep((sleep_time * 1000) + 500); } ZERO_STRUCT(r_scset_add1); r_scset_add1.in.ClientShadowCopyId = GUID_random(); r_scset_add1.in.ShadowCopySetId = *r_scset_start.out.pShadowCopySetId; r_scset_add1.in.ShareName = share; status = dcerpc_fss_AddToShadowCopySet_r(b, tmp_ctx, &r_scset_add1); torture_assert_ntstatus_ok(tctx, status, "AddToShadowCopySet failed"); if (inject == TEST_FSRVP_TOUT_START_SET) { torture_assert_int_equal(tctx, r_scset_add1.out.result, HRES_ERROR_V(HRES_E_INVALIDARG), "AddToShadowCopySet timeout response"); goto done; } torture_assert_int_equal(tctx, r_scset_add1.out.result, 0, "failed AddToShadowCopySet response"); torture_comment(tctx, "%s(%s): %s added to shadow-copy set\n", GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId), GUID_string(tmp_ctx, r_scset_add1.out.pShadowCopyId), r_scset_add1.in.ShareName); /* attempts to add the same share twice should fail */ ZERO_STRUCT(r_scset_add2); r_scset_add2.in.ClientShadowCopyId = GUID_random(); r_scset_add2.in.ShadowCopySetId = *r_scset_start.out.pShadowCopySetId; r_scset_add2.in.ShareName = share; status = dcerpc_fss_AddToShadowCopySet_r(b, tmp_ctx, &r_scset_add2); torture_assert_ntstatus_ok(tctx, status, "AddToShadowCopySet failed"); torture_assert_int_equal(tctx, r_scset_add2.out.result, FSRVP_E_OBJECT_ALREADY_EXISTS, "failed AddToShadowCopySet response"); if (inject == TEST_FSRVP_TOUT_ADD_TO_SET) { sleep_time = lpcfg_parm_int(tctx->lp_ctx, NULL, "fss", "sequence timeout", 1800); torture_comment(tctx, "sleeping for %d\n", sleep_time); smb_msleep((sleep_time * 1000) + 500); } start_time = time_mono(NULL); ZERO_STRUCT(r_scset_prep); r_scset_prep.in.ShadowCopySetId = *r_scset_start.out.pShadowCopySetId; // r_scset_prep.in.TimeOutInMilliseconds = (1800 * 1000); /* win8 */ r_scset_prep.in.TimeOutInMilliseconds = (240 * 1000); status = dcerpc_fss_PrepareShadowCopySet_r(b, tmp_ctx, &r_scset_prep); torture_assert_ntstatus_ok(tctx, status, "PrepareShadowCopySet failed"); if (inject == TEST_FSRVP_TOUT_ADD_TO_SET) { torture_assert_int_equal(tctx, r_scset_prep.out.result, HRES_ERROR_V(HRES_E_INVALIDARG), "PrepareShadowCopySet tout response"); goto done; } torture_assert_int_equal(tctx, r_scset_prep.out.result, 0, "failed PrepareShadowCopySet response"); torture_comment(tctx, "%s: prepare completed in %llu secs\n", GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId), (unsigned long long)(time_mono(NULL) - start_time)); if (inject == TEST_FSRVP_TOUT_PREPARE) { sleep_time = lpcfg_parm_int(tctx->lp_ctx, NULL, "fss", "sequence timeout", 1800); torture_comment(tctx, "sleeping for %d\n", sleep_time); smb_msleep((sleep_time * 1000) + 500); } start_time = time_mono(NULL); ZERO_STRUCT(r_scset_commit); r_scset_commit.in.ShadowCopySetId = *r_scset_start.out.pShadowCopySetId; r_scset_commit.in.TimeOutInMilliseconds = (180 * 1000); /* win8 */ status = dcerpc_fss_CommitShadowCopySet_r(b, tmp_ctx, &r_scset_commit); torture_assert_ntstatus_ok(tctx, status, "CommitShadowCopySet failed"); if (inject == TEST_FSRVP_TOUT_PREPARE) { torture_assert_int_equal(tctx, r_scset_commit.out.result, HRES_ERROR_V(HRES_E_INVALIDARG), "CommitShadowCopySet tout response"); goto done; } torture_assert_int_equal(tctx, r_scset_commit.out.result, 0, "failed CommitShadowCopySet response"); torture_comment(tctx, "%s: commit completed in %llu secs\n", GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId), (unsigned long long)(time_mono(NULL) - start_time)); if (inject == TEST_FSRVP_TOUT_COMMIT) { sleep_time = lpcfg_parm_int(tctx->lp_ctx, NULL, "fss", "sequence timeout", 180); torture_comment(tctx, "sleeping for %d\n", sleep_time); smb_msleep((sleep_time * 1000) + 500); } else if (inject == TEST_FSRVP_STOP_B4_EXPOSE) { /* return partial snapshot information */ map = talloc_zero(tctx, struct fssagent_share_mapping_1); map->ShadowCopySetId = *r_scset_start.out.pShadowCopySetId; map->ShadowCopyId = *r_scset_add1.out.pShadowCopyId; goto done; }
/* 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 (lpcfg_server_role(task->lp_ctx)) { case ROLE_STANDALONE: task_server_terminate(task, "dreplsrv: no DSDB replication required in standalone configuration", false); return; case ROLE_DOMAIN_MEMBER: task_server_terminate(task, "dreplsrv: no DSDB replication required in domain member configuration", false); return; case ROLE_ACTIVE_DIRECTORY_DC: /* 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", true); 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)), true); 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)), true); 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)), true); return; } periodic_startup_interval = lpcfg_parm_int(task->lp_ctx, NULL, "dreplsrv", "periodic_startup_interval", 15); /* in seconds */ service->periodic.interval = lpcfg_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)), true); return; } service->pending.im = tevent_create_immediate(service); if (service->pending.im == NULL) { task_server_terminate(task, "dreplsrv: Failed to create immediate " "task for future DsReplicaSync\n", true); return; } /* if we are a RODC then we do not send DSReplicaSync*/ if (!service->am_rodc) { service->notify.interval = lpcfg_parm_int(task->lp_ctx, NULL, "dreplsrv", "notify_interval", 5); /* in seconds */ status = dreplsrv_notify_schedule(service, service->notify.interval); if (!W_ERROR_IS_OK(status)) { task_server_terminate(task, talloc_asprintf(task, "dreplsrv: Failed to setup notify schedule: %s\n", win_errstr(status)), true); return; } } irpc_add_name(task->msg_ctx, "dreplsrv"); IRPC_REGISTER(task->msg_ctx, irpc, DREPLSRV_REFRESH, dreplsrv_refresh, service); IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICASYNC, drepl_replica_sync, service); IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICAADD, dreplsrv_replica_add, service); IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICADEL, dreplsrv_replica_del, service); IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICAMOD, dreplsrv_replica_mod, service); IRPC_REGISTER(task->msg_ctx, irpc, DREPL_TAKEFSMOROLE, drepl_take_FSMO_role, service); IRPC_REGISTER(task->msg_ctx, irpc, DREPL_TRIGGER_REPL_SECRET, drepl_trigger_repl_secret, service); imessaging_register(task->msg_ctx, service, MSG_DREPL_ALLOCATE_RID, dreplsrv_allocate_rid); }
/* * called to create a new server task */ static void prefork_new_task( struct tevent_context *ev, struct loadparm_context *lp_ctx, const char *service_name, void (*new_task_fn)(struct tevent_context *, struct loadparm_context *lp_ctx, struct server_id , void *, void *), void *private_data, const struct service_details *service_details, int from_parent_fd) { pid_t pid; struct tfork* t = NULL; int i, num_children; struct tevent_context *ev2; t = tfork_create(); if (t == NULL) { smb_panic("failure in tfork\n"); } pid = tfork_child_pid(t); if (pid != 0) { struct tevent_fd *fde = NULL; int fd = tfork_event_fd(t); /* Register a pipe handler that gets called when the prefork * master process terminates. */ fde = tevent_add_fd(ev, ev, fd, TEVENT_FD_READ, prefork_child_pipe_handler, t); if (fde == NULL) { smb_panic("Failed to add child pipe handler, " "after fork"); } tevent_fd_set_auto_close(fde); return; } pid = getpid(); setproctitle("task[%s] pre-fork master", service_name); /* * this will free all the listening sockets and all state that * is not associated with this new connection */ if (tevent_re_initialise(ev) != 0) { smb_panic("Failed to re-initialise tevent after fork"); } prefork_reload_after_fork(); setup_handlers(ev, from_parent_fd); if (service_details->inhibit_pre_fork) { new_task_fn(ev, lp_ctx, cluster_id(pid, 0), private_data, NULL); /* The task does not support pre-fork */ tevent_loop_wait(ev); TALLOC_FREE(ev); exit(0); } /* * This is now the child code. We need a completely new event_context * to work with */ ev2 = s4_event_context_init(NULL); /* setup this new connection: process will bind to it's sockets etc * * While we can use ev for the child, which has been re-initialised * above we must run the new task under ev2 otherwise the children would * be listening on the sockets. Also we don't want the top level * process accepting and handling requests, it's responsible for * monitoring and controlling the child work processes. */ new_task_fn(ev2, lp_ctx, cluster_id(pid, 0), private_data, NULL); { int default_children; default_children = lpcfg_prefork_children(lp_ctx); num_children = lpcfg_parm_int(lp_ctx, NULL, "prefork children", service_name, default_children); } if (num_children == 0) { DBG_WARNING("Number of pre-fork children for %s is zero, " "NO worker processes will be started for %s\n", service_name, service_name); } DBG_NOTICE("Forking %d %s worker processes\n", num_children, service_name); /* We are now free to spawn some worker processes */ for (i=0; i < num_children; i++) { struct tfork* w = NULL; w = tfork_create(); if (w == NULL) { smb_panic("failure in tfork\n"); } pid = tfork_child_pid(w); if (pid != 0) { struct tevent_fd *fde = NULL; int fd = tfork_event_fd(w); fde = tevent_add_fd(ev, ev, fd, TEVENT_FD_READ, prefork_child_pipe_handler, w); if (fde == NULL) { smb_panic("Failed to add child pipe handler, " "after fork"); } tevent_fd_set_auto_close(fde); } else { /* tfork uses malloc */ free(w); TALLOC_FREE(ev); setproctitle("task[%s] pre-forked worker", service_name); prefork_reload_after_fork(); setup_handlers(ev2, from_parent_fd); tevent_loop_wait(ev2); talloc_free(ev2); exit(0); } } /* Don't listen on the sockets we just gave to the children */ tevent_loop_wait(ev); TALLOC_FREE(ev); /* We need to keep ev2 until we're finished for the messaging to work */ TALLOC_FREE(ev2); exit(0); }
/* startup the kcc service task */ static void kccsrv_task_init(struct task_server *task) { WERROR status; struct kccsrv_service *service; uint32_t periodic_startup_interval; switch (lpcfg_server_role(task->lp_ctx)) { case ROLE_STANDALONE: task_server_terminate(task, "kccsrv: no KCC required in standalone configuration", false); return; case ROLE_DOMAIN_MEMBER: task_server_terminate(task, "kccsrv: no KCC required in domain member configuration", false); return; case ROLE_DOMAIN_CONTROLLER: /* Yes, we want a KCC */ break; } task_server_set_title(task, "task[kccsrv]"); service = talloc_zero(task, struct kccsrv_service); if (!service) { task_server_terminate(task, "kccsrv_task_init: out of memory", true); return; } service->task = task; service->startup_time = timeval_current(); task->private_data = service; status = kccsrv_init_creds(service); if (!W_ERROR_IS_OK(status)) { task_server_terminate(task, talloc_asprintf(task, "kccsrv: Failed to obtain server credentials: %s\n", win_errstr(status)), true); return; } status = kccsrv_connect_samdb(service, task->lp_ctx); if (!W_ERROR_IS_OK(status)) { task_server_terminate(task, talloc_asprintf(task, "kccsrv: Failed to connect to local samdb: %s\n", win_errstr(status)), true); return; } status = kccsrv_load_partitions(service); if (!W_ERROR_IS_OK(status)) { task_server_terminate(task, talloc_asprintf(task, "kccsrv: Failed to load partitions: %s\n", win_errstr(status)), true); return; } periodic_startup_interval = lpcfg_parm_int(task->lp_ctx, NULL, "kccsrv", "periodic_startup_interval", 15); /* in seconds */ service->periodic.interval = lpcfg_parm_int(task->lp_ctx, NULL, "kccsrv", "periodic_interval", 300); /* in seconds */ /* (kccsrv:samba_kcc=true) will run newer samba_kcc replication * topology generation code. */ service->samba_kcc_code = lpcfg_parm_bool(task->lp_ctx, NULL, "kccsrv", "samba_kcc", false); status = kccsrv_periodic_schedule(service, periodic_startup_interval); if (!W_ERROR_IS_OK(status)) { task_server_terminate(task, talloc_asprintf(task, "kccsrv: Failed to periodic schedule: %s\n", win_errstr(status)), true); return; } irpc_add_name(task->msg_ctx, "kccsrv"); IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSEXECUTEKCC, kccsrv_execute_kcc, service); IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICAGETINFO, kccsrv_replica_get_info, service); }
/* check to see if any deleted objects need scavenging */ NTSTATUS kccsrv_check_deleted(struct kccsrv_service *s, TALLOC_CTX *mem_ctx) { struct kccsrv_partition *part; int ret; uint32_t tombstoneLifetime; bool do_fs = false; time_t interval = lpcfg_parm_int(s->task->lp_ctx, NULL, "kccsrv", "check_deleted_full_scan_interval", 86400); time_t t = time(NULL); if (t - s->last_deleted_check < lpcfg_parm_int(s->task->lp_ctx, NULL, "kccsrv", "check_deleted_interval", 600)) { return NT_STATUS_OK; } s->last_deleted_check = t; ret = dsdb_tombstone_lifetime(s->samdb, &tombstoneLifetime); if (ret != LDB_SUCCESS) { DEBUG(1,(__location__ ": Failed to get tombstone lifetime\n")); return NT_STATUS_INTERNAL_DB_CORRUPTION; } if (s->last_full_scan_deleted_check > 0 && ((t - s->last_full_scan_deleted_check) > interval )) { do_fs = true; s->last_full_scan_deleted_check = t; } if (s->last_full_scan_deleted_check == 0) { /* * If we never made a full scan set the last full scan event to be in the past * and that 9/10 of the full scan interval has already passed. * This is done to avoid the full scan to fire just at the begining of samba * or a couple of minutes after the start. * With this "setup" and default values of interval, the full scan will fire * 2.4 hours after the start of samba */ s->last_full_scan_deleted_check = t - ((9 * interval) / 10); } for (part=s->partitions; part; part=part->next) { struct ldb_dn *do_dn; struct ldb_result *res; const char *attrs[] = { "whenChanged", NULL }; unsigned int i; ret = dsdb_get_deleted_objects_dn(s->samdb, mem_ctx, part->dn, &do_dn); if (ret != LDB_SUCCESS) { /* some partitions have no Deleted Objects container */ continue; } if (!do_fs && ldb_dn_compare(ldb_get_config_basedn(s->samdb), part->dn)) { ret = dsdb_search(s->samdb, do_dn, &res, do_dn, LDB_SCOPE_ONELEVEL, attrs, DSDB_SEARCH_SHOW_RECYCLED, NULL); } else { if (do_fs) { DEBUG(1, ("Doing a full scan on %s and looking for deleted object\n", ldb_dn_get_linearized(part->dn))); } ret = dsdb_search(s->samdb, part->dn, &res, part->dn, LDB_SCOPE_SUBTREE, attrs, DSDB_SEARCH_SHOW_RECYCLED, "(isDeleted=TRUE)"); } if (ret != LDB_SUCCESS) { DEBUG(1,(__location__ ": Failed to search for deleted objects in %s\n", ldb_dn_get_linearized(do_dn))); talloc_free(do_dn); continue; } for (i=0; i<res->count; i++) { const char *tstring; time_t whenChanged = 0; if (ldb_dn_compare(do_dn, res->msgs[i]->dn) == 0) { /* Skip the Deleted Object Container */ continue; } tstring = ldb_msg_find_attr_as_string(res->msgs[i], "whenChanged", NULL); if (tstring) { whenChanged = ldb_string_to_time(tstring); } if (t - whenChanged > tombstoneLifetime*60*60*24) { ret = dsdb_delete(s->samdb, res->msgs[i]->dn, DSDB_SEARCH_SHOW_DELETED); if (ret != LDB_SUCCESS) { DEBUG(1,(__location__ ": Failed to remove deleted object %s\n", ldb_dn_get_linearized(res->msgs[i]->dn))); } else { DEBUG(4,("Removed deleted object %s\n", ldb_dn_get_linearized(res->msgs[i]->dn))); } } } talloc_free(do_dn); } return NT_STATUS_OK; }