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; }
static errno_t sdap_get_idmap_primary_gid(struct sdap_options *opts, struct sysdb_attrs *attrs, char *sid_str, char *dom_sid_str, gid_t *_gid) { errno_t ret; TALLOC_CTX *tmpctx = NULL; gid_t gid, primary_gid; char *group_sid_str; tmpctx = talloc_new(NULL); if (!tmpctx) { ret = ENOMEM; goto done; } 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\n"); 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; ret = EOK; *_gid = gid; done: talloc_free(tmpctx); return ret; }
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; 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; }
/* 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; }