From 879ffa1b7c7465fda76675de02d6cb04c9cd7aa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= Date: Thu, 14 Oct 2021 12:24:52 +0200 Subject: [PATCH] sssd-2.6.0-1: Rebase to latest upstream release --- ...ubid-ranges-support-for-IPA-provider.patch | 1817 ----------------- 0002-TOOLS-replace-system-with-execvp.patch | 277 --- ...-unset-PYTHON_PREFIX-and-PYTHON_EXEC.patch | 43 - sssd.spec | 51 +- 4 files changed, 32 insertions(+), 2156 deletions(-) delete mode 100644 0001-Basics-of-subid-ranges-support-for-IPA-provider.patch delete mode 100644 0002-TOOLS-replace-system-with-execvp.patch delete mode 100644 0003-configure-do-not-unset-PYTHON_PREFIX-and-PYTHON_EXEC.patch diff --git a/0001-Basics-of-subid-ranges-support-for-IPA-provider.patch b/0001-Basics-of-subid-ranges-support-for-IPA-provider.patch deleted file mode 100644 index aac4e4e..0000000 --- a/0001-Basics-of-subid-ranges-support-for-IPA-provider.patch +++ /dev/null @@ -1,1817 +0,0 @@ -From f546088226872f24722bdd94388816792bd5891a Mon Sep 17 00:00:00 2001 -From: Alexey Tikhonov -Date: Sat, 1 May 2021 22:56:15 +0200 -Subject: [PATCH] Basics of 'subid ranges' support for IPA provider. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -:feature: Basic support of user's 'subuid and subgid ranges' for IPA -provider and corresponding plugin for shadow-utils were introduced. -Limitations: - - single subid interval pair (subuid+subgid) per user - - idviews aren't supported - - only forward lookup (user -> subid ranges) -Take a note, this is MVP of experimental feature. Significant changes -might be required later, after initial feedback. -Corresponding support in shadow-utils was merged upstream, but since there -is no upstream release available yet, SSSD feature isn't built by default. -Build can be enabled with `--with-subid` configure option. -Plugin's install path can be configured with `--with-subid-lib-path=` -("${libdir}" by default) - -For additional details about support in shadow-utils please see discussion -in https://github.com/shadow-maint/shadow/issues/154 and in related PRs. - -:config: New IPA provider's option `ipa_subid_ranges_search_base` allows -configuration of search base for user's subid ranges. -Default: `cn=subids,%basedn` - -Resolves: https://github.com/SSSD/sssd/issues/5197 - -Reviewed-by: Iker Pedrosa -Reviewed-by: Pavel Březina ---- - Makefile.am | 34 +++ - configure.ac | 2 + - src/conf_macros.m4 | 30 +++ - src/config/SSSDConfig/sssdoptions.py | 1 + - src/config/cfg_rules.ini | 1 + - src/config/etc/sssd.api.d/sssd-ipa.conf | 1 + - src/db/sysdb.h | 6 + - src/db/sysdb_subid.c | 163 +++++++++++ - src/db/sysdb_subid.h | 39 +++ - src/man/sssd-ipa.5.xml | 14 + - src/providers/data_provider_req.c | 2 + - src/providers/data_provider_req.h | 1 + - src/providers/ipa/ipa_common.c | 38 +++ - src/providers/ipa/ipa_common.h | 1 + - src/providers/ipa/ipa_id.c | 17 ++ - src/providers/ipa/ipa_opts.c | 12 + - src/providers/ipa/ipa_opts.h | 2 + - src/providers/ldap/ldap_common.h | 14 + - src/providers/ldap/ldap_id.c | 31 +++ - src/providers/ldap/ldap_id_subid.c | 255 ++++++++++++++++++ - src/providers/ldap/sdap.h | 19 ++ - src/responder/common/cache_req/cache_req.c | 4 + - src/responder/common/cache_req/cache_req.h | 4 + - .../common/cache_req/cache_req_data.c | 3 + - .../common/cache_req/cache_req_plugin.h | 3 + - .../plugins/cache_req_subid_ranges_by_name.c | 143 ++++++++++ - src/responder/common/responder.h | 1 + - src/responder/common/responder_dp.c | 4 + - src/responder/nss/nss_cmd.c | 20 ++ - src/responder/nss/nss_protocol.h | 8 + - src/responder/nss/nss_protocol_subid.c | 60 +++++ - src/sss_client/common.c | 2 +- - src/sss_client/sss_cli.h | 11 + - src/sss_client/subid/sss_subid.c | 209 ++++++++++++++ - src/sss_client/subid/sss_subid.exports | 12 + - src/systemtap/sssd_functions.stp | 2 +- - src/tests/cwrap/Makefile.am | 3 + - src/tests/dlopen-tests.c | 3 + - src/util/sss_cli_cmd.c | 5 + - src/util/util_errors.c | 1 + - src/util/util_errors.h | 1 + - 41 files changed, 1180 insertions(+), 2 deletions(-) - create mode 100644 src/db/sysdb_subid.c - create mode 100644 src/db/sysdb_subid.h - create mode 100644 src/providers/ldap/ldap_id_subid.c - create mode 100644 src/responder/common/cache_req/plugins/cache_req_subid_ranges_by_name.c - create mode 100644 src/responder/nss/nss_protocol_subid.c - create mode 100644 src/sss_client/subid/sss_subid.c - create mode 100644 src/sss_client/subid/sss_subid.exports - -diff --git a/Makefile.am b/Makefile.am -index 1dd06d74c..577935e7e 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -65,6 +65,7 @@ localedir = @localedir@ - nsslibdir = @nsslibdir@ - pamlibdir = @pammoddir@ - autofslibdir = @appmodpath@ -+subidlibdir = @subidlibpath@ - nfslibdir = @nfsidmaplibdir@ - - dbpath = @dbpath@ -@@ -596,6 +597,9 @@ SSSD_CACHE_REQ_OBJ = \ - src/responder/common/cache_req/plugins/cache_req_ip_network_by_name.c \ - src/responder/common/cache_req/plugins/cache_req_ip_network_by_addr.c \ - $(NULL) -+if BUILD_SUBID -+ SSSD_CACHE_REQ_OBJ += src/responder/common/cache_req/plugins/cache_req_subid_ranges_by_name.c -+endif - - SSSD_RESPONDER_IFACE_OBJ = \ - src/responder/common/responder_iface.c \ -@@ -810,6 +814,7 @@ dist_noinst_HEADERS = \ - src/db/sysdb_private.h \ - src/db/sysdb_services.h \ - src/db/sysdb_ssh.h \ -+ src/db/sysdb_subid.h \ - src/db/sysdb_domain_resolution_order.h \ - src/db/sysdb_computer.h \ - src/db/sysdb_iphosts.h \ -@@ -1247,6 +1252,7 @@ libsss_util_la_SOURCES = \ - src/db/sysdb_ipnetworks.c \ - src/util/sss_pam_data.c \ - src/db/sysdb_computer.c \ -+ src/db/sysdb_subid.c \ - src/util/util.c \ - src/util/util_ext.c \ - src/util/util_preauth.c \ -@@ -1558,6 +1564,9 @@ sssd_nss_LDADD = \ - libsss_iface.la \ - libsss_sbus.la \ - $(NULL) -+if BUILD_SUBID -+ sssd_nss_SOURCES += src/responder/nss/nss_protocol_subid.c -+endif - - sssd_pam_SOURCES = \ - src/responder/pam/pam_LOCAL_domain.c \ -@@ -2691,6 +2700,9 @@ nss_srv_tests_LDADD = \ - libsss_iface.la \ - libsss_sbus.la \ - $(NULL) -+if BUILD_SUBID -+ nss_srv_tests_SOURCES += src/responder/nss/nss_protocol_subid.c -+endif - - EXTRA_pam_srv_tests_DEPENDENCIES = \ - $(ldblib_LTLIBRARIES) \ -@@ -4217,6 +4229,21 @@ libsss_autofs_la_LDFLAGS = \ - -Wl,--version-script,$(srcdir)/src/sss_client/autofs/sss_autofs.exports - endif - -+if BUILD_SUBID -+subidlib_LTLIBRARIES = libsubid_sss.la -+libsubid_sss_la_SOURCES = \ -+ src/sss_client/common.c \ -+ src/sss_client/sss_cli.h \ -+ src/sss_client/subid/sss_subid.c -+ -+libsubid_sss_la_LIBADD = \ -+ $(CLIENT_LIBS) -+libsubid_sss_la_LDFLAGS = \ -+ -module \ -+ -avoid-version \ -+ -Wl,--version-script,$(srcdir)/src/sss_client/subid/sss_subid.exports -+endif -+ - dist_noinst_DATA += \ - src/sss_client/sss_nss.exports \ - src/sss_client/sss_pam.exports \ -@@ -4231,6 +4258,10 @@ if BUILD_AUTOFS - dist_noinst_DATA += src/sss_client/autofs/sss_autofs.exports - endif - -+if BUILD_SUBID -+dist_noinst_DATA += src/sss_client/subid/sss_subid.exports -+endif -+ - #################### - # Plugin Libraries # - #################### -@@ -4315,6 +4346,9 @@ libsss_ldap_common_la_LDFLAGS = \ - if BUILD_SYSTEMTAP - libsss_ldap_common_la_LIBADD += stap_generated_probes.lo - endif -+if BUILD_SUBID -+libsss_ldap_common_la_SOURCES += src/providers/ldap/ldap_id_subid.c -+endif - - if BUILD_SSH - libsss_ldap_common_la_SOURCES += src/providers/ldap/sdap_hostid.c -diff --git a/configure.ac b/configure.ac -index e98487cae..c14a59eef 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -161,6 +161,8 @@ WITH_APP_LIBS - WITH_SUDO - WITH_SUDO_LIB_PATH - WITH_AUTOFS -+WITH_SUBID -+WITH_SUBID_LIB_PATH - WITH_SSH - WITH_IFP - WITH_SYSLOG -diff --git a/src/conf_macros.m4 b/src/conf_macros.m4 -index cdffba11c..0a1e6dd8f 100644 ---- a/src/conf_macros.m4 -+++ b/src/conf_macros.m4 -@@ -675,6 +675,36 @@ AC_DEFUN([WITH_AUTOFS], - AM_CONDITIONAL([BUILD_AUTOFS], [test x"$with_autofs" = xyes]) - ]) - -+AC_DEFUN([WITH_SUBID], -+ [ AC_ARG_WITH([subid], -+ [AC_HELP_STRING([--with-subid], -+ [Whether to build with subid ranges support [no]] -+ ) -+ ], -+ [with_subid=$withval], -+ with_subid=no -+ ) -+ -+ if test x"$with_subid" = xyes; then -+ AC_DEFINE(BUILD_SUBID, 1, [whether to build with SUBID ranges support]) -+ fi -+ AM_CONDITIONAL([BUILD_SUBID], [test x"$with_subid" = xyes]) -+ ]) -+ -+AC_DEFUN([WITH_SUBID_LIB_PATH], -+ [ AC_ARG_WITH([subid-lib-path], -+ [AC_HELP_STRING([--with-subid-lib-path=], -+ [Path to the subid library] -+ ) -+ ] -+ ) -+ subidlibpath="${libdir}" -+ if test x"$with_subid_lib_path" != x; then -+ subidlibpath=$with_subid_lib_path -+ fi -+ AC_SUBST(subidlibpath) -+ ]) -+ - AC_DEFUN([WITH_SSH], - [ AC_ARG_WITH([ssh], - [AC_HELP_STRING([--with-ssh], -diff --git a/src/config/SSSDConfig/sssdoptions.py b/src/config/SSSDConfig/sssdoptions.py -index c4ce2588b..39380c462 100644 ---- a/src/config/SSSDConfig/sssdoptions.py -+++ b/src/config/SSSDConfig/sssdoptions.py -@@ -265,6 +265,7 @@ class SSSDOptions(object): - 'ipa_deskprofile_request_interval': _("The amount of time in minutes between lookups of Desktop Profiles " - "rules against the IPA server when the last request did not find any " - "rule"), -+ 'ipa_subid_ranges_search_base': _("Search base for SUBID ranges"), - 'ipa_host_fqdn': _('The LDAP attribute that contains FQDN of the host.'), - 'ipa_host_object_class': _('The object class of a host entry in LDAP.'), - 'ipa_host_search_base': _('Use the given string as search base for host objects.'), -diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini -index 0a3c32a97..d8190c2f4 100644 ---- a/src/config/cfg_rules.ini -+++ b/src/config/cfg_rules.ini -@@ -538,6 +538,7 @@ option = ipa_backup_server - option = ipa_deskprofile_refresh - option = ipa_deskprofile_request_interval - option = ipa_deskprofile_search_base -+option = ipa_subid_ranges_search_base - option = ipa_domain - option = ipa_dyndns_iface - option = ipa_dyndns_ttl -diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf -index 9a81389ca..02c9089fd 100644 ---- a/src/config/etc/sssd.api.d/sssd-ipa.conf -+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf -@@ -4,6 +4,7 @@ ipa_server = str, None, false - ipa_backup_server = str, None, false - ipa_hostname = str, None, false - ipa_deskprofile_search_base = str, None, false -+ipa_subid_ranges_search_base = str, None, false - ipa_dyndns_update = bool, None, false - ipa_dyndns_ttl = int, None, false - ipa_dyndns_iface = str, None, false -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index a29232f48..b638f4397 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -143,6 +143,12 @@ - - #define SYSDB_SSH_PUBKEY "sshPublicKey" - -+#define SYSDB_SUBID_UID_COUND "subUidCount" -+#define SYSDB_SUBID_GID_COUNT "subGidCount" -+#define SYSDB_SUBID_UID_NUMBER "subUidNumber" -+#define SYSDB_SUBID_GID_NUMBER "subGidNumber" -+#define SYSDB_SUBID_OWNER "subidOwner" -+ - #define SYSDB_AUTH_TYPE "authType" - #define SYSDB_USER_CERT "userCertificate" - #define SYSDB_USER_MAPPED_CERT "userMappedCertificate" -diff --git a/src/db/sysdb_subid.c b/src/db/sysdb_subid.c -new file mode 100644 -index 000000000..519b0834c ---- /dev/null -+++ b/src/db/sysdb_subid.c -@@ -0,0 +1,163 @@ -+/* -+ Copyright (C) 2021 Red Hat -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . -+*/ -+ -+#include -+ -+#include "db/sysdb_private.h" -+#include "db/sysdb_subid.h" -+ -+#define SUBID_SUBDIR "subid_ranges" -+ -+ -+errno_t sysdb_store_subid_range(struct sss_domain_info *domain, -+ const char *name, -+ int expiration_period, -+ struct sysdb_attrs *attrs) -+{ -+ TALLOC_CTX *tmp_ctx; -+ errno_t ret, sret; -+ bool in_transaction = false; -+ time_t now = time(NULL); -+ -+ DEBUG(SSSDBG_TRACE_FUNC, "Storing subid ranges for %s, expiration period = %d\n", -+ name, expiration_period); -+ -+ tmp_ctx = talloc_new(NULL); -+ if (!tmp_ctx) { -+ return ENOMEM; -+ } -+ -+ ret = sysdb_transaction_start(domain->sysdb); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n"); -+ goto done; -+ } -+ -+ in_transaction = true; -+ -+ ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS, SYSDB_SUBID_RANGE_OC); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Could not set object class [%d]: %s\n", ret, strerror(ret)); -+ goto done; -+ } -+ -+ ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Could not set name attribute [%d]: %s\n", ret, strerror(ret)); -+ goto done; -+ } -+ -+ ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Could not set sysdb lastUpdate [%d]: %s\n", -+ ret, strerror(ret)); -+ goto done; -+ } -+ -+ ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE, -+ expiration_period ? (now + expiration_period) : 0); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "Could not set sysdb cache expire [%d]: %s\n", -+ ret, strerror(ret)); -+ goto done; -+ } -+ -+ ret = sysdb_store_custom(domain, name, SUBID_SUBDIR, attrs); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ ret = sysdb_transaction_commit(domain->sysdb); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n"); -+ goto done; -+ } -+ -+ in_transaction = false; -+ -+ ret = EOK; -+ -+done: -+ if (in_transaction) { -+ sret = sysdb_transaction_cancel(domain->sysdb); -+ if (sret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n"); -+ } -+ } -+ -+ talloc_free(tmp_ctx); -+ -+ return ret; -+} -+ -+errno_t sysdb_get_subid_ranges(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ const char *name, -+ const char **attrs, -+ struct ldb_message **_range) -+{ -+ TALLOC_CTX *tmp_ctx; -+ errno_t ret; -+ const char *filter; -+ struct ldb_message **ranges; -+ size_t num_ranges; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (!tmp_ctx) { -+ return ENOMEM; -+ } -+ -+ filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)(%s=%s))", -+ SYSDB_OBJECTCLASS, SYSDB_SUBID_RANGE_OC, -+ SYSDB_NAME, name); -+ if (!filter) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = sysdb_search_custom(tmp_ctx, domain, filter, -+ SUBID_SUBDIR, attrs, -+ &num_ranges, &ranges); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ if (num_ranges > 1) { -+ ret = EINVAL; -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Found more than one range with name %s\n", name); -+ goto done; -+ } -+ -+ *_range = talloc_steal(mem_ctx, ranges[0]); -+ ret = EOK; -+ -+done: -+ talloc_free(tmp_ctx); -+ -+ return ret; -+} -+ -+errno_t sysdb_delete_subid_range(struct sss_domain_info *domain, -+ const char *name) -+{ -+ DEBUG(SSSDBG_TRACE_FUNC, "Deleting subid ranges for %s\n", name); -+ return sysdb_delete_custom(domain, name, SUBID_SUBDIR); -+} -diff --git a/src/db/sysdb_subid.h b/src/db/sysdb_subid.h -new file mode 100644 -index 000000000..4b4a86334 ---- /dev/null -+++ b/src/db/sysdb_subid.h -@@ -0,0 +1,39 @@ -+/* -+ Copyright (C) 2021 Red Hat -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . -+*/ -+ -+#ifndef _SYSDB_SUBID_H_ -+#define _SYSDB_SUBID_H_ -+ -+#include "db/sysdb.h" -+ -+#define SYSDB_SUBID_RANGE_OC "subordinateid" -+ -+errno_t sysdb_store_subid_range(struct sss_domain_info *domain, -+ const char *name, -+ int expiration_period, -+ struct sysdb_attrs *attrs); -+ -+errno_t sysdb_get_subid_ranges(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ const char *name, -+ const char **attrs, -+ struct ldb_message **range); -+ -+errno_t sysdb_delete_subid_range(struct sss_domain_info *domain, -+ const char *name); -+ -+#endif /* _SYSDB_SSH_H_ */ -diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml -index 7b630493d..2bbf67c83 100644 ---- a/src/man/sssd-ipa.5.xml -+++ b/src/man/sssd-ipa.5.xml -@@ -356,6 +356,20 @@ - - - -+ -+ ipa_subid_ranges_search_base (string) -+ -+ -+ Optional. Use the given string as search base for -+ subordinate ranges related objects. -+ -+ -+ Default: the value of -+ cn=subids,%basedn -+ -+ -+ -+ - - ipa_hbac_search_base (string) - -diff --git a/src/providers/data_provider_req.c b/src/providers/data_provider_req.c -index e22cfd71a..b7f4d152e 100644 ---- a/src/providers/data_provider_req.c -+++ b/src/providers/data_provider_req.c -@@ -44,6 +44,8 @@ const char *be_req2str(dbus_uint32_t req_type) - return be_req_to_str(BE_REQ_HOST); - case BE_REQ_IP_NETWORK: - return be_req_to_str(BE_REQ_IP_NETWORK); -+ case BE_REQ_SUBID_RANGES: -+ return be_req_to_str(BE_REQ_SUBID_RANGES); - case BE_REQ_BY_SECID: - return be_req_to_str(BE_REQ_BY_SECID); - case BE_REQ_USER_AND_GROUP: -diff --git a/src/providers/data_provider_req.h b/src/providers/data_provider_req.h -index 75f7f9713..4c6ab5a7e 100644 ---- a/src/providers/data_provider_req.h -+++ b/src/providers/data_provider_req.h -@@ -35,6 +35,7 @@ - #define BE_REQ_SUDO_RULES 0x0007 - #define BE_REQ_HOST 0x0008 - #define BE_REQ_IP_NETWORK 0x0009 -+#define BE_REQ_SUBID_RANGES 0x0010 - #define BE_REQ_BY_SECID 0x0011 - #define BE_REQ_USER_AND_GROUP 0x0012 - #define BE_REQ_BY_UUID 0x0013 -diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c -index 23b358819..1509cb1ce 100644 ---- a/src/providers/ipa/ipa_common.c -+++ b/src/providers/ipa/ipa_common.c -@@ -152,6 +152,9 @@ static errno_t ipa_parse_search_base(TALLOC_CTX *mem_ctx, - case IPA_DESKPROFILE_SEARCH_BASE: - class_name = "IPA_DESKPROFILE"; - break; -+ case IPA_SUBID_RANGES_SEARCH_BASE: -+ class_name = "IPA_SUBID_RANGES"; -+ break; - default: - DEBUG(SSSDBG_CONF_SETTINGS, - "Unknown search base type: [%d]\n", class); -@@ -481,6 +484,41 @@ int ipa_get_id_options(struct ipa_options *ipa_opts, - &ipa_opts->deskprofile_search_bases); - if (ret != EOK) goto done; - -+#ifdef BUILD_SUBID -+ if (NULL == dp_opt_get_string(ipa_opts->basic, -+ IPA_SUBID_RANGES_SEARCH_BASE)) { -+ value = talloc_asprintf(tmpctx, "cn=subids,%s", -+ ipa_opts->id->sdom->search_bases[0]->basedn); -+ if (!value) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = dp_opt_set_string(ipa_opts->basic, IPA_SUBID_RANGES_SEARCH_BASE, value); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ DEBUG(SSSDBG_TRACE_FUNC, "Option %s set to %s\n", -+ ipa_opts->basic[IPA_SUBID_RANGES_SEARCH_BASE].opt_name, -+ dp_opt_get_string(ipa_opts->basic, -+ IPA_SUBID_RANGES_SEARCH_BASE)); -+ } -+ ret = ipa_parse_search_base(ipa_opts->basic, ipa_opts->basic, -+ IPA_SUBID_RANGES_SEARCH_BASE, -+ &ipa_opts->id->sdom->subid_ranges_search_bases); -+ if (ret != EOK) goto done; -+ -+ ret = sdap_get_map(ipa_opts->id, -+ cdb, conf_path, -+ ipa_subid_map, -+ SDAP_OPTS_SUBID_RANGE, -+ &ipa_opts->id->subid_map); -+ if (ret != EOK) { -+ goto done; -+ } -+#endif -+ - value = dp_opt_get_string(ipa_opts->id->basic, SDAP_DEREF); - if (value != NULL) { - ret = deref_string_to_val(value, &i); -diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h -index 480f7b664..eb0eda8eb 100644 ---- a/src/providers/ipa/ipa_common.h -+++ b/src/providers/ipa/ipa_common.h -@@ -68,6 +68,7 @@ enum ipa_basic_opt { - IPA_DESKPROFILE_SEARCH_BASE, - IPA_DESKPROFILE_REFRESH, - IPA_DESKPROFILE_REQUEST_INTERVAL, -+ IPA_SUBID_RANGES_SEARCH_BASE, - - IPA_OPTS_BASIC /* opts counter */ - }; -diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c -index 2cbe0c9c7..636e07965 100644 ---- a/src/providers/ipa/ipa_id.c -+++ b/src/providers/ipa/ipa_id.c -@@ -728,6 +728,22 @@ static errno_t ipa_id_get_account_info_get_original_step(struct tevent_req *req, - struct ipa_id_get_account_info_state); - struct tevent_req *subreq; - -+#ifdef BUILD_SUBID -+ if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_SUBID_RANGES) { -+ if (!state->ctx->opts->sdom->subid_ranges_search_bases || -+ !state->ctx->opts->sdom->subid_ranges_search_bases[0] || -+ !state->ctx->opts->sdom->subid_ranges_search_bases[0]->basedn) { -+ DEBUG(SSSDBG_OP_FAILURE, "subid_ranges_search_bases isn't set\n"); -+ return EINVAL; -+ } -+ ar->extra_value = talloc_asprintf(ar, -+ "%s=%s,"SYSDB_USERS_CONTAINER",%s", -+ state->ctx->opts->user_map[SDAP_AT_USER_NAME].name, -+ ar->filter_value, -+ state->ctx->opts->sdom->user_search_bases[0]->basedn); -+ } -+#endif -+ - subreq = sdap_handle_acct_req_send(state, state->ctx->be, ar, - state->ipa_ctx->sdap_id_ctx, - state->ipa_ctx->sdap_id_ctx->opts->sdom, -@@ -769,6 +785,7 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq) - } - - if (! is_object_overridable(state->ar)) { -+ DEBUG(SSSDBG_FUNC_DATA, "Object not overridable, ending request\n"); - state->dp_error = DP_ERR_OK; - tevent_req_done(req); - return; -diff --git a/src/providers/ipa/ipa_opts.c b/src/providers/ipa/ipa_opts.c -index 09e360a43..dc0a2201b 100644 ---- a/src/providers/ipa/ipa_opts.c -+++ b/src/providers/ipa/ipa_opts.c -@@ -26,6 +26,7 @@ - #include "db/sysdb_autofs.h" - #include "db/sysdb_services.h" - #include "db/sysdb_selinux.h" -+#include "db/sysdb_subid.h" - #include "providers/ldap/ldap_common.h" - - struct dp_option ipa_basic_opts[] = { -@@ -51,6 +52,7 @@ struct dp_option ipa_basic_opts[] = { - { "ipa_deskprofile_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "ipa_deskprofile_refresh", DP_OPT_NUMBER, { .number = 5 }, NULL_NUMBER }, - { "ipa_deskprofile_request_interval", DP_OPT_NUMBER, { .number = 60 }, NULL_NUMBER }, -+ { "ipa_subid_ranges_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - DP_OPTION_TERMINATOR - }; - -@@ -250,6 +252,16 @@ struct sdap_attr_map ipa_netgroup_map[] = { - SDAP_ATTR_MAP_TERMINATOR - }; - -+struct sdap_attr_map ipa_subid_map[] = { -+ { "ipa_subuid_object_class", "ipasubordinateid", SYSDB_SUBID_RANGE_OC, NULL }, -+ { "ipa_subuid_count", "ipaSubUidCount", SYSDB_SUBID_UID_COUND, NULL }, -+ { "ipa_subgid_count", "ipaSubGidCount", SYSDB_SUBID_GID_COUNT, NULL }, -+ { "ipa_subuid_number", "ipaSubUidNumber", SYSDB_SUBID_UID_NUMBER, NULL }, -+ { "ipa_subgid_number", "ipaSubGidNumber", SYSDB_SUBID_GID_NUMBER, NULL }, -+ { "ipa_owner", "ipaOwner", SYSDB_SUBID_OWNER, NULL }, -+ SDAP_ATTR_MAP_TERMINATOR -+}; -+ - struct sdap_attr_map ipa_host_map[] = { - { "ipa_host_object_class", "ipaHost", SYSDB_HOST_CLASS, NULL }, - { "ipa_host_name", "cn", SYSDB_NAME, NULL }, -diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h -index 378a9922c..6f54e57a9 100644 ---- a/src/providers/ipa/ipa_opts.h -+++ b/src/providers/ipa/ipa_opts.h -@@ -40,6 +40,8 @@ extern struct sdap_attr_map ipa_group_map[]; - - extern struct sdap_attr_map ipa_netgroup_map[]; - -+extern struct sdap_attr_map ipa_subid_map[]; -+ - extern struct sdap_attr_map ipa_host_map[]; - - extern struct sdap_attr_map ipa_hostgroup_map[]; -diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h -index 13e6d4871..c78338b5d 100644 ---- a/src/providers/ldap/ldap_common.h -+++ b/src/providers/ldap/ldap_common.h -@@ -446,4 +446,18 @@ errno_t users_get_handle_no_user(TALLOC_CTX *mem_ctx, - errno_t groups_get_handle_no_group(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - int filter_type, const char *filter_value); -+ -+#ifdef BUILD_SUBID -+struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx, -+ struct tevent_context *ev, -+ struct sdap_id_ctx *ctx, -+ struct sdap_domain *sdom, -+ struct sdap_id_conn_ctx *conn, -+ const char* filter_value, -+ const char *extra_value); -+ -+int subid_ranges_get_recv(struct tevent_req *req, int *dp_error_out, -+ int *sdap_ret); -+#endif -+ - #endif /* _LDAP_COMMON_H_ */ -diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c -index ebc0ab8e4..9b67773a8 100644 ---- a/src/providers/ldap/ldap_id.c -+++ b/src/providers/ldap/ldap_id.c -@@ -1449,6 +1449,24 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, - noexist_delete); - break; - -+ case BE_REQ_SUBID_RANGES: -+#ifdef BUILD_SUBID -+ if (!ar->extra_value) { -+ ret = ERR_GET_ACCT_SUBID_RANGES_NOT_SUPPORTED; -+ state->err = "This id_provider doesn't support subid ranges"; -+ goto done; -+ } -+ subreq = subid_ranges_get_send(state, be_ctx->ev, id_ctx, -+ sdom, conn, -+ ar->filter_value, -+ ar->extra_value); -+#else -+ ret = ERR_GET_ACCT_SUBID_RANGES_NOT_SUPPORTED; -+ state->err = "Subid ranges are not supported"; -+ goto done; -+#endif -+ break; -+ - case BE_REQ_NETGROUP: - if (ar->filter_type != BE_FILTER_NAME) { - ret = EINVAL; -@@ -1533,6 +1551,11 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, - default: /*fail*/ - ret = EINVAL; - state->err = "Invalid request type"; -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Unexpected request type: 0x%X [%s:%s] in %s\n", -+ ar->entry_type, ar->filter_value, -+ ar->extra_value?ar->extra_value:"-", -+ ar->domain); - goto done; - } - -@@ -1578,6 +1601,14 @@ sdap_handle_acct_req_done(struct tevent_req *subreq) - err = "Init group lookup failed"; - ret = groups_by_user_recv(subreq, &state->dp_error, &state->sdap_ret); - break; -+ case BE_REQ_SUBID_RANGES: -+ err = "Subid ranges lookup failed"; -+#ifdef BUILD_SUBID -+ ret = subid_ranges_get_recv(subreq, &state->dp_error, &state->sdap_ret); -+#else -+ ret = EINVAL; -+#endif -+ break; - case BE_REQ_NETGROUP: - err = "Netgroup lookup failed"; - ret = ldap_netgroup_get_recv(subreq, &state->dp_error, &state->sdap_ret); -diff --git a/src/providers/ldap/ldap_id_subid.c b/src/providers/ldap/ldap_id_subid.c -new file mode 100644 -index 000000000..d25c6aaac ---- /dev/null -+++ b/src/providers/ldap/ldap_id_subid.c -@@ -0,0 +1,255 @@ -+/* -+ SSSD -+ -+ LDAP Identity Backend Module - subid ranges support -+ -+ Copyright (C) 2021 Red Hat -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . -+*/ -+ -+#include -+ -+#include "db/sysdb_subid.h" -+#include "providers/ldap/ldap_common.h" -+#include "providers/ldap/sdap_async.h" -+#include "providers/ldap/sdap_ops.h" -+ -+static int subid_ranges_get_retry(struct tevent_req *req); -+static void subid_ranges_get_connect_done(struct tevent_req *subreq); -+static void subid_ranges_get_search(struct tevent_req *req); -+static void subid_ranges_get_done(struct tevent_req *subreq); -+ -+ -+struct subid_ranges_get_state { -+ struct tevent_context *ev; -+ struct sdap_id_ctx *ctx; -+ struct sdap_domain *sdom; -+ struct sdap_id_conn_ctx *conn; -+ struct sdap_id_op *op; -+ struct sss_domain_info *domain; -+ -+ char *filter; -+ char *name; -+ const char **attrs; -+ -+ int dp_error; -+ int sdap_ret; -+}; -+ -+struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx, -+ struct tevent_context *ev, -+ struct sdap_id_ctx *ctx, -+ struct sdap_domain *sdom, -+ struct sdap_id_conn_ctx *conn, -+ const char *filter_value, -+ const char *extra_value) -+{ -+ struct tevent_req *req; -+ struct subid_ranges_get_state *state; -+ int ret; -+ -+ req = tevent_req_create(memctx, &state, struct subid_ranges_get_state); -+ if (!req) return NULL; -+ -+ state->ev = ev; -+ state->ctx = ctx; -+ state->sdom = sdom; -+ state->conn = conn; -+ state->dp_error = DP_ERR_FATAL; -+ state->name = talloc_strdup(state, filter_value); -+ if (!state->name) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ state->op = sdap_id_op_create(state, state->conn->conn_cache); -+ if (!state->op) { -+ DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ state->domain = sdom->dom; -+ -+ state->filter = talloc_asprintf(state, -+ "(&(%s=%s)(%s=%s))", -+ SYSDB_OBJECTCLASS, -+ ctx->opts->subid_map[SDAP_OC_SUBID_RANGE].name, -+ ctx->opts->subid_map[SDAP_AT_SUBID_RANGE_OWNER].name, -+ extra_value); -+ -+ ret = subid_ranges_get_retry(req); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ return req; -+ -+done: -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ } else { -+ tevent_req_done(req); -+ } -+ return tevent_req_post(req, ev); -+} -+ -+static int subid_ranges_get_retry(struct tevent_req *req) -+{ -+ struct subid_ranges_get_state *state = tevent_req_data(req, -+ struct subid_ranges_get_state); -+ struct tevent_req *subreq; -+ int ret = EOK; -+ -+ subreq = sdap_id_op_connect_send(state->op, state, &ret); -+ if (!subreq) { -+ return ret; -+ } -+ -+ tevent_req_set_callback(subreq, subid_ranges_get_connect_done, req); -+ return EOK; -+} -+ -+static void subid_ranges_get_connect_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct subid_ranges_get_state *state = tevent_req_data(req, -+ struct subid_ranges_get_state); -+ int dp_error = DP_ERR_FATAL; -+ int ret; -+ -+ ret = sdap_id_op_connect_recv(subreq, &dp_error); -+ talloc_zfree(subreq); -+ -+ if (ret != EOK) { -+ state->dp_error = dp_error; -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ subid_ranges_get_search(req); -+} -+ -+static void subid_ranges_get_search(struct tevent_req *req) -+{ -+ struct subid_ranges_get_state *state = tevent_req_data(req, -+ struct subid_ranges_get_state); -+ struct tevent_req *subreq = NULL; -+ const char **attrs; -+ int ret; -+ -+ ret = build_attrs_from_map(state, state->ctx->opts->subid_map, -+ SDAP_OPTS_SUBID_RANGE, NULL, &attrs, NULL); -+ if (ret != EOK) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ -+ subreq = sdap_search_bases_send(state, state->ev, state->ctx->opts, -+ sdap_id_op_handle(state->op), -+ state->sdom->subid_ranges_search_bases, -+ state->ctx->opts->subid_map, -+ false, /* allow_paging */ -+ dp_opt_get_int(state->ctx->opts->basic, -+ SDAP_SEARCH_TIMEOUT), -+ state->filter, -+ attrs, -+ NULL); -+ talloc_free(attrs); -+ if (!subreq) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, subid_ranges_get_done, req); -+} -+ -+static void subid_ranges_get_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct subid_ranges_get_state *state = tevent_req_data(req, -+ struct subid_ranges_get_state); -+ int dp_error = DP_ERR_FATAL; -+ int ret; -+ struct sysdb_attrs **results; -+ size_t num_results; -+ -+ ret = sdap_search_bases_recv(subreq, state, &num_results, &results); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ ret = sdap_id_op_done(state->op, ret, &dp_error); -+ if (dp_error == DP_ERR_OK && ret != EOK) { -+ /* retry */ -+ ret = subid_ranges_get_retry(req); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ return; -+ } -+ state->sdap_ret = ret; -+ -+ if (ret && ret != ENOENT) { -+ DEBUG(SSSDBG_OP_FAILURE, "Failed to retrieve subid ranges.\n"); -+ state->dp_error = dp_error; -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (num_results == 0 || !results) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "No such user '%s' or user doesn't have subid range\n", -+ state->name); -+ sysdb_delete_subid_range(state->domain, state->name); -+ } else { -+ if (num_results > 1) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Multiple subid ranges, only first will be processed\n"); -+ } -+ -+ /* store range */ -+ sysdb_store_subid_range(state->domain, state->name, -+ state->domain->user_timeout, -+ results[0]); -+ } -+ -+ state->dp_error = DP_ERR_OK; -+ tevent_req_done(req); -+} -+ -+int subid_ranges_get_recv(struct tevent_req *req, int *dp_error_out, -+ int *sdap_ret) -+{ -+ struct subid_ranges_get_state *state = tevent_req_data(req, -+ struct subid_ranges_get_state); -+ -+ if (dp_error_out) { -+ *dp_error_out = state->dp_error; -+ } -+ -+ if (sdap_ret) { -+ *sdap_ret = state->sdap_ret; -+ } -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ return EOK; -+} -diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h -index ffcbee8a5..6382bec25 100644 ---- a/src/providers/ldap/sdap.h -+++ b/src/providers/ldap/sdap.h -@@ -389,6 +389,19 @@ enum sdap_ipnetwork_entry_attrs { - SDAP_OPTS_IPNETWORK /* attrs counter */ - }; - -+#ifdef BUILD_SUBID -+enum sdap_subid_range_attrs { -+ SDAP_OC_SUBID_RANGE = 0, -+ SDAP_AT_SUBID_RANGE_UID_COUNT, -+ SDAP_AT_SUBID_RANGE_GID_COUNT, -+ SDAP_AT_SUBID_RANGE_UID_NUMBER, -+ SDAP_AT_SUBID_RANGE_GID_NUMBER, -+ SDAP_AT_SUBID_RANGE_OWNER, -+ -+ SDAP_OPTS_SUBID_RANGE /* attrs counter */ -+}; -+#endif -+ - enum sdap_autofs_map_attrs { - SDAP_OC_AUTOFS_MAP, - SDAP_AT_AUTOFS_MAP_NAME, -@@ -453,6 +466,9 @@ struct sdap_domain { - struct sdap_search_base **iphost_search_bases; - struct sdap_search_base **ipnetwork_search_bases; - struct sdap_search_base **autofs_search_bases; -+#ifdef BUILD_SUBID -+ struct sdap_search_base **subid_ranges_search_bases; -+#endif - - struct sdap_domain *next, *prev; - /* Need to modify the list from a talloc destructor */ -@@ -495,6 +511,9 @@ struct sdap_options { - struct sdap_attr_map *service_map; - struct sdap_attr_map *iphost_map; - struct sdap_attr_map *ipnetwork_map; -+#ifdef BUILD_SUBID -+ struct sdap_attr_map *subid_map; -+#endif - - /* ID-mapping support */ - struct sdap_idmap_ctx *idmap_ctx; -diff --git a/src/responder/common/cache_req/cache_req.c b/src/responder/common/cache_req/cache_req.c -index 889547ba7..750d655c1 100644 ---- a/src/responder/common/cache_req/cache_req.c -+++ b/src/responder/common/cache_req/cache_req.c -@@ -45,6 +45,10 @@ cache_req_get_plugin(enum cache_req_type type) - &cache_req_initgroups_by_name, - &cache_req_initgroups_by_upn, - -+#ifdef BUILD_SUBID -+ &cache_req_subid_ranges_by_name, -+#endif -+ - &cache_req_object_by_sid, - &cache_req_object_by_name, - &cache_req_object_by_id, -diff --git a/src/responder/common/cache_req/cache_req.h b/src/responder/common/cache_req/cache_req.h -index d5c25ccf0..055fb405b 100644 ---- a/src/responder/common/cache_req/cache_req.h -+++ b/src/responder/common/cache_req/cache_req.h -@@ -39,6 +39,10 @@ enum cache_req_type { - CACHE_REQ_INITGROUPS, - CACHE_REQ_INITGROUPS_BY_UPN, - -+#ifdef BUILD_SUBID -+ CACHE_REQ_SUBID_RANGES_BY_NAME, -+#endif -+ - CACHE_REQ_OBJECT_BY_SID, - CACHE_REQ_OBJECT_BY_NAME, - CACHE_REQ_OBJECT_BY_ID, -diff --git a/src/responder/common/cache_req/cache_req_data.c b/src/responder/common/cache_req/cache_req_data.c -index e82dc8ab6..3c60eb484 100644 ---- a/src/responder/common/cache_req/cache_req_data.c -+++ b/src/responder/common/cache_req/cache_req_data.c -@@ -90,6 +90,9 @@ cache_req_data_create(TALLOC_CTX *mem_ctx, - case CACHE_REQ_GROUP_BY_FILTER: - case CACHE_REQ_INITGROUPS: - case CACHE_REQ_INITGROUPS_BY_UPN: -+#ifdef BUILD_SUBID -+ case CACHE_REQ_SUBID_RANGES_BY_NAME: -+#endif - case CACHE_REQ_NETGROUP_BY_NAME: - case CACHE_REQ_OBJECT_BY_NAME: - case CACHE_REQ_AUTOFS_MAP_ENTRIES: -diff --git a/src/responder/common/cache_req/cache_req_plugin.h b/src/responder/common/cache_req/cache_req_plugin.h -index 9e4986f93..f86a02042 100644 ---- a/src/responder/common/cache_req/cache_req_plugin.h -+++ b/src/responder/common/cache_req/cache_req_plugin.h -@@ -302,6 +302,9 @@ extern const struct cache_req_plugin cache_req_group_by_name; - extern const struct cache_req_plugin cache_req_group_by_id; - extern const struct cache_req_plugin cache_req_initgroups_by_name; - extern const struct cache_req_plugin cache_req_initgroups_by_upn; -+#ifdef BUILD_SUBID -+extern const struct cache_req_plugin cache_req_subid_ranges_by_name; -+#endif - extern const struct cache_req_plugin cache_req_user_by_cert; - extern const struct cache_req_plugin cache_req_user_by_filter; - extern const struct cache_req_plugin cache_req_group_by_filter; -diff --git a/src/responder/common/cache_req/plugins/cache_req_subid_ranges_by_name.c b/src/responder/common/cache_req/plugins/cache_req_subid_ranges_by_name.c -new file mode 100644 -index 000000000..54852711f ---- /dev/null -+++ b/src/responder/common/cache_req/plugins/cache_req_subid_ranges_by_name.c -@@ -0,0 +1,143 @@ -+/* -+ Copyright (C) 2021 Red Hat -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . -+*/ -+ -+#include -+#include -+ -+#include "db/sysdb.h" -+#include "db/sysdb_subid.h" -+#include "util/util.h" -+#include "providers/data_provider.h" -+#include "responder/common/cache_req/cache_req_plugin.h" -+ -+static errno_t -+cache_req_subid_ranges_by_name_prepare_domain_data(struct cache_req *cr, -+ struct cache_req_data *data, -+ struct sss_domain_info *domain) -+{ -+ TALLOC_CTX *tmp_ctx; -+ const char *name; -+ errno_t ret; -+ -+ if (cr->data->name.name == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: parsed name is NULL?\n"); -+ return ERR_INTERNAL; -+ } -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ name = sss_get_cased_name(tmp_ctx, cr->data->name.name, -+ domain->case_sensitive); -+ if (name == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ name = sss_reverse_replace_space(tmp_ctx, name, cr->rctx->override_space); -+ if (name == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ talloc_zfree(data->name.lookup); -+ data->name.lookup = talloc_steal(data, name); -+ -+ ret = EOK; -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+static const char * -+cache_req_subid_ranges_by_name_create_debug_name(TALLOC_CTX *mem_ctx, -+ struct cache_req_data *data, -+ struct sss_domain_info *domain) -+{ -+ return talloc_strdup(mem_ctx, data->name.lookup); -+} -+ -+static errno_t -+cache_req_subid_ranges_by_name_lookup(TALLOC_CTX *mem_ctx, -+ struct cache_req *cr, -+ struct cache_req_data *data, -+ struct sss_domain_info *domain, -+ struct ldb_result **_result) -+{ -+ struct ldb_result *result; -+ struct ldb_message *msg; -+ errno_t ret; -+ -+ ret = sysdb_get_subid_ranges(mem_ctx, domain, data->name.name, -+ data->attrs, &msg); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ result = cache_req_create_ldb_result_from_msg(mem_ctx, msg); -+ if (result == NULL) { -+ return ENOMEM; -+ } -+ -+ *_result = result; -+ -+ return EOK; -+} -+ -+static struct tevent_req * -+cache_req_subid_ranges_by_name_dp_send(TALLOC_CTX *mem_ctx, -+ struct cache_req *cr, -+ struct cache_req_data *data, -+ struct sss_domain_info *domain, -+ struct ldb_result *result) -+{ -+ /* Views aren't yet supported */ -+ return sss_dp_get_account_send(mem_ctx, cr->rctx, domain, true, -+ SSS_DP_SUBID_RANGES, cr->data->name.lookup, 0, NULL); -+} -+ -+const struct cache_req_plugin cache_req_subid_ranges_by_name = { -+ .name = "SubID ranges by name", -+ .attr_expiration = SYSDB_CACHE_EXPIRE, -+ .parse_name = true, -+ .ignore_default_domain = false, -+ .bypass_cache = false, -+ .only_one_result = false, -+ .search_all_domains = false, -+ .require_enumeration = false, -+ .allow_missing_fqn = false, -+ .allow_switch_to_upn = false, -+ .upn_equivalent = CACHE_REQ_SENTINEL, -+ .get_next_domain_flags = SSS_GND_DESCEND, -+ -+ .is_well_known_fn = NULL, -+ .prepare_domain_data_fn = cache_req_subid_ranges_by_name_prepare_domain_data, -+ .create_debug_name_fn = cache_req_subid_ranges_by_name_create_debug_name, -+ .global_ncache_add_fn = NULL, -+ .ncache_check_fn = NULL, -+ .ncache_add_fn = NULL, -+ .ncache_filter_fn = NULL, -+ .lookup_fn = cache_req_subid_ranges_by_name_lookup, -+ .dp_send_fn = cache_req_subid_ranges_by_name_dp_send, -+ .dp_recv_fn = cache_req_common_dp_recv, -+ .dp_get_domain_check_fn = NULL, -+ .dp_get_domain_send_fn = NULL, -+ .dp_get_domain_recv_fn = NULL, -+}; -diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h -index a5d6359a0..fbe46f335 100644 ---- a/src/responder/common/responder.h -+++ b/src/responder/common/responder.h -@@ -273,6 +273,7 @@ enum sss_dp_acct_type { - SSS_DP_USER = 1, - SSS_DP_GROUP, - SSS_DP_INITGROUPS, -+ SSS_DP_SUBID_RANGES, - SSS_DP_NETGR, - SSS_DP_SERVICES, - SSS_DP_SECID, -diff --git a/src/responder/common/responder_dp.c b/src/responder/common/responder_dp.c -index 8076e1e43..1b016dba1 100644 ---- a/src/responder/common/responder_dp.c -+++ b/src/responder/common/responder_dp.c -@@ -70,6 +70,7 @@ sss_dp_account_files_params(struct sss_domain_info *dom, - *_opt_name_out = opt_name_in; - return EAGAIN; - /* These are not handled by the files provider, just fall back */ -+ case SSS_DP_SUBID_RANGES: - case SSS_DP_NETGR: - case SSS_DP_SERVICES: - case SSS_DP_SECID: -@@ -109,6 +110,9 @@ sss_dp_get_account_filter(TALLOC_CTX *mem_ctx, - case SSS_DP_INITGROUPS: - entry_type = BE_REQ_INITGROUPS; - break; -+ case SSS_DP_SUBID_RANGES: -+ entry_type = BE_REQ_SUBID_RANGES; -+ break; - case SSS_DP_NETGR: - entry_type = BE_REQ_NETGROUP; - break; -diff --git a/src/responder/nss/nss_cmd.c b/src/responder/nss/nss_cmd.c -index a487e1c24..ef59daea8 100644 ---- a/src/responder/nss/nss_cmd.c -+++ b/src/responder/nss/nss_cmd.c -@@ -1041,6 +1041,25 @@ static errno_t nss_cmd_initgroups_ex(struct cli_ctx *cli_ctx) - SSS_MC_INITGROUPS, nss_protocol_fill_initgr); - } - -+static errno_t nss_cmd_subid_ranges(struct cli_ctx *cli_ctx) -+{ -+#ifdef BUILD_SUBID -+ const char *attrs[] = -+ { -+ SYSDB_SUBID_UID_COUND, -+ SYSDB_SUBID_GID_COUNT, -+ SYSDB_SUBID_UID_NUMBER, -+ SYSDB_SUBID_GID_NUMBER, -+ NULL -+ }; -+ -+ return nss_getby_name(cli_ctx, false, CACHE_REQ_SUBID_RANGES_BY_NAME, attrs, -+ SSS_MC_NONE, nss_protocol_fill_subid_ranges); -+#else -+ return ENOTSUP; -+#endif -+} -+ - static errno_t nss_cmd_setnetgrent(struct cli_ctx *cli_ctx) - { - struct nss_state_ctx *state_ctx; -@@ -1332,6 +1351,7 @@ struct sss_cmd_table *get_nss_cmds(void) - { SSS_NSS_GETGRENT, nss_cmd_getgrent }, - { SSS_NSS_ENDGRENT, nss_cmd_endgrent }, - { SSS_NSS_INITGR, nss_cmd_initgroups }, -+ { SSS_NSS_GET_SUBID_RANGES, nss_cmd_subid_ranges }, - { SSS_NSS_SETNETGRENT, nss_cmd_setnetgrent }, - /* { SSS_NSS_GETNETGRENT, "not needed" }, */ - /* { SSS_NSS_ENDNETGRENT, "not needed" }, */ -diff --git a/src/responder/nss/nss_protocol.h b/src/responder/nss/nss_protocol.h -index 364f19c83..949b6291a 100644 ---- a/src/responder/nss/nss_protocol.h -+++ b/src/responder/nss/nss_protocol.h -@@ -147,6 +147,14 @@ nss_protocol_fill_initgr(struct nss_ctx *nss_ctx, - struct sss_packet *packet, - struct cache_req_result *result); - -+#ifdef BUILD_SUBID -+errno_t -+nss_protocol_fill_subid_ranges(struct nss_ctx *nss_ctx, -+ struct nss_cmd_ctx *cmd_ctx, -+ struct sss_packet *packet, -+ struct cache_req_result *result); -+#endif -+ - errno_t - nss_protocol_fill_netgrent(struct nss_ctx *nss_ctx, - struct nss_cmd_ctx *cmd_ctx, -diff --git a/src/responder/nss/nss_protocol_subid.c b/src/responder/nss/nss_protocol_subid.c -new file mode 100644 -index 000000000..29a957762 ---- /dev/null -+++ b/src/responder/nss/nss_protocol_subid.c -@@ -0,0 +1,60 @@ -+/* -+ Copyright (C) 2021 Red Hat -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . -+*/ -+ -+#include "responder/nss/nss_protocol.h" -+ -+errno_t -+nss_protocol_fill_subid_ranges(struct nss_ctx *nss_ctx, -+ struct nss_cmd_ctx *cmd_ctx, -+ struct sss_packet *packet, -+ struct cache_req_result *result) -+{ -+ static const uint32_t one = 1; -+ errno_t ret; -+ uint8_t *body; -+ size_t body_len; -+ size_t rp = 0; -+ uint32_t gid, uid, gidCount, uidCount; -+ -+ if (!result->count || !result->msgs) { -+ return ENOENT; -+ } -+ -+ uid = ldb_msg_find_attr_as_uint(result->msgs[0], SYSDB_SUBID_UID_NUMBER, 0); -+ uidCount = ldb_msg_find_attr_as_uint(result->msgs[0], SYSDB_SUBID_UID_COUND, 0); -+ gid = ldb_msg_find_attr_as_uint(result->msgs[0], SYSDB_SUBID_GID_NUMBER, 0); -+ gidCount = ldb_msg_find_attr_as_uint(result->msgs[0], SYSDB_SUBID_GID_COUNT, 0); -+ if (!uid || !gid || !gidCount || !uidCount) { -+ return ENOENT; -+ } -+ -+ /* only single uid & gid range is expected currently */ -+ ret = sss_packet_grow(packet, (2 + 2*2) * sizeof(uint32_t)); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ sss_packet_get_body(packet, &body, &body_len); -+ SAFEALIGN_COPY_UINT32(&body[rp], &one, &rp); -+ SAFEALIGN_COPY_UINT32(&body[rp], &one, &rp); -+ SAFEALIGN_COPY_UINT32(&body[rp], &uid, &rp); -+ SAFEALIGN_COPY_UINT32(&body[rp], &uidCount, &rp); -+ SAFEALIGN_COPY_UINT32(&body[rp], &gid, &rp); -+ SAFEALIGN_COPY_UINT32(&body[rp], &gidCount, &rp); -+ -+ return EOK; -+} -diff --git a/src/sss_client/common.c b/src/sss_client/common.c -index d29332939..9416e21d1 100644 ---- a/src/sss_client/common.c -+++ b/src/sss_client/common.c -@@ -1008,7 +1008,7 @@ void sss_pam_close_fd(void) - sss_pam_unlock(); - } - --static enum sss_status -+enum sss_status - sss_cli_make_request_with_checks(enum sss_cli_command cmd, - struct sss_cli_req_data *rd, - int timeout, -diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h -index 2c3c71bc4..1347ce71d 100644 ---- a/src/sss_client/sss_cli.h -+++ b/src/sss_client/sss_cli.h -@@ -284,6 +284,10 @@ SSS_NSS_GETSIDBYGID = 0x0119, /**< Takes an unsigned 32bit integer (POSIX GID) - and return the zero terminated string - representation of the SID of the object - with the given UID. */ -+ -+/* subid */ -+ SSS_NSS_GET_SUBID_RANGES = 0x0130, /**< Requests both subuid and subgid ranges -+ defined for a user. */ - }; - - /** -@@ -631,6 +635,13 @@ enum sss_cli_error_codes { - - const char *ssscli_err2string(int err); - -+enum sss_status sss_cli_make_request_with_checks(enum sss_cli_command cmd, -+ struct sss_cli_req_data *rd, -+ int timeout, -+ uint8_t **repbuf, size_t *replen, -+ int *errnop, -+ const char *socket_name); -+ - enum nss_status sss_nss_make_request(enum sss_cli_command cmd, - struct sss_cli_req_data *rd, - uint8_t **repbuf, size_t *replen, -diff --git a/src/sss_client/subid/sss_subid.c b/src/sss_client/subid/sss_subid.c -new file mode 100644 -index 000000000..ae74ece3c ---- /dev/null -+++ b/src/sss_client/subid/sss_subid.c -@@ -0,0 +1,209 @@ -+/* -+ Copyright (C) 2021 Red Hat -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . -+*/ -+ -+#include -+#include -+#include -+#include "sss_cli.h" -+ -+/* This shadow-utils plugin contains partial SSSD implementation -+ * of `subid_nss_ops` API as described in -+ * https://github.com/shadow-maint/shadow/blob/d4b6d1549b2af48ce3cb6ff78d9892095fb8fdd9/lib/prototypes.h#L271 -+ */ -+ -+/* Find all subid ranges delegated to a user. -+ * -+ * Usage in shadow-utils: -+ * libsubid: get_sub?id_ranges() -> list_owner_ranges() -+ * -+ * SUBID_RANGES Reply: -+ * -+ * 0-3: 32bit unsigned number of UID results -+ * 4-7: 32bit unsigned number of GID results -+ * For each result (sub-uid ranges first): -+ * 0-3: 32bit number with "start" id -+ * 4-7: 32bit number with "count" (range size) -+ */ -+enum subid_status shadow_subid_list_owner_ranges(const char *user, -+ enum subid_type id_type, -+ struct subid_range **ranges, -+ int *count) -+{ -+ size_t user_len; -+ enum sss_status ret; -+ uint8_t *repbuf = NULL; -+ size_t index = 0; -+ size_t replen; -+ int errnop; -+ struct sss_cli_req_data rd; -+ uint32_t num_results = 0; -+ uint32_t val; -+ -+ if ( !user || !ranges || !count || -+ ((id_type != ID_TYPE_UID) && (id_type != ID_TYPE_GID)) ) { -+ return SUBID_STATUS_ERROR; -+ } -+ -+ ret = sss_strnlen(user, SSS_NAME_MAX, &user_len); -+ if (ret != 0) { -+ return SUBID_STATUS_UNKNOWN_USER; -+ } -+ rd.len = user_len + 1; -+ rd.data = user; -+ -+ sss_nss_lock(); -+ /* Anticipated workflow will always request both -+ * sub-uid and sub-gid ranges anyway. -+ * So don't bother with dedicated commands - -+ * just request everything in one shot. -+ * The second request will get data from the cache. -+ */ -+ ret = sss_cli_make_request_with_checks(SSS_NSS_GET_SUBID_RANGES, &rd, -+ SSS_CLI_SOCKET_TIMEOUT, -+ &repbuf, &replen, &errnop, -+ SSS_NSS_SOCKET_NAME); -+ sss_nss_unlock(); -+ -+ if ((ret != SSS_STATUS_SUCCESS) || (errnop != EOK)) { -+ free(repbuf); -+ if (ret == SSS_STATUS_UNAVAIL) { -+ return SUBID_STATUS_ERROR_CONN; -+ } -+ return SUBID_STATUS_ERROR; -+ } -+ -+ SAFEALIGN_COPY_UINT32(&num_results, repbuf, NULL); -+ if (id_type == ID_TYPE_UID) { -+ index = 2 * sizeof(uint32_t); -+ } else { -+ index = (2 + 2*num_results) * sizeof(uint32_t); -+ SAFEALIGN_COPY_UINT32(&num_results, repbuf + sizeof(uint32_t), NULL); -+ } -+ if (num_results == 0) { -+ /* TODO: how to distinguish "user not found" vs "user doesn't have ranges defined" here? -+ * Options: -+ * - special "fake" entry in the cache -+ * - provide 'nss_protocol_done_fn' to 'nss_getby_name' to avoid "ENOENT -> "empty packet" logic -+ * - add custom error code for this case and handle in generic 'nss_protocol_done' -+ * -+ * Note: at the moment this is not important, since shadow-utils doesn't use return code internally -+ * and returns -1 from libsubid on any error anyway. -+ */ -+ free(repbuf); -+ return SUBID_STATUS_UNKNOWN_USER; -+ } -+ -+ *count = num_results; -+ if (*count < 0) { -+ free(repbuf); -+ return SUBID_STATUS_ERROR; -+ } -+ -+ *ranges = malloc(num_results * sizeof(struct subid_range)); -+ if (!*ranges) { -+ free(repbuf); -+ return SUBID_STATUS_ERROR; -+ } -+ -+ for (uint32_t c = 0; c < num_results; ++c) { -+ SAFEALIGN_COPY_UINT32(&val, repbuf + index, &index); -+ (*ranges)[c].start = val; -+ SAFEALIGN_COPY_UINT32(&val, repbuf + index, &index); -+ (*ranges)[c].count = val; -+ } -+ free(repbuf); -+ -+ return SUBID_STATUS_SUCCESS; -+} -+ -+/* Does a user own a given subid range? -+ * -+ * Usage in shadow-utils: -+ * newuidmap/user busy : have_sub_uids() -> has_range() -+ */ -+enum subid_status shadow_subid_has_range(const char *owner, -+ unsigned long start, -+ unsigned long count, -+ enum subid_type id_type, -+ bool *result) -+{ -+ enum subid_status ret; -+ struct subid_range *range; -+ int amount; -+ unsigned long end = start + count; -+ -+ if (!result || (end < start)) { -+ return SUBID_STATUS_ERROR; -+ } -+ -+ if (count == 0) { -+ *result = true; -+ return SUBID_STATUS_SUCCESS; -+ } -+ -+ /* Anticipated workflow is the following: -+ * -+ * 1) Podman figures out ranges available for a user: -+ * libsubid::get_subid_ranges() -> ... -> list_owner_ranges() -+ * -+ * 2) Podman maps available ranges: -+ * newuidmap -> have_sub_uids() -> has_range() -+ * At this point all ranges are available in a cache from step (1) -+ * so it doesn't make sense to try "smart" LDAP searches (even if possible) -+ * Let's just reuse list_owner_ranges() and do a check. -+ * -+ * It might have some sense to do a check at responder's side (i.e. without -+ * fetching all ranges), but range is just a couple of numbers (and FreeIPA -+ * only supports a single range per user anyway), so this optimization -+ * wouldn't save much traffic anyway, but would introduce new -+ * `sss_cli_command`/responder handler. -+ */ -+ -+ ret = shadow_subid_list_owner_ranges(owner, id_type, &range, &amount); -+ if (ret != SUBID_STATUS_SUCCESS) { -+ return ret; -+ } -+ -+ *result = false; -+ -+ for (int i = 0; i < amount; ++i) { -+ if ((range[i].start <= start) && -+ (range[i].start + range[i].count >= end)) { -+ *result = true; -+ } -+ /* TODO: handle coverage via multiple ranges (once IPA supports this) */ -+ } -+ -+ free(range); -+ return ret; -+} -+ -+/* Find uids who own a given subid. -+ * -+ * Usage in shadow-utils: -+ * libsubid: get_sub?id_owners() -> find_subid_owners() -+ */ -+enum subid_status shadow_subid_find_subid_owners(unsigned long subid, -+ enum subid_type id_type, -+ uid_t **uids, -+ int *count) -+{ -+ /* Not yet implemented. -+ * Currently there are no users of this function. -+ */ -+ return SUBID_STATUS_ERROR; -+} -diff --git a/src/sss_client/subid/sss_subid.exports b/src/sss_client/subid/sss_subid.exports -new file mode 100644 -index 000000000..87c073b48 ---- /dev/null -+++ b/src/sss_client/subid/sss_subid.exports -@@ -0,0 +1,12 @@ -+EXPORTED { -+ -+ # public functions -+ global: -+ shadow_subid_has_range; -+ shadow_subid_list_owner_ranges; -+ shadow_subid_find_subid_owners; -+ -+ # everything else is local -+ local: -+ *; -+}; -diff --git a/src/systemtap/sssd_functions.stp b/src/systemtap/sssd_functions.stp -index 01f553177..513029046 100644 ---- a/src/systemtap/sssd_functions.stp -+++ b/src/systemtap/sssd_functions.stp -@@ -29,8 +29,8 @@ function acct_req_desc(entry_type) - str_entry_type = "host" - } else if (entry_type == 0x0009) { - str_entry_type = "ip_network" -- # See src/providers/data_provider_req.h, no 0x0010 there.. - } else if (entry_type == 0x0010) { -+ str_entry_type = "subid_ranges" - } else if (entry_type == 0x0011) { - str_entry_type = "by_secid" - } else if (entry_type == 0x0012) { -diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am -index 60f71036e..6d3dc45e5 100644 ---- a/src/tests/cwrap/Makefile.am -+++ b/src/tests/cwrap/Makefile.am -@@ -74,6 +74,9 @@ SSSD_CACHE_REQ_OBJ = \ - ../../../src/responder/common/cache_req/plugins/cache_req_ip_network_by_name.c \ - ../../../src/responder/common/cache_req/plugins/cache_req_ip_network_by_addr.c \ - $(NULL) -+if BUILD_SUBID -+ SSSD_CACHE_REQ_OBJ += ../../../src/responder/common/cache_req/plugins/cache_req_subid_ranges_by_name.c -+endif - - SSSD_RESPONDER_IFACE_OBJ = \ - ../../../src/responder/common/responder_iface.c \ -diff --git a/src/tests/dlopen-tests.c b/src/tests/dlopen-tests.c -index ab44c213c..6d3345cbe 100644 ---- a/src/tests/dlopen-tests.c -+++ b/src/tests/dlopen-tests.c -@@ -60,6 +60,9 @@ struct so { - #ifdef BUILD_AUTOFS - { "libsss_autofs.so", { LIBPFX"libsss_autofs.so", NULL } }, - #endif -+#ifdef BUILD_SUBID -+ { "libsubid_sss.so", { LIBPFX"libsubid_sss.so", NULL } }, -+#endif - #ifdef HAVE_KRB5_LOCATOR_PLUGIN - { "sssd_krb5_locator_plugin.so", { LIBPFX"sssd_krb5_locator_plugin.so", - NULL } }, -diff --git a/src/util/sss_cli_cmd.c b/src/util/sss_cli_cmd.c -index 82dc33b33..bc9332aaa 100644 ---- a/src/util/sss_cli_cmd.c -+++ b/src/util/sss_cli_cmd.c -@@ -230,6 +230,11 @@ const char *sss_cmd2str(enum sss_cli_command cmd) - return "SSS_NSS_GETIDBYSID"; - case SSS_NSS_GETORIGBYNAME: - return "SSS_NSS_GETORIGBYNAME"; -+ -+ /* SUBID ranges */ -+ case SSS_NSS_GET_SUBID_RANGES: -+ return "SSS_NSS_GET_SUBID_RANGES"; -+ - default: - DEBUG(SSSDBG_MINOR_FAILURE, - "Translation's string is missing for command [%#x].\n", cmd); -diff --git a/src/util/util_errors.c b/src/util/util_errors.c -index 7ba2621d1..f2d1d5dfc 100644 ---- a/src/util/util_errors.c -+++ b/src/util/util_errors.c -@@ -120,6 +120,7 @@ struct err_string error_to_str[] = { - { "Unable to verify peer" }, /* ERR_UNABLE_TO_VERIFY_PEER */ - { "Unable to resolve host" }, /* ERR_UNABLE_TO_RESOLVE_HOST */ - { "GetAccountDomain() not supported" }, /* ERR_GET_ACCT_DOM_NOT_SUPPORTED */ -+ { "Subid ranges are not supported by this provider" }, /* ERR_GET_ACCT_SUBID_RANGES_NOT_SUPPORTED */ - { "The last GetAccountDomain() result is still valid" }, /* ERR_GET_ACCT_DOM_CACHED */ - { "ID is outside the allowed range" }, /* ERR_ID_OUTSIDE_RANGE */ - { "Group ID is duplicated" }, /* ERR_GID_DUPLICATED */ -diff --git a/src/util/util_errors.h b/src/util/util_errors.h -index 37ce2de23..4098e818d 100644 ---- a/src/util/util_errors.h -+++ b/src/util/util_errors.h -@@ -141,6 +141,7 @@ enum sssd_errors { - ERR_UNABLE_TO_VERIFY_PEER, - ERR_UNABLE_TO_RESOLVE_HOST, - ERR_GET_ACCT_DOM_NOT_SUPPORTED, -+ ERR_GET_ACCT_SUBID_RANGES_NOT_SUPPORTED, - ERR_GET_ACCT_DOM_CACHED, - ERR_ID_OUTSIDE_RANGE, - ERR_GID_DUPLICATED, --- -2.26.3 - diff --git a/0002-TOOLS-replace-system-with-execvp.patch b/0002-TOOLS-replace-system-with-execvp.patch deleted file mode 100644 index 081bf29..0000000 --- a/0002-TOOLS-replace-system-with-execvp.patch +++ /dev/null @@ -1,277 +0,0 @@ -From 5a9a2f53ff44b1bd25a6de7c4ba91c709b63b0ba Mon Sep 17 00:00:00 2001 -From: Alexey Tikhonov -Date: Fri, 18 Jun 2021 13:17:19 +0200 -Subject: [PATCH] TOOLS: replace system() with execvp() to avoid execution of - user supplied command - -A flaw was found in SSSD, where the sssctl command was vulnerable -to shell command injection via the logs-fetch and cache-expire -subcommands. This flaw allows an attacker to trick the root user -into running a specially crafted sssctl command, such as via sudo, -to gain root access. The highest threat from this vulnerability is -to confidentiality, integrity, as well as system availability. - -:fixes: CVE-2021-3621 ---- - src/tools/sssctl/sssctl.c | 39 ++++++++++++++++------- - src/tools/sssctl/sssctl.h | 2 +- - src/tools/sssctl/sssctl_data.c | 57 +++++++++++----------------------- - src/tools/sssctl/sssctl_logs.c | 32 +++++++++++++++---- - 4 files changed, 73 insertions(+), 57 deletions(-) - -diff --git a/src/tools/sssctl/sssctl.c b/src/tools/sssctl/sssctl.c -index 2997dbf968acdd0b9821f726414f8ae1cf34b5d8..8adaf30910e13ea9e7c8ab8b151920c4f307427b 100644 ---- a/src/tools/sssctl/sssctl.c -+++ b/src/tools/sssctl/sssctl.c -@@ -97,22 +97,36 @@ sssctl_prompt(const char *message, - return SSSCTL_PROMPT_ERROR; - } - --errno_t sssctl_run_command(const char *command) -+errno_t sssctl_run_command(const char *const argv[]) - { - int ret; -+ int wstatus; - -- DEBUG(SSSDBG_TRACE_FUNC, "Running %s\n", command); -+ DEBUG(SSSDBG_TRACE_FUNC, "Running '%s'\n", argv[0]); - -- ret = system(command); -+ ret = fork(); - if (ret == -1) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to execute %s\n", command); - ERROR("Error while executing external command\n"); - return EFAULT; -- } else if (WEXITSTATUS(ret) != 0) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Command %s failed with [%d]\n", -- command, WEXITSTATUS(ret)); -+ } -+ -+ if (ret == 0) { -+ /* cast is safe - see -+ https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html -+ "The statement about argv[] and envp[] being constants ... " -+ */ -+ execvp(argv[0], discard_const_p(char * const, argv)); - ERROR("Error while executing external command\n"); -- return EIO; -+ _exit(1); -+ } else { -+ if (waitpid(ret, &wstatus, 0) == -1) { -+ ERROR("Error while executing external command '%s'\n", argv[0]); -+ return EFAULT; -+ } else if (WEXITSTATUS(wstatus) != 0) { -+ ERROR("Command '%s' failed with [%d]\n", -+ argv[0], WEXITSTATUS(wstatus)); -+ return EIO; -+ } - } - - return EOK; -@@ -132,11 +146,14 @@ static errno_t sssctl_manage_service(enum sssctl_svc_action action) - #elif defined(HAVE_SERVICE) - switch (action) { - case SSSCTL_SVC_START: -- return sssctl_run_command(SERVICE_PATH" sssd start"); -+ return sssctl_run_command( -+ (const char *[]){SERVICE_PATH, "sssd", "start", NULL}); - case SSSCTL_SVC_STOP: -- return sssctl_run_command(SERVICE_PATH" sssd stop"); -+ return sssctl_run_command( -+ (const char *[]){SERVICE_PATH, "sssd", "stop", NULL}); - case SSSCTL_SVC_RESTART: -- return sssctl_run_command(SERVICE_PATH" sssd restart"); -+ return sssctl_run_command( -+ (const char *[]){SERVICE_PATH, "sssd", "restart", NULL}); - } - #endif - -diff --git a/src/tools/sssctl/sssctl.h b/src/tools/sssctl/sssctl.h -index 0115b2457c48bb0b8ad8ef8fd20d6fc81bdb58b4..599ef65196fcae6454cd5b46aa7a2cf6e7cbba73 100644 ---- a/src/tools/sssctl/sssctl.h -+++ b/src/tools/sssctl/sssctl.h -@@ -47,7 +47,7 @@ enum sssctl_prompt_result - sssctl_prompt(const char *message, - enum sssctl_prompt_result defval); - --errno_t sssctl_run_command(const char *command); -+errno_t sssctl_run_command(const char *const argv[]); /* argv[0] - command */ - bool sssctl_start_sssd(bool force); - bool sssctl_stop_sssd(bool force); - bool sssctl_restart_sssd(bool force); -diff --git a/src/tools/sssctl/sssctl_data.c b/src/tools/sssctl/sssctl_data.c -index 8d79b977fdb63fd6c6c925538230bb4ca74a103b..bf2291341668590f4c600237593ea1fd8fe4e4dc 100644 ---- a/src/tools/sssctl/sssctl_data.c -+++ b/src/tools/sssctl/sssctl_data.c -@@ -105,15 +105,15 @@ static errno_t sssctl_backup(bool force) - } - } - -- ret = sssctl_run_command("sss_override user-export " -- SSS_BACKUP_USER_OVERRIDES); -+ ret = sssctl_run_command((const char *[]){"sss_override", "user-export", -+ SSS_BACKUP_USER_OVERRIDES, NULL}); - if (ret != EOK) { - ERROR("Unable to export user overrides\n"); - return ret; - } - -- ret = sssctl_run_command("sss_override group-export " -- SSS_BACKUP_GROUP_OVERRIDES); -+ ret = sssctl_run_command((const char *[]){"sss_override", "group-export", -+ SSS_BACKUP_GROUP_OVERRIDES, NULL}); - if (ret != EOK) { - ERROR("Unable to export group overrides\n"); - return ret; -@@ -158,8 +158,8 @@ static errno_t sssctl_restore(bool force_start, bool force_restart) - } - - if (sssctl_backup_file_exists(SSS_BACKUP_USER_OVERRIDES)) { -- ret = sssctl_run_command("sss_override user-import " -- SSS_BACKUP_USER_OVERRIDES); -+ ret = sssctl_run_command((const char *[]){"sss_override", "user-import", -+ SSS_BACKUP_USER_OVERRIDES, NULL}); - if (ret != EOK) { - ERROR("Unable to import user overrides\n"); - return ret; -@@ -167,8 +167,8 @@ static errno_t sssctl_restore(bool force_start, bool force_restart) - } - - if (sssctl_backup_file_exists(SSS_BACKUP_USER_OVERRIDES)) { -- ret = sssctl_run_command("sss_override group-import " -- SSS_BACKUP_GROUP_OVERRIDES); -+ ret = sssctl_run_command((const char *[]){"sss_override", "group-import", -+ SSS_BACKUP_GROUP_OVERRIDES, NULL}); - if (ret != EOK) { - ERROR("Unable to import group overrides\n"); - return ret; -@@ -296,40 +296,19 @@ errno_t sssctl_cache_expire(struct sss_cmdline *cmdline, - void *pvt) - { - errno_t ret; -- char *cmd_args = NULL; -- const char *cachecmd = SSS_CACHE; -- char *cmd = NULL; -- int i; - -- if (cmdline->argc == 0) { -- ret = sssctl_run_command(cachecmd); -- goto done; -+ const char **args = talloc_array_size(tool_ctx, -+ sizeof(char *), -+ cmdline->argc + 2); -+ if (!args) { -+ return ENOMEM; - } -+ memcpy(&args[1], cmdline->argv, sizeof(char *) * cmdline->argc); -+ args[0] = SSS_CACHE; -+ args[cmdline->argc + 1] = NULL; - -- cmd_args = talloc_strdup(tool_ctx, ""); -- if (cmd_args == NULL) { -- ret = ENOMEM; -- goto done; -- } -- -- for (i = 0; i < cmdline->argc; i++) { -- cmd_args = talloc_strdup_append(cmd_args, cmdline->argv[i]); -- if (i != cmdline->argc - 1) { -- cmd_args = talloc_strdup_append(cmd_args, " "); -- } -- } -- -- cmd = talloc_asprintf(tool_ctx, "%s %s", cachecmd, cmd_args); -- if (cmd == NULL) { -- ret = ENOMEM; -- goto done; -- } -- -- ret = sssctl_run_command(cmd); -- --done: -- talloc_free(cmd_args); -- talloc_free(cmd); -+ ret = sssctl_run_command(args); - -+ talloc_free(args); - return ret; - } -diff --git a/src/tools/sssctl/sssctl_logs.c b/src/tools/sssctl/sssctl_logs.c -index 9ff2be05b61108414462d6e17a2c4c4887907a59..ebb2c4571caec487d29ff2d5ceaee1561e845506 100644 ---- a/src/tools/sssctl/sssctl_logs.c -+++ b/src/tools/sssctl/sssctl_logs.c -@@ -31,6 +31,7 @@ - #include - #include - #include -+#include - - #include "util/util.h" - #include "tools/common/sss_process.h" -@@ -230,6 +231,7 @@ errno_t sssctl_logs_remove(struct sss_cmdline *cmdline, - { - struct sssctl_logs_opts opts = {0}; - errno_t ret; -+ glob_t globbuf; - - /* Parse command line. */ - struct poptOption options[] = { -@@ -253,8 +255,20 @@ errno_t sssctl_logs_remove(struct sss_cmdline *cmdline, - - sss_signal(SIGHUP); - } else { -+ globbuf.gl_offs = 4; -+ ret = glob(LOG_PATH"/*.log", GLOB_ERR|GLOB_DOOFFS, NULL, &globbuf); -+ if (ret != 0) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to expand log files list\n"); -+ return ret; -+ } -+ globbuf.gl_pathv[0] = discard_const_p(char, "truncate"); -+ globbuf.gl_pathv[1] = discard_const_p(char, "--no-create"); -+ globbuf.gl_pathv[2] = discard_const_p(char, "--size"); -+ globbuf.gl_pathv[3] = discard_const_p(char, "0"); -+ - PRINT("Truncating log files...\n"); -- ret = sssctl_run_command("truncate --no-create --size 0 " LOG_FILES); -+ ret = sssctl_run_command((const char * const*)globbuf.gl_pathv); -+ globfree(&globbuf); - if (ret != EOK) { - ERROR("Unable to truncate log files\n"); - return ret; -@@ -269,8 +283,8 @@ errno_t sssctl_logs_fetch(struct sss_cmdline *cmdline, - void *pvt) - { - const char *file; -- const char *cmd; - errno_t ret; -+ glob_t globbuf; - - /* Parse command line. */ - ret = sss_tool_popt_ex(cmdline, NULL, SSS_TOOL_OPT_OPTIONAL, NULL, NULL, -@@ -280,13 +294,19 @@ errno_t sssctl_logs_fetch(struct sss_cmdline *cmdline, - return ret; - } - -- cmd = talloc_asprintf(tool_ctx, "tar -czf %s %s", file, LOG_FILES); -- if (cmd == NULL) { -- ERROR("Out of memory!"); -+ globbuf.gl_offs = 3; -+ ret = glob(LOG_PATH"/*.log", GLOB_ERR|GLOB_DOOFFS, NULL, &globbuf); -+ if (ret != 0) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to expand log files list\n"); -+ return ret; - } -+ globbuf.gl_pathv[0] = discard_const_p(char, "tar"); -+ globbuf.gl_pathv[1] = discard_const_p(char, "-czf"); -+ globbuf.gl_pathv[2] = discard_const_p(char, file); - - PRINT("Archiving log files into %s...\n", file); -- ret = sssctl_run_command(cmd); -+ ret = sssctl_run_command((const char * const*)globbuf.gl_pathv); -+ globfree(&globbuf); - if (ret != EOK) { - ERROR("Unable to archive log files\n"); - return ret; --- -2.31.1 - diff --git a/0003-configure-do-not-unset-PYTHON_PREFIX-and-PYTHON_EXEC.patch b/0003-configure-do-not-unset-PYTHON_PREFIX-and-PYTHON_EXEC.patch deleted file mode 100644 index dd2dee1..0000000 --- a/0003-configure-do-not-unset-PYTHON_PREFIX-and-PYTHON_EXEC.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 9e47b63e4fe5c17b1fb308ce98a5f04ce5b5624b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Mon, 6 Sep 2021 13:48:06 +0200 -Subject: [PATCH] configure: do not unset PYTHON_PREFIX and PYTHON_EXEC_PREFIX - -Recent changes in autoconf changed location of directories from: - -``` -checking for /usr/bin/python3 script directory... ${prefix}/lib/python3.9/site-packages -checking for /usr/bin/python3 extension module directory... ${exec_prefix}/lib64/python3.9/site-packages -``` - -to - -``` -checking for /usr/bin/python3 script directory... ${PYTHON_PREFIX}/lib/python3.10/site-packages -checking for /usr/bin/python3 extension module directory... ${PYTHON_EXEC_PREFIX}/lib64/python3.10/site-packages -``` - -However, we unset these variables in SSS_CLEAN_PYTHON_VARIABLES and -therefore the correct prefix is not applied anymore during installation. - -Reviewed-by: Pawel Polawski ---- - src/external/python.m4 | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/external/python.m4 b/src/external/python.m4 -index 1738f9f8f..6a6283511 100644 ---- a/src/external/python.m4 -+++ b/src/external/python.m4 -@@ -73,7 +73,7 @@ AC_DEFUN([SSS_CLEAN_PYTHON_VARIABLES], - [ - unset pyexecdir pkgpyexecdir pythondir pgkpythondir - unset PYTHON PYTHON_CFLAGS PYTHON_LIBS PYTHON_INCLUDES -- unset PYTHON_PREFIX PYTHON_EXEC_PREFIX PYTHON_VERSION PYTHON_CONFIG -+ unset PYTHON_VERSION PYTHON_CONFIG - - dnl removed cached variables, required for reusing of AM_PATH_PYTHON - unset am_cv_pathless_PYTHON ac_cv_path_PYTHON am_cv_python_version --- -2.31.1 - diff --git a/sssd.spec b/sssd.spec index a8ba869..a9bf74b 100644 --- a/sssd.spec +++ b/sssd.spec @@ -14,6 +14,16 @@ %global child_attrs 4750 %endif +%if 0%{?fedora} >= 34 +%global build_kcm_renewals 1 +%global krb5_version 1.19.1 +%elif 0%{?rhel} >= 8 +%global build_kcm_renewals 1 +%global krb5_version 1.18.2 +%else +%global build_kcm_renewals 0 +%endif + # we don't want to provide private python extension libs %define __provides_exclude_from %{python3_sitearch}/.*\.so$ @@ -26,17 +36,14 @@ %global samba_package_version %(rpm -q samba-devel --queryformat %{version}-%{release}) Name: sssd -Version: 2.5.2 -Release: 7%{?dist} +Version: 2.6.0 +Release: 1%{?dist} Summary: System Security Services Daemon License: GPLv3+ URL: https://github.com/SSSD/sssd/ -Source0: https://github.com/SSSD/sssd/releases/download/2.5.2/sssd-2.5.2.tar.gz +Source0: https://github.com/SSSD/sssd/releases/download/2.6.0/sssd-2.6.0.tar.gz ### Patches ### -Patch0001: 0001-Basics-of-subid-ranges-support-for-IPA-provider.patch -Patch0002: 0002-TOOLS-replace-system-with-execvp.patch -Patch0003: 0003-configure-do-not-unset-PYTHON_PREFIX-and-PYTHON_EXEC.patch ### Dependencies ### @@ -76,10 +83,8 @@ BuildRequires: findutils BuildRequires: gcc BuildRequires: gdm-pam-extensions-devel BuildRequires: gettext-devel -BuildRequires: glib2-devel # required for p11_child smartcard tests BuildRequires: gnutls-utils -BuildRequires: jansson-devel BuildRequires: keyutils-libs-devel BuildRequires: krb5-devel BuildRequires: libcmocka-devel >= 1.0.0 @@ -95,6 +100,8 @@ BuildRequires: libtalloc-devel BuildRequires: libtdb-devel BuildRequires: libtevent-devel BuildRequires: libtool +BuildRequires: libunistring +BuildRequires: libunistring-devel BuildRequires: libuuid-devel BuildRequires: libxml2 BuildRequires: libxslt @@ -123,6 +130,9 @@ BuildRequires: systemd-devel BuildRequires: systemtap-sdt-devel BuildRequires: uid_wrapper BuildRequires: po4a +%if %{build_kcm_renewals} +BuildRequires: krb5-libs >= %{krb5_version} +%endif %description Provides a set of daemons to manage access to remote directories and @@ -197,13 +207,13 @@ Requires: sssd-common = %{version}-%{release} Requires: python3-sss = %{version}-%{release} Requires: python3-sssdconfig = %{version}-%{release} Requires: libsss_certmap = %{version}-%{release} +# required by sss_analyze +Requires: python3-systemd +Requires: python3-click Recommends: sssd-dbus %description tools -Provides userspace tools for manipulating users, groups, and nested groups in -SSSD when using id_provider = local in /etc/sssd/sssd.conf. - -Also provides several other administrative tools: +Provides several administrative tools: * sss_debuglevel to change the debug level on the fly * sss_seed which pre-creates a user entry for use in kickstarts * sss_obfuscate for generating an obfuscated LDAP password @@ -225,11 +235,8 @@ Requires: sssd-common = %{version}-%{release} %{?python_provide:%python_provide python3-sss} %description -n python3-sss -Provides python3 module for manipulating users, groups, and nested groups in -SSSD when using id_provider = local in /etc/sssd/sssd.conf. - -Also provides several other useful python3 bindings: - * function for retrieving list of groups user belongs to. +Provides python3 bindings: + * function for retrieving list of groups user belongs to * class for obfuscation of passwords %package -n python3-sss-murmur @@ -470,7 +477,9 @@ Library to map certificates to users based on rules Summary: An implementation of a Kerberos KCM server License: GPLv3+ Requires: sssd-common = %{version}-%{release} -Requires: krb5-libs >= 1.19.1 +%if %{build_kcm_renewals} +Requires: krb5-libs >= %{krb5_version} +%endif %{?systemd_requires} %description kcm @@ -512,6 +521,7 @@ autoreconf -ivf %make_build all docs runstatedir=%{_rundir} +%py3_shebang_fix src/tools/analyzer/sss_analyze.py sed -i -e 's:/usr/bin/python:/usr/bin/python3:' src/tools/sss_obfuscate %check @@ -841,6 +851,7 @@ done %{_sbindir}/sss_debuglevel %{_sbindir}/sss_seed %{_sbindir}/sssctl +%{python3_sitelib}/sssd/ %{_mandir}/man8/sss_obfuscate.8* %{_mandir}/man8/sss_override.8* %{_mandir}/man8/sss_debuglevel.8* @@ -926,7 +937,6 @@ done %{_unitdir}/sssd-kcm.socket %{_unitdir}/sssd-kcm.service %{_mandir}/man8/sssd-kcm.8* -%{_libdir}/%{name}/libsss_secrets.so %if 0%{?rhel} %pre common @@ -1002,6 +1012,9 @@ fi %systemd_postun_with_restart sssd.service %changelog +* Thu Oct 14 2021 Pavel Březina - 2.6.0-1 +- Rebase to SSSD 2.6.0 + * Tue Sep 21 2021 Iker Pedrosa - 2.5.2-7 - Solve compilation problem with autoconf