sdap_idmap.c revision dea636af4d1902a081ee891f1b19ee2f8729d759
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi/*
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi SSSD
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi Authors:
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi Stephen Gallagher <sgallagh@redhat.com>
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi Copyright (C) 2012 Red Hat
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi This program is free software; you can redistribute it and/or modify
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi it under the terms of the GNU General Public License as published by
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi the Free Software Foundation; either version 3 of the License, or
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi (at your option) any later version.
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi This program is distributed in the hope that it will be useful,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi but WITHOUT ANY WARRANTY; without even the implied warranty of
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi GNU General Public License for more details.
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi You should have received a copy of the GNU General Public License
a5ba96715d4ef264c43d4f187251de491ba198c0KATOH Yasufumi along with this program. If not, see <http://www.gnu.org/licenses/>.
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi*/
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi#include "util/util.h"
faefa7f8584a7d1567df2e6f1f9240a28a6466abStéphane Graber#include "util/dlinklist.h"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi#include "util/murmurhash3.h"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi#include "providers/ldap/sdap_idmap.h"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi#include "util/util_sss_idmap.h"
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumistatic errno_t
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumisdap_idmap_get_configured_external_range(struct sdap_idmap_ctx *idmap_ctx,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi struct sss_idmap_range *range)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi{
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi int int_id;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi struct sdap_id_ctx *id_ctx;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi uint32_t min;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi uint32_t max;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (idmap_ctx == NULL) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi return EINVAL;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi }
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi id_ctx = idmap_ctx->id_ctx;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi int_id = dp_opt_get_int(id_ctx->opts->basic, SDAP_MIN_ID);
6127da6b3f5815028bee187ac98840cd94313841KATOH Yasufumi if (int_id < 0) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi DEBUG(SSSDBG_CONF_SETTINGS, "ldap_min_id must be greater than 0.\n");
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi return EINVAL;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi }
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi min = int_id;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi int_id = dp_opt_get_int(id_ctx->opts->basic, SDAP_MAX_ID);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (int_id < 0) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi DEBUG(SSSDBG_CONF_SETTINGS, "ldap_max_id must be greater than 0.\n");
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi return EINVAL;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi }
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi max = int_id;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if ((min == 0 && max != 0) || (min != 0 && max == 0)) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi DEBUG(SSSDBG_CONF_SETTINGS, "Both ldap_min_id and ldap_max_id " \
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "either must be 0 (not set) " \
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "or positive integers.\n");
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi return EINVAL;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi }
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi if (min == 0 && max == 0) {
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi /* ldap_min_id and ldap_max_id not set, using min_id and max_id */
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi min = id_ctx->be->domain->id_min;
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi max = id_ctx->be->domain->id_max;
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi if (max == 0) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi max = UINT32_MAX;
dc421f3aac1f0e516c763dd156629a8ed2a7b4caKATOH Yasufumi }
dc421f3aac1f0e516c763dd156629a8ed2a7b4caKATOH Yasufumi }
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi range->min = min;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi range->max =max;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi return EOK;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi}
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumistatic errno_t
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumisdap_idmap_add_configured_external_range(struct sdap_idmap_ctx *idmap_ctx)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi{
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi int ret;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi struct sss_idmap_range range;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi struct sdap_id_ctx *id_ctx;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi enum idmap_error_code err;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi ret = sdap_idmap_get_configured_external_range(idmap_ctx, &range);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (ret != EOK) {
dc421f3aac1f0e516c763dd156629a8ed2a7b4caKATOH Yasufumi DEBUG(SSSDBG_OP_FAILURE,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "sdap_idmap_get_configured_external_range failed.\n");
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi return ret;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi }
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi id_ctx = idmap_ctx->id_ctx;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi err = sss_idmap_add_auto_domain_ex(idmap_ctx->map,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi id_ctx->be->domain->name,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi id_ctx->be->domain->domain_id, &range,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi NULL, 0, true, NULL, NULL);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (err != IDMAP_SUCCESS) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi DEBUG(SSSDBG_CRIT_FAILURE,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "Could not add domain [%s] to the map: [%d]\n",
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi id_ctx->be->domain->name, err);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi return EIO;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi }
dc421f3aac1f0e516c763dd156629a8ed2a7b4caKATOH Yasufumi
dc421f3aac1f0e516c763dd156629a8ed2a7b4caKATOH Yasufumi return EOK;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi}
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumierrno_t sdap_idmap_find_new_domain(struct sdap_idmap_ctx *idmap_ctx,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi const char *dom_name,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi const char *dom_sid_str)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi{
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi int ret;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi ret = sdap_idmap_add_domain(idmap_ctx,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi dom_name, dom_sid_str,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi -1);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (ret != EOK) {
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi DEBUG(SSSDBG_MINOR_FAILURE,
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi "Could not add new domain [%s]\n", dom_name);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi return ret;
dc421f3aac1f0e516c763dd156629a8ed2a7b4caKATOH Yasufumi }
dc421f3aac1f0e516c763dd156629a8ed2a7b4caKATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi return EOK;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi}
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumierrno_t
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumisdap_idmap_init(TALLOC_CTX *mem_ctx,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi struct sdap_id_ctx *id_ctx,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi struct sdap_idmap_ctx **_idmap_ctx)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi{
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi errno_t ret;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi TALLOC_CTX *tmp_ctx;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi enum idmap_error_code err;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi size_t i;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi struct ldb_result *res;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi const char *dom_name;
dc421f3aac1f0e516c763dd156629a8ed2a7b4caKATOH Yasufumi const char *sid_str;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi id_t slice_num;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi id_t idmap_lower;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi id_t idmap_upper;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi id_t rangesize;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi bool autorid_mode;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi int extra_slice_init;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi struct sdap_idmap_ctx *idmap_ctx = NULL;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi tmp_ctx = talloc_new(NULL);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (!tmp_ctx) return ENOMEM;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi idmap_ctx = talloc_zero(tmp_ctx, struct sdap_idmap_ctx);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (!idmap_ctx) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi ret = ENOMEM;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi goto done;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi }
dc421f3aac1f0e516c763dd156629a8ed2a7b4caKATOH Yasufumi idmap_ctx->id_ctx = id_ctx;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi idmap_ctx->find_new_domain = sdap_idmap_find_new_domain;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi idmap_lower = dp_opt_get_int(idmap_ctx->id_ctx->opts->basic,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi SDAP_IDMAP_LOWER);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi idmap_upper = dp_opt_get_int(idmap_ctx->id_ctx->opts->basic,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi SDAP_IDMAP_UPPER);
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi rangesize = dp_opt_get_int(idmap_ctx->id_ctx->opts->basic,
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi SDAP_IDMAP_RANGESIZE);
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi autorid_mode = dp_opt_get_bool(idmap_ctx->id_ctx->opts->basic,
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi SDAP_IDMAP_AUTORID_COMPAT);
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi extra_slice_init = dp_opt_get_int(idmap_ctx->id_ctx->opts->basic,
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi SDAP_IDMAP_EXTRA_SLICE_INIT);
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi /* Validate that the values make sense */
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi if (rangesize <= 0
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi || idmap_upper <= idmap_lower
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi || (idmap_upper-idmap_lower) < rangesize)
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi {
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi DEBUG(SSSDBG_FATAL_FAILURE,
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi "Invalid settings for range selection: "
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi "[%"SPRIid"][%"SPRIid"][%"SPRIid"]\n",
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi idmap_lower, idmap_upper, rangesize);
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi ret = EINVAL;
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi goto done;
dc421f3aac1f0e516c763dd156629a8ed2a7b4caKATOH Yasufumi }
dc421f3aac1f0e516c763dd156629a8ed2a7b4caKATOH Yasufumi
dc421f3aac1f0e516c763dd156629a8ed2a7b4caKATOH Yasufumi if (((idmap_upper - idmap_lower) % rangesize) != 0) {
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi DEBUG(SSSDBG_CONF_SETTINGS,
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi "Range size does not divide evenly. Uppermost range will "
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi "not be used\n");
dc421f3aac1f0e516c763dd156629a8ed2a7b4caKATOH Yasufumi }
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi /* Initialize the map */
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi err = sss_idmap_init(sss_idmap_talloc, idmap_ctx,
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi sss_idmap_talloc_free,
dc421f3aac1f0e516c763dd156629a8ed2a7b4caKATOH Yasufumi &idmap_ctx->map);
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi if (err != IDMAP_SUCCESS) {
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi DEBUG(SSSDBG_CRIT_FAILURE,
56390ccb5764945d7dbf8bca9efc541ef178d688KATOH Yasufumi "Could not initialize the ID map: [%s]\n",
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi idmap_error_string(err));
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (err == IDMAP_OUT_OF_MEMORY) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi ret = ENOMEM;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi } else {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi ret = EINVAL;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi }
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi goto done;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi }
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi err = sss_idmap_ctx_set_autorid(idmap_ctx->map, autorid_mode);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi err |= sss_idmap_ctx_set_lower(idmap_ctx->map, idmap_lower);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi err |= sss_idmap_ctx_set_upper(idmap_ctx->map, idmap_upper);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi err |= sss_idmap_ctx_set_rangesize(idmap_ctx->map, rangesize);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi err |= sss_idmap_ctx_set_extra_slice_init(idmap_ctx->map, extra_slice_init);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (err != IDMAP_SUCCESS) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi /* This should never happen */
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi DEBUG(SSSDBG_CRIT_FAILURE, "sss_idmap_ctx corrupted\n");
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi ret = EIO;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi goto done;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi }
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi /* Setup range for externally managed IDs, i.e. IDs are read from the
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi * ldap_user_uid_number and ldap_group_gid_number attributes. */
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi 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) {
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) {
struct sss_domain_info *domain = idmap_ctx->id_ctx->be->domain;
domain->domain_id = talloc_strdup(domain, sid_str);
if (domain->domain_id == NULL) {
ret = ENOMEM;
goto done;
}
/* 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;
}
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_auto_domain_ex(idmap_ctx->map, dom_name, dom_sid,
&range, NULL, 0, external_mapping,
NULL, NULL);
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;
}
errno_t
sdap_idmap_get_dom_sid_from_object(TALLOC_CTX *mem_ctx,
const char *object_sid,
char **dom_sid_str)
{
const char *p;
long long a;
size_t c;
char *endptr;
if (object_sid == NULL
|| strncmp(object_sid, DOM_SID_PREFIX, DOM_SID_PREFIX_LEN) != 0) {
return EINVAL;
}
p = object_sid + DOM_SID_PREFIX_LEN;
c = 0;
do {
errno = 0;
a = strtoull(p, &endptr, 10);
if (errno != 0 || a > UINT32_MAX) {
return EINVAL;
}
if (*endptr == '-') {
p = endptr + 1;
} else {
return EINVAL;
}
c++;
} while(c < 3);
/* If we made it here, we are now one character past
* the last hyphen in the object-sid.
* Copy the dom-sid substring.
*/
*dom_sid_str = talloc_strndup(mem_ctx, object_sid,
(endptr-object_sid));
if (!*dom_sid_str) return ENOMEM;
return EOK;
}
errno_t
sdap_idmap_sid_to_unix(struct sdap_idmap_ctx *idmap_ctx,
const char *sid_str,
id_t *id)
{
errno_t ret;
enum idmap_error_code err;
char *dom_sid_str = NULL;
/* Convert the SID into a UNIX ID */
err = sss_idmap_sid_to_unix(idmap_ctx->map,
sid_str,
(uint32_t *)id);
switch (err) {
case IDMAP_SUCCESS:
break;
case IDMAP_NO_DOMAIN:
/* 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.
*/
ret = sdap_idmap_get_dom_sid_from_object(NULL, sid_str,
&dom_sid_str);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE,
"Could not parse domain SID from [%s]\n", sid_str);
goto done;
}
ret = idmap_ctx->find_new_domain(idmap_ctx, dom_sid_str, dom_sid_str);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE,
"Could not add new domain for sid [%s]\n", sid_str);
goto done;
}
/* Now try converting to a UNIX ID again */
err = sss_idmap_sid_to_unix(idmap_ctx->map,
sid_str,
(uint32_t *)id);
if (err != IDMAP_SUCCESS) {
DEBUG(SSSDBG_MINOR_FAILURE,
"Could not convert objectSID [%s] to a UNIX ID\n",
sid_str);
ret = EIO;
goto done;
}
break;
case IDMAP_BUILTIN_SID:
DEBUG(SSSDBG_TRACE_FUNC,
"Object SID [%s] is a built-in one.\n", sid_str);
/* ENOTSUP indicates built-in SID */
ret = ENOTSUP;
goto done;
break;
case IDMAP_NO_RANGE:
DEBUG(SSSDBG_IMPORTANT_INFO,
"Object SID [%s] has a RID that is larger than the "
"ldap_idmap_range_size. See the \"ID MAPPING\" section of "
"sssd-ad(5) for an explanation of how to resolve this issue.\n",
sid_str);
/* Fall through intentionally */
default:
DEBUG(SSSDBG_MINOR_FAILURE,
"Could not convert objectSID [%s] to a UNIX ID\n",
sid_str);
ret = EIO;
goto done;
}
ret = EOK;
done:
talloc_free(dom_sid_str);
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)
&& dp_target_enabled(ctx->id_ctx->be->provider, "ldap", DPT_ID)) {
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;
}
/* If there is no SID, e.g. IPA without enabled trust support, we cannot
* have algorithmic mapping */
if (dom_sid == NULL) {
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;
}