1818 lines
64 KiB
Diff
1818 lines
64 KiB
Diff
|
From f546088226872f24722bdd94388816792bd5891a Mon Sep 17 00:00:00 2001
|
||
|
From: Alexey Tikhonov <atikhono@redhat.com>
|
||
|
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 <ipedrosa@redhat.com>
|
||
|
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
|
||
|
---
|
||
|
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>],
|
||
|
+ [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 <http://www.gnu.org/licenses/>.
|
||
|
+*/
|
||
|
+
|
||
|
+#include <talloc.h>
|
||
|
+
|
||
|
+#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 <http://www.gnu.org/licenses/>.
|
||
|
+*/
|
||
|
+
|
||
|
+#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 @@
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
|
||
|
+ <varlistentry condition="with_subid">
|
||
|
+ <term>ipa_subid_ranges_search_base (string)</term>
|
||
|
+ <listitem>
|
||
|
+ <para>
|
||
|
+ Optional. Use the given string as search base for
|
||
|
+ subordinate ranges related objects.
|
||
|
+ </para>
|
||
|
+ <para>
|
||
|
+ Default: the value of
|
||
|
+ <emphasis>cn=subids,%basedn</emphasis>
|
||
|
+ </para>
|
||
|
+ </listitem>
|
||
|
+ </varlistentry>
|
||
|
+
|
||
|
<varlistentry>
|
||
|
<term>ipa_hbac_search_base (string)</term>
|
||
|
<listitem>
|
||
|
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 <http://www.gnu.org/licenses/>.
|
||
|
+*/
|
||
|
+
|
||
|
+#include <errno.h>
|
||
|
+
|
||
|
+#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 <http://www.gnu.org/licenses/>.
|
||
|
+*/
|
||
|
+
|
||
|
+#include <talloc.h>
|
||
|
+#include <ldb.h>
|
||
|
+
|
||
|
+#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 <http://www.gnu.org/licenses/>.
|
||
|
+*/
|
||
|
+
|
||
|
+#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 <http://www.gnu.org/licenses/>.
|
||
|
+*/
|
||
|
+
|
||
|
+#include <stdlib.h>
|
||
|
+#include <string.h>
|
||
|
+#include <shadow/subid.h>
|
||
|
+#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
|
||
|
|