static void assert_defaults(struct dp_option *opts) { char *s; struct dp_opt_blob b; int i; bool bo; s = dp_opt_get_string(opts, OPT_STRING_NODEFAULT); assert_null(s); s = dp_opt_get_string(opts, OPT_STRING_DEFAULT); assert_non_null(s); assert_string_equal(s, STRING_DEFAULT); b = dp_opt_get_blob(opts, OPT_BLOB_NODEFAULT); assert_null(b.data); assert_int_equal(b.length, 0); b = dp_opt_get_blob(opts, OPT_BLOB_DEFAULT); assert_non_null(b.data); assert_int_equal(b.length, strlen(BLOB_DEFAULT)); assert_memory_equal(b.data, BLOB_DEFAULT, strlen(BLOB_DEFAULT)); i = dp_opt_get_int(opts, OPT_INT_NODEFAULT); assert_int_equal(i, 0); i = dp_opt_get_int(opts, OPT_INT_DEFAULT); assert_int_equal(i, INT_DEFAULT); bo = dp_opt_get_bool(opts, OPT_BOOL_TRUE); assert_true(bo == true); bo = dp_opt_get_bool(opts, OPT_BOOL_FALSE); assert_true(bo == false); }
static void ldap_id_enumerate_timer(struct tevent_context *ev, struct tevent_timer *tt, struct timeval tv, void *pvt) { struct sdap_id_ctx *ctx = talloc_get_type(pvt, struct sdap_id_ctx); struct tevent_timer *timeout; struct tevent_req *req; int delay; errno_t ret; if (be_is_offline(ctx->be)) { DEBUG(4, ("Backend is marked offline, retry later!\n")); /* schedule starting from now, not the last run */ delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); tv = tevent_timeval_current_ofs(delay, 0); ldap_id_enumerate_set_timer(ctx, tv); return; } req = ldap_id_enumerate_send(ev, ctx); if (!req) { DEBUG(1, ("Failed to schedule enumeration, retrying later!\n")); /* schedule starting from now, not the last run */ delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); tv = tevent_timeval_current_ofs(delay, 0); ret = ldap_id_enumerate_set_timer(ctx, tv); if (ret != EOK) { DEBUG(1, ("Error setting up enumerate timer\n")); } return; } tevent_req_set_callback(req, ldap_id_enumerate_reschedule, ctx); /* if enumeration takes so long, either we try to enumerate too * frequently, or something went seriously wrong */ delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); tv = tevent_timeval_current_ofs(delay, 0); timeout = tevent_add_timer(ctx->be->ev, req, tv, ldap_id_enumerate_timeout, req); if (timeout == NULL) { /* If we can't guarantee a timeout, we * need to cancel the request, to avoid * the possibility of starting another * concurrently */ talloc_zfree(req); DEBUG(1, ("Failed to schedule enumeration, retrying later!\n")); /* schedule starting from now, not the last run */ delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); tv = tevent_timeval_current_ofs(delay, 0); ret = ldap_id_enumerate_set_timer(ctx, tv); if (ret != EOK) { DEBUG(1, ("Error setting up enumerate timer\n")); } return; } return; }
void opt_test_get(void **state) { int ret; struct sss_test_ctx *tctx; struct dp_option *opts; struct sss_test_conf_param params[] = { { "string_nodefault", "stringval2" }, { "blob_nodefault", "blobval2" }, { "int_nodefault", "456" }, { "bool_true", "false" }, { NULL, NULL }, /* Sentinel */ }; char *s; struct dp_opt_blob b; int i; bool bo; tctx = create_dom_test_ctx(global_talloc_context, TESTS_PATH, TEST_CONF_DB, TEST_DOM_NAME, TEST_ID_PROVIDER, params); assert_non_null(tctx); ret = dp_get_options(global_talloc_context, tctx->confdb, tctx->conf_dom_path, test_def_opts, OPT_NUM_OPTS, &opts); assert_int_equal(ret, EOK); /* Options that were not specified explicitly should only have the default * value, those that have been specified explicitly should carry that * value */ s = dp_opt_get_string(opts, OPT_STRING_NODEFAULT); assert_non_null(s); assert_string_equal(s, "stringval2"); s = dp_opt_get_string(opts, OPT_STRING_DEFAULT); assert_non_null(s); assert_string_equal(s, STRING_DEFAULT); b = dp_opt_get_blob(opts, OPT_BLOB_NODEFAULT); assert_non_null(b.data); assert_int_equal(b.length, strlen("blobval2")); assert_memory_equal(b.data, "blobval2", strlen("blobval2")); b = dp_opt_get_blob(opts, OPT_BLOB_DEFAULT); assert_non_null(b.data); assert_int_equal(b.length, strlen(BLOB_DEFAULT)); assert_memory_equal(b.data, BLOB_DEFAULT, strlen(BLOB_DEFAULT)); i = dp_opt_get_int(opts, OPT_INT_NODEFAULT); assert_int_equal(i, 456); i = dp_opt_get_int(opts, OPT_INT_DEFAULT); assert_int_equal(i, INT_DEFAULT); bo = dp_opt_get_bool(opts, OPT_BOOL_TRUE); assert_true(bo == false); bo = dp_opt_get_bool(opts, OPT_BOOL_FALSE); assert_true(bo == false); }
static void sdap_sudo_periodical_first_refresh_done(struct tevent_req *req) { struct tevent_req *subreq = NULL; /* req from sdap_sudo_full_refresh_send() */ struct sdap_sudo_ctx *sudo_ctx = NULL; time_t delay; int dp_error = DP_ERR_OK; int error = EOK; int ret; ret = sdap_sudo_timer_recv(req, req, &subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("Sudo timer failed [%d]: %s\n", ret, strerror(ret))); goto schedule; } ret = sdap_sudo_full_refresh_recv(subreq, &dp_error, &error); if (dp_error != DP_ERR_OK || error != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("Periodical full refresh of sudo rules " "failed [dp_error: %d] ([%d]: %s)\n", dp_error, error, strerror(error))); goto schedule; } schedule: sudo_ctx = tevent_req_callback_data(req, struct sdap_sudo_ctx); talloc_zfree(req); /* full refresh */ delay = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic, SDAP_SUDO_FULL_REFRESH_INTERVAL); if (delay == 0) { /* runtime configuration change? */ DEBUG(SSSDBG_TRACE_FUNC, ("Periodical full refresh of sudo rules " "is disabled\n")); return; } ret = sdap_sudo_schedule_full_refresh(sudo_ctx, delay); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("Full periodical refresh will not work.\n")); } /* smart refresh */ delay = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic, SDAP_SUDO_SMART_REFRESH_INTERVAL); if (delay == 0) { /* runtime configuration change? */ DEBUG(SSSDBG_TRACE_FUNC, ("Periodical smart refresh of sudo rules " "is disabled\n")); return; } ret = sdap_sudo_schedule_smart_refresh(sudo_ctx, delay); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("Smart periodical refresh will not work.\n")); } }
void opt_test_copy_options(void **state) { int ret; TALLOC_CTX *mem_ctx; struct dp_option *opts; char *s; struct dp_opt_blob b; int i; bool bo; mem_ctx = talloc_new(global_talloc_context); assert_non_null(mem_ctx); ret = dp_copy_options(mem_ctx, test_def_opts, OPT_NUM_OPTS, &opts); assert_int_equal(ret, EOK); assert_int_equal(ret, EOK); ret = dp_opt_set_string(opts, OPT_STRING_NODEFAULT, "str1"); assert_int_equal(ret, EOK); b.data = discard_const_p(uint8_t, "blob1"); b.length = strlen("blob1"); ret = dp_opt_set_blob(opts, OPT_BLOB_NODEFAULT, b); assert_int_equal(ret, EOK); ret = dp_opt_set_int(opts, OPT_INT_NODEFAULT, 456); assert_int_equal(ret, EOK); ret = dp_opt_set_bool(opts, OPT_BOOL_TRUE, false); assert_int_equal(ret, EOK); /* Test that options set to an explicit value retain * the value and even options with default value * do not return the default unless explicitly set */ s = dp_opt_get_string(opts, OPT_STRING_NODEFAULT); assert_string_equal(s, "str1"); s = dp_opt_get_string(opts, OPT_STRING_DEFAULT); assert_null(s); b = dp_opt_get_blob(opts, OPT_BLOB_NODEFAULT); assert_non_null(b.data); assert_int_equal(b.length, strlen("blob1")); assert_memory_equal(b.data, "blob1", strlen("blob1")); b = dp_opt_get_blob(opts, OPT_BLOB_DEFAULT); assert_null(b.data); assert_int_equal(b.length, 0); i = dp_opt_get_int(opts, OPT_INT_NODEFAULT); assert_int_equal(i, 456); i = dp_opt_get_int(opts, OPT_INT_DEFAULT); assert_int_equal(i, 0); bo = dp_opt_get_bool(opts, OPT_BOOL_TRUE); assert_false(bo == true); }
static errno_t sdap_idmap_get_configured_external_range(struct sdap_idmap_ctx *idmap_ctx, struct sss_idmap_range *range) { int int_id; struct sdap_id_ctx *id_ctx; uint32_t min; uint32_t max; if (idmap_ctx == NULL) { return EINVAL; } id_ctx = idmap_ctx->id_ctx; int_id = dp_opt_get_int(id_ctx->opts->basic, SDAP_MIN_ID); if (int_id < 0) { DEBUG(SSSDBG_CONF_SETTINGS, "ldap_min_id must be greater than 0.\n"); return EINVAL; } min = int_id; int_id = dp_opt_get_int(id_ctx->opts->basic, SDAP_MAX_ID); if (int_id < 0) { DEBUG(SSSDBG_CONF_SETTINGS, "ldap_max_id must be greater than 0.\n"); return EINVAL; } max = int_id; if ((min == 0 && max != 0) || (min != 0 && max == 0)) { DEBUG(SSSDBG_CONF_SETTINGS, "Both ldap_min_id and ldap_max_id " \ "either must be 0 (not set) " \ "or positive integers.\n"); return EINVAL; } if (min == 0 && max == 0) { /* ldap_min_id and ldap_max_id not set, using min_id and max_id */ min = id_ctx->be->domain->id_min; max = id_ctx->be->domain->id_max; if (max == 0) { max = UINT32_MAX; } } range->min = min; range->max =max; return EOK; }
static void ldap_id_enumerate_reschedule(struct tevent_req *req) { struct sdap_id_ctx *ctx = tevent_req_callback_data(req, struct sdap_id_ctx); enum tevent_req_state tstate; uint64_t err; struct timeval tv; int delay; errno_t ret; if (tevent_req_is_error(req, &tstate, &err)) { /* On error schedule starting from now, not the last run */ tv = tevent_timeval_current(); } else { tv = ctx->last_enum; /* Ok, we've completed an enumeration. Save this to the * sysdb so we can postpone starting up the enumeration * process on the next SSSD service restart (to avoid * slowing down system boot-up */ ret = sysdb_set_enumerated(ctx->be->sysdb, true); if (ret != EOK) { DEBUG(1, ("Could not mark domain as having enumerated.\n")); /* This error is non-fatal, so continue */ } } talloc_zfree(req); delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); tv = tevent_timeval_add(&tv, delay, 0); ldap_id_enumerate_set_timer(ctx, tv); }
static int hbac_retry(struct hbac_ctx *hbac_ctx) { struct tevent_req *subreq; int ret; bool offline; time_t now, refresh_interval; struct ipa_access_ctx *access_ctx = hbac_ctx->access_ctx; struct be_ctx *be_ctx = be_req_get_be_ctx(hbac_ctx->be_req); offline = be_is_offline(be_ctx); DEBUG(9, ("Connection status is [%s].\n", offline ? "offline" : "online")); refresh_interval = dp_opt_get_int(hbac_ctx->ipa_options, IPA_HBAC_REFRESH); now = time(NULL); if (now < access_ctx->last_update + refresh_interval) { /* Simulate offline mode and just go to the cache */ DEBUG(6, ("Performing cached HBAC evaluation\n")); offline = true; } if (!offline) { if (hbac_ctx->sdap_op == NULL) { hbac_ctx->sdap_op = sdap_id_op_create(hbac_ctx, hbac_ctx->sdap_ctx->conn->conn_cache); if (hbac_ctx->sdap_op == NULL) { DEBUG(1, ("sdap_id_op_create failed.\n")); return EIO; } } subreq = sdap_id_op_connect_send(hbac_ctx->sdap_op, hbac_ctx, &ret); if (!subreq) { DEBUG(1, ("sdap_id_op_connect_send failed: %d(%s).\n", ret, strerror(ret))); talloc_zfree(hbac_ctx->sdap_op); return ret; } tevent_req_set_callback(subreq, hbac_connect_done, hbac_ctx); } else { /* Evaluate the rules based on what we have in the * sysdb */ ipa_hbac_evaluate_rules(hbac_ctx); return EOK; } return EOK; }
static void ldap_id_enumerate_timeout(struct tevent_context *ev, struct tevent_timer *te, struct timeval tv, void *pvt) { struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); struct sdap_id_ctx *ctx = tevent_req_callback_data(req, struct sdap_id_ctx); int delay; delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); DEBUG(1, ("Enumeration timed out! Timeout too small? (%ds)!\n", delay)); tv = tevent_timeval_current_ofs(delay, 0); ldap_id_enumerate_set_timer(ctx, tv); talloc_zfree(req); }
static void sdap_sudo_full_refresh_online_cb(void *pvt) { struct sdap_sudo_ctx *sudo_ctx = NULL; time_t timeout; int ret; sudo_ctx = talloc_get_type(pvt, struct sdap_sudo_ctx); /* remove online callback */ talloc_zfree(sudo_ctx->first_refresh_online_cb); /* schedule new first refresh only if this callback wasn't triggered * by ongoing full refresh */ if (sudo_ctx->full_refresh_in_progress) { return; } /* otherwise cancel the concurrent timer for full refresh */ talloc_zfree(sudo_ctx->first_refresh_timer); /* and fire full refresh immediately */ timeout = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic, SDAP_SUDO_FULL_REFRESH_INTERVAL); if (timeout == 0) { /* runtime configuration change? */ DEBUG(SSSDBG_TRACE_FUNC, "Periodical full refresh of sudo rules " "is disabled\n"); return; } ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx, SDAP_SUDO_REFRESH_FULL, sdap_sudo_periodical_first_refresh_done, 0, timeout, NULL); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule full refresh of sudo " "rules! Periodical updates will not work!\n"); } }
static int sdap_sudo_setup_periodical_refresh(struct sdap_sudo_ctx *sudo_ctx) { struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx; struct tevent_req *req; time_t smart_default; time_t smart_interval; time_t full_interval; time_t last_full; struct timeval tv; int ret; smart_interval = dp_opt_get_int(id_ctx->opts->basic, SDAP_SUDO_SMART_REFRESH_INTERVAL); full_interval = dp_opt_get_int(id_ctx->opts->basic, SDAP_SUDO_FULL_REFRESH_INTERVAL); if (smart_interval == 0 && full_interval == 0) { smart_default = id_ctx->opts->basic[SDAP_SUDO_SMART_REFRESH_INTERVAL].def_val.number; DEBUG(SSSDBG_MINOR_FAILURE, ("At least one periodical update has to be " "enabled. Setting smart refresh interval to default value (%d).\n", smart_default)); ret = dp_opt_set_int(id_ctx->opts->basic, SDAP_SUDO_SMART_REFRESH_INTERVAL, smart_default); if (ret != EOK) { return ret; } } if (full_interval <= smart_interval) { DEBUG(SSSDBG_MINOR_FAILURE, ("Full refresh interval has to be greater" "than smart refresh interval. Periodical full refresh will be " "disabled.\n")); ret = dp_opt_set_int(id_ctx->opts->basic, SDAP_SUDO_FULL_REFRESH_INTERVAL, 0); if (ret != EOK) { return ret; } } ret = sysdb_sudo_get_last_full_refresh(id_ctx->be->sysdb, &last_full); if (ret != EOK) { return ret; } if (last_full == 0) { /* If this is the first startup, we need to kick off * an refresh immediately, to close a window where * clients requesting sudo information won't get an * immediate reply with no entries */ tv = tevent_timeval_current(); } else { /* At least one update has previously run, * so clients will get cached data. * We will delay the refresh so we don't slow * down the startup process if this is happening * during system boot. */ /* delay at least by 10s */ tv = tevent_timeval_current_ofs(10, 0); } req = sdap_sudo_timer_send(sudo_ctx, id_ctx->be->ev, sudo_ctx, tv, full_interval, sdap_sudo_full_refresh_send); if (req == NULL) { DEBUG(SSSDBG_OP_FAILURE, ("Unable to schedule full refresh of sudo " "rules! Periodical updates will not work!\n")); return ENOMEM; } tevent_req_set_callback(req, sdap_sudo_periodical_first_refresh_done, sudo_ctx); DEBUG(SSSDBG_TRACE_FUNC, ("Full refresh scheduled at: %lld\n", (long long)tv.tv_sec)); return EOK; }
errno_t sdap_idmap_init(TALLOC_CTX *mem_ctx, struct sdap_id_ctx *id_ctx, struct sdap_idmap_ctx **_idmap_ctx) { errno_t ret; TALLOC_CTX *tmp_ctx; enum idmap_error_code err; size_t i; struct ldb_result *res; const char *dom_name; const char *sid_str; id_t slice_num; id_t idmap_lower; id_t idmap_upper; id_t rangesize; bool autorid_mode; struct sdap_idmap_ctx *idmap_ctx = NULL; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) return ENOMEM; idmap_ctx = talloc_zero(tmp_ctx, struct sdap_idmap_ctx); if (!idmap_ctx) { ret = ENOMEM; goto done; } idmap_ctx->id_ctx = id_ctx; idmap_ctx->find_new_domain = sdap_idmap_find_new_domain; idmap_lower = dp_opt_get_int(idmap_ctx->id_ctx->opts->basic, SDAP_IDMAP_LOWER); idmap_upper = dp_opt_get_int(idmap_ctx->id_ctx->opts->basic, SDAP_IDMAP_UPPER); rangesize = dp_opt_get_int(idmap_ctx->id_ctx->opts->basic, SDAP_IDMAP_RANGESIZE); autorid_mode = dp_opt_get_bool(idmap_ctx->id_ctx->opts->basic, SDAP_IDMAP_AUTORID_COMPAT); /* Validate that the values make sense */ if (rangesize <= 0 || idmap_upper <= idmap_lower || (idmap_upper-idmap_lower) < rangesize) { DEBUG(SSSDBG_FATAL_FAILURE, "Invalid settings for range selection: " "[%"SPRIid"][%"SPRIid"][%"SPRIid"]\n", idmap_lower, idmap_upper, rangesize); ret = EINVAL; goto done; } if (((idmap_upper - idmap_lower) % rangesize) != 0) { DEBUG(SSSDBG_CONF_SETTINGS, "Range size does not divide evenly. Uppermost range will " "not be used\n"); } /* Initialize the map */ err = sss_idmap_init(sss_idmap_talloc, idmap_ctx, sss_idmap_talloc_free, &idmap_ctx->map); if (err != IDMAP_SUCCESS) { DEBUG(SSSDBG_CRIT_FAILURE, "Could not initialize the ID map: [%s]\n", idmap_error_string(err)); if (err == IDMAP_OUT_OF_MEMORY) { ret = ENOMEM; } else { ret = EINVAL; } goto done; } err = sss_idmap_ctx_set_autorid(idmap_ctx->map, autorid_mode); err |= sss_idmap_ctx_set_lower(idmap_ctx->map, idmap_lower); err |= sss_idmap_ctx_set_upper(idmap_ctx->map, idmap_upper); err |= sss_idmap_ctx_set_rangesize(idmap_ctx->map, rangesize); if (err != IDMAP_SUCCESS) { /* This should never happen */ DEBUG(SSSDBG_CRIT_FAILURE, "sss_idmap_ctx corrupted\n"); return EIO; } /* Setup range for externally managed IDs, i.e. IDs are read from the * ldap_user_uid_number and ldap_group_gid_number attributes. */ if (!dp_opt_get_bool(idmap_ctx->id_ctx->opts->basic, SDAP_ID_MAPPING)) { ret = sdap_idmap_add_configured_external_range(idmap_ctx); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "sdap_idmap_add_configured_external_range failed.\n"); goto done; } } /* Read in any existing mappings from the cache */ ret = sysdb_idmap_get_mappings(tmp_ctx, id_ctx->be->domain, &res); if (ret != EOK && ret != ENOENT) { DEBUG(SSSDBG_FATAL_FAILURE, "Could not read ID mappings from the cache: [%s]\n", strerror(ret)); goto done; } if (ret == EOK && res->count > 0) { DEBUG(SSSDBG_CONF_SETTINGS, "Initializing [%d] domains for ID-mapping\n", res->count); for (i = 0; i < res->count; i++) { dom_name = ldb_msg_find_attr_as_string(res->msgs[i], SYSDB_NAME, NULL); if (!dom_name) { /* This should never happen */ ret = EINVAL; goto done; } sid_str = ldb_msg_find_attr_as_string(res->msgs[i], SYSDB_IDMAP_SID_ATTR, NULL); if (!sid_str) { /* This should never happen */ ret = EINVAL; goto done; } slice_num = ldb_msg_find_attr_as_int(res->msgs[i], SYSDB_IDMAP_SLICE_ATTR, -1); if (slice_num == -1) { /* This should never happen */ ret = EINVAL; goto done; } ret = sdap_idmap_add_domain(idmap_ctx, dom_name, sid_str, slice_num); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Could not add domain [%s][%s][%"SPRIid"] " "to ID map: [%s]\n", dom_name, sid_str, slice_num, strerror(ret)); goto done; } } } else { /* This is the first time we're setting up id-mapping * Store the default domain as slice 0 */ dom_name = dp_opt_get_string(idmap_ctx->id_ctx->opts->basic, SDAP_IDMAP_DEFAULT_DOMAIN); if (!dom_name) { /* If it's not explicitly specified, use the SSSD domain name */ dom_name = idmap_ctx->id_ctx->be->domain->name; ret = dp_opt_set_string(idmap_ctx->id_ctx->opts->basic, SDAP_IDMAP_DEFAULT_DOMAIN, dom_name); if (ret != EOK) goto done; } sid_str = dp_opt_get_string(idmap_ctx->id_ctx->opts->basic, SDAP_IDMAP_DEFAULT_DOMAIN_SID); if (sid_str) { /* Set the default domain as slice 0 */ ret = sdap_idmap_add_domain(idmap_ctx, dom_name, sid_str, 0); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Could not add domain [%s][%s][%u] to ID map: [%s]\n", dom_name, sid_str, 0, strerror(ret)); goto done; } } else { if (dp_opt_get_bool(idmap_ctx->id_ctx->opts->basic, SDAP_IDMAP_AUTORID_COMPAT)) { /* In autorid compatibility mode, we MUST have a slice 0 */ DEBUG(SSSDBG_CRIT_FAILURE, "WARNING: Autorid compatibility mode selected, " "but %s is not set. UID/GID values may differ " "between clients.\n", idmap_ctx->id_ctx->opts->basic[SDAP_IDMAP_DEFAULT_DOMAIN_SID].opt_name); } /* Otherwise, we'll just fall back to hash values as they are seen */ } } *_idmap_ctx = talloc_steal(mem_ctx, idmap_ctx); ret = EOK; done: talloc_free(tmp_ctx); return ret; }
static errno_t sdap_save_netgroup(TALLOC_CTX *memctx, struct sysdb_ctx *ctx, struct sdap_options *opts, struct sss_domain_info *dom, struct sysdb_attrs *attrs, char **_timestamp) { struct ldb_message_element *el; struct sysdb_attrs *netgroup_attrs; const char *name = NULL; int ret; char *timestamp = NULL; size_t c; ret = sysdb_attrs_get_el(attrs, opts->netgroup_map[SDAP_AT_NETGROUP_NAME].sys_name, &el); if (ret) goto fail; if (el->num_values == 0) { ret = EINVAL; goto fail; } name = (const char *)el->values[0].data; netgroup_attrs = sysdb_new_attrs(memctx); if (!netgroup_attrs) { ret = ENOMEM; goto fail; } ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el); if (ret) { goto fail; } if (el->num_values == 0) { DEBUG(7, ("Original DN is not available for [%s].\n", name)); } else { DEBUG(7, ("Adding original DN [%s] to attributes of [%s].\n", el->values[0].data, name)); ret = sysdb_attrs_add_string(netgroup_attrs, SYSDB_ORIG_DN, (const char *)el->values[0].data); if (ret) { goto fail; } } ret = sysdb_attrs_get_el(attrs, opts->netgroup_map[SDAP_AT_NETGROUP_MODSTAMP].sys_name, &el); if (ret) { goto fail; } if (el->num_values == 0) { DEBUG(7, ("Original mod-Timestamp is not available for [%s].\n", name)); } else { ret = sysdb_attrs_add_string(netgroup_attrs, opts->netgroup_map[SDAP_AT_NETGROUP_MODSTAMP].sys_name, (const char*)el->values[0].data); if (ret) { goto fail; } timestamp = talloc_strdup(memctx, (const char*)el->values[0].data); if (!timestamp) { ret = ENOMEM; goto fail; } } ret = sysdb_attrs_get_el(attrs, opts->netgroup_map[SDAP_AT_NETGROUP_TRIPLE].sys_name, &el); if (ret) { goto fail; } if (el->num_values == 0) { DEBUG(7, ("No netgroup triples for netgroup [%s].\n", name)); } else { for(c = 0; c < el->num_values; c++) { ret = sysdb_attrs_add_string(netgroup_attrs, opts->netgroup_map[SDAP_AT_NETGROUP_TRIPLE].sys_name, (const char*)el->values[c].data); if (ret) { goto fail; } } } ret = sysdb_attrs_get_el(attrs, opts->netgroup_map[SDAP_AT_NETGROUP_MEMBER].sys_name, &el); if (ret != EOK) { goto fail; } if (el->num_values == 0) { DEBUG(7, ("No original members for netgroup [%s]\n", name)); } else { DEBUG(7, ("Adding original members to netgroup [%s]\n", name)); for(c = 0; c < el->num_values; c++) { ret = sysdb_attrs_add_string(netgroup_attrs, opts->netgroup_map[SDAP_AT_NETGROUP_MEMBER].sys_name, (const char*)el->values[c].data); if (ret) { goto fail; } } } ret = sysdb_attrs_get_el(attrs, SYSDB_NETGROUP_MEMBER, &el); if (ret != EOK) { goto fail; } if (el->num_values == 0) { DEBUG(7, ("No members for netgroup [%s]\n", name)); } else { DEBUG(7, ("Adding members to netgroup [%s]\n", name)); for(c = 0; c < el->num_values; c++) { ret = sysdb_attrs_add_string(netgroup_attrs, SYSDB_NETGROUP_MEMBER, (const char*)el->values[c].data); if (ret) { goto fail; } } } DEBUG(6, ("Storing info for netgroup %s\n", name)); ret = sysdb_add_netgroup(ctx, name, NULL, netgroup_attrs, dp_opt_get_int(opts->basic, SDAP_ENTRY_CACHE_TIMEOUT)); if (ret) goto fail; if (_timestamp) { *_timestamp = timestamp; } return EOK; fail: DEBUG(2, ("Failed to save netgroup %s\n", name)); return ret; }
static void sdap_sudo_periodical_first_refresh_done(struct tevent_req *req) { struct tevent_req *subreq = NULL; /* req from sdap_sudo_full_refresh_send() */ struct sdap_sudo_ctx *sudo_ctx = NULL; time_t delay; time_t timeout; int dp_error = DP_ERR_OK; int error = EOK; int ret; ret = sdap_sudo_timer_recv(req, req, &subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Sudo timer failed [%d]: %s\n", ret, strerror(ret)); goto schedule; } ret = sdap_sudo_full_refresh_recv(subreq, &dp_error, &error); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Periodical full refresh of sudo rules " "failed [%d]: %s)\n", ret, strerror(ret)); goto schedule; } if (dp_error != DP_ERR_OK || error != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Periodical full refresh of sudo rules " "failed [dp_error: %d] ([%d]: %s)\n", dp_error, error, strerror(error)); goto schedule; } schedule: sudo_ctx = tevent_req_callback_data(req, struct sdap_sudo_ctx); if (sudo_ctx->first_refresh_timer == req) { sudo_ctx->first_refresh_timer = NULL; } talloc_zfree(req); /* full refresh */ delay = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic, SDAP_SUDO_FULL_REFRESH_INTERVAL); if (delay == 0) { /* runtime configuration change? */ DEBUG(SSSDBG_TRACE_FUNC, "Periodical full refresh of sudo rules " "is disabled\n"); return; } /* if we are offline, we will try to perform another full refresh */ if (dp_error == DP_ERR_OFFLINE) { sudo_ctx->full_refresh_attempts++; timeout = delay; delay = sudo_ctx->full_refresh_attempts << 1; if (delay > SUDO_MAX_FIRST_REFRESH_DELAY) { delay = SUDO_MAX_FIRST_REFRESH_DELAY; } DEBUG(SSSDBG_TRACE_FUNC, "Data provider is offline. " "Scheduling another full refresh in %ld minutes.\n", delay); ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx, SDAP_SUDO_REFRESH_FULL, sdap_sudo_periodical_first_refresh_done, delay * 60, timeout, &sudo_ctx->first_refresh_timer); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule full refresh of sudo " "rules! Periodical updates will not work!\n"); } /* also setup online callback to make sure the refresh is fired as soon * as possible */ ret = be_add_online_cb(sudo_ctx->id_ctx->be, sudo_ctx->id_ctx->be, sdap_sudo_full_refresh_online_cb, sudo_ctx, &sudo_ctx->first_refresh_online_cb); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Could not set up online callback\n"); } return; } ret = sdap_sudo_schedule_full_refresh(sudo_ctx, delay); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Full periodical refresh will not work.\n"); } /* smart refresh */ delay = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic, SDAP_SUDO_SMART_REFRESH_INTERVAL); if (delay == 0) { /* runtime configuration change? */ DEBUG(SSSDBG_TRACE_FUNC, "Periodical smart refresh of sudo rules " "is disabled\n"); return; } ret = sdap_sudo_schedule_smart_refresh(sudo_ctx, delay); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Smart periodical refresh will not work.\n"); } }
static void assert_nondefault_int_set(struct dp_option *opts) { int i; i = dp_opt_get_int(opts, OPT_INT_NODEFAULT); assert_int_equal(i, 456); }
static int sdap_sudo_setup_periodical_refresh(struct sdap_sudo_ctx *sudo_ctx) { struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx; time_t smart_default; time_t smart_interval; time_t full_interval; time_t last_full; time_t delay; int ret; smart_interval = dp_opt_get_int(id_ctx->opts->basic, SDAP_SUDO_SMART_REFRESH_INTERVAL); full_interval = dp_opt_get_int(id_ctx->opts->basic, SDAP_SUDO_FULL_REFRESH_INTERVAL); if (smart_interval == 0 && full_interval == 0) { smart_default = id_ctx->opts->basic[SDAP_SUDO_SMART_REFRESH_INTERVAL].def_val.number; DEBUG(SSSDBG_MINOR_FAILURE, "At least one periodical update has to be " "enabled. Setting smart refresh interval to default value (%ld).\n", smart_default); ret = dp_opt_set_int(id_ctx->opts->basic, SDAP_SUDO_SMART_REFRESH_INTERVAL, smart_default); if (ret != EOK) { return ret; } } if (full_interval <= smart_interval) { DEBUG(SSSDBG_MINOR_FAILURE, "Full refresh interval has to be greater" "than smart refresh interval. Periodical full refresh will be " "disabled.\n"); ret = dp_opt_set_int(id_ctx->opts->basic, SDAP_SUDO_FULL_REFRESH_INTERVAL, 0); if (ret != EOK) { return ret; } } ret = sysdb_sudo_get_last_full_refresh(id_ctx->be->domain, &last_full); if (ret != EOK) { return ret; } if (last_full == 0) { /* If this is the first startup, we need to kick off * an refresh immediately, to close a window where * clients requesting sudo information won't get an * immediate reply with no entries */ delay = 0; } else { /* At least one update has previously run, * so clients will get cached data. * We will delay the refresh so we don't slow * down the startup process if this is happening * during system boot. */ /* delay at least by 10s */ delay = 10; } ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx, SDAP_SUDO_REFRESH_FULL, sdap_sudo_periodical_first_refresh_done, delay, full_interval, NULL); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule full refresh of sudo " "rules! Periodical updates will not work!\n"); return ret; } return EOK; }
errno_t sdap_sudo_ptask_setup_generic(struct be_ctx *be_ctx, struct dp_option *opts, be_ptask_send_t full_send_fn, be_ptask_recv_t full_recv_fn, be_ptask_send_t smart_send_fn, be_ptask_recv_t smart_recv_fn, void *pvt) { time_t smart; time_t full; time_t delay; time_t last_refresh; errno_t ret; smart = dp_opt_get_int(opts, SDAP_SUDO_SMART_REFRESH_INTERVAL); full = dp_opt_get_int(opts, SDAP_SUDO_FULL_REFRESH_INTERVAL); if (smart == 0 && full == 0) { /* We don't allow both types to be disabled. At least smart refresh * needs to be enabled. In this case smart refresh will catch up new * and modified rules and deleted rules are caught when expired. */ smart = opts[SDAP_SUDO_SMART_REFRESH_INTERVAL].def_val.number; DEBUG(SSSDBG_CONF_SETTINGS, "At least smart refresh needs to be " "enabled. Setting smart refresh interval to default value " "(%ld) seconds.\n", smart); } else if (full > 0 && full <= smart) { /* In this case it does not make any sense to run smart refresh. */ smart = 0; DEBUG(SSSDBG_CONF_SETTINGS, "Smart refresh interval has to be lower " "than full refresh interval. Periodical smart refresh will be " "disabled.\n"); } ret = sysdb_sudo_get_last_full_refresh(be_ctx->domain, &last_refresh); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Unable to obtain time of last full " "refresh. Assuming none was performed so far.\n"); last_refresh = 0; } if (last_refresh == 0) { /* If this is the first startup, we need to kick off an refresh * immediately, to close a window where clients requesting sudo * information won't get an immediate reply with no entries */ delay = 0; } else { /* At least one update has previously run, so clients will get cached * data. We will delay the refresh so we don't slow down the startup * process if this is happening during system boot. */ delay = 10; } /* Full refresh. * * Disable when offline and run immediately when SSSD goes back online. * Since we have periodical online check we don't have to run this task * when offline. */ if (full > 0) { ret = be_ptask_create(be_ctx, be_ctx, full, delay, 0, 0, full, BE_PTASK_OFFLINE_DISABLE, 0, full_send_fn, full_recv_fn, pvt, "SUDO Full Refresh", NULL); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup full refresh ptask " "[%d]: %s\n", ret, sss_strerror(ret)); return ret; } } /* Smart refresh. * * Disable when offline and reschedule normally when SSSD goes back online. * Since we have periodical online check we don't have to run this task * when offline. */ if (smart > 0) { ret = be_ptask_create(be_ctx, be_ctx, smart, delay + smart, smart, 0, smart, BE_PTASK_OFFLINE_DISABLE, 0, smart_send_fn, smart_recv_fn, pvt, "SUDO Smart Refresh", NULL); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup smart refresh ptask " "[%d]: %s\n", ret, sss_strerror(ret)); return ret; } } return EOK; }
int ldap_get_options(TALLOC_CTX *memctx, struct sss_domain_info *dom, struct confdb_ctx *cdb, const char *conf_path, struct data_provider *dp, struct sdap_options **_opts) { struct sdap_attr_map *default_attr_map; struct sdap_attr_map *default_user_map; struct sdap_attr_map *default_group_map; struct sdap_attr_map *default_netgroup_map; struct sdap_attr_map *default_host_map; struct sdap_attr_map *default_service_map; struct sdap_options *opts; char *schema; char *pwmodify; const char *search_base; const char *pwd_policy; int ret; int account_cache_expiration; int offline_credentials_expiration; const char *ldap_deref; int ldap_deref_val; int o; const char *authtok_type; struct dp_opt_blob authtok_blob; char *cleartext; const int search_base_options[] = { SDAP_USER_SEARCH_BASE, SDAP_GROUP_SEARCH_BASE, SDAP_NETGROUP_SEARCH_BASE, SDAP_HOST_SEARCH_BASE, SDAP_SERVICE_SEARCH_BASE, -1 }; opts = talloc_zero(memctx, struct sdap_options); if (!opts) return ENOMEM; opts->dp = dp; ret = sdap_domain_add(opts, dom, NULL); if (ret != EOK) { goto done; } ret = dp_get_options(opts, cdb, conf_path, default_basic_opts, SDAP_OPTS_BASIC, &opts->basic); if (ret != EOK) { goto done; } /* Handle search bases */ search_base = dp_opt_get_string(opts->basic, SDAP_SEARCH_BASE); if (search_base != NULL) { /* set user/group/netgroup search bases if they are not */ for (o = 0; search_base_options[o] != -1; o++) { if (NULL == dp_opt_get_string(opts->basic, search_base_options[o])) { ret = dp_opt_set_string(opts->basic, search_base_options[o], search_base); if (ret != EOK) { goto done; } DEBUG(SSSDBG_TRACE_FUNC, "Option %s set to %s\n", opts->basic[search_base_options[o]].opt_name, dp_opt_get_string(opts->basic, search_base_options[o])); } } } else { DEBUG(SSSDBG_FUNC_DATA, "Search base not set, trying to discover it later when " "connecting to the LDAP server.\n"); } /* Default search */ ret = sdap_parse_search_base(opts, opts->basic, SDAP_SEARCH_BASE, &opts->sdom->search_bases); if (ret != EOK && ret != ENOENT) goto done; /* User search */ ret = sdap_parse_search_base(opts, opts->basic, SDAP_USER_SEARCH_BASE, &opts->sdom->user_search_bases); if (ret != EOK && ret != ENOENT) goto done; /* Group search base */ ret = sdap_parse_search_base(opts, opts->basic, SDAP_GROUP_SEARCH_BASE, &opts->sdom->group_search_bases); if (ret != EOK && ret != ENOENT) goto done; /* Netgroup search */ ret = sdap_parse_search_base(opts, opts->basic, SDAP_NETGROUP_SEARCH_BASE, &opts->sdom->netgroup_search_bases); if (ret != EOK && ret != ENOENT) goto done; /* Netgroup search */ ret = sdap_parse_search_base(opts, opts->basic, SDAP_HOST_SEARCH_BASE, &opts->sdom->host_search_bases); if (ret != EOK && ret != ENOENT) goto done; /* Service search */ ret = sdap_parse_search_base(opts, opts->basic, SDAP_SERVICE_SEARCH_BASE, &opts->sdom->service_search_bases); if (ret != EOK && ret != ENOENT) goto done; pwd_policy = dp_opt_get_string(opts->basic, SDAP_PWD_POLICY); if (pwd_policy == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Missing password policy, this may not happen.\n"); ret = EINVAL; goto done; } if (strcasecmp(pwd_policy, PWD_POL_OPT_NONE) != 0 && strcasecmp(pwd_policy, PWD_POL_OPT_SHADOW) != 0 && strcasecmp(pwd_policy, PWD_POL_OPT_MIT) != 0) { DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported password policy [%s].\n", pwd_policy); ret = EINVAL; goto done; } /* account_cache_expiration must be >= than offline_credentials_expiration */ ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY, CONFDB_PAM_CRED_TIMEOUT, 0, &offline_credentials_expiration); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot get value of %s from confdb \n", CONFDB_PAM_CRED_TIMEOUT); goto done; } account_cache_expiration = dp_opt_get_int(opts->basic, SDAP_ACCOUNT_CACHE_EXPIRATION); /* account cache_expiration must not be smaller than * offline_credentials_expiration to prevent deleting entries that * still contain credentials valid for offline login. * * offline_credentials_expiration == 0 is a special case that says * that the cached credentials are valid forever. Therefore, the cached * entries must not be purged from cache. */ if (!offline_credentials_expiration && account_cache_expiration) { DEBUG(SSSDBG_CRIT_FAILURE, "Conflicting values for options %s (unlimited) " "and %s (%d)\n", opts->basic[SDAP_ACCOUNT_CACHE_EXPIRATION].opt_name, CONFDB_PAM_CRED_TIMEOUT, offline_credentials_expiration); ret = EINVAL; goto done; } if (offline_credentials_expiration && account_cache_expiration && offline_credentials_expiration > account_cache_expiration) { DEBUG(SSSDBG_CRIT_FAILURE, "Value of %s (now %d) must be larger " "than value of %s (now %d)\n", opts->basic[SDAP_ACCOUNT_CACHE_EXPIRATION].opt_name, account_cache_expiration, CONFDB_PAM_CRED_TIMEOUT, offline_credentials_expiration); ret = EINVAL; goto done; } ldap_deref = dp_opt_get_string(opts->basic, SDAP_DEREF); if (ldap_deref != NULL) { ret = deref_string_to_val(ldap_deref, &ldap_deref_val); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to verify ldap_deref option.\n"); goto done; } } #ifndef HAVE_LDAP_CONNCB bool ldap_referrals; ldap_referrals = dp_opt_get_bool(opts->basic, SDAP_REFERRALS); if (ldap_referrals) { DEBUG(SSSDBG_CRIT_FAILURE, "LDAP referrals are not supported, because the LDAP library " "is too old, see sssd-ldap(5) for details.\n"); ret = dp_opt_set_bool(opts->basic, SDAP_REFERRALS, false); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "dp_opt_set_string failed.\n"); goto done; } } #endif /* schema type */ schema = dp_opt_get_string(opts->basic, SDAP_SCHEMA); if (strcasecmp(schema, "rfc2307") == 0) { opts->schema_type = SDAP_SCHEMA_RFC2307; default_attr_map = generic_attr_map; default_user_map = rfc2307_user_map; default_group_map = rfc2307_group_map; default_netgroup_map = netgroup_map; default_host_map = host_map; default_service_map = service_map; } else if (strcasecmp(schema, "rfc2307bis") == 0) { opts->schema_type = SDAP_SCHEMA_RFC2307BIS; default_attr_map = generic_attr_map; default_user_map = rfc2307bis_user_map; default_group_map = rfc2307bis_group_map; default_netgroup_map = netgroup_map; default_host_map = host_map; default_service_map = service_map; } else if (strcasecmp(schema, "IPA") == 0) { opts->schema_type = SDAP_SCHEMA_IPA_V1; default_attr_map = gen_ipa_attr_map; default_user_map = rfc2307bis_user_map; default_group_map = rfc2307bis_group_map; default_netgroup_map = netgroup_map; default_host_map = host_map; default_service_map = service_map; } else if (strcasecmp(schema, "AD") == 0) { opts->schema_type = SDAP_SCHEMA_AD; default_attr_map = gen_ad_attr_map; default_user_map = gen_ad2008r2_user_map; default_group_map = gen_ad2008r2_group_map; default_netgroup_map = netgroup_map; default_host_map = host_map; default_service_map = service_map; } else { DEBUG(SSSDBG_FATAL_FAILURE, "Unrecognized schema type: %s\n", schema); ret = EINVAL; goto done; } /* pwmodify mode */ pwmodify = dp_opt_get_string(opts->basic, SDAP_PWMODIFY_MODE); if (strcasecmp(pwmodify, "exop") == 0) { opts->pwmodify_mode = SDAP_PWMODIFY_EXOP; } else if (strcasecmp(pwmodify, "ldap_modify") == 0) { opts->pwmodify_mode = SDAP_PWMODIFY_LDAP; } else { DEBUG(SSSDBG_FATAL_FAILURE, "Unrecognized pwmodify mode: %s\n", pwmodify); ret = EINVAL; goto done; } ret = sdap_get_map(opts, cdb, conf_path, default_attr_map, SDAP_AT_GENERAL, &opts->gen_map); if (ret != EOK) { goto done; } ret = sdap_get_map(opts, cdb, conf_path, default_user_map, SDAP_OPTS_USER, &opts->user_map); if (ret != EOK) { goto done; } ret = sdap_extend_map_with_list(opts, opts, SDAP_USER_EXTRA_ATTRS, opts->user_map, SDAP_OPTS_USER, &opts->user_map, &opts->user_map_cnt); if (ret != EOK) { goto done; } ret = sdap_get_map(opts, cdb, conf_path, default_group_map, SDAP_OPTS_GROUP, &opts->group_map); if (ret != EOK) { goto done; } ret = sdap_get_map(opts, cdb, conf_path, default_netgroup_map, SDAP_OPTS_NETGROUP, &opts->netgroup_map); if (ret != EOK) { goto done; } ret = sdap_get_map(opts, cdb, conf_path, default_host_map, SDAP_OPTS_HOST, &opts->host_map); if (ret != EOK) { goto done; } ret = sdap_get_map(opts, cdb, conf_path, default_service_map, SDAP_OPTS_SERVICES, &opts->service_map); if (ret != EOK) { goto done; } /* If there is no KDC, try the deprecated krb5_kdcip option, too */ /* FIXME - this can be removed in a future version */ ret = krb5_try_kdcip(cdb, conf_path, opts->basic, SDAP_KRB5_KDC); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "sss_krb5_try_kdcip failed.\n"); goto done; } authtok_type = dp_opt_get_string(opts->basic, SDAP_DEFAULT_AUTHTOK_TYPE); if (authtok_type != NULL && strcasecmp(authtok_type,"obfuscated_password") == 0) { DEBUG(SSSDBG_TRACE_ALL, "Found obfuscated password, " "trying to convert to cleartext.\n"); authtok_blob = dp_opt_get_blob(opts->basic, SDAP_DEFAULT_AUTHTOK); if (authtok_blob.data == NULL || authtok_blob.length == 0) { DEBUG(SSSDBG_CRIT_FAILURE, "Missing obfuscated password string.\n"); ret = EINVAL; goto done; } ret = sss_password_decrypt(memctx, (char *) authtok_blob.data, &cleartext); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot convert the obfuscated " "password back to cleartext\n"); goto done; } authtok_blob.data = (uint8_t *) cleartext; authtok_blob.length = strlen(cleartext); ret = dp_opt_set_blob(opts->basic, SDAP_DEFAULT_AUTHTOK, authtok_blob); talloc_free(cleartext); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "dp_opt_set_string failed.\n"); goto done; } ret = dp_opt_set_string(opts->basic, SDAP_DEFAULT_AUTHTOK_TYPE, "password"); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "dp_opt_set_string failed.\n"); goto done; } } ret = EOK; *_opts = opts; done: if (ret != EOK) { talloc_zfree(opts); } return ret; }