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); }
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); }
void opt_test_inherit(void **state) { struct dp_option *opts = talloc_get_type(*state, struct dp_option); int ret; struct dp_option *opts_copy; const char *s; const char *sd_inherit_match[] = { "string_nodefault", "blob_nodefault", "int_nodefault", "bool_true", NULL }; ret = dp_copy_defaults(opts, test_def_opts, OPT_NUM_OPTS, &opts_copy); assert_int_equal(ret, EOK); assert_defaults(opts); dp_option_inherit(NULL, OPT_STRING_NODEFAULT, opts, opts_copy); s = dp_opt_get_string(opts_copy, OPT_STRING_NODEFAULT); assert_null(s); /* string */ assert_nondefault_string_empty(opts_copy); set_nondefault_string(opts); dp_option_inherit(discard_const(sd_inherit_match), OPT_STRING_NODEFAULT, opts, opts_copy); check_nondefault_string(opts_copy); /* blob */ assert_nondefault_blob_empty(opts_copy); set_nondefault_blob(opts); dp_option_inherit(discard_const(sd_inherit_match), OPT_BLOB_NODEFAULT, opts, opts_copy); check_nondefault_blob(opts_copy); /* number */ assert_nondefault_int_notset(opts_copy); set_nondefault_int(opts); dp_option_inherit(discard_const(sd_inherit_match), OPT_INT_NODEFAULT, opts, opts_copy); assert_nondefault_int_set(opts_copy); /* bool */ assert_true(dp_opt_get_bool(opts_copy, OPT_BOOL_TRUE)); ret = dp_opt_set_bool(opts, OPT_BOOL_TRUE, false); assert_int_equal(ret, EOK); dp_option_inherit(discard_const(sd_inherit_match), OPT_BOOL_TRUE, opts, opts_copy); assert_false(dp_opt_get_bool(opts_copy, OPT_BOOL_TRUE)); }
int ldap_get_sudo_options(struct confdb_ctx *cdb, const char *conf_path, struct sdap_options *opts, bool *use_host_filter, bool *include_regexp, bool *include_netgroups) { const char *search_base; int ret; /* search base */ search_base = dp_opt_get_string(opts->basic, SDAP_SEARCH_BASE); if (search_base != NULL) { /* set sudo search bases if they are not */ if (dp_opt_get_string(opts->basic, SDAP_SUDO_SEARCH_BASE) == NULL) { ret = dp_opt_set_string(opts->basic, SDAP_SUDO_SEARCH_BASE, search_base); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Could not set SUDO search base" "to default value\n"); return ret; } DEBUG(SSSDBG_FUNC_DATA, "Option %s set to %s\n", opts->basic[SDAP_SUDO_SEARCH_BASE].opt_name, dp_opt_get_string(opts->basic, SDAP_SUDO_SEARCH_BASE)); } } else { DEBUG(SSSDBG_TRACE_FUNC, "Search base not set, trying to discover it later " "connecting to the LDAP server.\n"); } ret = sdap_parse_search_base(opts, opts->basic, SDAP_SUDO_SEARCH_BASE, &opts->sdom->sudo_search_bases); if (ret != EOK && ret != ENOENT) { DEBUG(SSSDBG_OP_FAILURE, "Could not parse SUDO search base\n"); return ret; } /* attrs map */ ret = sdap_get_map(opts, cdb, conf_path, native_sudorule_map, SDAP_OPTS_SUDO, &opts->sudorule_map); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Could not get SUDO attribute map\n"); return ret; } /* host filter */ *use_host_filter = dp_opt_get_bool(opts->basic, SDAP_SUDO_USE_HOST_FILTER); *include_netgroups = dp_opt_get_bool(opts->basic, SDAP_SUDO_INCLUDE_NETGROUPS); *include_regexp = dp_opt_get_bool(opts->basic, SDAP_SUDO_INCLUDE_REGEXP); return EOK; }
void opt_test_getset_bool(void **state) { struct dp_option *opts = talloc_get_type(*state, struct dp_option); int ret; bool b; b = dp_opt_get_bool(opts, OPT_BOOL_TRUE); assert_true(b == true); ret = dp_opt_set_bool(opts, OPT_BOOL_TRUE, false); assert_int_equal(ret, EOK); b = dp_opt_get_bool(opts, OPT_BOOL_TRUE); assert_false(b == true); }
static void ipa_account_info_done(struct tevent_req *req) { struct be_req *breq = tevent_req_callback_data(req, struct be_req); struct be_ctx *be_ctx = be_req_get_be_ctx(breq); struct ipa_id_ctx *ipa_ctx; struct be_acct_req *ar = talloc_get_type(be_req_get_data(breq), struct be_acct_req); const char *error_text; int ret, dp_error; ipa_ctx = talloc_get_type(be_ctx->bet_info[BET_ID].pvt_bet_data, struct ipa_id_ctx); if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_NETGROUP) { ret = ipa_id_get_netgroup_recv(req, &dp_error); } else { if (dp_opt_get_bool(ipa_ctx->ipa_options->basic, IPA_SERVER_MODE)) { ret = ipa_get_ad_acct_recv(req, &dp_error); } else { ret = ipa_get_subdom_acct_recv(req, &dp_error); } } talloc_zfree(req); error_text = ipa_account_info_error_text(ret, &dp_error, "Account info lookup failed"); sdap_handler_done(breq, dp_error, ret, error_text); }
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); }
errno_t ad_dyndns_init(struct be_ctx *be_ctx, struct ad_options *ad_opts) { errno_t ret; /* nsupdate is available. Dynamic updates * are supported */ ret = ad_get_dyndns_options(be_ctx, ad_opts); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("Could not set AD options\n")); return ret; } if (dp_opt_get_bool(ad_opts->dyndns_ctx->opts, DP_OPT_DYNDNS_UPDATE) == false) { DEBUG(SSSDBG_CONF_SETTINGS, ("Dynamic DNS updates not set\n")); return EOK; } DEBUG(SSSDBG_CONF_SETTINGS, ("Dynamic DNS updates are on. Checking for nsupdate..\n")); ret = be_nsupdate_check(); if (ret == ENOENT) { DEBUG(SSSDBG_MINOR_FAILURE, ("DNS updates requested but nsupdate not available\n")); return EOK; } else if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("Could not check for nsupdate\n")); return ret; } ad_opts->be_res = be_ctx->be_res; if (ad_opts->be_res == NULL) { DEBUG(SSSDBG_OP_FAILURE, ("Resolver must be initialized in order " "to use the AD dynamic DNS updates\n")); return EINVAL; } ret = be_nsupdate_init_timer(ad_opts->dyndns_ctx, be_ctx->ev, ad_dyndns_timer, ad_opts); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("Could not set up periodic update\n")); return ret; } ret = be_add_online_cb(be_ctx, be_ctx, ad_dyndns_update, ad_opts, NULL); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("Could not set up online callback\n")); return ret; } return EOK; }
static errno_t krb5_init_kpasswd(struct krb5_ctx *ctx, struct be_ctx *be_ctx) { const char *realm; const char *primary_servers; const char *backup_servers; const char *kdc_servers; bool use_kdcinfo; size_t n_lookahead_primary; size_t n_lookahead_backup; errno_t ret; realm = dp_opt_get_string(ctx->opts, KRB5_REALM); if (realm == NULL) { DEBUG(SSSDBG_FATAL_FAILURE, "Missing krb5_realm option!\n"); return EINVAL; } kdc_servers = dp_opt_get_string(ctx->opts, KRB5_KDC); primary_servers = dp_opt_get_string(ctx->opts, KRB5_KPASSWD); backup_servers = dp_opt_get_string(ctx->opts, KRB5_BACKUP_KPASSWD); use_kdcinfo = dp_opt_get_bool(ctx->opts, KRB5_USE_KDCINFO); sss_krb5_parse_lookahead(dp_opt_get_string(ctx->opts, KRB5_KDCINFO_LOOKAHEAD), &n_lookahead_primary, &n_lookahead_backup); if (primary_servers == NULL && backup_servers != NULL) { DEBUG(SSSDBG_CONF_SETTINGS, "kpasswd server wasn't specified but " "backup_servers kpasswd given. Using it as primary_servers\n"); primary_servers = backup_servers; backup_servers = NULL; } if (primary_servers == NULL && kdc_servers != NULL) { DEBUG(SSSDBG_FATAL_FAILURE, "Missing krb5_kpasswd option and KDC set " "explicitly, will use KDC for pasword change operations!\n"); ctx->kpasswd_service = NULL; } else { ret = krb5_service_init(ctx, be_ctx, SSS_KRB5KPASSWD_FO_SRV, primary_servers, backup_servers, realm, use_kdcinfo, n_lookahead_primary, n_lookahead_backup, &ctx->kpasswd_service); if (ret != EOK) { DEBUG(SSSDBG_FATAL_FAILURE, "Failed to init KRB5KPASSWD failover service!\n"); return ret; } } return EOK; }
void ipa_account_info_handler(struct be_req *breq) { struct be_ctx *be_ctx = be_req_get_be_ctx(breq); struct ipa_id_ctx *ipa_ctx; struct sdap_id_ctx *ctx; struct be_acct_req *ar; struct tevent_req *req = NULL; ipa_ctx = talloc_get_type(be_ctx->bet_info[BET_ID].pvt_bet_data, struct ipa_id_ctx); ctx = ipa_ctx->sdap_id_ctx; if (be_is_offline(ctx->be)) { return sdap_handler_done(breq, DP_ERR_OFFLINE, EAGAIN, "Offline"); } ar = talloc_get_type(be_req_get_data(breq), struct be_acct_req); if (strcasecmp(ar->domain, be_ctx->domain->name) != 0) { /* if domain names do not match, this is a subdomain case * subdomain lookups are handled differently on the server * and the client */ if (dp_opt_get_bool(ipa_ctx->ipa_options->basic, IPA_SERVER_MODE)) { req = ipa_get_ad_acct_send(breq, be_ctx->ev, ipa_ctx, breq, ar); } else { req = ipa_get_subdom_acct_send(breq, be_ctx->ev, ctx, ar); } } else if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_NETGROUP) { /* netgroups are handled by a separate request function */ if (ar->filter_type != BE_FILTER_NAME) { return sdap_handler_done(breq, DP_ERR_FATAL, EINVAL, "Invalid filter type"); } req = ipa_id_get_netgroup_send(breq, be_ctx->ev, ipa_ctx, ar->filter_value); } else { /* any account request is handled by sdap, * any invalid request is caught there. */ return sdap_handle_account_info(breq, ctx, ctx->conn); } if (!req) { return sdap_handler_done(breq, DP_ERR_FATAL, ENOMEM, "Out of memory"); } tevent_req_set_callback(req, ipa_account_info_done, breq); }
static int hbac_get_host_info_step(struct hbac_ctx *hbac_ctx) { struct be_ctx *be_ctx = be_req_get_be_ctx(hbac_ctx->be_req); const char *hostname; struct tevent_req *req; if (dp_opt_get_bool(hbac_ctx->ipa_options, IPA_HBAC_SUPPORT_SRCHOST)) { /* Support srchost * -> we don't want any particular host, * we want all hosts */ hostname = NULL; /* THIS FEATURE IS DEPRECATED */ DEBUG(SSSDBG_MINOR_FAILURE, ("WARNING: Using deprecated option " "ipa_hbac_support_srchost.\n")); sss_log(SSS_LOG_NOTICE, "WARNING: Using deprecated option " "ipa_hbac_support_srchost.\n"); } else { hostname = dp_opt_get_string(hbac_ctx->ipa_options, IPA_HOSTNAME); } req = ipa_host_info_send(hbac_ctx, be_ctx->ev, sdap_id_op_handle(hbac_ctx->sdap_op), hbac_ctx->sdap_ctx->opts, hostname, hbac_ctx->access_ctx->host_map, hbac_ctx->access_ctx->hostgroup_map, hbac_ctx->access_ctx->host_search_bases); if (req == NULL) { DEBUG(1, ("Could not get host info\n")); return ENOMEM; } tevent_req_set_callback(req, hbac_get_service_info_step, hbac_ctx); return EOK; }
static errno_t krb5_init_kdc(struct krb5_ctx *ctx, struct be_ctx *be_ctx) { const char *primary_servers; const char *backup_servers; const char *realm; bool use_kdcinfo; size_t n_lookahead_primary; size_t n_lookahead_backup; errno_t ret; realm = dp_opt_get_string(ctx->opts, KRB5_REALM); if (realm == NULL) { DEBUG(SSSDBG_FATAL_FAILURE, "Missing krb5_realm option!\n"); return EINVAL; } primary_servers = dp_opt_get_string(ctx->opts, KRB5_KDC); backup_servers = dp_opt_get_string(ctx->opts, KRB5_BACKUP_KDC); use_kdcinfo = dp_opt_get_bool(ctx->opts, KRB5_USE_KDCINFO); sss_krb5_parse_lookahead(dp_opt_get_string(ctx->opts, KRB5_KDCINFO_LOOKAHEAD), &n_lookahead_primary, &n_lookahead_backup); ret = krb5_service_init(ctx, be_ctx, SSS_KRB5KDC_FO_SRV, primary_servers, backup_servers, realm, use_kdcinfo, n_lookahead_primary, n_lookahead_backup, &ctx->service); if (ret != EOK) { DEBUG(SSSDBG_FATAL_FAILURE, "Failed to init KRB5 failover service!\n"); return ret; } 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; }
/* FIXME: support storing additional attributes */ int sdap_save_user(TALLOC_CTX *memctx, struct sdap_options *opts, struct sss_domain_info *dom, struct sysdb_attrs *attrs, char **_usn_value, time_t now) { struct ldb_message_element *el; int ret; const char *user_name = NULL; const char *fullname = NULL; const char *pwd; const char *gecos; const char *homedir; const char *shell; const char *orig_dn = NULL; uid_t uid; gid_t gid; struct sysdb_attrs *user_attrs; char *upn = NULL; size_t i; int cache_timeout; char *usn_value = NULL; char **missing = NULL; TALLOC_CTX *tmpctx = NULL; bool use_id_mapping; char *sid_str; char *dom_sid_str = NULL; struct sss_domain_info *subdomain; DEBUG(SSSDBG_TRACE_FUNC, "Save user\n"); tmpctx = talloc_new(NULL); if (!tmpctx) { ret = ENOMEM; goto done; } user_attrs = sysdb_new_attrs(tmpctx); if (user_attrs == NULL) { ret = ENOMEM; goto done; } /* Always store SID string if available */ ret = sdap_attrs_get_sid_str(tmpctx, opts->idmap_ctx, attrs, opts->user_map[SDAP_AT_USER_OBJECTSID].sys_name, &sid_str); if (ret == EOK) { ret = sysdb_attrs_add_string(user_attrs, SYSDB_SID_STR, sid_str); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Could not add SID string: [%s]\n", sss_strerror(ret)); goto done; } } else if (ret == ENOENT) { DEBUG(SSSDBG_TRACE_ALL, "objectSID: not available for user\n"); sid_str = NULL; } else { DEBUG(SSSDBG_MINOR_FAILURE, "Could not identify objectSID: [%s]\n", sss_strerror(ret)); sid_str = NULL; } /* Always store UUID if available */ ret = sysdb_handle_original_uuid(opts->user_map[SDAP_AT_USER_UUID].def_name, attrs, opts->user_map[SDAP_AT_USER_UUID].sys_name, user_attrs, SYSDB_UUID); if (ret != EOK) { DEBUG((ret == ENOENT) ? SSSDBG_TRACE_ALL : SSSDBG_MINOR_FAILURE, "Failed to retrieve UUID [%d][%s].\n", ret, sss_strerror(ret)); } /* If this object has a SID available, we will determine the correct * domain by its SID. */ if (sid_str != NULL) { subdomain = find_domain_by_sid(get_domains_head(dom), sid_str); if (subdomain) { dom = subdomain; } else { DEBUG(SSSDBG_TRACE_FUNC, "SID %s does not belong to any known " "domain\n", sid_str); } } ret = sdap_get_user_primary_name(memctx, opts, attrs, dom, &user_name); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Failed to get user name\n"); goto done; } DEBUG(SSSDBG_TRACE_FUNC, "Processing user %s\n", user_name); if (opts->schema_type == SDAP_SCHEMA_AD) { ret = sysdb_attrs_get_string(attrs, opts->user_map[SDAP_AT_USER_FULLNAME].sys_name, &fullname); if (ret == EOK) { ret = sysdb_attrs_add_string(user_attrs, SYSDB_FULLNAME, fullname); if (ret != EOK) { goto done; } } else if (ret != ENOENT) { goto done; } } ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_PWD].sys_name, &el); if (ret) goto done; if (el->num_values == 0) pwd = NULL; else pwd = (const char *)el->values[0].data; ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_GECOS].sys_name, &el); if (ret) goto done; if (el->num_values == 0) gecos = NULL; else gecos = (const char *)el->values[0].data; if (!gecos) { /* Fall back to the user's full name */ ret = sysdb_attrs_get_el( attrs, opts->user_map[SDAP_AT_USER_FULLNAME].sys_name, &el); if (ret) goto done; if (el->num_values > 0) gecos = (const char *)el->values[0].data; } ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_HOME].sys_name, &el); if (ret) goto done; if (el->num_values == 0) homedir = NULL; else homedir = (const char *)el->values[0].data; ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_SHELL].sys_name, &el); if (ret) goto done; if (el->num_values == 0) shell = NULL; else shell = (const char *)el->values[0].data; use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(opts->idmap_ctx, dom->name, sid_str); /* Retrieve or map the UID as appropriate */ if (use_id_mapping) { if (sid_str == NULL) { DEBUG(SSSDBG_MINOR_FAILURE, "SID not available, cannot map a " \ "unix ID to user [%s].\n", user_name); ret = ENOENT; goto done; } DEBUG(SSSDBG_TRACE_LIBS, "Mapping user [%s] objectSID [%s] to unix ID\n", user_name, sid_str); /* Convert the SID into a UNIX user ID */ ret = sdap_idmap_sid_to_unix(opts->idmap_ctx, sid_str, &uid); if (ret == ENOTSUP) { DEBUG(SSSDBG_TRACE_FUNC, "Skipping built-in object.\n"); ret = EOK; goto done; } else if (ret != EOK) { goto done; } /* Store the UID in the ldap_attrs so it doesn't get * treated as a missing attribute from LDAP and removed. */ ret = sdap_replace_id(attrs, SYSDB_UIDNUM, uid); if (ret) { DEBUG(SSSDBG_OP_FAILURE, "Cannot set the id-mapped UID\n"); goto done; } } else { ret = sysdb_attrs_get_uint32_t(attrs, opts->user_map[SDAP_AT_USER_UID].sys_name, &uid); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "no uid provided for [%s] in domain [%s].\n", user_name, dom->name); ret = EINVAL; goto done; } } /* check that the uid is valid for this domain */ if (OUT_OF_ID_RANGE(uid, dom->id_min, dom->id_max)) { DEBUG(SSSDBG_OP_FAILURE, "User [%s] filtered out! (uid out of range)\n", user_name); ret = EINVAL; goto done; } if (use_id_mapping) { ret = sdap_get_idmap_primary_gid(opts, attrs, sid_str, dom_sid_str, &gid); if (ret) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot get the GID for [%s] in domain [%s].\n", user_name, dom->name); goto done; } if (IS_SUBDOMAIN(dom)) { /* For subdomain users, only create the private group as * the subdomain is an MPG domain. * But we have to save the GID of the original primary group * becasuse otherwise this information might be lost because * typically (Unix and AD) the user is not listed in his primary * group as a member. */ ret = sysdb_attrs_add_uint32(user_attrs, SYSDB_PRIMARY_GROUP_GIDNUM, (uint32_t) gid); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_uint32 failed.\n"); goto done; } gid = 0; } /* Store the GID in the ldap_attrs so it doesn't get * treated as a missing attribute from LDAP and removed. */ ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, gid); if (ret != EOK) goto done; } else { ret = sysdb_attrs_get_uint32_t(attrs, opts->user_map[SDAP_AT_USER_GID].sys_name, &gid); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "no gid provided for [%s] in domain [%s].\n", user_name, dom->name); ret = EINVAL; goto done; } } /* check that the gid is valid for this domain */ if (IS_SUBDOMAIN(dom) == false && OUT_OF_ID_RANGE(gid, dom->id_min, dom->id_max)) { DEBUG(SSSDBG_CRIT_FAILURE, "User [%s] filtered out! (primary gid out of range)\n", user_name); ret = EINVAL; goto done; } ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el); if (ret) { goto done; } if (!el || el->num_values == 0) { DEBUG(SSSDBG_MINOR_FAILURE, "originalDN is not available for [%s].\n", user_name); } else { orig_dn = (const char *) el->values[0].data; DEBUG(SSSDBG_TRACE_INTERNAL, "Adding originalDN [%s] to attributes " "of [%s].\n", orig_dn, user_name); ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_DN, orig_dn); if (ret) { goto done; } } ret = sysdb_attrs_get_el(attrs, SYSDB_MEMBEROF, &el); if (ret) { goto done; } if (el->num_values == 0) { DEBUG(SSSDBG_TRACE_FUNC, "Original memberOf is not available for [%s].\n", user_name); } else { DEBUG(SSSDBG_TRACE_FUNC, "Adding original memberOf attributes to [%s].\n", user_name); for (i = 0; i < el->num_values; i++) { ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_MEMBEROF, (const char *) el->values[i].data); if (ret) { goto done; } } } ret = sdap_attrs_add_string(attrs, opts->user_map[SDAP_AT_USER_MODSTAMP].sys_name, "original mod-Timestamp", user_name, user_attrs); if (ret != EOK) { goto done; } ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_USN].sys_name, &el); if (ret) { goto done; } if (el->num_values == 0) { DEBUG(SSSDBG_TRACE_FUNC, "Original USN value is not available for [%s].\n", user_name); } else { ret = sysdb_attrs_add_string(user_attrs, opts->user_map[SDAP_AT_USER_USN].sys_name, (const char*)el->values[0].data); if (ret) { goto done; } usn_value = talloc_strdup(tmpctx, (const char*)el->values[0].data); if (!usn_value) { ret = ENOMEM; goto done; } } ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_PRINC].sys_name, &el); if (ret) { goto done; } if (el->num_values == 0) { DEBUG(SSSDBG_TRACE_FUNC, "User principal is not available for [%s].\n", user_name); } else { upn = talloc_strdup(user_attrs, (const char*) el->values[0].data); if (!upn) { ret = ENOMEM; goto done; } if (dp_opt_get_bool(opts->basic, SDAP_FORCE_UPPER_CASE_REALM)) { make_realm_upper_case(upn); } DEBUG(SSSDBG_TRACE_FUNC, "Adding user principal [%s] to attributes of [%s].\n", upn, user_name); ret = sysdb_attrs_add_string(user_attrs, SYSDB_UPN, upn); if (ret) { goto done; } } for (i = SDAP_FIRST_EXTRA_USER_AT; i < opts->user_map_cnt; i++) { ret = sdap_attrs_add_list(attrs, opts->user_map[i].sys_name, NULL, user_name, user_attrs); if (ret) { goto done; } } cache_timeout = dom->user_timeout; ret = sdap_save_all_names(user_name, attrs, dom, user_attrs); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to save user names\n"); goto done; } /* Make sure that any attributes we requested from LDAP that we * did not receive are also removed from the sysdb */ ret = list_missing_attrs(user_attrs, opts->user_map, opts->user_map_cnt, attrs, &missing); if (ret != EOK) { goto done; } DEBUG(SSSDBG_TRACE_FUNC, "Storing info for user %s\n", user_name); ret = sysdb_store_user(dom, user_name, pwd, uid, gid, gecos, homedir, shell, orig_dn, user_attrs, missing, cache_timeout, now); if (ret) goto done; if (_usn_value) { *_usn_value = talloc_steal(memctx, usn_value); } talloc_steal(memctx, user_attrs); ret = EOK; done: if (ret) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to save user [%s]\n", user_name ? user_name : "Unknown"); } talloc_free(tmpctx); return ret; }
int sssm_ldap_id_init(struct be_ctx *bectx, struct bet_ops **ops, void **pvt_data) { struct sdap_id_ctx *ctx; const char *urls; const char *dns_service_name; const char *sasl_mech; int ret; /* If we're already set up, just return that */ if(bectx->bet_info[BET_ID].mod_name && strcmp("ldap", bectx->bet_info[BET_ID].mod_name) == 0) { DEBUG(8, ("Re-using sdap_id_ctx for this provider\n")); *ops = bectx->bet_info[BET_ID].bet_ops; *pvt_data = bectx->bet_info[BET_ID].pvt_bet_data; return EOK; } ctx = talloc_zero(bectx, struct sdap_id_ctx); if (!ctx) return ENOMEM; ctx->be = bectx; ret = ldap_get_options(ctx, bectx->cdb, bectx->conf_path, &ctx->opts); if (ret != EOK) { goto done; } dns_service_name = dp_opt_get_string(ctx->opts->basic, SDAP_DNS_SERVICE_NAME); DEBUG(7, ("Service name for discovery set to %s\n", dns_service_name)); urls = dp_opt_get_string(ctx->opts->basic, SDAP_URI); if (!urls) { DEBUG(1, ("Missing ldap_uri, will use service discovery\n")); } ret = sdap_service_init(ctx, ctx->be, "LDAP", dns_service_name, urls, &ctx->service); if (ret != EOK) { DEBUG(1, ("Failed to initialize failover service!\n")); goto done; } sasl_mech = dp_opt_get_string(ctx->opts->basic, SDAP_SASL_MECH); if (sasl_mech && strcasecmp(sasl_mech, "GSSAPI") == 0) { if (dp_opt_get_bool(ctx->opts->basic, SDAP_KRB5_KINIT)) { ret = sdap_gssapi_init(ctx, ctx->opts->basic, ctx->be, ctx->service, &ctx->krb5_service); if (ret != EOK) { DEBUG(1, ("sdap_gssapi_init failed [%d][%s].\n", ret, strerror(ret))); goto done; } } } ret = setup_tls_config(ctx->opts->basic); if (ret != EOK) { DEBUG(1, ("setup_tls_config failed [%d][%s].\n", ret, strerror(ret))); goto done; } ret = sdap_id_conn_cache_create(ctx, ctx, &ctx->conn_cache); if (ret != EOK) { goto done; } ret = sdap_id_setup_tasks(ctx); if (ret != EOK) { goto done; } ret = setup_child(ctx); if (ret != EOK) { DEBUG(1, ("setup_child failed [%d][%s].\n", ret, strerror(ret))); goto done; } *ops = &sdap_id_ops; *pvt_data = ctx; ret = EOK; done: if (ret != EOK) { talloc_free(ctx); } return ret; }
errno_t check_and_export_options(struct dp_option *opts, struct sss_domain_info *dom, struct krb5_ctx *krb5_ctx) { int ret; const char *realm; const char *dummy; char *use_fast_str; char *fast_principal; enum sss_krb5_cc_type cc_be; realm = dp_opt_get_cstring(opts, KRB5_REALM); if (realm == NULL) { ret = dp_opt_set_string(opts, KRB5_REALM, dom->name); if (ret != EOK) { DEBUG(1, ("dp_opt_set_string failed.\n")); return ret; } realm = dom->name; } ret = setenv(SSSD_KRB5_REALM, realm, 1); if (ret != EOK) { DEBUG(2, ("setenv %s failed, authentication might fail.\n", SSSD_KRB5_REALM)); } ret = check_and_export_lifetime(opts, KRB5_RENEWABLE_LIFETIME, SSSD_KRB5_RENEWABLE_LIFETIME); if (ret != EOK) { DEBUG(1, ("Failed to check value of krb5_renewable_lifetime. [%d][%s]\n", ret, strerror(ret))); return ret; } ret = check_and_export_lifetime(opts, KRB5_LIFETIME, SSSD_KRB5_LIFETIME); if (ret != EOK) { DEBUG(1, ("Failed to check value of krb5_lifetime. [%d][%s]\n", ret, strerror(ret))); return ret; } use_fast_str = dp_opt_get_string(opts, KRB5_USE_FAST); if (use_fast_str != NULL) { ret = check_fast(use_fast_str, &krb5_ctx->use_fast); if (ret != EOK) { DEBUG(1, ("check_fast failed.\n")); return ret; } if (krb5_ctx->use_fast) { ret = setenv(SSSD_KRB5_USE_FAST, use_fast_str, 1); if (ret != EOK) { DEBUG(2, ("setenv [%s] failed.\n", SSSD_KRB5_USE_FAST)); } else { fast_principal = dp_opt_get_string(opts, KRB5_FAST_PRINCIPAL); if (fast_principal != NULL) { ret = setenv(SSSD_KRB5_FAST_PRINCIPAL, fast_principal, 1); if (ret != EOK) { DEBUG(2, ("setenv [%s] failed.\n", SSSD_KRB5_FAST_PRINCIPAL)); } } } } } if (dp_opt_get_bool(opts, KRB5_CANONICALIZE)) { ret = setenv(SSSD_KRB5_CANONICALIZE, "true", 1); } else { ret = setenv(SSSD_KRB5_CANONICALIZE, "false", 1); } if (ret != EOK) { DEBUG(2, ("setenv [%s] failed.\n", SSSD_KRB5_CANONICALIZE)); } dummy = dp_opt_get_cstring(opts, KRB5_KDC); if (dummy == NULL) { DEBUG(SSSDBG_CONF_SETTINGS, ("No KDC explicitly configured, using defaults.\n")); } dummy = dp_opt_get_cstring(opts, KRB5_KPASSWD); if (dummy == NULL) { DEBUG(SSSDBG_CONF_SETTINGS, ("No kpasswd server explicitly configured, " "using the KDC or defaults.\n")); } dummy = dp_opt_get_cstring(opts, KRB5_CCNAME_TMPL); if (dummy == NULL) { DEBUG(1, ("Missing credential cache name template.\n")); return EINVAL; } cc_be = sss_krb5_get_type(dummy); switch (cc_be) { case SSS_KRB5_TYPE_FILE: DEBUG(SSSDBG_CONF_SETTINGS, ("ccache is of type FILE\n")); krb5_ctx->cc_be = &file_cc; if (dummy[0] != '/') { /* FILE:/path/to/cc */ break; } DEBUG(SSSDBG_CONF_SETTINGS, ("The ccname template was " "missing an explicit type, but is an absolute " "path specifier. Assuming FILE:\n")); dummy = talloc_asprintf(opts, "FILE:%s", dummy); if (!dummy) return ENOMEM; ret = dp_opt_set_string(opts, KRB5_CCNAME_TMPL, dummy); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("dp_opt_set_string failed.\n")); return ret; } break; #ifdef HAVE_KRB5_DIRCACHE case SSS_KRB5_TYPE_DIR: DEBUG(SSSDBG_CONF_SETTINGS, ("ccache is of type DIR\n")); krb5_ctx->cc_be = &dir_cc; break; #endif default: DEBUG(SSSDBG_OP_FAILURE, ("Unknown ccname database\n")); return EINVAL; break; } return EOK; }
errno_t krb5_child_init(struct krb5_ctx *krb5_auth_ctx, struct be_ctx *bectx) { errno_t ret; time_t renew_intv = 0; krb5_deltat renew_interval_delta; char *renew_interval_str; if (dp_opt_get_bool(krb5_auth_ctx->opts, KRB5_STORE_PASSWORD_IF_OFFLINE)) { ret = init_delayed_online_authentication(krb5_auth_ctx, bectx, bectx->ev); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "init_delayed_online_authentication failed.\n"); goto done; } } renew_interval_str = dp_opt_get_string(krb5_auth_ctx->opts, KRB5_RENEW_INTERVAL); if (renew_interval_str != NULL) { ret = krb5_string_to_deltat(renew_interval_str, &renew_interval_delta); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Reading krb5_renew_interval failed.\n"); renew_interval_delta = 0; } renew_intv = renew_interval_delta; } if (renew_intv > 0) { ret = init_renew_tgt(krb5_auth_ctx, bectx, bectx->ev, renew_intv); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "init_renew_tgt failed.\n"); goto done; } } ret = check_and_export_options(krb5_auth_ctx->opts, bectx->domain, krb5_auth_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "check_and_export_opts failed.\n"); goto done; } ret = krb5_install_offline_callback(bectx, krb5_auth_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "krb5_install_offline_callback failed.\n"); goto done; } ret = krb5_install_sigterm_handler(bectx->ev, krb5_auth_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "krb5_install_sigterm_handler failed.\n"); goto done; } krb5_auth_ctx->child_debug_fd = -1; /* -1 means not initialized */ ret = child_debug_init(KRB5_CHILD_LOG_FILE, &krb5_auth_ctx->child_debug_fd); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Could not set krb5_child debugging!\n"); goto done; } ret = parse_krb5_map_user(krb5_auth_ctx, dp_opt_get_cstring(krb5_auth_ctx->opts, KRB5_MAP_USER), bectx->domain->name, &krb5_auth_ctx->name_to_primary); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "parse_krb5_map_user failed: %s:[%d]\n", sss_strerror(ret), ret); goto done; } ret = EOK; done: return ret; }
int sssm_ipa_id_init(struct be_ctx *bectx, struct bet_ops **ops, void **pvt_data) { struct ipa_id_ctx *ipa_ctx; struct sdap_id_ctx *sdap_ctx; const char *hostname; const char *ipa_domain; const char *ipa_servers; struct ipa_srv_plugin_ctx *srv_ctx; bool server_mode; int ret; if (!ipa_options) { ret = common_ipa_init(bectx); if (ret != EOK) { return ret; } } if (ipa_options->id_ctx) { /* already initialized */ *ops = &ipa_id_ops; *pvt_data = ipa_options->id_ctx; return EOK; } ipa_ctx = talloc_zero(ipa_options, struct ipa_id_ctx); if (!ipa_ctx) { return ENOMEM; } ipa_options->id_ctx = ipa_ctx; ipa_ctx->ipa_options = ipa_options; sdap_ctx = sdap_id_ctx_new(ipa_options, bectx, ipa_options->service->sdap); if (sdap_ctx == NULL) { return ENOMEM; } ipa_ctx->sdap_id_ctx = sdap_ctx; ret = ipa_get_id_options(ipa_options, bectx->cdb, bectx->conf_path, &sdap_ctx->opts); if (ret != EOK) { goto done; } ret = ipa_get_dyndns_options(bectx, ipa_options); if (ret != EOK) { goto done; } if (dp_opt_get_bool(ipa_options->dyndns_ctx->opts, DP_OPT_DYNDNS_UPDATE)) { /* Perform automatic DNS updates when the * IP address changes. * Register a callback for successful LDAP * reconnections. This is the easiest way to * identify that we have gone online. */ DEBUG(SSSDBG_CONF_SETTINGS, "Dynamic DNS updates are on. Checking for nsupdate..\n"); ret = be_nsupdate_check(); if (ret == EOK) { /* nsupdate is available. Dynamic updates * are supported */ ret = ipa_dyndns_init(sdap_ctx->be, ipa_options); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failure setting up automatic DNS update\n"); /* We will continue without DNS updating */ } } } ret = setup_tls_config(sdap_ctx->opts->basic); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "setup_tls_config failed [%d][%s].\n", ret, strerror(ret)); goto done; } /* Set up the ID mapping object */ ret = ipa_idmap_init(sdap_ctx, sdap_ctx, &sdap_ctx->opts->idmap_ctx); if (ret != EOK) { DEBUG(SSSDBG_FATAL_FAILURE, "Could not initialize ID mapping. In case ID mapping properties " "changed on the server, please remove the SSSD database\n"); goto done; } ret = ldap_id_setup_tasks(sdap_ctx); if (ret != EOK) { goto done; } ret = sdap_setup_child(); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "setup_child failed [%d][%s].\n", ret, strerror(ret)); goto done; } /* setup SRV lookup plugin */ hostname = dp_opt_get_string(ipa_options->basic, IPA_HOSTNAME); server_mode = dp_opt_get_bool(ipa_options->basic, IPA_SERVER_MODE); if (server_mode == true) { ipa_ctx->view_name = talloc_strdup(ipa_ctx, SYSDB_DEFAULT_VIEW_NAME); if (ipa_ctx->view_name == NULL) { DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); ret = ENOMEM; goto done; } ret = sysdb_update_view_name(bectx->domain->sysdb, ipa_ctx->view_name); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot add/update view name to sysdb.\n"); goto done; } ipa_servers = dp_opt_get_string(ipa_options->basic, IPA_SERVER); if (srv_in_server_list(ipa_servers) == true || dp_opt_get_bool(ipa_options->basic, IPA_ENABLE_DNS_SITES) == true) { DEBUG(SSSDBG_MINOR_FAILURE, "SRV resolution or IPA sites enabled " "on the IPA server. Site discovery of trusted AD servers " "might not work\n"); /* If SRV discovery is enabled on the server and * dns_discovery_domain is set explicitly, then * the current failover code would use the dns_discovery * domain to try to find AD servers and fail */ if (dp_opt_get_string(bectx->be_res->opts, DP_RES_OPT_DNS_DOMAIN)) { sss_log(SSS_LOG_ERR, ("SRV discovery is enabled on the IPA " "server while using custom dns_discovery_domain. " "DNS discovery of trusted AD domain will likely fail. " "It is recommended not to use SRV discovery or the " "dns_discovery_domain option for the IPA domain while " "running on the server itself\n")); DEBUG(SSSDBG_CRIT_FAILURE, "SRV discovery is enabled on IPA " "server while using custom dns_discovery_domain. " "DNS discovery of trusted AD domain will likely fail. " "It is recommended not to use SRV discovery or the " "dns_discovery_domain option for the IPA domain while " "running on the server itself\n"); } ret = be_fo_set_dns_srv_lookup_plugin(bectx, hostname); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set SRV lookup plugin " "[%d]: %s\n", ret, strerror(ret)); goto done; } } else { /* In server mode we need to ignore the dns_discovery_domain if set * and only discover servers based on AD domains */ ret = dp_opt_set_string(bectx->be_res->opts, DP_RES_OPT_DNS_DOMAIN, NULL); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Could not reset the " "dns_discovery_domain, trusted AD domains discovery " "might fail. Please remove dns_discovery_domain " "from the config file and restart the SSSD\n"); } else { DEBUG(SSSDBG_CONF_SETTINGS, "The value of dns_discovery_domain " "will be ignored in ipa_server_mode\n"); } } } else { ret = sysdb_get_view_name(ipa_ctx, bectx->domain->sysdb, &ipa_ctx->view_name); if (ret != EOK) { if (ret == ENOENT) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find view name in the cache. " \ "Will do online lookup later.\n"); } else { DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_view_name failed.\n"); goto done; } } if (dp_opt_get_bool(ipa_options->basic, IPA_ENABLE_DNS_SITES)) { /* use IPA plugin */ ipa_domain = dp_opt_get_string(ipa_options->basic, IPA_DOMAIN); srv_ctx = ipa_srv_plugin_ctx_init(bectx, bectx->be_res->resolv, hostname, ipa_domain); if (srv_ctx == NULL) { DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?\n"); ret = ENOMEM; goto done; } be_fo_set_srv_lookup_plugin(bectx, ipa_srv_plugin_send, ipa_srv_plugin_recv, srv_ctx, "IPA"); } else { /* fall back to standard plugin on clients. */ ret = be_fo_set_dns_srv_lookup_plugin(bectx, hostname); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set SRV lookup plugin " "[%d]: %s\n", ret, strerror(ret)); goto done; } } } /* setup periodical refresh of expired records */ ret = sdap_refresh_init(bectx->refresh_ctx, sdap_ctx); if (ret != EOK && ret != EEXIST) { DEBUG(SSSDBG_MINOR_FAILURE, "Periodical refresh " "will not work [%d]: %s\n", ret, strerror(ret)); } ipa_ctx->sdap_id_ctx->opts->ext_ctx = ipa_create_ext_members_ctx( ipa_ctx->sdap_id_ctx->opts, ipa_ctx); if (ipa_ctx->sdap_id_ctx->opts->ext_ctx == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set SRV the extrernal group ctx\n"); ret = ENOMEM; goto done; } *ops = &ipa_id_ops; *pvt_data = ipa_ctx; ret = EOK; done: if (ret != EOK) { talloc_zfree(ipa_options->id_ctx); } return ret; }
int sssm_ipa_auth_init(struct be_ctx *bectx, struct bet_ops **ops, void **pvt_data) { struct ipa_auth_ctx *ipa_auth_ctx; struct ipa_id_ctx *id_ctx; struct krb5_ctx *krb5_auth_ctx; struct sdap_auth_ctx *sdap_auth_ctx; struct bet_ops *id_ops; int ret; if (!ipa_options) { ret = common_ipa_init(bectx); if (ret != EOK) { return ret; } } if (ipa_options->auth_ctx) { /* already initialized */ *ops = &ipa_auth_ops; *pvt_data = ipa_options->auth_ctx; return EOK; } ipa_auth_ctx = talloc_zero(ipa_options, struct ipa_auth_ctx); if (!ipa_auth_ctx) { return ENOMEM; } ipa_options->auth_ctx = ipa_auth_ctx; ret = sssm_ipa_id_init(bectx, &id_ops, (void **) &id_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "sssm_ipa_id_init failed.\n"); goto done; } ipa_auth_ctx->sdap_id_ctx = id_ctx->sdap_id_ctx; ret = dp_copy_options(ipa_auth_ctx, ipa_options->basic, IPA_OPTS_BASIC, &ipa_auth_ctx->ipa_options); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "dp_copy_options failed.\n"); goto done; } krb5_auth_ctx = talloc_zero(ipa_auth_ctx, struct krb5_ctx); if (!krb5_auth_ctx) { ret = ENOMEM; goto done; } krb5_auth_ctx->service = ipa_options->service->krb5_service; if (dp_opt_get_bool(id_ctx->ipa_options->basic, IPA_SERVER_MODE) == true) { krb5_auth_ctx->config_type = K5C_IPA_SERVER; } else { krb5_auth_ctx->config_type = K5C_IPA_CLIENT; } ipa_options->auth_ctx->krb5_auth_ctx = krb5_auth_ctx; ret = ipa_get_auth_options(ipa_options, bectx->cdb, bectx->conf_path, &krb5_auth_ctx->opts); if (ret != EOK) { goto done; } sdap_auth_ctx = talloc_zero(ipa_auth_ctx, struct sdap_auth_ctx); if (!sdap_auth_ctx) { ret = ENOMEM; goto done; } sdap_auth_ctx->be = bectx; sdap_auth_ctx->service = ipa_options->service->sdap; if (ipa_options->id == NULL) { ret = EINVAL; goto done; } sdap_auth_ctx->opts = ipa_options->id; ipa_options->auth_ctx->sdap_auth_ctx = sdap_auth_ctx; ret = setup_tls_config(sdap_auth_ctx->opts->basic); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "setup_tls_config failed [%d][%s].\n", ret, strerror(ret)); goto done; } /* Initialize features needed by the krb5_child */ ret = krb5_child_init(krb5_auth_ctx, bectx); if (ret != EOK) { DEBUG(SSSDBG_FATAL_FAILURE, "Could not initialize krb5_child settings: [%s]\n", strerror(ret)); goto done; } ret = create_ipa_preauth_indicator(); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create preauth indicator file, special password " "prompting might not be available.\n"); sss_log(SSSDBG_CRIT_FAILURE, "Failed to create preauth indicator file, special password " "prompting might not be available.\n"); } *ops = &ipa_auth_ops; *pvt_data = ipa_auth_ctx; ret = EOK; done: if (ret != EOK) { talloc_zfree(ipa_options->auth_ctx); } return ret; }
/* FIXME: support storing additional attributes */ int sdap_save_user(TALLOC_CTX *memctx, struct sysdb_ctx *ctx, struct sdap_options *opts, struct sss_domain_info *dom, struct sysdb_attrs *attrs, bool is_initgr, char **_usn_value, time_t now) { struct ldb_message_element *el; int ret; const char *name = NULL; const char *fullname = NULL; const char *pwd; const char *gecos; const char *homedir; const char *shell; const char *orig_dn = NULL; uid_t uid; gid_t gid, primary_gid; struct sysdb_attrs *user_attrs; char *upn = NULL; size_t i; int cache_timeout; char *usn_value = NULL; char **missing = NULL; TALLOC_CTX *tmpctx = NULL; bool use_id_mapping = dp_opt_get_bool(opts->basic, SDAP_ID_MAPPING); char *sid_str; char *dom_sid_str = NULL; char *group_sid_str; DEBUG(9, ("Save user\n")); tmpctx = talloc_new(NULL); if (!tmpctx) { ret = ENOMEM; goto done; } user_attrs = sysdb_new_attrs(tmpctx); if (user_attrs == NULL) { ret = ENOMEM; goto done; } ret = sysdb_attrs_primary_name(ctx, attrs, opts->user_map[SDAP_AT_USER_NAME].name, &name); if (ret != EOK) { DEBUG(1, ("Failed to save the user - entry has no name attribute\n")); goto done; } if (opts->schema_type == SDAP_SCHEMA_AD) { ret = sysdb_attrs_get_string(attrs, opts->user_map[SDAP_AT_USER_FULLNAME].sys_name, &fullname); if (ret == EOK) { ret = sysdb_attrs_add_string(user_attrs, SYSDB_FULLNAME, fullname); if (ret != EOK) { goto done; } } else if (ret != ENOENT) { goto done; } } ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_PWD].sys_name, &el); if (ret) goto done; if (el->num_values == 0) pwd = NULL; else pwd = (const char *)el->values[0].data; ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_GECOS].sys_name, &el); if (ret) goto done; if (el->num_values == 0) gecos = NULL; else gecos = (const char *)el->values[0].data; if (!gecos) { /* Fall back to the user's full name */ ret = sysdb_attrs_get_el( attrs, opts->user_map[SDAP_AT_USER_FULLNAME].sys_name, &el); if (ret) goto done; if (el->num_values > 0) gecos = (const char *)el->values[0].data; } ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_HOME].sys_name, &el); if (ret) goto done; if (el->num_values == 0) homedir = NULL; else homedir = (const char *)el->values[0].data; ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_SHELL].sys_name, &el); if (ret) goto done; if (el->num_values == 0) shell = NULL; else shell = (const char *)el->values[0].data; /* Retrieve or map the UID as appropriate */ if (use_id_mapping) { DEBUG(SSSDBG_TRACE_LIBS, ("Mapping user [%s] objectSID to unix ID\n", name)); ret = sdap_attrs_get_sid_str( tmpctx, opts->idmap_ctx, attrs, opts->user_map[SDAP_AT_USER_OBJECTSID].sys_name, &sid_str); if (ret != EOK) goto done; /* Add string representation to the cache for easier * debugging */ ret = sysdb_attrs_add_string(user_attrs, SYSDB_SID_STR, sid_str); if (ret != EOK) goto done; /* Convert the SID into a UNIX user ID */ ret = sdap_idmap_sid_to_unix(opts->idmap_ctx, sid_str, &uid); if (ret == ENOTSUP) { DEBUG(SSSDBG_TRACE_FUNC, ("Skipping built-in object.\n")); ret = EOK; goto done; } else if (ret != EOK) { goto done; } /* Store the UID in the ldap_attrs so it doesn't get * treated as a missing attribute from LDAP and removed. */ ret = sdap_replace_id(attrs, SYSDB_UIDNUM, uid); if (ret) { DEBUG(SSSDBG_OP_FAILURE, ("Cannot set the id-mapped UID\n")); goto done; } } else { ret = sysdb_attrs_get_uint32_t(attrs, opts->user_map[SDAP_AT_USER_UID].sys_name, &uid); if (ret != EOK) { DEBUG(1, ("no uid provided for [%s] in domain [%s].\n", name, dom->name)); ret = EINVAL; goto done; } } /* check that the uid is valid for this domain */ if (OUT_OF_ID_RANGE(uid, dom->id_min, dom->id_max)) { DEBUG(2, ("User [%s] filtered out! (uid out of range)\n", name)); ret = EINVAL; goto done; } if (use_id_mapping) { ret = sysdb_attrs_get_uint32_t( attrs, opts->user_map[SDAP_AT_USER_PRIMARY_GROUP].sys_name, &primary_gid); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, ("no primary group ID provided for [%s] in domain [%s].\n", name, dom->name)); ret = EINVAL; goto done; } /* The primary group ID is just the RID part of the objectSID * of the group. Generate the GID by adding this to the domain * SID value. */ /* First, get the domain SID if we didn't do so above */ if (!dom_sid_str) { ret = sdap_idmap_get_dom_sid_from_object(tmpctx, sid_str, &dom_sid_str); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, ("Could not parse domain SID from [%s]\n", sid_str)); goto done; } } /* Add the RID to the end */ group_sid_str = talloc_asprintf(tmpctx, "%s-%lu", dom_sid_str, (unsigned long)primary_gid); if (!group_sid_str) { ret = ENOMEM; goto done; } /* Convert the SID into a UNIX group ID */ ret = sdap_idmap_sid_to_unix(opts->idmap_ctx, group_sid_str, &gid); if (ret != EOK) goto done; /* Store the GID in the ldap_attrs so it doesn't get * treated as a missing attribute from LDAP and removed. */ ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, gid); if (ret != EOK) goto done; } else { ret = sysdb_attrs_get_uint32_t(attrs, opts->user_map[SDAP_AT_USER_GID].sys_name, &gid); if (ret != EOK) { DEBUG(1, ("no gid provided for [%s] in domain [%s].\n", name, dom->name)); ret = EINVAL; goto done; } } /* check that the gid is valid for this domain */ if (OUT_OF_ID_RANGE(gid, dom->id_min, dom->id_max)) { DEBUG(2, ("User [%s] filtered out! (primary gid out of range)\n", name)); ret = EINVAL; goto done; } ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el); if (ret) { goto done; } if (!el || el->num_values == 0) { DEBUG(SSSDBG_MINOR_FAILURE, ("originalDN is not available for [%s].\n", name)); } else { orig_dn = (const char *) el->values[0].data; DEBUG(SSSDBG_TRACE_INTERNAL, ("Adding originalDN [%s] to attributes " "of [%s].\n", orig_dn, name)); ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_DN, orig_dn); if (ret) { goto done; } } ret = sysdb_attrs_get_el(attrs, SYSDB_MEMBEROF, &el); if (ret) { goto done; } if (el->num_values == 0) { DEBUG(7, ("Original memberOf is not available for [%s].\n", name)); } else { DEBUG(7, ("Adding original memberOf attributes to [%s].\n", name)); for (i = 0; i < el->num_values; i++) { ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_MEMBEROF, (const char *) el->values[i].data); if (ret) { goto done; } } } ret = sdap_attrs_add_string(attrs, opts->user_map[SDAP_AT_USER_MODSTAMP].sys_name, "original mod-Timestamp", name, user_attrs); if (ret != EOK) { goto done; } ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_USN].sys_name, &el); if (ret) { goto done; } if (el->num_values == 0) { DEBUG(7, ("Original USN value is not available for [%s].\n", name)); } else { ret = sysdb_attrs_add_string(user_attrs, opts->user_map[SDAP_AT_USER_USN].sys_name, (const char*)el->values[0].data); if (ret) { goto done; } usn_value = talloc_strdup(tmpctx, (const char*)el->values[0].data); if (!usn_value) { ret = ENOMEM; goto done; } } ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_PRINC].sys_name, &el); if (ret) { goto done; } if (el->num_values == 0) { DEBUG(7, ("User principal is not available for [%s].\n", name)); } else { upn = talloc_strdup(user_attrs, (const char*) el->values[0].data); if (!upn) { ret = ENOMEM; goto done; } if (dp_opt_get_bool(opts->basic, SDAP_FORCE_UPPER_CASE_REALM)) { make_realm_upper_case(upn); } DEBUG(7, ("Adding user principal [%s] to attributes of [%s].\n", upn, name)); ret = sysdb_attrs_add_string(user_attrs, SYSDB_UPN, upn); if (ret) { goto done; } } for (i = SDAP_FIRST_EXTRA_USER_AT; i < SDAP_OPTS_USER; i++) { ret = sdap_attrs_add_list(attrs, opts->user_map[i].sys_name, NULL, name, user_attrs); if (ret) { goto done; } } cache_timeout = dom->user_timeout; if (is_initgr) { ret = sysdb_attrs_add_time_t(user_attrs, SYSDB_INITGR_EXPIRE, (cache_timeout ? (time(NULL) + cache_timeout) : 0)); if (ret) { goto done; } } ret = sdap_save_all_names(name, attrs, !dom->case_sensitive, user_attrs); if (ret != EOK) { DEBUG(1, ("Failed to save user names\n")); goto done; } /* Make sure that any attributes we requested from LDAP that we * did not receive are also removed from the sysdb */ ret = list_missing_attrs(user_attrs, opts->user_map, SDAP_OPTS_USER, attrs, &missing); if (ret != EOK) { goto done; } DEBUG(6, ("Storing info for user %s\n", name)); ret = sysdb_store_user(ctx, dom, name, pwd, uid, gid, gecos, homedir, shell, orig_dn, user_attrs, missing, cache_timeout, now); if (ret) goto done; if (_usn_value) { *_usn_value = talloc_steal(memctx, usn_value); } talloc_steal(memctx, user_attrs); ret = EOK; done: if (ret) { DEBUG(2, ("Failed to save user [%s]\n", name ? name : "Unknown")); } talloc_free(tmpctx); return ret; }
int sssm_ldap_id_init(struct be_ctx *bectx, struct bet_ops **ops, void **pvt_data) { struct sdap_id_ctx *ctx = NULL; const char *urls; const char *backup_urls; const char *dns_service_name; const char *sasl_mech; struct sdap_service *sdap_service; struct sdap_options *opts = NULL; int ret; /* If we're already set up, just return that */ if(bectx->bet_info[BET_ID].mod_name && strcmp("ldap", bectx->bet_info[BET_ID].mod_name) == 0) { DEBUG(8, ("Re-using sdap_id_ctx for this provider\n")); *ops = bectx->bet_info[BET_ID].bet_ops; *pvt_data = bectx->bet_info[BET_ID].pvt_bet_data; return EOK; } ret = ldap_get_options(bectx, bectx->domain, bectx->cdb, bectx->conf_path, &opts); if (ret != EOK) { goto done; } dns_service_name = dp_opt_get_string(opts->basic, SDAP_DNS_SERVICE_NAME); DEBUG(SSSDBG_CONF_SETTINGS, ("Service name for discovery set to %s\n", dns_service_name)); urls = dp_opt_get_string(opts->basic, SDAP_URI); backup_urls = dp_opt_get_string(opts->basic, SDAP_BACKUP_URI); ret = sdap_service_init(bectx, bectx, "LDAP", dns_service_name, urls, backup_urls, &sdap_service); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("Failed to initialize failover service!\n")); goto done; } ctx = sdap_id_ctx_new(bectx, bectx, sdap_service); if (!ctx) { ret = ENOMEM; goto done; } ctx->opts = talloc_steal(ctx, opts); sasl_mech = dp_opt_get_string(ctx->opts->basic, SDAP_SASL_MECH); if (sasl_mech && strcasecmp(sasl_mech, "GSSAPI") == 0) { if (dp_opt_get_bool(ctx->opts->basic, SDAP_KRB5_KINIT)) { ret = sdap_gssapi_init(ctx, ctx->opts->basic, ctx->be, ctx->conn->service, &ctx->krb5_service); if (ret != EOK) { DEBUG(1, ("sdap_gssapi_init failed [%d][%s].\n", ret, strerror(ret))); goto done; } } } ret = setup_tls_config(ctx->opts->basic); if (ret != EOK) { DEBUG(1, ("setup_tls_config failed [%d][%s].\n", ret, strerror(ret))); goto done; } /* Set up the ID mapping object */ ret = sdap_idmap_init(ctx, ctx, &ctx->opts->idmap_ctx); if (ret != EOK) goto done; ret = ldap_id_setup_tasks(ctx); if (ret != EOK) { goto done; } ret = sdap_setup_child(); if (ret != EOK) { DEBUG(1, ("setup_child failed [%d][%s].\n", ret, strerror(ret))); goto done; } /* setup SRV lookup plugin */ ret = be_fo_set_dns_srv_lookup_plugin(bectx, NULL); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to set SRV lookup plugin " "[%d]: %s\n", ret, strerror(ret))); goto done; } /* setup periodical refresh of expired records */ ret = be_refresh_add_cb(bectx->refresh_ctx, BE_REFRESH_TYPE_NETGROUPS, sdap_refresh_netgroups_send, sdap_refresh_netgroups_recv, ctx); if (ret != EOK && ret != EEXIST) { DEBUG(SSSDBG_MINOR_FAILURE, ("Periodical refresh of netgroups " "will not work [%d]: %s\n", ret, strerror(ret))); } *ops = &sdap_id_ops; *pvt_data = ctx; ret = EOK; done: if (ret != EOK) { talloc_free(opts); talloc_free(ctx); } return ret; }
errno_t sdap_idmap_add_domain(struct sdap_idmap_ctx *idmap_ctx, const char *dom_name, const char *dom_sid, id_t slice) { errno_t ret; struct sss_idmap_range range; enum idmap_error_code err; id_t idmap_upper; bool external_mapping = true; ret = sss_idmap_ctx_get_upper(idmap_ctx->map, &idmap_upper); if (ret != IDMAP_SUCCESS) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to get upper bound of available ID range.\n"); ret = EIO; goto done; } if (dp_opt_get_bool(idmap_ctx->id_ctx->opts->basic, SDAP_ID_MAPPING)) { external_mapping = false; ret = sss_idmap_calculate_range(idmap_ctx->map, dom_sid, &slice, &range); if (ret != IDMAP_SUCCESS) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to calculate range for domain [%s]: [%d]\n", dom_name, ret); ret = EIO; goto done; } DEBUG(SSSDBG_TRACE_LIBS, "Adding domain [%s] as slice [%"SPRIid"]\n", dom_sid, slice); if (range.max > idmap_upper) { /* This should never happen */ DEBUG(SSSDBG_CRIT_FAILURE, "BUG: Range maximum exceeds the global maximum: " "%u > %"SPRIid"\n", range.max, idmap_upper); ret = EINVAL; goto done; } } else { ret = sdap_idmap_get_configured_external_range(idmap_ctx, &range); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "sdap_idmap_get_configured_external_range failed.\n"); return ret; } } /* Add this domain to the map */ err = sss_idmap_add_domain_ex(idmap_ctx->map, dom_name, dom_sid, &range, NULL, 0, external_mapping); if (err != IDMAP_SUCCESS) { DEBUG(SSSDBG_CRIT_FAILURE, "Could not add domain [%s] to the map: [%d]\n", dom_name, err); ret = EIO; goto done; } /* If algorithmic mapping is used add this domain to the SYSDB cache so it * will survive reboot */ if (!external_mapping) { ret = sysdb_idmap_store_mapping(idmap_ctx->id_ctx->be->domain, dom_name, dom_sid, slice); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "sysdb_idmap_store_mapping failed.\n"); goto done; } } done: return ret; }
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; }
bool sdap_idmap_domain_has_algorithmic_mapping(struct sdap_idmap_ctx *ctx, const char *dom_name, const char *dom_sid) { enum idmap_error_code err; bool has_algorithmic_mapping; char *new_dom_sid; int ret; TALLOC_CTX *tmp_ctx = NULL; if (dp_opt_get_bool(ctx->id_ctx->opts->basic, SDAP_ID_MAPPING) && 0 == strcmp("ldap", ctx->id_ctx->be->bet_info[BET_ID].mod_name)) { return true; } err = sss_idmap_domain_has_algorithmic_mapping(ctx->map, dom_sid, &has_algorithmic_mapping); switch (err){ case IDMAP_SUCCESS: return has_algorithmic_mapping; case IDMAP_SID_INVALID: /* FALLTHROUGH */ case IDMAP_SID_UNKNOWN: /* FALLTHROUGH */ case IDMAP_NO_DOMAIN: /* FALLTHROUGH */ /* continue with idmap_domain_by_name */ break; default: return false; } err = sss_idmap_domain_by_name_has_algorithmic_mapping(ctx->map, dom_name, &has_algorithmic_mapping); if (err == IDMAP_SUCCESS) { return has_algorithmic_mapping; } else if (err != IDMAP_NAME_UNKNOWN && err != IDMAP_NO_DOMAIN) { return false; } /* This is the first time we've seen this domain * Create a new domain for it. We'll use the dom-sid * as the domain name for now, since we don't have * any way to get the real name. */ if (is_domain_sid(dom_sid)) { new_dom_sid = discard_const(dom_sid); } else { tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); return false; } ret = sdap_idmap_get_dom_sid_from_object(tmp_ctx, dom_sid, &new_dom_sid); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Could not parse domain SID from [%s]\n", dom_sid); talloc_free(tmp_ctx); return false; } } ret = ctx->find_new_domain(ctx, dom_name, new_dom_sid); talloc_free(tmp_ctx); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Could not add new domain for sid [%s]\n", dom_sid); return false; } err = sss_idmap_domain_has_algorithmic_mapping(ctx->map, dom_sid, &has_algorithmic_mapping); if (err == IDMAP_SUCCESS) { return has_algorithmic_mapping; } return false; }
errno_t krb5_child_init(struct krb5_ctx *krb5_auth_ctx, struct be_ctx *bectx) { errno_t ret; FILE *debug_filep; time_t renew_intv = 0; krb5_deltat renew_interval_delta; char *renew_interval_str; if (dp_opt_get_bool(krb5_auth_ctx->opts, KRB5_STORE_PASSWORD_IF_OFFLINE)) { ret = init_delayed_online_authentication(krb5_auth_ctx, bectx, bectx->ev); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "init_delayed_online_authentication failed.\n"); goto done; } } renew_interval_str = dp_opt_get_string(krb5_auth_ctx->opts, KRB5_RENEW_INTERVAL); if (renew_interval_str != NULL) { ret = krb5_string_to_deltat(renew_interval_str, &renew_interval_delta); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Reading krb5_renew_interval failed.\n"); renew_interval_delta = 0; } renew_intv = renew_interval_delta; } if (renew_intv > 0) { ret = init_renew_tgt(krb5_auth_ctx, bectx, bectx->ev, renew_intv); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "init_renew_tgt failed.\n"); goto done; } } ret = check_and_export_options(krb5_auth_ctx->opts, bectx->domain, krb5_auth_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "check_and_export_opts failed.\n"); goto done; } ret = krb5_install_offline_callback(bectx, krb5_auth_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "krb5_install_offline_callback failed.\n"); goto done; } ret = krb5_install_sigterm_handler(bectx->ev, krb5_auth_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "krb5_install_sigterm_handler failed.\n"); goto done; } if (debug_to_file != 0) { ret = open_debug_file_ex(KRB5_CHILD_LOG_FILE, &debug_filep, false); if (ret != EOK) { DEBUG(SSSDBG_FATAL_FAILURE, "Error setting up logging (%d) [%s]\n", ret, strerror(ret)); goto done; } krb5_auth_ctx->child_debug_fd = fileno(debug_filep); if (krb5_auth_ctx->child_debug_fd == -1) { DEBUG(SSSDBG_FATAL_FAILURE, "fileno failed [%d][%s]\n", errno, strerror(errno)); ret = errno; goto done; } } done: return ret; }