3148 lines
110 KiB
Diff
3148 lines
110 KiB
Diff
|
From f982039c75ec064894deb676ae53ee57de868590 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
|
||
|
Date: Wed, 2 Nov 2016 00:15:16 +0100
|
||
|
Subject: [PATCH 53/93] DESKPROFILE: Introduce the new IPA session provider
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
In order to provide FleetCommander[0] integration, a session provider
|
||
|
has been introduced for IPA. The design of this feature and more
|
||
|
technical details can be found at [1] and [2], which are the design
|
||
|
pages of both freeIPA and SSSD parts.
|
||
|
|
||
|
As there's no way to test freeIPA integration with our upstream tests,
|
||
|
no test has been provided yet.
|
||
|
|
||
|
Is also worth to mention that the name "deskprofile" has been chosen
|
||
|
instead of "fleetcmd" in order to match with the freeIPA plugin. It
|
||
|
means that, for consistence, all source files, directories created,
|
||
|
options added, functions prefixes and so on are following the choice
|
||
|
accordingly.
|
||
|
|
||
|
[0]: https://wiki.gnome.org/Projects/FleetCommander
|
||
|
[1]: https://github.com/abbra/freeipa-desktop-profile/blob/master/plugin/Feature.mediawiki
|
||
|
[2]: https://docs.pagure.org/SSSD.sssd/design_pages/fleet_commander_integration.html
|
||
|
|
||
|
Resolves:
|
||
|
https://pagure.io/SSSD/sssd/issue/2995
|
||
|
|
||
|
Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
|
||
|
|
||
|
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
|
||
|
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
|
||
|
---
|
||
|
Makefile.am | 11 +
|
||
|
contrib/sssd.spec.in | 2 +
|
||
|
src/confdb/confdb.h | 1 +
|
||
|
src/config/SSSDConfig/__init__.py.in | 3 +
|
||
|
src/config/SSSDConfig/sssd_upgrade_config.py | 1 +
|
||
|
src/config/SSSDConfigTest.py | 3 +
|
||
|
src/config/cfg_rules.ini | 3 +
|
||
|
src/config/etc/sssd.api.conf | 1 +
|
||
|
src/config/etc/sssd.api.d/sssd-ipa.conf | 2 +
|
||
|
src/man/sssd-ipa.5.xml | 29 +
|
||
|
src/man/sssd.conf.5.xml | 24 +
|
||
|
src/providers/data_provider/dp.h | 2 +
|
||
|
src/providers/data_provider/dp_target_auth.c | 10 +-
|
||
|
src/providers/data_provider/dp_targets.c | 2 +
|
||
|
src/providers/ipa/ipa_common.c | 26 +
|
||
|
src/providers/ipa/ipa_common.h | 3 +
|
||
|
src/providers/ipa/ipa_deskprofile_config.c | 156 +++++
|
||
|
src/providers/ipa/ipa_deskprofile_config.h | 45 ++
|
||
|
src/providers/ipa/ipa_deskprofile_private.h | 50 ++
|
||
|
src/providers/ipa/ipa_deskprofile_rules.c | 367 ++++++++++
|
||
|
src/providers/ipa/ipa_deskprofile_rules.h | 43 ++
|
||
|
src/providers/ipa/ipa_deskprofile_rules_util.c | 932 +++++++++++++++++++++++++
|
||
|
src/providers/ipa/ipa_deskprofile_rules_util.h | 57 ++
|
||
|
src/providers/ipa/ipa_init.c | 49 ++
|
||
|
src/providers/ipa/ipa_opts.c | 2 +
|
||
|
src/providers/ipa/ipa_session.c | 833 ++++++++++++++++++++++
|
||
|
src/providers/ipa/ipa_session.h | 52 ++
|
||
|
src/responder/ifp/ifp_components.c | 3 +-
|
||
|
28 files changed, 2709 insertions(+), 3 deletions(-)
|
||
|
create mode 100644 src/providers/ipa/ipa_deskprofile_config.c
|
||
|
create mode 100644 src/providers/ipa/ipa_deskprofile_config.h
|
||
|
create mode 100644 src/providers/ipa/ipa_deskprofile_private.h
|
||
|
create mode 100644 src/providers/ipa/ipa_deskprofile_rules.c
|
||
|
create mode 100644 src/providers/ipa/ipa_deskprofile_rules.h
|
||
|
create mode 100644 src/providers/ipa/ipa_deskprofile_rules_util.c
|
||
|
create mode 100644 src/providers/ipa/ipa_deskprofile_rules_util.h
|
||
|
create mode 100644 src/providers/ipa/ipa_session.c
|
||
|
create mode 100644 src/providers/ipa/ipa_session.h
|
||
|
|
||
|
diff --git a/Makefile.am b/Makefile.am
|
||
|
index c292c1317ae45ae73cc3e86eb464d72e77eaf1fe..6cda729d381948d27fae702a557b5f3aab423683 100644
|
||
|
--- a/Makefile.am
|
||
|
+++ b/Makefile.am
|
||
|
@@ -88,6 +88,7 @@ polkitdir = @polkitdir@
|
||
|
pamconfdir = $(sysconfdir)/pam.d
|
||
|
systemtap_tapdir = @tapset_dir@
|
||
|
sssdkcmdatadir = $(datadir)/sssd-kcm
|
||
|
+deskprofilepath = $(sss_statedir)/deskprofile
|
||
|
|
||
|
if HAVE_SYSTEMD_UNIT
|
||
|
ifp_exec_cmd = $(sssdlibexecdir)/sssd_ifp --uid 0 --gid 0 --debug-to-files --dbus-activated
|
||
|
@@ -801,6 +802,7 @@ dist_noinst_HEADERS = \
|
||
|
src/providers/ipa/ipa_srv.h \
|
||
|
src/providers/ipa/ipa_dn.h \
|
||
|
src/providers/ipa/ipa_sudo.h \
|
||
|
+ src/providers/ipa/ipa_session.h \
|
||
|
src/providers/ad/ad_srv.h \
|
||
|
src/providers/ad/ad_common.h \
|
||
|
src/providers/ad/ad_pac.h \
|
||
|
@@ -3892,6 +3894,14 @@ libsss_ipa_la_SOURCES = \
|
||
|
src/providers/ipa/ipa_hbac_common.c \
|
||
|
src/providers/ipa/ipa_rules_common.c \
|
||
|
src/providers/ipa/ipa_rules_common.h \
|
||
|
+ src/providers/ipa/ipa_session.c \
|
||
|
+ src/providers/ipa/ipa_deskprofile_private.h \
|
||
|
+ src/providers/ipa/ipa_deskprofile_config.c \
|
||
|
+ src/providers/ipa/ipa_deskprofile_config.h \
|
||
|
+ src/providers/ipa/ipa_deskprofile_rules.c \
|
||
|
+ src/providers/ipa/ipa_deskprofile_rules.h \
|
||
|
+ src/providers/ipa/ipa_deskprofile_rules_util.c \
|
||
|
+ src/providers/ipa/ipa_deskprofile_rules_util.h \
|
||
|
src/providers/ipa/ipa_srv.c \
|
||
|
src/providers/ipa/ipa_idmap.c \
|
||
|
src/providers/ipa/ipa_dn.c \
|
||
|
@@ -4617,6 +4627,7 @@ SSSD_USER_DIRS = \
|
||
|
$(DESTDIR)$(sssdconfdir)/conf.d \
|
||
|
$(DESTDIR)$(sssddefaultconfdir) \
|
||
|
$(DESTDIR)$(logpath) \
|
||
|
+ $(DESTDIR)$(deskprofilepath) \
|
||
|
$(NULL)
|
||
|
|
||
|
installsssddirs::
|
||
|
diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
|
||
|
index 0b7a6115778a185eae78be0f5447e6d883be6eb9..942d57f8eae88eec477e1e344412f1a92404e0f0 100644
|
||
|
--- a/contrib/sssd.spec.in
|
||
|
+++ b/contrib/sssd.spec.in
|
||
|
@@ -156,6 +156,7 @@ Requires: python2-sssdconfig = %{version}-%{release}
|
||
|
%global pubconfpath %{sssdstatedir}/pubconf
|
||
|
%global gpocachepath %{sssdstatedir}/gpo_cache
|
||
|
%global secdbpath %{sssdstatedir}/secrets
|
||
|
+%global deskprofilepath %{sssdstatedir}/deskprofile
|
||
|
|
||
|
### Build Dependencies ###
|
||
|
|
||
|
@@ -958,6 +959,7 @@ done
|
||
|
%if (0%{?with_secrets} == 1)
|
||
|
%attr(700,root,root) %dir %{secdbpath}
|
||
|
%endif
|
||
|
+%attr(700,root,root) %dir %{deskprofilepath}
|
||
|
%ghost %attr(0644,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/passwd
|
||
|
%ghost %attr(0644,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/group
|
||
|
%ghost %attr(0644,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/initgroups
|
||
|
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
|
||
|
index 66ecc041398fda973c0f30a47a3f5944c88d19c2..da725fb667afea6747d22d1d3a4315fb7a7bace2 100644
|
||
|
--- a/src/confdb/confdb.h
|
||
|
+++ b/src/confdb/confdb.h
|
||
|
@@ -183,6 +183,7 @@
|
||
|
#define CONFDB_DOMAIN_SELINUX_PROVIDER "selinux_provider"
|
||
|
#define CONFDB_DOMAIN_HOSTID_PROVIDER "hostid_provider"
|
||
|
#define CONFDB_DOMAIN_SUBDOMAINS_PROVIDER "subdomains_provider"
|
||
|
+#define CONFDB_DOMAIN_SESSION_PROVIDER "session_provider"
|
||
|
#define CONFDB_DOMAIN_COMMAND "command"
|
||
|
#define CONFDB_DOMAIN_TIMEOUT "timeout"
|
||
|
#define CONFDB_DOMAIN_ATTR "cn"
|
||
|
diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
|
||
|
index de757521cff58460049bb8c4873efaf6bf0b8d95..2a19b60a987c5f2c5c59ac2466f8f6821803e146 100644
|
||
|
--- a/src/config/SSSDConfig/__init__.py.in
|
||
|
+++ b/src/config/SSSDConfig/__init__.py.in
|
||
|
@@ -154,6 +154,7 @@ option_strings = {
|
||
|
'autofs_provider' : _('Autofs provider'),
|
||
|
'hostid_provider' : _('Host identity provider'),
|
||
|
'selinux_provider' : _('SELinux provider'),
|
||
|
+ 'session_provider' : _('Session management provider'),
|
||
|
|
||
|
# [domain]
|
||
|
'domain_type' : _('Whether the domain is usable by the OS or by applications'),
|
||
|
@@ -217,6 +218,8 @@ option_strings = {
|
||
|
'ipa_anchor_uuid': _("Attribute with the reference to the original object"),
|
||
|
'ipa_user_override_object_class': _("Objectclass for user override objects"),
|
||
|
'ipa_group_override_object_class': _("Objectclass for group override objects"),
|
||
|
+ 'ipa_deskprofile_search_base': _("Search base for Desktop Profile related objects"),
|
||
|
+ 'ipa_deskprofile_refresh': _("The amount of time in seconds between lookups of the Desktop Profile rules against the IPA server"),
|
||
|
|
||
|
# [provider/ad]
|
||
|
'ad_domain' : _('Active Directory domain'),
|
||
|
diff --git a/src/config/SSSDConfig/sssd_upgrade_config.py b/src/config/SSSDConfig/sssd_upgrade_config.py
|
||
|
index 767d06ddc18b16f1a1af65805516518f5a3f8ad6..d2d94b21e87920c76065462e4ccb10606c3aca93 100644
|
||
|
--- a/src/config/SSSDConfig/sssd_upgrade_config.py
|
||
|
+++ b/src/config/SSSDConfig/sssd_upgrade_config.py
|
||
|
@@ -148,6 +148,7 @@ class SSSDConfigFile(SSSDChangeConf):
|
||
|
'auth_provider' : 'auth-module',
|
||
|
'access_provider' : 'access-module',
|
||
|
'chpass_provider' : 'chpass-module',
|
||
|
+ 'session_provider' : 'session-module',
|
||
|
'use_fully_qualified_names' : 'useFullyQualifiedNames',
|
||
|
'store_legacy_passwords' : 'store-legacy-passwords',
|
||
|
}
|
||
|
diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py
|
||
|
index 5f3ff3958d033dded386850a8653db9872fe4718..d0e97f02beaf5695149702c5c029197634ab8923 100755
|
||
|
--- a/src/config/SSSDConfigTest.py
|
||
|
+++ b/src/config/SSSDConfigTest.py
|
||
|
@@ -616,6 +616,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
|
||
|
'hostid_provider',
|
||
|
'subdomains_provider',
|
||
|
'selinux_provider',
|
||
|
+ 'session_provider',
|
||
|
'realmd_tags',
|
||
|
'subdomain_refresh_interval',
|
||
|
'subdomain_inherit',
|
||
|
@@ -986,6 +987,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
|
||
|
'hostid_provider',
|
||
|
'subdomains_provider',
|
||
|
'selinux_provider',
|
||
|
+ 'session_provider',
|
||
|
'realmd_tags',
|
||
|
'subdomain_refresh_interval',
|
||
|
'subdomain_inherit',
|
||
|
@@ -1381,6 +1383,7 @@ class SSSDConfigTestSSSDConfig(unittest.TestCase):
|
||
|
'id_provider',
|
||
|
'auth_provider',
|
||
|
'access_provider',
|
||
|
+ 'session_provider',
|
||
|
'default_shell',
|
||
|
'fallback_homedir',
|
||
|
'cache_credentials',
|
||
|
diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini
|
||
|
index cba59d2c3813f44b8ab85b4c246108232f9d8fd4..3ebd39e93cec6d1ddf547d7ebdb49884e637f8c7 100644
|
||
|
--- a/src/config/cfg_rules.ini
|
||
|
+++ b/src/config/cfg_rules.ini
|
||
|
@@ -330,6 +330,7 @@ option = autofs_provider
|
||
|
option = hostid_provider
|
||
|
option = subdomains_provider
|
||
|
option = selinux_provider
|
||
|
+option = session_provider
|
||
|
|
||
|
# Options available to all domains
|
||
|
option = domain_type
|
||
|
@@ -438,6 +439,8 @@ option = ad_site
|
||
|
option = ipa_anchor_uuid
|
||
|
option = ipa_automount_location
|
||
|
option = ipa_backup_server
|
||
|
+option = ipa_deskprofile_refresh
|
||
|
+option = ipa_deskprofile_search_base
|
||
|
option = ipa_domain
|
||
|
option = ipa_dyndns_iface
|
||
|
option = ipa_dyndns_ttl
|
||
|
diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
|
||
|
index 0d11771ae3df50ba9f380e44747a5385a224544d..9eb6aeb83bbc1989cec7465e6442a1bf7762d9d8 100644
|
||
|
--- a/src/config/etc/sssd.api.conf
|
||
|
+++ b/src/config/etc/sssd.api.conf
|
||
|
@@ -139,6 +139,7 @@ autofs_provider = str, None, false
|
||
|
hostid_provider = str, None, false
|
||
|
subdomains_provider = str, None, false
|
||
|
selinux_provider = str, None, false
|
||
|
+session_provider = str, None, false
|
||
|
|
||
|
[domain]
|
||
|
# Options available to all domains
|
||
|
diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf
|
||
|
index f36b568c3ea813db3f46fdd69059957f6373801e..8178b123e3b42cb92029db8b879d26f1fd16cf3e 100644
|
||
|
--- a/src/config/etc/sssd.api.d/sssd-ipa.conf
|
||
|
+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
|
||
|
@@ -3,6 +3,7 @@ ipa_domain = str, None, false
|
||
|
ipa_server = str, None, false
|
||
|
ipa_backup_server = str, None, false
|
||
|
ipa_hostname = str, None, false
|
||
|
+ipa_deskprofile_search_base = str, None, false
|
||
|
ipa_dyndns_update = bool, None, false
|
||
|
ipa_dyndns_ttl = int, None, false
|
||
|
ipa_dyndns_iface = str, None, false
|
||
|
@@ -193,6 +194,7 @@ ldap_autofs_search_base = str, None, false
|
||
|
[provider/ipa/chpass]
|
||
|
|
||
|
[provider/ipa/session]
|
||
|
+ipa_deskprofile_refresh = int, None, false
|
||
|
ipa_host_object_class = str, None, false
|
||
|
ipa_host_name = str, None, false
|
||
|
ipa_host_fqdn = str, None, false
|
||
|
diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml
|
||
|
index 5e7f8ff1a581cf206c9aec99ba8084e3de56a7e6..4d1c3c8a11dea956c31be690f5bdceea94252fd2 100644
|
||
|
--- a/src/man/sssd-ipa.5.xml
|
||
|
+++ b/src/man/sssd-ipa.5.xml
|
||
|
@@ -306,6 +306,19 @@
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
|
||
|
+ <varlistentry>
|
||
|
+ <term>ipa_deskprofile_search_base (string)</term>
|
||
|
+ <listitem>
|
||
|
+ <para>
|
||
|
+ Optional. Use the given string as search base for
|
||
|
+ Desktop Profile related objects.
|
||
|
+ </para>
|
||
|
+ <para>
|
||
|
+ Default: Use base DN
|
||
|
+ </para>
|
||
|
+ </listitem>
|
||
|
+ </varlistentry>
|
||
|
+
|
||
|
<varlistentry>
|
||
|
<term>ipa_hbac_search_base (string)</term>
|
||
|
<listitem>
|
||
|
@@ -447,6 +460,22 @@
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
|
||
|
+ <varlistentry>
|
||
|
+ <term>ipa_deskprofile_refresh (integer)</term>
|
||
|
+ <listitem>
|
||
|
+ <para>
|
||
|
+ The amount of time between lookups of the Desktop
|
||
|
+ Profile rules against the IPA server. This will
|
||
|
+ reduce the latency and load on the IPA server if
|
||
|
+ there are many desktop profiles requests made in a
|
||
|
+ short period.
|
||
|
+ </para>
|
||
|
+ <para>
|
||
|
+ Default: 5 (seconds)
|
||
|
+ </para>
|
||
|
+ </listitem>
|
||
|
+ </varlistentry>
|
||
|
+
|
||
|
<varlistentry>
|
||
|
<term>ipa_hbac_refresh (integer)</term>
|
||
|
<listitem>
|
||
|
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
|
||
|
index 7b5abebbf68a832c3b0af9bcff9c535eca77778a..c26f4a3bac1f009d19d9a5a3a49ad7370ac72791 100644
|
||
|
--- a/src/man/sssd.conf.5.xml
|
||
|
+++ b/src/man/sssd.conf.5.xml
|
||
|
@@ -2387,6 +2387,30 @@ pam_account_locked_message = Account locked, please contact help desk.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
+ <varlistentry>
|
||
|
+ <term>session_provider (string)</term>
|
||
|
+ <listitem>
|
||
|
+ <para>
|
||
|
+ The provider which configures and manages user session
|
||
|
+ related tasks. The only user session task currently
|
||
|
+ provided is the integration with Fleet Commander, which
|
||
|
+ works only with IPA.
|
||
|
+ Supported session providers are:
|
||
|
+ </para>
|
||
|
+ <para>
|
||
|
+ <quote>ipa</quote> to allow performing user session
|
||
|
+ related tasks.
|
||
|
+ </para>
|
||
|
+ <para>
|
||
|
+ <quote>none</quote> does not perform any kind of user
|
||
|
+ session related tasks.
|
||
|
+ </para>
|
||
|
+ <para>
|
||
|
+ Default: <quote>id_provider</quote> is used if it
|
||
|
+ is set and can perform session related tasks.
|
||
|
+ </para>
|
||
|
+ </listitem>
|
||
|
+ </varlistentry>
|
||
|
|
||
|
<varlistentry condition="with_autofs">
|
||
|
<term>autofs_provider (string)</term>
|
||
|
diff --git a/src/providers/data_provider/dp.h b/src/providers/data_provider/dp.h
|
||
|
index e80a6c3398784dfc176baeff2daf7203c52fc072..9cdbe5b3a56ba159f9a10df6e010e616e4aefcac 100644
|
||
|
--- a/src/providers/data_provider/dp.h
|
||
|
+++ b/src/providers/data_provider/dp.h
|
||
|
@@ -66,6 +66,7 @@ enum dp_targets {
|
||
|
DPT_SELINUX,
|
||
|
DPT_HOSTID,
|
||
|
DPT_SUBDOMAINS,
|
||
|
+ DPT_SESSION,
|
||
|
|
||
|
DP_TARGET_SENTINEL
|
||
|
};
|
||
|
@@ -80,6 +81,7 @@ enum dp_methods {
|
||
|
DPM_AUTOFS_HANDLER,
|
||
|
DPM_HOSTID_HANDLER,
|
||
|
DPM_DOMAINS_HANDLER,
|
||
|
+ DPM_SESSION_HANDLER,
|
||
|
|
||
|
DP_METHOD_SENTINEL
|
||
|
};
|
||
|
diff --git a/src/providers/data_provider/dp_target_auth.c b/src/providers/data_provider/dp_target_auth.c
|
||
|
index 78c4cce7ee76e3e169a3aac48c11399bc3d05ce1..6bb3313b2de002466e5ca84464c962acd2412bfa 100644
|
||
|
--- a/src/providers/data_provider/dp_target_auth.c
|
||
|
+++ b/src/providers/data_provider/dp_target_auth.c
|
||
|
@@ -126,9 +126,15 @@ static void choose_target(struct data_provider *provider,
|
||
|
name = "PAM Chpass 2nd";
|
||
|
break;
|
||
|
case SSS_PAM_OPEN_SESSION:
|
||
|
- target = DP_TARGET_SENTINEL;
|
||
|
- method = DP_METHOD_SENTINEL;
|
||
|
name = "PAM Open Session";
|
||
|
+ if (dp_method_enabled(provider, DPT_SESSION, DPM_SESSION_HANDLER)) {
|
||
|
+ target = DPT_SESSION;
|
||
|
+ method = DPM_SESSION_HANDLER;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ target = DP_TARGET_SENTINEL;
|
||
|
+ method = DP_METHOD_SENTINEL;
|
||
|
pd->pam_status = PAM_SUCCESS;
|
||
|
break;
|
||
|
case SSS_PAM_SETCRED:
|
||
|
diff --git a/src/providers/data_provider/dp_targets.c b/src/providers/data_provider/dp_targets.c
|
||
|
index e2a45bbac969ca7b9b13729f26b8cded8ab7eebc..2dd15d80d7094aa760f8767588dc096d1482052b 100644
|
||
|
--- a/src/providers/data_provider/dp_targets.c
|
||
|
+++ b/src/providers/data_provider/dp_targets.c
|
||
|
@@ -114,6 +114,8 @@ const char *dp_target_to_string(enum dp_targets target)
|
||
|
return "hostid";
|
||
|
case DPT_SUBDOMAINS:
|
||
|
return "subdomains";
|
||
|
+ case DPT_SESSION:
|
||
|
+ return "session";
|
||
|
case DP_TARGET_SENTINEL:
|
||
|
return NULL;
|
||
|
}
|
||
|
diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
|
||
|
index 6b29f2fde31f3866bb62b5c03e47e6c24f837550..6bb1e679c4b5abcb7bb74fa17cdbd296f6eaef59 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_VIEWS_SEARCH_BASE:
|
||
|
class_name = "IPA_VIEWS";
|
||
|
break;
|
||
|
+ case IPA_DESKPROFILE_SEARCH_BASE:
|
||
|
+ class_name = "IPA_DESKPROFILE";
|
||
|
+ break;
|
||
|
default:
|
||
|
DEBUG(SSSDBG_CONF_SETTINGS,
|
||
|
"Unknown search base type: [%d]\n", class);
|
||
|
@@ -398,6 +401,29 @@ int ipa_get_id_options(struct ipa_options *ipa_opts,
|
||
|
&ipa_opts->selinux_search_bases);
|
||
|
if (ret != EOK) goto done;
|
||
|
|
||
|
+ if (NULL == dp_opt_get_string(ipa_opts->basic,
|
||
|
+ IPA_DESKPROFILE_SEARCH_BASE)) {
|
||
|
+ value = talloc_asprintf(tmpctx, "cn=desktop-profile,%s", basedn);
|
||
|
+ if (!value) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = dp_opt_set_string(ipa_opts->basic, IPA_DESKPROFILE_SEARCH_BASE, value);
|
||
|
+ if (ret != EOK) {
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC, "Option %s set to %s\n",
|
||
|
+ ipa_opts->basic[IPA_DESKPROFILE_SEARCH_BASE].opt_name,
|
||
|
+ dp_opt_get_string(ipa_opts->basic,
|
||
|
+ IPA_DESKPROFILE_SEARCH_BASE));
|
||
|
+ }
|
||
|
+ ret = ipa_parse_search_base(ipa_opts->basic, ipa_opts->basic,
|
||
|
+ IPA_DESKPROFILE_SEARCH_BASE,
|
||
|
+ &ipa_opts->deskprofile_search_bases);
|
||
|
+ if (ret != EOK) goto done;
|
||
|
+
|
||
|
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 b1d90d3624b5bc6a126709e6bd6fb1fdbbaafad8..5b3507cd47aab75a4a7bbc16a8146d82411f2d16 100644
|
||
|
--- a/src/providers/ipa/ipa_common.h
|
||
|
+++ b/src/providers/ipa/ipa_common.h
|
||
|
@@ -56,6 +56,8 @@ enum ipa_basic_opt {
|
||
|
IPA_SERVER_MODE,
|
||
|
IPA_VIEWS_SEARCH_BASE,
|
||
|
IPA_KRB5_CONFD_PATH,
|
||
|
+ IPA_DESKPROFILE_SEARCH_BASE,
|
||
|
+ IPA_DESKPROFILE_REFRESH,
|
||
|
|
||
|
IPA_OPTS_BASIC /* opts counter */
|
||
|
};
|
||
|
@@ -218,6 +220,7 @@ struct ipa_options {
|
||
|
struct sdap_search_base **master_domain_search_bases;
|
||
|
struct sdap_search_base **ranges_search_bases;
|
||
|
struct sdap_search_base **views_search_bases;
|
||
|
+ struct sdap_search_base **deskprofile_search_bases;
|
||
|
struct ipa_service *service;
|
||
|
|
||
|
/* id provider */
|
||
|
diff --git a/src/providers/ipa/ipa_deskprofile_config.c b/src/providers/ipa/ipa_deskprofile_config.c
|
||
|
new file mode 100644
|
||
|
index 0000000000000000000000000000000000000000..8c66dda7550f200887ab99932b8be4c00e9785c0
|
||
|
--- /dev/null
|
||
|
+++ b/src/providers/ipa/ipa_deskprofile_config.c
|
||
|
@@ -0,0 +1,156 @@
|
||
|
+/*
|
||
|
+ SSSD
|
||
|
+
|
||
|
+ Authors:
|
||
|
+ Fabiano Fidêncio <fidencio@redhat.com>
|
||
|
+
|
||
|
+ Copyright (C) 2017 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 "util/util.h"
|
||
|
+#include "providers/ipa/ipa_common.h"
|
||
|
+#include "providers/ipa/ipa_deskprofile_private.h"
|
||
|
+#include "providers/ipa/ipa_deskprofile_config.h"
|
||
|
+#include "providers/ldap/sdap_async.h"
|
||
|
+
|
||
|
+struct ipa_deskprofile_config_state {
|
||
|
+ struct sysdb_attrs *config;
|
||
|
+};
|
||
|
+
|
||
|
+static void
|
||
|
+ipa_deskprofile_get_config_done(struct tevent_req *subreq);
|
||
|
+
|
||
|
+struct tevent_req *
|
||
|
+ipa_deskprofile_get_config_send(TALLOC_CTX *mem_ctx,
|
||
|
+ struct tevent_context *ev,
|
||
|
+ struct sdap_handle *sh,
|
||
|
+ struct sdap_options *opts,
|
||
|
+ struct dp_option *ipa_opts)
|
||
|
+{
|
||
|
+ struct tevent_req *req = NULL;
|
||
|
+ struct tevent_req *subreq;
|
||
|
+ struct ipa_deskprofile_rule_state *state;
|
||
|
+ char *rule_filter;
|
||
|
+ const char *attrs[] = { IPA_DESKPROFILE_PRIORITY, NULL };
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ req = tevent_req_create(mem_ctx, &state,
|
||
|
+ struct ipa_deskprofile_config_state);
|
||
|
+ if (req == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed.\n");
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ rule_filter = talloc_asprintf(state, "(objectclass=%s)",
|
||
|
+ IPA_DESKPROFILE_CONFIG);
|
||
|
+ if (rule_filter == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ subreq = sdap_get_generic_send(state, ev, opts, sh,
|
||
|
+ dp_opt_get_string(ipa_opts,
|
||
|
+ IPA_DESKPROFILE_SEARCH_BASE),
|
||
|
+ LDAP_SCOPE_BASE, rule_filter,
|
||
|
+ attrs, NULL, 0,
|
||
|
+ dp_opt_get_int(opts->basic,
|
||
|
+ SDAP_ENUM_SEARCH_TIMEOUT),
|
||
|
+ false);
|
||
|
+ if (subreq == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "sdap_get_generic_send failed.\n");
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ tevent_req_set_callback(subreq, ipa_deskprofile_get_config_done, req);
|
||
|
+
|
||
|
+ ret = EOK;
|
||
|
+
|
||
|
+done:
|
||
|
+ if (ret != EOK) {
|
||
|
+ tevent_req_error(req, ret);
|
||
|
+ tevent_req_post(req, ev);
|
||
|
+ }
|
||
|
+
|
||
|
+ return req;
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+ipa_deskprofile_get_config_done(struct tevent_req *subreq)
|
||
|
+{
|
||
|
+ struct tevent_req *req;
|
||
|
+ struct ipa_deskprofile_config_state *state;
|
||
|
+ size_t reply_count;
|
||
|
+ struct sysdb_attrs **reply = NULL;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+
|
||
|
+ req = tevent_req_callback_data(subreq, struct tevent_req);
|
||
|
+ state = tevent_req_data(req, struct ipa_deskprofile_config_state);
|
||
|
+
|
||
|
+ ret = sdap_get_generic_recv(subreq, state, &reply_count, &reply);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
||
|
+ "Could not retrieve Desktop Profile config\n");
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (reply_count == 0) {
|
||
|
+ /*
|
||
|
+ * When connecting to an old server that doesn't support Desktop
|
||
|
+ * Profile, the reply_count will be zero.
|
||
|
+ * In order to not throw a unnecessary error and fail let's just
|
||
|
+ * return ENOENT and print a debug message about it.
|
||
|
+ */
|
||
|
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
||
|
+ "Server doesn't support Desktop Profile.\n");
|
||
|
+ ret = ENOENT;
|
||
|
+ goto done;
|
||
|
+ } else if (reply_count != 1) {
|
||
|
+ DEBUG(SSSDBG_OP_FAILURE,
|
||
|
+ "Unexpected number of results, expected 1, got %zu.\n",
|
||
|
+ reply_count);
|
||
|
+ ret = EINVAL;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ state->config = reply[0];
|
||
|
+
|
||
|
+ ret = EOK;
|
||
|
+
|
||
|
+done:
|
||
|
+ if (ret != EOK) {
|
||
|
+ tevent_req_error(req, ret);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ tevent_req_done(req);
|
||
|
+}
|
||
|
+
|
||
|
+errno_t
|
||
|
+ipa_deskprofile_get_config_recv(struct tevent_req *req,
|
||
|
+ TALLOC_CTX *mem_ctx,
|
||
|
+ struct sysdb_attrs **config)
|
||
|
+{
|
||
|
+ struct ipa_deskprofile_config_state *state;
|
||
|
+
|
||
|
+ state = tevent_req_data(req, struct ipa_deskprofile_config_state);
|
||
|
+ TEVENT_REQ_RETURN_ON_ERROR(req);
|
||
|
+
|
||
|
+ *config = talloc_steal(mem_ctx, state->config);
|
||
|
+
|
||
|
+ return EOK;
|
||
|
+}
|
||
|
diff --git a/src/providers/ipa/ipa_deskprofile_config.h b/src/providers/ipa/ipa_deskprofile_config.h
|
||
|
new file mode 100644
|
||
|
index 0000000000000000000000000000000000000000..c4a05b2152beac95691e38c513b464bd5ab5becc
|
||
|
--- /dev/null
|
||
|
+++ b/src/providers/ipa/ipa_deskprofile_config.h
|
||
|
@@ -0,0 +1,45 @@
|
||
|
+/*
|
||
|
+ SSSD
|
||
|
+
|
||
|
+ Authors:
|
||
|
+ Fabiano Fidêncio <fidencio@redhat.com>
|
||
|
+
|
||
|
+ Copyright (C) 2017 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 IPA_DESKPROFILE_CONFIG_H_
|
||
|
+#define IPA_DESKPROFILE_CONFIG_H_
|
||
|
+
|
||
|
+#include <talloc.h>
|
||
|
+#include <tevent.h>
|
||
|
+
|
||
|
+#include "providers/ldap/ldap_common.h"
|
||
|
+#include "db/sysdb.h"
|
||
|
+
|
||
|
+/* From ipa_deskprofile_config.c */
|
||
|
+struct tevent_req *
|
||
|
+ipa_deskprofile_get_config_send(TALLOC_CTX *mem_ctx,
|
||
|
+ struct tevent_context *ev,
|
||
|
+ struct sdap_handle *sh,
|
||
|
+ struct sdap_options *opts,
|
||
|
+ struct dp_option *ipa_opts);
|
||
|
+
|
||
|
+errno_t
|
||
|
+ipa_deskprofile_get_config_recv(struct tevent_req *req,
|
||
|
+ TALLOC_CTX *mem_ctx,
|
||
|
+ struct sysdb_attrs **config);
|
||
|
+
|
||
|
+#endif /* IPA_DESKPROFILE_CONFIG_H_ */
|
||
|
diff --git a/src/providers/ipa/ipa_deskprofile_private.h b/src/providers/ipa/ipa_deskprofile_private.h
|
||
|
new file mode 100644
|
||
|
index 0000000000000000000000000000000000000000..1db154b76a7bbe3114c2a4fc28eddc3fa16d9460
|
||
|
--- /dev/null
|
||
|
+++ b/src/providers/ipa/ipa_deskprofile_private.h
|
||
|
@@ -0,0 +1,50 @@
|
||
|
+/*
|
||
|
+ SSSD
|
||
|
+
|
||
|
+ Authors:
|
||
|
+ Fabiano Fidêncio <fidencio@redhat.com>
|
||
|
+
|
||
|
+ Copyright (C) 2017 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 IPA_DESKPROFILE_PRIVATE_H_
|
||
|
+#define IPA_DESKPROFILE_PRIVATE_H_
|
||
|
+
|
||
|
+#define IPA_DESKPROFILE_CONFIG "ipaDeskProfileConfig"
|
||
|
+#define IPA_DESKPROFILE_RULE "ipaDeskProfileRule"
|
||
|
+#define IPA_DESKPROFILE_PRIORITY "ipaDeskProfilePriority"
|
||
|
+#define IPA_DESKPROFILE_DATA "ipaDeskData"
|
||
|
+
|
||
|
+#define DESKPROFILE_HOSTS_SUBDIR "deskprofile_hosts"
|
||
|
+#define DESKPROFILE_HOSTGROUPS_SUBDIR "deskprofile_hostgroups"
|
||
|
+
|
||
|
+#define IPA_SESSION_RULE_TYPE "sessionRuleType"
|
||
|
+
|
||
|
+#define IPA_DESKPROFILE_BASE_TMPL "cn=desktop-profile,%s"
|
||
|
+
|
||
|
+#define SYSDB_DESKPROFILE_BASE_TMPL "cn=desktop-profile,"SYSDB_TMPL_CUSTOM_BASE
|
||
|
+
|
||
|
+#define DESKPROFILE_RULES_SUBDIR "deskprofile_rules"
|
||
|
+
|
||
|
+#define DESKPROFILE_CONFIG_SUBDIR "deskprofile_config"
|
||
|
+
|
||
|
+struct deskprofile_rule {
|
||
|
+ const char *name;
|
||
|
+ int priority;
|
||
|
+ const char *data;
|
||
|
+};
|
||
|
+
|
||
|
+#endif /* IPA_DESKPROFILE_PRIVATE_H_ */
|
||
|
diff --git a/src/providers/ipa/ipa_deskprofile_rules.c b/src/providers/ipa/ipa_deskprofile_rules.c
|
||
|
new file mode 100644
|
||
|
index 0000000000000000000000000000000000000000..65994356e82515611dc13c214d5a504b1009870d
|
||
|
--- /dev/null
|
||
|
+++ b/src/providers/ipa/ipa_deskprofile_rules.c
|
||
|
@@ -0,0 +1,367 @@
|
||
|
+/*
|
||
|
+ SSSD
|
||
|
+
|
||
|
+ Authors:
|
||
|
+ Fabiano Fidêncio <fidencio@redhat.com>
|
||
|
+
|
||
|
+ Copyright (C) 2017 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 "util/util.h"
|
||
|
+#include "providers/ldap/ldap_common.h"
|
||
|
+#include "providers/ldap/sdap_async_private.h"
|
||
|
+#include "providers/ipa/ipa_rules_common.h"
|
||
|
+#include "providers/ipa/ipa_deskprofile_private.h"
|
||
|
+#include "providers/ipa/ipa_deskprofile_rules.h"
|
||
|
+#include "providers/ipa/ipa_deskprofile_rules_util.h"
|
||
|
+
|
||
|
+struct ipa_deskprofile_rule_state {
|
||
|
+ struct tevent_context *ev;
|
||
|
+ struct sdap_handle *sh;
|
||
|
+ struct sdap_options *opts;
|
||
|
+
|
||
|
+ int search_base_iter;
|
||
|
+ struct sdap_search_base **search_bases;
|
||
|
+
|
||
|
+ const char **attrs;
|
||
|
+ char *rules_filter;
|
||
|
+ char *cur_filter;
|
||
|
+
|
||
|
+ size_t rule_count;
|
||
|
+ struct sysdb_attrs **rules;
|
||
|
+};
|
||
|
+
|
||
|
+static errno_t
|
||
|
+ipa_deskprofile_rule_info_next(struct tevent_req *req,
|
||
|
+ struct ipa_deskprofile_rule_state *state);
|
||
|
+static void
|
||
|
+ipa_deskprofile_rule_info_done(struct tevent_req *subreq);
|
||
|
+
|
||
|
+struct tevent_req *
|
||
|
+ipa_deskprofile_rule_info_send(TALLOC_CTX *mem_ctx,
|
||
|
+ struct tevent_context *ev,
|
||
|
+ struct sdap_handle *sh,
|
||
|
+ struct sdap_options *opts,
|
||
|
+ struct sdap_search_base **search_bases,
|
||
|
+ struct sysdb_attrs *ipa_host,
|
||
|
+ struct sss_domain_info *domain,
|
||
|
+ const char *username)
|
||
|
+{
|
||
|
+ struct tevent_req *req = NULL;
|
||
|
+ struct ipa_deskprofile_rule_state *state;
|
||
|
+ char *user;
|
||
|
+ char *group;
|
||
|
+ char *host_dn_clean;
|
||
|
+ char *group_clean;
|
||
|
+ char *host_group_clean;
|
||
|
+ char *rule_filter;
|
||
|
+ const char *host_dn;
|
||
|
+ const char **memberof_list;
|
||
|
+ char **groups_list;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ req = tevent_req_create(mem_ctx, &state, struct ipa_deskprofile_rule_state);
|
||
|
+ if (req == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create failed.\n");
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (ipa_host == NULL) {
|
||
|
+ ret = EINVAL;
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing host\n");
|
||
|
+ goto immediate;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sysdb_attrs_get_string(ipa_host, SYSDB_ORIG_DN, &host_dn);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Could not identify IPA hostname\n");
|
||
|
+ goto immediate;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sss_filter_sanitize(state, host_dn, &host_dn_clean);
|
||
|
+ if (ret != EOK) {
|
||
|
+ goto immediate;
|
||
|
+ }
|
||
|
+
|
||
|
+ state->ev = ev;
|
||
|
+ state->sh = sh;
|
||
|
+ state->opts = opts;
|
||
|
+ state->search_bases = search_bases;
|
||
|
+ state->search_base_iter = 0;
|
||
|
+ state->attrs = deskprofile_get_attrs_to_get_cached_rules(state);
|
||
|
+ if (state->attrs == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "deskprofile_get_attrs_get_cached_rules() failed\n");
|
||
|
+ goto immediate;
|
||
|
+ }
|
||
|
+
|
||
|
+ rule_filter = talloc_asprintf(state,
|
||
|
+ "(&(objectclass=%s)"
|
||
|
+ "(%s=%s)"
|
||
|
+ "(|(%s=%s)(%s=%s)(%s=%s)",
|
||
|
+ IPA_DESKPROFILE_RULE,
|
||
|
+ IPA_ENABLED_FLAG, IPA_TRUE_VALUE,
|
||
|
+ IPA_HOST_CATEGORY, "all",
|
||
|
+ IPA_USER_CATEGORY, "all",
|
||
|
+ IPA_MEMBER_HOST, host_dn_clean);
|
||
|
+ if (rule_filter == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto immediate;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Add all parent groups of ipa_hostname to the filter */
|
||
|
+ ret = sysdb_attrs_get_string_array(ipa_host, SYSDB_ORIG_MEMBEROF,
|
||
|
+ state, &memberof_list);
|
||
|
+ if (ret != EOK && ret != ENOENT) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Could not identify.\n");
|
||
|
+ } else if (ret == ENOENT) {
|
||
|
+ /* This host is not a member of any hostgroups */
|
||
|
+ memberof_list = talloc_array(state, const char *, 1);
|
||
|
+ if (memberof_list == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto immediate;
|
||
|
+ }
|
||
|
+ memberof_list[0] = NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ for (size_t i = 0; memberof_list[i] != NULL; i++) {
|
||
|
+ ret = sss_filter_sanitize(state,
|
||
|
+ memberof_list[i],
|
||
|
+ &host_group_clean);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "sss_filter_sanitize() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto immediate;
|
||
|
+ }
|
||
|
+
|
||
|
+ rule_filter = talloc_asprintf_append(rule_filter, "(%s=%s)",
|
||
|
+ IPA_MEMBER_HOST,
|
||
|
+ host_group_clean);
|
||
|
+ if (rule_filter == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto immediate;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Add the username to the filter */
|
||
|
+ ret = sss_parse_internal_fqname(state, username, &user, NULL);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "sss_parse_internal_fqname() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto immediate;
|
||
|
+ }
|
||
|
+
|
||
|
+ rule_filter = talloc_asprintf_append(rule_filter, "(%s=%s)",
|
||
|
+ IPA_MEMBER_USER, user);
|
||
|
+ if (rule_filter == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto immediate;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Add all parent groups of `username` to the filter */
|
||
|
+ ret = get_sysdb_grouplist(state, domain->sysdb, domain, username,
|
||
|
+ &groups_list);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "get_sysdb_grouplist() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto immediate;
|
||
|
+ }
|
||
|
+
|
||
|
+ for (size_t i = 0; groups_list[i] != NULL; i++) {
|
||
|
+ ret = sss_filter_sanitize(state, groups_list[i], &group_clean);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "sss_filter_sanitize() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto immediate;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sss_parse_internal_fqname(state, group_clean, &group, NULL);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "sss_parse_internal_fqname() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto immediate;
|
||
|
+ }
|
||
|
+
|
||
|
+ rule_filter = talloc_asprintf_append(rule_filter, "(%s=%s)",
|
||
|
+ IPA_MEMBER_USER, group);
|
||
|
+ if (rule_filter == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto immediate;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ rule_filter = talloc_asprintf_append(rule_filter, "))");
|
||
|
+ if (rule_filter == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto immediate;
|
||
|
+ }
|
||
|
+ state->rules_filter = talloc_steal(state, rule_filter);
|
||
|
+
|
||
|
+ ret = ipa_deskprofile_rule_info_next(req, state);
|
||
|
+ if (ret != EAGAIN) {
|
||
|
+ if (ret == EOK) {
|
||
|
+ /* ipa_deskprofile_rule_info_next should always have a search base
|
||
|
+ * when called for the first time.
|
||
|
+ *
|
||
|
+ * For the subsequent iterations, not finding any more search bases
|
||
|
+ * is fine though (thus the function returns EOK).
|
||
|
+ *
|
||
|
+ * As, here, it's the first case happening, let's return EINVAL.
|
||
|
+ */
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "No search base found\n");
|
||
|
+ ret = EINVAL;
|
||
|
+ }
|
||
|
+ goto immediate;
|
||
|
+ }
|
||
|
+
|
||
|
+ return req;
|
||
|
+
|
||
|
+immediate:
|
||
|
+ if (ret == EOK) {
|
||
|
+ tevent_req_done(req);
|
||
|
+ } else {
|
||
|
+ tevent_req_error(req, ret);
|
||
|
+ }
|
||
|
+ tevent_req_post(req, ev);
|
||
|
+ return req;
|
||
|
+}
|
||
|
+
|
||
|
+static errno_t
|
||
|
+ipa_deskprofile_rule_info_next(struct tevent_req *req,
|
||
|
+ struct ipa_deskprofile_rule_state *state)
|
||
|
+{
|
||
|
+ struct tevent_req *subreq;
|
||
|
+ struct sdap_search_base *base;
|
||
|
+
|
||
|
+ base = state->search_bases[state->search_base_iter];
|
||
|
+ if (base == NULL) {
|
||
|
+ return EOK;
|
||
|
+ }
|
||
|
+
|
||
|
+ talloc_zfree(state->cur_filter);
|
||
|
+ state->cur_filter = sdap_combine_filters(state, state->rules_filter,
|
||
|
+ base->filter);
|
||
|
+ if (state->cur_filter == NULL) {
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC,
|
||
|
+ "Sending request for next search base: [%s][%d][%s]\n",
|
||
|
+ base->basedn, base->scope, state->cur_filter);
|
||
|
+
|
||
|
+ subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
|
||
|
+ base->basedn, base->scope,
|
||
|
+ state->cur_filter, state->attrs,
|
||
|
+ NULL, 0,
|
||
|
+ dp_opt_get_int(state->opts->basic,
|
||
|
+ SDAP_ENUM_SEARCH_TIMEOUT),
|
||
|
+ true);
|
||
|
+ if (subreq == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "sdap_get_generic_send failed.\n");
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+ tevent_req_set_callback(subreq, ipa_deskprofile_rule_info_done, req);
|
||
|
+
|
||
|
+ return EAGAIN;
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+ipa_deskprofile_rule_info_done(struct tevent_req *subreq)
|
||
|
+{
|
||
|
+ errno_t ret;
|
||
|
+ struct tevent_req *req;
|
||
|
+ struct ipa_deskprofile_rule_state *state;
|
||
|
+ size_t rule_count;
|
||
|
+ size_t total_count;
|
||
|
+ struct sysdb_attrs **rules;
|
||
|
+ struct sysdb_attrs **target;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ req = tevent_req_callback_data(subreq, struct tevent_req);
|
||
|
+ state = tevent_req_data(req, struct ipa_deskprofile_rule_state);
|
||
|
+
|
||
|
+ ret = sdap_get_generic_recv(subreq, state,
|
||
|
+ &rule_count,
|
||
|
+ &rules);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
||
|
+ "Could not retrieve Desktop Profile rules\n");
|
||
|
+ goto fail;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (rule_count > 0) {
|
||
|
+ total_count = rule_count + state->rule_count;
|
||
|
+ state->rules = talloc_realloc(state, state->rules,
|
||
|
+ struct sysdb_attrs *,
|
||
|
+ total_count);
|
||
|
+ if (state->rules == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto fail;
|
||
|
+ }
|
||
|
+
|
||
|
+ i = 0;
|
||
|
+ while (state->rule_count < total_count) {
|
||
|
+ target = &state->rules[state->rule_count];
|
||
|
+ *target = talloc_steal(state->rules, rules[i]);
|
||
|
+
|
||
|
+ state->rule_count++;
|
||
|
+ i++;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ state->search_base_iter++;
|
||
|
+ ret = ipa_deskprofile_rule_info_next(req, state);
|
||
|
+ if (ret == EAGAIN) {
|
||
|
+ return;
|
||
|
+ } else if (ret != EOK) {
|
||
|
+ goto fail;
|
||
|
+ } else if (ret == EOK && state->rule_count == 0) {
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC, "No rules apply to this host\n");
|
||
|
+ tevent_req_error(req, ENOENT);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* We went through all search bases and we have some results */
|
||
|
+ tevent_req_done(req);
|
||
|
+
|
||
|
+ return;
|
||
|
+
|
||
|
+fail:
|
||
|
+ tevent_req_error(req, ret);
|
||
|
+}
|
||
|
+
|
||
|
+errno_t
|
||
|
+ipa_deskprofile_rule_info_recv(struct tevent_req *req,
|
||
|
+ TALLOC_CTX *mem_ctx,
|
||
|
+ size_t *_rule_count,
|
||
|
+ struct sysdb_attrs ***_rules)
|
||
|
+{
|
||
|
+ struct ipa_deskprofile_rule_state *state;
|
||
|
+
|
||
|
+ TEVENT_REQ_RETURN_ON_ERROR(req);
|
||
|
+
|
||
|
+ state = tevent_req_data(req, struct ipa_deskprofile_rule_state);
|
||
|
+
|
||
|
+ *_rule_count = state->rule_count;
|
||
|
+ *_rules = talloc_steal(mem_ctx, state->rules);
|
||
|
+
|
||
|
+ return EOK;
|
||
|
+}
|
||
|
diff --git a/src/providers/ipa/ipa_deskprofile_rules.h b/src/providers/ipa/ipa_deskprofile_rules.h
|
||
|
new file mode 100644
|
||
|
index 0000000000000000000000000000000000000000..313e526780c0780bce667fb459b27de7cc6fe9e9
|
||
|
--- /dev/null
|
||
|
+++ b/src/providers/ipa/ipa_deskprofile_rules.h
|
||
|
@@ -0,0 +1,43 @@
|
||
|
+/*
|
||
|
+ SSSD
|
||
|
+
|
||
|
+ Authors:
|
||
|
+ Fabiano Fidêncio <fidencio@redhat.com>
|
||
|
+
|
||
|
+ Copyright (C) 2017 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 IPA_DESKPROFILE_RULES_H_
|
||
|
+#define IPA_DESKPROFILE_RULES_H_
|
||
|
+
|
||
|
+/* From ipa_deskprofile_rules.c */
|
||
|
+struct tevent_req *
|
||
|
+ipa_deskprofile_rule_info_send(TALLOC_CTX *mem_ctx,
|
||
|
+ struct tevent_context *ev,
|
||
|
+ struct sdap_handle *sh,
|
||
|
+ struct sdap_options *opts,
|
||
|
+ struct sdap_search_base **search_bases,
|
||
|
+ struct sysdb_attrs *ipa_host,
|
||
|
+ struct sss_domain_info *domain,
|
||
|
+ const char *username);
|
||
|
+
|
||
|
+errno_t
|
||
|
+ipa_deskprofile_rule_info_recv(struct tevent_req *req,
|
||
|
+ TALLOC_CTX *mem_ctx,
|
||
|
+ size_t *rule_count,
|
||
|
+ struct sysdb_attrs ***rules);
|
||
|
+
|
||
|
+#endif /* IPA_DESKPROFILE_RULES_H_ */
|
||
|
diff --git a/src/providers/ipa/ipa_deskprofile_rules_util.c b/src/providers/ipa/ipa_deskprofile_rules_util.c
|
||
|
new file mode 100644
|
||
|
index 0000000000000000000000000000000000000000..1f5b7f9c5244c5863dec4096e2af58914425c37c
|
||
|
--- /dev/null
|
||
|
+++ b/src/providers/ipa/ipa_deskprofile_rules_util.c
|
||
|
@@ -0,0 +1,932 @@
|
||
|
+/*
|
||
|
+ SSSD
|
||
|
+
|
||
|
+ Authors:
|
||
|
+ Fabiano Fidêncio <fidencio@redhat.com>
|
||
|
+
|
||
|
+ Copyright (C) 2017 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 "providers/ipa/ipa_deskprofile_rules_util.h"
|
||
|
+#include "providers/ipa/ipa_deskprofile_private.h"
|
||
|
+#include "providers/ipa/ipa_rules_common.h"
|
||
|
+#include <ctype.h>
|
||
|
+#include <fcntl.h>
|
||
|
+
|
||
|
+#define DESKPROFILE_GLOBAL_POLICY_MIN_VALUE 1
|
||
|
+#define DESKPROFILE_GLOBAL_POLICY_MAX_VALUE 24
|
||
|
+
|
||
|
+enum deskprofile_name {
|
||
|
+ RULES_DIR = 0,
|
||
|
+ DOMAIN,
|
||
|
+ USERNAME,
|
||
|
+ PRIORITY,
|
||
|
+ USER,
|
||
|
+ GROUP,
|
||
|
+ HOST,
|
||
|
+ HOSTGROUP,
|
||
|
+ RULE_NAME,
|
||
|
+ EXTENSION,
|
||
|
+ DESKPROFILE_NAME_SENTINEL
|
||
|
+};
|
||
|
+
|
||
|
+/*
|
||
|
+ * The rule's filename has to follow a global policy, used by FleetCommander
|
||
|
+ * client that shows how the profile should be applied.
|
||
|
+ *
|
||
|
+ * This global policy is represented by an integer from 1 to 24 (inclusive) and
|
||
|
+ * has the following meaning:
|
||
|
+ * 1 = user, group, host, hostgroup
|
||
|
+ * 2 = user, group, hostgroup, host
|
||
|
+ * 3 = user, host, group, hostgroup
|
||
|
+ * 4 = user, host, hostgroup, group
|
||
|
+ * 5 = user, hostgroup, group, host
|
||
|
+ * 6 = user, hostgroup, host, group
|
||
|
+ * 7 = group, user, host, hostgroup
|
||
|
+ * 8 = group, user, hostgroup, host
|
||
|
+ * 9 = group, host, user, hostgroup
|
||
|
+ * 10 = group, host, hostgroup, user
|
||
|
+ * 11 = group, hostgroup, user, host
|
||
|
+ * 12 = group, hostgroup, host, user
|
||
|
+ * 13 = host, user, group, hostgroup
|
||
|
+ * 14 = host, user, hostgroup, group
|
||
|
+ * 15 = host, group, user, hostgroup
|
||
|
+ * 16 = host, group, hostgroup, user
|
||
|
+ * 17 = host, hostgroup, user, group
|
||
|
+ * 18 = host, hostgroup, group, user
|
||
|
+ * 19 = hostgroup, user, group, host
|
||
|
+ * 20 = hostgroup, user, host, group
|
||
|
+ * 21 = hostgroup, group, user, host
|
||
|
+ * 22 = hostgroup, group, host, user
|
||
|
+ * 23 = hostgroup, host, user, group
|
||
|
+ * 24 = hostgroup, host, group, user
|
||
|
+ *
|
||
|
+ * Having the table above in mind and considering the following example:
|
||
|
+ * - rule name: testrule
|
||
|
+ * - policy: 22
|
||
|
+ * - priority: 420
|
||
|
+ * - client's machine matches: host and group
|
||
|
+ *
|
||
|
+ * So, the filename will be: "000420_000000_000420_000420_000000_testrule.json"
|
||
|
+ *
|
||
|
+ * The function below not only helps us to create this filename in the correct
|
||
|
+ * format, but also create the whole path for this rule's file.
|
||
|
+ *
|
||
|
+ * An example of the full path would be:
|
||
|
+ * "/var/lib/sss/deskprofile/ipa.example/user_foobar/000420_000000_000420_000420_000000_testrule.json"
|
||
|
+ * | RULES DIR | DOMAIN | USERNAME | | |GROUP | HOST | USER | |
|
||
|
+ * PRIORITY RULE NAME
|
||
|
+ * HOSTGROUP EXTENSION
|
||
|
+ *
|
||
|
+ * In case a element has to be added/remove, please, remember to update:
|
||
|
+ * - deskprofile_name enum;
|
||
|
+ * - permuts's matrix;
|
||
|
+ * - vals array;
|
||
|
+ */
|
||
|
+static errno_t
|
||
|
+ipa_deskprofile_get_filename_path(TALLOC_CTX *mem_ctx,
|
||
|
+ uint16_t config_priority,
|
||
|
+ const char *rules_dir,
|
||
|
+ const char *domain,
|
||
|
+ const char *username,
|
||
|
+ const char *priority,
|
||
|
+ const char *user_priority,
|
||
|
+ const char *group_priority,
|
||
|
+ const char *host_priority,
|
||
|
+ const char *hostgroup_priority,
|
||
|
+ const char *rule_name,
|
||
|
+ const char *extension,
|
||
|
+ char **_filename_path)
|
||
|
+{
|
||
|
+ TALLOC_CTX *tmp_ctx;
|
||
|
+ static const uint8_t permuts[][DESKPROFILE_NAME_SENTINEL] = {
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, USER, GROUP, HOST, HOSTGROUP, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, USER, GROUP, HOSTGROUP, HOST, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, USER, HOST, GROUP, HOSTGROUP, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, USER, HOST, HOSTGROUP, GROUP, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, USER, HOSTGROUP, GROUP, HOST, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, USER, HOSTGROUP, HOST, GROUP, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, GROUP, USER, HOST, HOSTGROUP, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, GROUP, USER, HOSTGROUP, HOST, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, GROUP, HOST, USER, HOSTGROUP, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, GROUP, HOST, HOSTGROUP, HOST, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, GROUP, HOSTGROUP, USER, HOST, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, GROUP, HOSTGROUP, HOST, USER, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, HOST, USER, GROUP, HOSTGROUP, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, HOST, USER, HOSTGROUP, GROUP, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, HOST, GROUP, USER, HOSTGROUP, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, HOST, GROUP, HOSTGROUP, USER, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, HOST, HOSTGROUP, USER, GROUP, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, HOST, HOSTGROUP, GROUP, USER, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, HOSTGROUP, USER, GROUP, HOST, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, HOSTGROUP, USER, HOST, GROUP, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, HOSTGROUP, GROUP, USER, HOST, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, HOSTGROUP, GROUP, HOST, USER, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, HOSTGROUP, HOST, USER, GROUP, RULE_NAME, EXTENSION},
|
||
|
+ {RULES_DIR, DOMAIN, USERNAME, PRIORITY, HOSTGROUP, HOST, GROUP, USER, RULE_NAME, EXTENSION},
|
||
|
+ };
|
||
|
+ const char *vals[] = {
|
||
|
+ rules_dir,
|
||
|
+ domain,
|
||
|
+ username,
|
||
|
+ priority,
|
||
|
+ user_priority,
|
||
|
+ group_priority,
|
||
|
+ host_priority,
|
||
|
+ hostgroup_priority,
|
||
|
+ rule_name,
|
||
|
+ extension,
|
||
|
+ NULL,
|
||
|
+ };
|
||
|
+ const uint8_t *perms;
|
||
|
+ char *result;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ tmp_ctx = talloc_new(mem_ctx);
|
||
|
+ if (tmp_ctx == NULL) {
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (config_priority < DESKPROFILE_GLOBAL_POLICY_MIN_VALUE ||
|
||
|
+ config_priority > DESKPROFILE_GLOBAL_POLICY_MAX_VALUE) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "The configuration priority has an invalid value: %d!\n",
|
||
|
+ config_priority);
|
||
|
+ ret = EINVAL;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ perms = permuts[config_priority - 1];
|
||
|
+
|
||
|
+ result = talloc_strdup(tmp_ctx, "");
|
||
|
+ if (result == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ for (int i = 0; i < DESKPROFILE_NAME_SENTINEL; i++) {
|
||
|
+ switch(perms[i]) {
|
||
|
+ case RULES_DIR:
|
||
|
+ case DOMAIN:
|
||
|
+ case USERNAME:
|
||
|
+ result = talloc_asprintf_append(result, "%s/", vals[perms[i]]);
|
||
|
+ break;
|
||
|
+ case PRIORITY:
|
||
|
+ case USER:
|
||
|
+ case GROUP:
|
||
|
+ case HOST:
|
||
|
+ case HOSTGROUP:
|
||
|
+ result = talloc_asprintf_append(result, "%s_", vals[perms[i]]);
|
||
|
+ break;
|
||
|
+ case RULE_NAME:
|
||
|
+ result = talloc_asprintf_append(result, "%s", vals[perms[i]]);
|
||
|
+ break;
|
||
|
+ case EXTENSION:
|
||
|
+ result = talloc_asprintf_append(result, ".%s", vals[perms[i]]);
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
||
|
+ "This situation should never happen\n");
|
||
|
+ ret = EINVAL;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (result == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ *_filename_path = talloc_steal(mem_ctx, result);
|
||
|
+ ret = EOK;
|
||
|
+
|
||
|
+done:
|
||
|
+ talloc_free(tmp_ctx);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+errno_t
|
||
|
+ipa_deskprofile_rules_create_user_dir(
|
||
|
+ const char *username, /* fully-qualified */
|
||
|
+ uid_t uid,
|
||
|
+ gid_t gid)
|
||
|
+{
|
||
|
+ TALLOC_CTX *tmp_ctx;
|
||
|
+ char *shortname;
|
||
|
+ char *domain;
|
||
|
+ char *domain_dir;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ tmp_ctx = talloc_new(NULL);
|
||
|
+ if (tmp_ctx == NULL) {
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sss_parse_internal_fqname(tmp_ctx, username, &shortname, &domain);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "sss_parse_internal_fqname() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sss_create_dir(IPA_DESKPROFILE_RULES_USER_DIR, domain, 0755,
|
||
|
+ getuid(), getgid());
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "Failed to create the directory \"%s/%s\" that would be used to "
|
||
|
+ "store the Desktop Profile rules users' directory [%d]: %s\n",
|
||
|
+ IPA_DESKPROFILE_RULES_USER_DIR, domain,
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ domain_dir = talloc_asprintf(tmp_ctx, IPA_DESKPROFILE_RULES_USER_DIR"/%s",
|
||
|
+ domain);
|
||
|
+ if (domain_dir == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sss_create_dir(domain_dir, shortname, 0600, uid, gid);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "Failed to create the directory \"%s/%s/%s\" that would be used "
|
||
|
+ "to store the Desktop Profile rules for the user \"%s\" [%d]: "
|
||
|
+ "%s\n",
|
||
|
+ IPA_DESKPROFILE_RULES_USER_DIR, domain, shortname, username,
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = EOK;
|
||
|
+
|
||
|
+done:
|
||
|
+ talloc_free(tmp_ctx);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static errno_t
|
||
|
+ipa_deskprofile_get_normalized_rule_name(TALLOC_CTX *mem_ctx,
|
||
|
+ const char *name,
|
||
|
+ char **_rule_name)
|
||
|
+{
|
||
|
+ char buffer[PATH_MAX];
|
||
|
+ size_t buffer_len;
|
||
|
+ size_t name_len;
|
||
|
+
|
||
|
+ name_len = strlen(name);
|
||
|
+ buffer_len = 0;
|
||
|
+ for (size_t i = 0; i < name_len; i++) {
|
||
|
+ char character;
|
||
|
+ bool replace;
|
||
|
+
|
||
|
+ character = name[i];
|
||
|
+ replace = false;
|
||
|
+
|
||
|
+ if (isalnum(character) == 0) {
|
||
|
+ char next_character;
|
||
|
+
|
||
|
+ next_character = name[i+1];
|
||
|
+ if (i + 1 >= name_len || isalnum(next_character) == 0) {
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+
|
||
|
+ replace = true;
|
||
|
+ }
|
||
|
+
|
||
|
+ buffer[buffer_len] = replace ? '_' : character;
|
||
|
+ buffer_len++;
|
||
|
+ }
|
||
|
+ buffer[buffer_len] = '\0';
|
||
|
+
|
||
|
+ *_rule_name = talloc_strdup(mem_ctx, buffer);
|
||
|
+ if (*_rule_name == NULL) {
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ return EOK;
|
||
|
+}
|
||
|
+
|
||
|
+static errno_t
|
||
|
+ipa_deskprofile_rule_check_memberuser(
|
||
|
+ TALLOC_CTX *mem_ctx,
|
||
|
+ struct sss_domain_info *domain,
|
||
|
+ struct sysdb_attrs *rule,
|
||
|
+ const char *rule_name,
|
||
|
+ const char *rule_prio,
|
||
|
+ const char *base_dn,
|
||
|
+ const char *username, /* fully-qualified */
|
||
|
+ char **_user_prio,
|
||
|
+ char **_group_prio)
|
||
|
+{
|
||
|
+ TALLOC_CTX *tmp_ctx;
|
||
|
+ struct ldb_message_element *el;
|
||
|
+ struct ldb_result *res;
|
||
|
+ size_t num_groups;
|
||
|
+ char **groups = NULL;
|
||
|
+ const char *fqgroupname = NULL;
|
||
|
+ char *groupname = NULL;
|
||
|
+ char *shortname;
|
||
|
+ char *domainname;
|
||
|
+ char *data;
|
||
|
+ char *memberuser;
|
||
|
+ char *membergroup;
|
||
|
+ char *user_prio;
|
||
|
+ char *group_prio;
|
||
|
+ bool user = false;
|
||
|
+ bool group = false;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ tmp_ctx = talloc_new(mem_ctx);
|
||
|
+ if (tmp_ctx == NULL) {
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sss_parse_internal_fqname(tmp_ctx, username,
|
||
|
+ &shortname, &domainname);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "sss_parse_internal_fqname() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sysdb_initgroups(tmp_ctx, domain, username, &res);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "sysdb_initgroups() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (res->count == 0) {
|
||
|
+ /* This really should NOT happen at this point */
|
||
|
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
||
|
+ "User [%s] not found in cache\n", username);
|
||
|
+ ret = ENOENT;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ groups = talloc_array(tmp_ctx, char *, res->count);
|
||
|
+ if (groups == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ num_groups = 0;
|
||
|
+ /* Start counting from 1 to exclude the user entry */
|
||
|
+ for (size_t i = 1; i < res->count; i++) {
|
||
|
+ fqgroupname = ldb_msg_find_attr_as_string(res->msgs[i],
|
||
|
+ SYSDB_NAME,
|
||
|
+ NULL);
|
||
|
+ if (fqgroupname == NULL) {
|
||
|
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
||
|
+ "Skipping malformed entry [%s]\n",
|
||
|
+ ldb_dn_get_linearized(res->msgs[i]->dn));
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sss_parse_internal_fqname(tmp_ctx, fqgroupname,
|
||
|
+ &groupname, NULL);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
||
|
+ "Malformed name %s, skipping!\n", fqgroupname);
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+
|
||
|
+ groups[num_groups] = groupname;
|
||
|
+ num_groups++;
|
||
|
+ }
|
||
|
+ groups[num_groups] = NULL;
|
||
|
+
|
||
|
+ ret = sysdb_attrs_get_el(rule, IPA_MEMBER_USER, &el);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC,
|
||
|
+ "Failed to get the Desktop Profile Rule memberUser for rule "
|
||
|
+ "\"%s\" [%d]: %s\n",
|
||
|
+ rule_name, ret, sss_strerror(ret));
|
||
|
+
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ memberuser = talloc_asprintf(tmp_ctx, "uid=%s,cn=users,cn=accounts,%s",
|
||
|
+ shortname, base_dn);
|
||
|
+ if (memberuser == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to allocate memberuser\n");
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ for (size_t i = 0; i < el->num_values; i++) {
|
||
|
+ if (user && group) {
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ data = (char *)el->values[i].data;
|
||
|
+
|
||
|
+ if (!user && data != NULL && strcmp(memberuser, data) == 0) {
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC,
|
||
|
+ "Desktop Profile rule \"%s\" matches with the user \"%s\" "
|
||
|
+ "for the \"%s\" domain!\n",
|
||
|
+ rule_name, shortname, domainname);
|
||
|
+ user = true;
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!group && data != NULL) {
|
||
|
+ for (size_t j = 0; !group && groups[j] != NULL; j++) {
|
||
|
+ membergroup = talloc_asprintf(tmp_ctx,
|
||
|
+ "cn=%s,cn=groups,cn=accounts,%s",
|
||
|
+ groups[j], base_dn);
|
||
|
+ if (membergroup == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "Failed to allocate membergroup\n");
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (strcmp(membergroup, data) == 0) {
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC,
|
||
|
+ "Desktop Profile rule \"%s\" matches with (at least) "
|
||
|
+ "the group \"%s\" for the \"%s\" domain!\n",
|
||
|
+ rule_name, groups[j], domainname);
|
||
|
+ group = true;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ user_prio = user ? talloc_strdup(tmp_ctx, rule_prio) :
|
||
|
+ talloc_asprintf(tmp_ctx, "%06d", 0);
|
||
|
+ if (user_prio == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to allocate the user priority\n");
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ group_prio = group ? talloc_strdup(tmp_ctx, rule_prio) :
|
||
|
+ talloc_asprintf(tmp_ctx, "%06d", 0);
|
||
|
+ if (group_prio == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to allocate the group priority\n");
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ *_user_prio = talloc_steal(mem_ctx, user_prio);
|
||
|
+ *_group_prio = talloc_steal(mem_ctx, group_prio);
|
||
|
+
|
||
|
+ ret = EOK;
|
||
|
+
|
||
|
+done:
|
||
|
+ talloc_free(tmp_ctx);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static errno_t
|
||
|
+ipa_deskprofile_rule_check_memberhost(TALLOC_CTX *mem_ctx,
|
||
|
+ struct sss_domain_info *domain,
|
||
|
+ struct sysdb_attrs *rule,
|
||
|
+ const char *rule_name,
|
||
|
+ const char *rule_prio,
|
||
|
+ const char *base_dn,
|
||
|
+ const char *hostname,
|
||
|
+ char **_host_prio,
|
||
|
+ char **_hostgroup_prio)
|
||
|
+{
|
||
|
+ TALLOC_CTX *tmp_ctx;
|
||
|
+ struct ldb_dn *host_dn;
|
||
|
+ struct ldb_message_element *el_orig_memberof = NULL;
|
||
|
+ struct ldb_message_element *el = NULL;
|
||
|
+ struct ldb_message **msgs;
|
||
|
+ size_t count;
|
||
|
+ size_t num_memberhostgroup;
|
||
|
+ char **memberhostgroups = NULL;
|
||
|
+ char *data;
|
||
|
+ char *memberhost;
|
||
|
+ char *memberhostgroup;
|
||
|
+ char *name;
|
||
|
+ char *host_prio;
|
||
|
+ char *hostgroup_prio;
|
||
|
+ const char *memberof_attrs[] = { SYSDB_ORIG_MEMBEROF, NULL };
|
||
|
+ bool host = false;
|
||
|
+ bool hostgroup = false;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ tmp_ctx = talloc_new(mem_ctx);
|
||
|
+ if (tmp_ctx == NULL) {
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ host_dn = sysdb_custom_dn(tmp_ctx, domain, hostname,
|
||
|
+ DESKPROFILE_HOSTS_SUBDIR);
|
||
|
+ if (host_dn == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sysdb_search_entry(tmp_ctx, domain->sysdb, host_dn,
|
||
|
+ LDB_SCOPE_BASE, NULL,
|
||
|
+ memberof_attrs,
|
||
|
+ &count, &msgs);
|
||
|
+ if (ret == ENOENT || count == 0) {
|
||
|
+ memberhostgroups = talloc_array(tmp_ctx, char *, 1);
|
||
|
+ memberhostgroups[0] = NULL;
|
||
|
+ } else if (ret != EOK) {
|
||
|
+ goto done;
|
||
|
+ } else if (count > 1) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "More than one result for a BASE search!\n");
|
||
|
+ ret = EIO;
|
||
|
+ goto done;
|
||
|
+ } else { /* ret == EOK && count == 1 */
|
||
|
+ el_orig_memberof = ldb_msg_find_element(msgs[0], SYSDB_ORIG_MEMBEROF);
|
||
|
+ memberhostgroups = talloc_array(tmp_ctx,
|
||
|
+ char *,
|
||
|
+ el_orig_memberof->num_values);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (el_orig_memberof != NULL) {
|
||
|
+ num_memberhostgroup = 0;
|
||
|
+ for (size_t i = 0; i < el_orig_memberof->num_values; i++) {
|
||
|
+ data = (char *)el_orig_memberof->values[i].data;
|
||
|
+
|
||
|
+ ret = ipa_common_get_hostgroupname(tmp_ctx, domain->sysdb, data,
|
||
|
+ &name);
|
||
|
+
|
||
|
+ /* ERR_UNEXPECTED_ENTRY_TYPE means we had a memberOf entry that
|
||
|
+ * wasn't a host group, thus we'll just ignore those.
|
||
|
+ */
|
||
|
+ if (ret != EOK && ret != ERR_UNEXPECTED_ENTRY_TYPE) {
|
||
|
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
||
|
+ "Skipping malformed entry [%s]\n",
|
||
|
+ data);
|
||
|
+ continue;
|
||
|
+ } else if (ret == EOK) {
|
||
|
+ memberhostgroups[num_memberhostgroup] = name;
|
||
|
+ num_memberhostgroup++;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ memberhostgroups[num_memberhostgroup] = NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sysdb_attrs_get_el(rule, IPA_MEMBER_HOST, &el);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC,
|
||
|
+ "Failed to get the Desktop Profile Rule memberHost for rule "
|
||
|
+ "\"%s\" [%d]: %s\n",
|
||
|
+ rule_name, ret, sss_strerror(ret));
|
||
|
+
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ memberhost = talloc_asprintf(tmp_ctx, "fqdn=%s,cn=computers,cn=accounts,%s",
|
||
|
+ hostname, base_dn);
|
||
|
+ if (memberhost == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to allocate memberhost\n");
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ for (size_t i = 0; i < el->num_values; i++) {
|
||
|
+ if (host && hostgroup) {
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ data = (char *)el->values[i].data;
|
||
|
+
|
||
|
+ if (!host && data != NULL && strcmp(memberhost, data) == 0) {
|
||
|
+ host = true;
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC,
|
||
|
+ "Desktop Profile rule \"%s\" matches with the host \"%s\" "
|
||
|
+ "for the \"%s\" domain!\n",
|
||
|
+ rule_name, hostname, domain->name);
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!hostgroup && data != NULL) {
|
||
|
+ for (size_t j = 0; !hostgroup && memberhostgroups[j] != NULL; j++) {
|
||
|
+ memberhostgroup = talloc_asprintf(
|
||
|
+ tmp_ctx,
|
||
|
+ "cn=%s,cn=hostgroups,cn=accounts,%s",
|
||
|
+ memberhostgroups[j], base_dn);
|
||
|
+
|
||
|
+ if (memberhostgroup == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "Failed to allocate memberhostgroup\n");
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (strcmp(memberhostgroup, data) == 0) {
|
||
|
+ hostgroup = true;
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC,
|
||
|
+ "Desktop Profile rule \"%s\" matches with (at least) "
|
||
|
+ "the hostgroup \"%s\" for the \"%s\" domain!\n",
|
||
|
+ rule_name, memberhostgroups[j], domain->name);
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ host_prio = host ? talloc_strdup(tmp_ctx, rule_prio) :
|
||
|
+ talloc_asprintf(tmp_ctx, "%06d", 0);
|
||
|
+ if (host_prio == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to allocate the host priority\n");
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ hostgroup_prio = hostgroup ? talloc_strdup(tmp_ctx, rule_prio) :
|
||
|
+ talloc_asprintf(tmp_ctx, "%06d", 0);
|
||
|
+ if (hostgroup_prio == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to allocate the hostgroup priority\n");
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ *_host_prio = talloc_steal(mem_ctx, host_prio);
|
||
|
+ *_hostgroup_prio = talloc_steal(mem_ctx, hostgroup_prio);
|
||
|
+
|
||
|
+ ret = EOK;
|
||
|
+
|
||
|
+done:
|
||
|
+ talloc_free(tmp_ctx);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+errno_t
|
||
|
+ipa_deskprofile_rules_save_rule_to_disk(
|
||
|
+ TALLOC_CTX *mem_ctx,
|
||
|
+ uint16_t priority,
|
||
|
+ struct sysdb_attrs *rule,
|
||
|
+ struct sss_domain_info *domain,
|
||
|
+ const char *hostname,
|
||
|
+ const char *username, /* fully-qualified */
|
||
|
+ uid_t uid,
|
||
|
+ gid_t gid)
|
||
|
+{
|
||
|
+ TALLOC_CTX *tmp_ctx;
|
||
|
+ const char *rule_name;
|
||
|
+ const char *data;
|
||
|
+ char *shortname;
|
||
|
+ char *domainname;
|
||
|
+ char *base_dn;
|
||
|
+ char *rule_prio;
|
||
|
+ char *user_prio;
|
||
|
+ char *group_prio;
|
||
|
+ char *host_prio;
|
||
|
+ char *hostgroup_prio;
|
||
|
+ char *normalized_rule_name = NULL;
|
||
|
+ char *filename_path = NULL;
|
||
|
+ const char *extension = "json";
|
||
|
+ uint32_t prio;
|
||
|
+ int fd = -1;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ tmp_ctx = talloc_new(mem_ctx);
|
||
|
+ if (tmp_ctx == NULL) {
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sysdb_attrs_get_string(rule, IPA_CN, &rule_name);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC,
|
||
|
+ "Failed to get the Desktop Profile Rule name [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sysdb_attrs_get_uint32_t(rule, IPA_DESKPROFILE_PRIORITY, &prio);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC,
|
||
|
+ "Failed to get the Desktop Profile Rule priority for rule "
|
||
|
+ "\"%s\" [%d]: %s\n",
|
||
|
+ rule_name, ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ rule_prio = talloc_asprintf(tmp_ctx, "%06d", prio);
|
||
|
+ if (rule_prio == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to allocate rule priority\n");
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sysdb_attrs_get_string(rule, IPA_DESKPROFILE_DATA, &data);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC,
|
||
|
+ "Failed to get the Desktop Profile Rule data for rule \"%s\" "
|
||
|
+ "[%d]: %s\n",
|
||
|
+ rule_name, ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sss_parse_internal_fqname(tmp_ctx, username, &shortname, &domainname);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "sss_parse_internal_fqname() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = domain_to_basedn(tmp_ctx, domainname, &base_dn);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "domain_to_basedn() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = ipa_deskprofile_rule_check_memberuser(tmp_ctx, domain, rule,
|
||
|
+ rule_name, rule_prio,
|
||
|
+ base_dn, username,
|
||
|
+ &user_prio, &group_prio);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "ipa_deskprofile_rule_check_memberuser() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = ipa_deskprofile_rule_check_memberhost(tmp_ctx, domain, rule,
|
||
|
+ rule_name, rule_prio,
|
||
|
+ base_dn, hostname,
|
||
|
+ &host_prio, &hostgroup_prio);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "ipa_deskprofile_rule_check_memberhost() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = ipa_deskprofile_get_normalized_rule_name(mem_ctx, rule_name,
|
||
|
+ &normalized_rule_name);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "ipa_deskprofile_get_normalized_rule_name() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = ipa_deskprofile_get_filename_path(tmp_ctx,
|
||
|
+ priority,
|
||
|
+ IPA_DESKPROFILE_RULES_USER_DIR,
|
||
|
+ domainname,
|
||
|
+ shortname,
|
||
|
+ rule_prio,
|
||
|
+ user_prio,
|
||
|
+ group_prio,
|
||
|
+ host_prio,
|
||
|
+ hostgroup_prio,
|
||
|
+ normalized_rule_name,
|
||
|
+ extension,
|
||
|
+ &filename_path);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "ipa_deskprofile_get_filename_path() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ fd = open(filename_path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||
|
+ if (fd == -1) {
|
||
|
+ ret = errno;
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "Failed to create the Desktop Profile rule file \"%s\" "
|
||
|
+ "[%d]: %s\n",
|
||
|
+ filename_path, ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = dprintf(fd, "%s", data);
|
||
|
+ if (ret < 0) {
|
||
|
+ ret = EIO;
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "Failed to write the content of the Desktop Profile rule for "
|
||
|
+ "the \"%s\" file.\n",
|
||
|
+ filename_path);
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = fchown(fd, uid, gid);
|
||
|
+ if (ret != EOK) {
|
||
|
+ ret = errno;
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "Failed to own the Desktop Profile Rule file \"%s\" [%d]: %s\n",
|
||
|
+ filename_path, ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = EOK;
|
||
|
+
|
||
|
+done:
|
||
|
+ if (fd != -1) {
|
||
|
+ close(fd);
|
||
|
+ }
|
||
|
+ talloc_free(tmp_ctx);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+errno_t
|
||
|
+ipa_deskprofile_rules_remove_user_dir(const char *user_dir)
|
||
|
+{
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ ret = sss_remove_tree(user_dir);
|
||
|
+ if (ret == ENOENT) {
|
||
|
+ return EOK;
|
||
|
+ } else if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "Cannot remove \"%s\" directory [%d]: %s\n",
|
||
|
+ user_dir, ret, sss_strerror(ret));
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
+ return EOK;
|
||
|
+}
|
||
|
+
|
||
|
+errno_t
|
||
|
+deskprofile_get_cached_priority(struct sss_domain_info *domain,
|
||
|
+ uint16_t *_priority)
|
||
|
+{
|
||
|
+ TALLOC_CTX *tmp_ctx;
|
||
|
+ const char *attrs[] = { IPA_DESKPROFILE_PRIORITY, NULL };
|
||
|
+ struct ldb_message **resp;
|
||
|
+ size_t resp_count;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ tmp_ctx = talloc_new(NULL);
|
||
|
+ if (tmp_ctx == NULL) {
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sysdb_search_custom_by_name(tmp_ctx,
|
||
|
+ domain,
|
||
|
+ IPA_DESKPROFILE_PRIORITY,
|
||
|
+ DESKPROFILE_CONFIG_SUBDIR,
|
||
|
+ attrs, &resp_count, &resp);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "sysdb_search_custom_by_name() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (resp_count != 1) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "sysdb_search_custom_by_name() got more attributes than "
|
||
|
+ "expected. Expected (%d), got (%"PRIu64")\n", 1, resp_count);
|
||
|
+ ret = EINVAL;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ *_priority = ldb_msg_find_attr_as_uint(resp[0],
|
||
|
+ IPA_DESKPROFILE_PRIORITY,
|
||
|
+ 0);
|
||
|
+ ret = EOK;
|
||
|
+
|
||
|
+done:
|
||
|
+ talloc_free(tmp_ctx);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+const char **
|
||
|
+deskprofile_get_attrs_to_get_cached_rules(TALLOC_CTX *mem_ctx)
|
||
|
+{
|
||
|
+ const char **attrs = talloc_zero_array(mem_ctx, const char *, 11);
|
||
|
+ if (attrs == NULL) {
|
||
|
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_array() failed\n");
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ attrs[0] = OBJECTCLASS;
|
||
|
+ attrs[1] = IPA_CN;
|
||
|
+ attrs[2] = IPA_UNIQUE_ID;
|
||
|
+ attrs[3] = IPA_ENABLED_FLAG;
|
||
|
+ attrs[4] = IPA_MEMBER_USER;
|
||
|
+ attrs[5] = IPA_USER_CATEGORY;
|
||
|
+ attrs[6] = IPA_MEMBER_HOST;
|
||
|
+ attrs[7] = IPA_HOST_CATEGORY;
|
||
|
+ attrs[8] = IPA_DESKPROFILE_PRIORITY;
|
||
|
+ attrs[9] = IPA_DESKPROFILE_DATA;
|
||
|
+ attrs[10] = NULL;
|
||
|
+
|
||
|
+done:
|
||
|
+ return attrs;
|
||
|
+}
|
||
|
diff --git a/src/providers/ipa/ipa_deskprofile_rules_util.h b/src/providers/ipa/ipa_deskprofile_rules_util.h
|
||
|
new file mode 100644
|
||
|
index 0000000000000000000000000000000000000000..61f404df83382e139abc859ed43db65037d04ace
|
||
|
--- /dev/null
|
||
|
+++ b/src/providers/ipa/ipa_deskprofile_rules_util.h
|
||
|
@@ -0,0 +1,57 @@
|
||
|
+/*
|
||
|
+ SSSD
|
||
|
+
|
||
|
+ Authors:
|
||
|
+ Fabiano Fidêncio <fidencio@redhat.com>
|
||
|
+
|
||
|
+ Copyright (C) 2017 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 IPA_DESKPROFILE_RULES_UTIL_H_
|
||
|
+#define IPA_DESKPROFILE_RULES_UTIL_H_
|
||
|
+
|
||
|
+#include "db/sysdb.h"
|
||
|
+
|
||
|
+#ifndef IPA_DESKPROFILE_RULES_USER_DIR
|
||
|
+#define IPA_DESKPROFILE_RULES_USER_DIR SSS_STATEDIR"/deskprofile"
|
||
|
+#endif /* IPA_DESKPROFILE_RULES_USER_DIR */
|
||
|
+
|
||
|
+errno_t
|
||
|
+ipa_deskprofile_rules_create_user_dir(
|
||
|
+ const char *username, /* fully-qualified */
|
||
|
+ uid_t uid,
|
||
|
+ gid_t gid);
|
||
|
+errno_t
|
||
|
+ipa_deskprofile_rules_save_rule_to_disk(
|
||
|
+ TALLOC_CTX *mem_ctx,
|
||
|
+ uint16_t priority,
|
||
|
+ struct sysdb_attrs *rule,
|
||
|
+ struct sss_domain_info *domain,
|
||
|
+ const char *hostname,
|
||
|
+ const char *username, /* fully-qualified */
|
||
|
+ uid_t uid,
|
||
|
+ gid_t gid);
|
||
|
+errno_t
|
||
|
+ipa_deskprofile_rules_remove_user_dir(const char *user_dir);
|
||
|
+
|
||
|
+errno_t
|
||
|
+deskprofile_get_cached_priority(struct sss_domain_info *domain,
|
||
|
+ uint16_t *_priority);
|
||
|
+
|
||
|
+const char **
|
||
|
+deskprofile_get_attrs_to_get_cached_rules(TALLOC_CTX *mem_ctx);
|
||
|
+
|
||
|
+#endif /* IPA_DESKPROFILE_RULES_UTIL_H_ */
|
||
|
diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c
|
||
|
index 7dec4d1fb8541a48470d4e44f10838e5bea67ad5..7cae43c065e0cd687a80620faf6a354f001bd41c 100644
|
||
|
--- a/src/providers/ipa/ipa_init.c
|
||
|
+++ b/src/providers/ipa/ipa_init.c
|
||
|
@@ -42,6 +42,7 @@
|
||
|
#include "providers/ipa/ipa_subdomains.h"
|
||
|
#include "providers/ipa/ipa_srv.h"
|
||
|
#include "providers/be_dyndns.h"
|
||
|
+#include "providers/ipa/ipa_session.h"
|
||
|
|
||
|
#define DNS_SRV_MISCONFIGURATION "SRV discovery is enabled on the IPA " \
|
||
|
"server while using custom dns_discovery_domain. DNS discovery of " \
|
||
|
@@ -940,3 +941,51 @@ errno_t sssm_ipa_sudo_init(TALLOC_CTX *mem_ctx,
|
||
|
return EOK;
|
||
|
#endif
|
||
|
}
|
||
|
+
|
||
|
+errno_t sssm_ipa_session_init(TALLOC_CTX *mem_ctx,
|
||
|
+ struct be_ctx *be_ctx,
|
||
|
+ void *module_data,
|
||
|
+ struct dp_method *dp_methods)
|
||
|
+{
|
||
|
+ struct ipa_session_ctx *session_ctx;
|
||
|
+ struct ipa_init_ctx *init_ctx;
|
||
|
+ struct ipa_id_ctx *id_ctx;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ init_ctx = talloc_get_type(module_data, struct ipa_init_ctx);
|
||
|
+ id_ctx = init_ctx->id_ctx;
|
||
|
+
|
||
|
+ session_ctx = talloc_zero(mem_ctx, struct ipa_session_ctx);
|
||
|
+ if (session_ctx == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero() failed.\n");
|
||
|
+
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ session_ctx->sdap_ctx = id_ctx->sdap_id_ctx;
|
||
|
+ session_ctx->host_map = id_ctx->ipa_options->host_map;
|
||
|
+ session_ctx->hostgroup_map = id_ctx->ipa_options->hostgroup_map;
|
||
|
+ session_ctx->host_search_bases = id_ctx->ipa_options->host_search_bases;
|
||
|
+ session_ctx->deskprofile_search_bases = id_ctx->ipa_options->deskprofile_search_bases;
|
||
|
+
|
||
|
+ ret = dp_copy_options(session_ctx, id_ctx->ipa_options->basic,
|
||
|
+ IPA_OPTS_BASIC, &session_ctx->ipa_options);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "dp_copy_options() failed.\n");
|
||
|
+
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ dp_set_method(dp_methods, DPM_SESSION_HANDLER,
|
||
|
+ ipa_pam_session_handler_send, ipa_pam_session_handler_recv, session_ctx,
|
||
|
+ struct ipa_session_ctx, struct pam_data, struct pam_data *);
|
||
|
+
|
||
|
+ ret = EOK;
|
||
|
+
|
||
|
+done:
|
||
|
+ if (ret != EOK) {
|
||
|
+ talloc_free(session_ctx);
|
||
|
+ }
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
diff --git a/src/providers/ipa/ipa_opts.c b/src/providers/ipa/ipa_opts.c
|
||
|
index f9f3a2a6992be6cf5cb3c699b30c45ca9dbb42ab..4836445dad82c4d3ecaecc32d22cb6f9730f0fcb 100644
|
||
|
--- a/src/providers/ipa/ipa_opts.c
|
||
|
+++ b/src/providers/ipa/ipa_opts.c
|
||
|
@@ -48,6 +48,8 @@ struct dp_option ipa_basic_opts[] = {
|
||
|
{ "ipa_server_mode", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
|
||
|
{ "ipa_views_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
|
||
|
{ "krb5_confd_path", DP_OPT_STRING, { KRB5_MAPPING_DIR }, NULL_STRING },
|
||
|
+ { "ipa_deskprofile_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
|
||
|
+ { "ipa_deskprofile_refresh", DP_OPT_NUMBER, { .number = 5 }, NULL_NUMBER },
|
||
|
DP_OPTION_TERMINATOR
|
||
|
};
|
||
|
|
||
|
diff --git a/src/providers/ipa/ipa_session.c b/src/providers/ipa/ipa_session.c
|
||
|
new file mode 100644
|
||
|
index 0000000000000000000000000000000000000000..7adf8b6d7dfef9b2c29c1ee42f47842131773e90
|
||
|
--- /dev/null
|
||
|
+++ b/src/providers/ipa/ipa_session.c
|
||
|
@@ -0,0 +1,833 @@
|
||
|
+/*
|
||
|
+ SSSD
|
||
|
+
|
||
|
+ IPA Backend Module -- Session Management
|
||
|
+
|
||
|
+ Authors:
|
||
|
+ Fabiano Fidêncio <fidencio@redhat.com>
|
||
|
+
|
||
|
+ Copyright (C) 2017 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 <security/pam_modules.h>
|
||
|
+
|
||
|
+#include "util/child_common.h"
|
||
|
+#include "providers/ldap/sdap_async.h"
|
||
|
+#include "providers/ipa/ipa_common.h"
|
||
|
+#include "providers/ipa/ipa_config.h"
|
||
|
+#include "providers/ipa/ipa_hosts.h"
|
||
|
+#include "providers/ipa/ipa_subdomains.h"
|
||
|
+#include "providers/ipa/ipa_session.h"
|
||
|
+#include "providers/ipa/ipa_rules_common.h"
|
||
|
+#include "providers/ipa/ipa_deskprofile_private.h"
|
||
|
+#include "providers/ipa/ipa_deskprofile_config.h"
|
||
|
+#include "providers/ipa/ipa_deskprofile_rules.h"
|
||
|
+#include "providers/ipa/ipa_deskprofile_rules_util.h"
|
||
|
+
|
||
|
+/* Those here are used for sending a message to the deskprofile client
|
||
|
+ * informing that our side is done. */
|
||
|
+#define SSS_FLEETCOMMANDERCLIENT_BUS "org.freedesktop.FleetCommanderClient"
|
||
|
+#define SSS_FLEETCOMMANDERCLIENT_PATH "/org/freedesktop/FleetCommanderClient"
|
||
|
+#define SSS_FLEETCOMMANDERCLIENT_IFACE "org.freedesktop.FleetCommanderClient"
|
||
|
+
|
||
|
+struct ipa_fetch_deskprofile_state {
|
||
|
+ struct tevent_context *ev;
|
||
|
+ struct be_ctx *be_ctx;
|
||
|
+ struct sdap_id_ctx *sdap_ctx;
|
||
|
+ struct ipa_session_ctx *session_ctx;
|
||
|
+ struct sdap_id_op *sdap_op;
|
||
|
+ struct dp_option *ipa_options;
|
||
|
+ struct sdap_search_base **search_bases;
|
||
|
+ const char *username;
|
||
|
+
|
||
|
+ /* Hosts */
|
||
|
+ struct ipa_common_entries *hosts;
|
||
|
+ struct sysdb_attrs *ipa_host;
|
||
|
+
|
||
|
+ /* Rules */
|
||
|
+ struct ipa_common_entries *rules;
|
||
|
+ struct sysdb_attrs *config;
|
||
|
+ uint16_t priority;
|
||
|
+};
|
||
|
+
|
||
|
+static errno_t ipa_fetch_deskprofile_retry(struct tevent_req *req);
|
||
|
+static void ipa_fetch_deskprofile_connect_done(struct tevent_req *subreq);
|
||
|
+static errno_t ipa_fetch_deskprofile_hostinfo(struct tevent_req *req);
|
||
|
+static void ipa_fetch_deskprofile_hostinfo_done(struct tevent_req *subreq);
|
||
|
+static void ipa_fetch_deskprofile_config_done(struct tevent_req *subreq);
|
||
|
+static void ipa_fetch_deskprofile_rules_done(struct tevent_req *subreq);
|
||
|
+
|
||
|
+static struct tevent_req *
|
||
|
+ipa_fetch_deskprofile_send(TALLOC_CTX *mem_ctx,
|
||
|
+ struct tevent_context *ev,
|
||
|
+ struct be_ctx *be_ctx,
|
||
|
+ struct ipa_session_ctx *session_ctx,
|
||
|
+ const char *username)
|
||
|
+{
|
||
|
+ struct ipa_fetch_deskprofile_state *state;
|
||
|
+ struct tevent_req *req;
|
||
|
+ time_t now;
|
||
|
+ time_t refresh_interval;
|
||
|
+ bool offline;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ req = tevent_req_create(mem_ctx, &state,
|
||
|
+ struct ipa_fetch_deskprofile_state);
|
||
|
+ if (req == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ state->ev = ev;
|
||
|
+ state->be_ctx = be_ctx;
|
||
|
+ state->session_ctx = session_ctx;
|
||
|
+ state->sdap_ctx = session_ctx->sdap_ctx;
|
||
|
+ state->ipa_options = session_ctx->ipa_options;
|
||
|
+ state->search_bases = session_ctx->deskprofile_search_bases;
|
||
|
+ state->username = username;
|
||
|
+ state->hosts = talloc_zero(state, struct ipa_common_entries);
|
||
|
+ if (state->hosts == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto immediately;
|
||
|
+ }
|
||
|
+ state->rules = talloc_zero(state, struct ipa_common_entries);
|
||
|
+ if (state->rules == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto immediately;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (state->search_bases == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "No Desktop Profile search base found.\n");
|
||
|
+ ret = EINVAL;
|
||
|
+ goto immediately;
|
||
|
+ }
|
||
|
+
|
||
|
+ state->sdap_op = sdap_id_op_create(state,
|
||
|
+ state->sdap_ctx->conn->conn_cache);
|
||
|
+ if (state->sdap_op == NULL) {
|
||
|
+ DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n");
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto immediately;
|
||
|
+ }
|
||
|
+
|
||
|
+ offline = be_is_offline(be_ctx);
|
||
|
+ DEBUG(SSSDBG_TRACE_ALL, "Connection status is [%s].\n",
|
||
|
+ offline ? "offline" : "online");
|
||
|
+
|
||
|
+ refresh_interval = dp_opt_get_int(state->ipa_options,
|
||
|
+ IPA_DESKPROFILE_REFRESH);
|
||
|
+ now = time(NULL);
|
||
|
+
|
||
|
+ if (offline || now < session_ctx->last_update + refresh_interval) {
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC,
|
||
|
+ "Performing cached Desktop Profile evaluation\n");
|
||
|
+ ret = EOK;
|
||
|
+ goto immediately;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = ipa_fetch_deskprofile_retry(req);
|
||
|
+ if (ret != EAGAIN) {
|
||
|
+ goto immediately;
|
||
|
+ }
|
||
|
+
|
||
|
+ return req;
|
||
|
+
|
||
|
+immediately:
|
||
|
+ if (ret == EOK) {
|
||
|
+ tevent_req_done(req);
|
||
|
+ } else {
|
||
|
+ tevent_req_error(req, ret);
|
||
|
+ }
|
||
|
+ tevent_req_post(req, ev);
|
||
|
+
|
||
|
+ return req;
|
||
|
+}
|
||
|
+
|
||
|
+static errno_t
|
||
|
+ipa_fetch_deskprofile_retry(struct tevent_req *req)
|
||
|
+{
|
||
|
+ struct tevent_req *subreq;
|
||
|
+ struct ipa_fetch_deskprofile_state *state;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ state = tevent_req_data(req, struct ipa_fetch_deskprofile_state);
|
||
|
+
|
||
|
+ subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
|
||
|
+ if (subreq == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "sdap_id_op_connect_send() failed: %d (%s)\n",
|
||
|
+ ret, strerror(ret));
|
||
|
+
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
+ tevent_req_set_callback(subreq, ipa_fetch_deskprofile_connect_done, req);
|
||
|
+
|
||
|
+ return EAGAIN;
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+ipa_fetch_deskprofile_connect_done(struct tevent_req *subreq)
|
||
|
+{
|
||
|
+ struct tevent_req *req = NULL;
|
||
|
+ int dp_error;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ req = tevent_req_callback_data(subreq, struct tevent_req);
|
||
|
+
|
||
|
+ ret = sdap_id_op_connect_recv(subreq, &dp_error);
|
||
|
+ talloc_zfree(subreq);
|
||
|
+ if (ret != EOK) {
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = ipa_fetch_deskprofile_hostinfo(req);
|
||
|
+ if (ret == EAGAIN) {
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+done:
|
||
|
+ if (ret == EOK) {
|
||
|
+ tevent_req_done(req);
|
||
|
+ } else {
|
||
|
+ tevent_req_error(req, ret);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static errno_t
|
||
|
+ipa_fetch_deskprofile_hostinfo(struct tevent_req *req)
|
||
|
+{
|
||
|
+ struct tevent_req *subreq;
|
||
|
+ struct ipa_fetch_deskprofile_state *state;
|
||
|
+ const char *hostname;
|
||
|
+
|
||
|
+ state = tevent_req_data(req, struct ipa_fetch_deskprofile_state);
|
||
|
+ hostname = dp_opt_get_string(state->ipa_options, IPA_HOSTNAME);
|
||
|
+
|
||
|
+ subreq = ipa_host_info_send(state,
|
||
|
+ state->ev,
|
||
|
+ sdap_id_op_handle(state->sdap_op),
|
||
|
+ state->sdap_ctx->opts,
|
||
|
+ hostname,
|
||
|
+ state->session_ctx->host_map,
|
||
|
+ state->session_ctx->hostgroup_map,
|
||
|
+ state->session_ctx->host_search_bases);
|
||
|
+ if (subreq == NULL) {
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ tevent_req_set_callback(subreq, ipa_fetch_deskprofile_hostinfo_done, req);
|
||
|
+
|
||
|
+ return EAGAIN;
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+ipa_fetch_deskprofile_hostinfo_done(struct tevent_req *subreq)
|
||
|
+{
|
||
|
+ struct tevent_req *req;
|
||
|
+ struct ipa_fetch_deskprofile_state *state;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ req = tevent_req_callback_data(subreq, struct tevent_req);
|
||
|
+ state = tevent_req_data(req, struct ipa_fetch_deskprofile_state);
|
||
|
+
|
||
|
+ ret = ipa_host_info_recv(subreq, state,
|
||
|
+ &state->hosts->entry_count,
|
||
|
+ &state->hosts->entries,
|
||
|
+ &state->hosts->group_count,
|
||
|
+ &state->hosts->groups);
|
||
|
+ state->hosts->entry_subdir = DESKPROFILE_HOSTS_SUBDIR;
|
||
|
+ state->hosts->group_subdir = DESKPROFILE_HOSTGROUPS_SUBDIR;
|
||
|
+ talloc_zfree(subreq);
|
||
|
+ if (ret != EOK) {
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = ipa_get_host_attrs(state->ipa_options,
|
||
|
+ state->hosts->entry_count,
|
||
|
+ state->hosts->entries,
|
||
|
+ &state->ipa_host);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Could not locate IPA host.\n");
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ subreq = ipa_deskprofile_get_config_send(state,
|
||
|
+ state->ev,
|
||
|
+ sdap_id_op_handle(state->sdap_op),
|
||
|
+ state->sdap_ctx->opts,
|
||
|
+ state->ipa_options);
|
||
|
+ if (subreq == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ tevent_req_set_callback(subreq, ipa_fetch_deskprofile_config_done, req);
|
||
|
+ return;
|
||
|
+
|
||
|
+done:
|
||
|
+ tevent_req_error(req, ret);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+ipa_fetch_deskprofile_config_done(struct tevent_req *subreq)
|
||
|
+{
|
||
|
+ struct tevent_req *req;
|
||
|
+ struct ipa_fetch_deskprofile_state *state;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ req = tevent_req_callback_data(subreq, struct tevent_req);
|
||
|
+ state = tevent_req_data(req, struct ipa_fetch_deskprofile_state);
|
||
|
+
|
||
|
+ ret = ipa_deskprofile_get_config_recv(subreq, state, &state->config);
|
||
|
+ talloc_zfree(subreq);
|
||
|
+ if (ret != EOK) {
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sysdb_store_custom(state->be_ctx->domain, IPA_DESKPROFILE_PRIORITY,
|
||
|
+ DESKPROFILE_CONFIG_SUBDIR, state->config);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to save Desktop Profile policy\n");
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ subreq = ipa_deskprofile_rule_info_send(state,
|
||
|
+ state->ev,
|
||
|
+ sdap_id_op_handle(state->sdap_op),
|
||
|
+ state->sdap_ctx->opts,
|
||
|
+ state->search_bases,
|
||
|
+ state->ipa_host,
|
||
|
+ state->be_ctx->domain,
|
||
|
+ state->username);
|
||
|
+ if (subreq == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ tevent_req_set_callback(subreq, ipa_fetch_deskprofile_rules_done, req);
|
||
|
+ return;
|
||
|
+
|
||
|
+done:
|
||
|
+ tevent_req_error(req, ret);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+ipa_fetch_deskprofile_rules_done(struct tevent_req *subreq)
|
||
|
+{
|
||
|
+ struct tevent_req *req;
|
||
|
+ struct ipa_fetch_deskprofile_state *state;
|
||
|
+ int dp_error;
|
||
|
+ errno_t ret;
|
||
|
+ bool found;
|
||
|
+
|
||
|
+ req = tevent_req_callback_data(subreq, struct tevent_req);
|
||
|
+ state = tevent_req_data(req, struct ipa_fetch_deskprofile_state);
|
||
|
+
|
||
|
+ ret = ipa_deskprofile_rule_info_recv(subreq,
|
||
|
+ state,
|
||
|
+ &state->rules->entry_count,
|
||
|
+ &state->rules->entries);
|
||
|
+ state->rules->entry_subdir = DESKPROFILE_RULES_SUBDIR;
|
||
|
+ talloc_zfree(subreq);
|
||
|
+ if (ret == ENOENT) {
|
||
|
+ /* Set ret to EOK so we can safely call sdap_id_op_done. */
|
||
|
+ ret = EOK;
|
||
|
+ found = false;
|
||
|
+ } else if (ret == EOK) {
|
||
|
+ found = true;
|
||
|
+ } else {
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
|
||
|
+ if (dp_error == DP_ERR_OK && ret != EOK) {
|
||
|
+ /* retry */
|
||
|
+ ret = ipa_fetch_deskprofile_retry(req);
|
||
|
+ if (ret != EAGAIN) {
|
||
|
+ tevent_req_error(req, ret);
|
||
|
+ }
|
||
|
+ return;
|
||
|
+ } else if (ret != EOK) {
|
||
|
+ tevent_req_error(req, ret);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* For now, let's completely purge the previous stored
|
||
|
+ * rules before saving the new ones */
|
||
|
+ ret = ipa_common_purge_rules(state->be_ctx->domain,
|
||
|
+ DESKPROFILE_RULES_SUBDIR);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "Unable to remove Desktop Profile rules\n");
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!found) {
|
||
|
+ ret = ENOENT;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = ipa_common_save_rules(state->be_ctx->domain,
|
||
|
+ state->hosts, NULL, state->rules,
|
||
|
+ &state->session_ctx->last_update);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to save Desktop Profile rules\n");
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = EOK;
|
||
|
+
|
||
|
+done:
|
||
|
+ if (ret != EOK) {
|
||
|
+ tevent_req_error(req, ret);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ tevent_req_done(req);
|
||
|
+}
|
||
|
+
|
||
|
+static errno_t
|
||
|
+ipa_fetch_deskprofile_recv(struct tevent_req *req)
|
||
|
+{
|
||
|
+ TEVENT_REQ_RETURN_ON_ERROR(req);
|
||
|
+
|
||
|
+ return EOK;
|
||
|
+}
|
||
|
+
|
||
|
+struct ipa_pam_session_handler_state {
|
||
|
+ struct tevent_context *ev;
|
||
|
+ struct be_ctx *be_ctx;
|
||
|
+ struct ipa_session_ctx *session_ctx;
|
||
|
+ struct pam_data *pd;
|
||
|
+
|
||
|
+ /* Those attributes are used for:
|
||
|
+ * - saving the deskprofile rules to the disk;
|
||
|
+ * - deleting the deskprofile rules from the disk;
|
||
|
+ * - contacting the deskprofile client that everything is ready;
|
||
|
+ */
|
||
|
+ char *shortname;
|
||
|
+ char *domain;
|
||
|
+ char *user_dir;
|
||
|
+ uid_t uid;
|
||
|
+ gid_t gid;
|
||
|
+};
|
||
|
+
|
||
|
+static errno_t
|
||
|
+ipa_pam_session_handler_get_deskprofile_user_info(
|
||
|
+ TALLOC_CTX *mem_ctx,
|
||
|
+ struct sss_domain_info *domain,
|
||
|
+ const char *username,
|
||
|
+ char **_shortname,
|
||
|
+ char **_domain,
|
||
|
+ char **_user_dir,
|
||
|
+ uid_t *uid,
|
||
|
+ gid_t *gid);
|
||
|
+static void ipa_pam_session_handler_done(struct tevent_req *subreq);
|
||
|
+static errno_t
|
||
|
+ipa_pam_session_handler_save_deskprofile_rules(
|
||
|
+ struct be_ctx *be_ctx,
|
||
|
+ struct sss_domain_info *domain,
|
||
|
+ const char *username, /* fully-qualified */
|
||
|
+ const char *user_dir,
|
||
|
+ const char *hostname,
|
||
|
+ uid_t uid,
|
||
|
+ gid_t gid);
|
||
|
+static errno_t
|
||
|
+ipa_pam_session_handler_notify_deskprofile_client(uid_t uid,
|
||
|
+ const char *user_dir,
|
||
|
+ uint16_t prio);
|
||
|
+
|
||
|
+
|
||
|
+struct tevent_req *
|
||
|
+ipa_pam_session_handler_send(TALLOC_CTX *mem_ctx,
|
||
|
+ struct ipa_session_ctx *session_ctx,
|
||
|
+ struct pam_data *pd,
|
||
|
+ struct dp_req_params *params)
|
||
|
+{
|
||
|
+ struct tevent_req *req;
|
||
|
+ struct tevent_req *subreq;
|
||
|
+ struct ipa_pam_session_handler_state *state;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC, "Retrieving Desktop Profile rules\n");
|
||
|
+ req = tevent_req_create(mem_ctx, &state,
|
||
|
+ struct ipa_pam_session_handler_state);
|
||
|
+ if (req == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ state->pd = pd;
|
||
|
+ state->ev = params->ev;
|
||
|
+ state->be_ctx = params->be_ctx;
|
||
|
+ state->session_ctx = session_ctx;
|
||
|
+
|
||
|
+ /* Get all the user info that will be needed in order the delete the
|
||
|
+ * user's deskprofile directory from the disk, create the user's directory,
|
||
|
+ * save the fetched rules to the disk and notify the deskprofile client
|
||
|
+ * that this operation is done. */
|
||
|
+ ret = ipa_pam_session_handler_get_deskprofile_user_info(
|
||
|
+ state,
|
||
|
+ state->be_ctx->domain,
|
||
|
+ pd->user,
|
||
|
+ &state->shortname,
|
||
|
+ &state->domain,
|
||
|
+ &state->user_dir,
|
||
|
+ &state->uid,
|
||
|
+ &state->gid);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "ipa_deskprofile_get_user_info() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ state->pd->pam_status = PAM_SESSION_ERR;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* As no proper merging mechanism has been implemented yet ...
|
||
|
+ * let's just remove the user directory stored in the disk as it's
|
||
|
+ * going to be created again in case there's any rule fetched. */
|
||
|
+ ret = ipa_deskprofile_rules_remove_user_dir(state->user_dir);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "ipa_deskprofile_rules_remove_user_dir() failed.\n");
|
||
|
+ state->pd->pam_status = PAM_SESSION_ERR;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ subreq = ipa_fetch_deskprofile_send(state, state->ev, state->be_ctx,
|
||
|
+ state->session_ctx, pd->user);
|
||
|
+ if (subreq == NULL) {
|
||
|
+ state->pd->pam_status = PAM_SESSION_ERR;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ tevent_req_set_callback(subreq, ipa_pam_session_handler_done, req);
|
||
|
+ return req;
|
||
|
+
|
||
|
+done:
|
||
|
+ tevent_req_done(req);
|
||
|
+ tevent_req_post(req, params->ev);
|
||
|
+
|
||
|
+ return req;
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+ipa_pam_session_handler_done(struct tevent_req *subreq)
|
||
|
+{
|
||
|
+ struct tevent_req *req;
|
||
|
+ struct ipa_pam_session_handler_state *state;
|
||
|
+ const char *hostname;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ req = tevent_req_callback_data(subreq, struct tevent_req);
|
||
|
+ state = tevent_req_data(req, struct ipa_pam_session_handler_state);
|
||
|
+
|
||
|
+ ret = ipa_fetch_deskprofile_recv(subreq);
|
||
|
+ talloc_free(subreq);
|
||
|
+
|
||
|
+ if (ret == ENOENT) {
|
||
|
+ DEBUG(SSSDBG_IMPORTANT_INFO, "No Desktop Profile rules found\n");
|
||
|
+ state->pd->pam_status = PAM_SUCCESS;
|
||
|
+ goto done;
|
||
|
+ } else if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "Unable to fetch Desktop Profile rules [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ state->pd->pam_status = PAM_SYSTEM_ERR;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ hostname = dp_opt_get_string(state->session_ctx->ipa_options, IPA_HOSTNAME);
|
||
|
+ ret = ipa_pam_session_handler_save_deskprofile_rules(state->be_ctx,
|
||
|
+ state->be_ctx->domain,
|
||
|
+ state->pd->user,
|
||
|
+ state->user_dir,
|
||
|
+ hostname,
|
||
|
+ state->uid,
|
||
|
+ state->gid);
|
||
|
+
|
||
|
+ state->pd->pam_status = (ret == EOK) ? PAM_SUCCESS : PAM_SESSION_ERR;
|
||
|
+
|
||
|
+done:
|
||
|
+ /* TODO For backward compatibility we always return EOK to DP now. */
|
||
|
+ tevent_req_done(req);
|
||
|
+}
|
||
|
+
|
||
|
+errno_t
|
||
|
+ipa_pam_session_handler_recv(TALLOC_CTX *mem_ctx,
|
||
|
+ struct tevent_req *req,
|
||
|
+ struct pam_data **_data)
|
||
|
+{
|
||
|
+ struct ipa_pam_session_handler_state *state = NULL;
|
||
|
+
|
||
|
+ state = tevent_req_data(req, struct ipa_pam_session_handler_state);
|
||
|
+
|
||
|
+ TEVENT_REQ_RETURN_ON_ERROR(req);
|
||
|
+
|
||
|
+ *_data = talloc_steal(mem_ctx, state->pd);
|
||
|
+
|
||
|
+ return EOK;
|
||
|
+}
|
||
|
+
|
||
|
+static errno_t
|
||
|
+ipa_pam_session_handler_get_deskprofile_user_info(TALLOC_CTX *mem_ctx,
|
||
|
+ struct sss_domain_info *domain,
|
||
|
+ const char *username,
|
||
|
+ char **_shortname,
|
||
|
+ char **_domain,
|
||
|
+ char **_user_dir,
|
||
|
+ uid_t *_uid,
|
||
|
+ gid_t *_gid)
|
||
|
+{
|
||
|
+ TALLOC_CTX *tmp_ctx;
|
||
|
+ struct ldb_result *res = NULL;
|
||
|
+ char *shortname;
|
||
|
+ char *domain_name;
|
||
|
+ char *user_dir;
|
||
|
+ uid_t uid;
|
||
|
+ gid_t gid;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ tmp_ctx = talloc_new(NULL);
|
||
|
+ if (tmp_ctx == NULL) {
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sss_parse_internal_fqname(tmp_ctx, username,
|
||
|
+ &shortname, &domain_name);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC, "Failed to parse \"%s\" [%d]: %s\n",
|
||
|
+ username, ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ user_dir = talloc_asprintf(tmp_ctx, IPA_DESKPROFILE_RULES_USER_DIR"/%s/%s",
|
||
|
+ domain_name, shortname);
|
||
|
+ if (user_dir == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed!\n");
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = sysdb_getpwnam(tmp_ctx, domain, username, &res);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_getpwnam() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (res->count != 1) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "sysdb_getpwnam() got more users than expected. "
|
||
|
+ "Expected [%d], got [%d]\n", 1, res->count);
|
||
|
+ ret = EINVAL;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ uid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_UIDNUM, 0);
|
||
|
+ gid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_GIDNUM, 0);
|
||
|
+ if (uid == 0 || gid == 0) {
|
||
|
+ /* As IPA doesn't handle root users ou groups, we know for sure that's
|
||
|
+ * something wrong in case we get uid = 0 or gid = 0.
|
||
|
+ */
|
||
|
+ ret = EINVAL;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = EOK;
|
||
|
+
|
||
|
+ *_shortname = talloc_steal(mem_ctx, shortname);
|
||
|
+ *_domain = talloc_steal(mem_ctx, domain_name);
|
||
|
+ *_user_dir = talloc_steal(mem_ctx, user_dir);
|
||
|
+ *_uid = uid;
|
||
|
+ *_gid = gid;
|
||
|
+
|
||
|
+done:
|
||
|
+ talloc_free(tmp_ctx);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static errno_t
|
||
|
+ipa_pam_session_handler_save_deskprofile_rules(
|
||
|
+ struct be_ctx *be_ctx,
|
||
|
+ struct sss_domain_info *domain,
|
||
|
+ const char *username, /* fully-qualified */
|
||
|
+ const char *user_dir,
|
||
|
+ const char *hostname,
|
||
|
+ uid_t uid,
|
||
|
+ gid_t gid)
|
||
|
+{
|
||
|
+ TALLOC_CTX *tmp_ctx;
|
||
|
+ const char **attrs_get_cached_rules;
|
||
|
+ size_t rule_count;
|
||
|
+ struct sysdb_attrs **rules;
|
||
|
+ uint16_t priority;
|
||
|
+ errno_t ret;
|
||
|
+
|
||
|
+ tmp_ctx = talloc_new(NULL);
|
||
|
+ if (tmp_ctx == NULL) {
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Get Desktop Profile priority from sysdb */
|
||
|
+ ret = deskprofile_get_cached_priority(be_ctx->domain, &priority);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "deskprofile_get_cached_priority() failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+
|
||
|
+ /* Get Desktop Profile rules from sysdb */
|
||
|
+ attrs_get_cached_rules = deskprofile_get_attrs_to_get_cached_rules(tmp_ctx);
|
||
|
+ if (attrs_get_cached_rules == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "deskprofile_get_attrs_get_cached_rules() failed\n");
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+ ret = ipa_common_get_cached_rules(tmp_ctx, be_ctx->domain,
|
||
|
+ IPA_DESKPROFILE_RULE,
|
||
|
+ DESKPROFILE_RULES_SUBDIR,
|
||
|
+ attrs_get_cached_rules,
|
||
|
+ &rule_count,
|
||
|
+ &rules);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "Could not retrieve Desktop Profile rules from the cache\n");
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Create the user directory where the rules are going to be stored */
|
||
|
+ ret = ipa_deskprofile_rules_create_user_dir(username, uid, gid);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "Cannot create the user directory [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Save the rules to the disk */
|
||
|
+ for (size_t i = 0; i < rule_count; i++) {
|
||
|
+ ret = ipa_deskprofile_rules_save_rule_to_disk(tmp_ctx,
|
||
|
+ priority,
|
||
|
+ rules[i],
|
||
|
+ domain,
|
||
|
+ hostname,
|
||
|
+ username,
|
||
|
+ uid,
|
||
|
+ gid);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_OP_FAILURE,
|
||
|
+ "Failed to save a Desktop Profile Rule to disk [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Notify FleetCommander that our side is done */
|
||
|
+ ret = ipa_pam_session_handler_notify_deskprofile_client(uid,
|
||
|
+ user_dir,
|
||
|
+ priority);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "ipa_pam_session_handler_notify_deskprofile_client() "
|
||
|
+ "failed [%d]: %s\n",
|
||
|
+ ret, sss_strerror(ret));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = EOK;
|
||
|
+
|
||
|
+done:
|
||
|
+ talloc_free(tmp_ctx);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static DBusConnection *
|
||
|
+ipa_deskprofile_client_connect(void)
|
||
|
+{
|
||
|
+ DBusConnection *conn;
|
||
|
+ DBusError error;
|
||
|
+
|
||
|
+ dbus_error_init(&error);
|
||
|
+ conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
|
||
|
+ if (dbus_error_is_set(&error)) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
||
|
+ "Unable to connect to the FleetCommanderClient bus [%s]: %s\n",
|
||
|
+ error.name, error.message);
|
||
|
+ conn = NULL;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+done:
|
||
|
+ dbus_error_free(&error);
|
||
|
+ return conn;
|
||
|
+}
|
||
|
+
|
||
|
+static errno_t
|
||
|
+ipa_pam_session_handler_notify_deskprofile_client(uid_t uid,
|
||
|
+ const char *user_dir,
|
||
|
+ uint16_t prio)
|
||
|
+{
|
||
|
+ DBusConnection *conn = NULL;
|
||
|
+ DBusMessage *msg = NULL;
|
||
|
+ DBusError error;
|
||
|
+ errno_t ret;
|
||
|
+ bool dbus_ret;
|
||
|
+
|
||
|
+ dbus_error_init(&error);
|
||
|
+
|
||
|
+ conn = ipa_deskprofile_client_connect();
|
||
|
+ if (conn == NULL) {
|
||
|
+ ret = EIO;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ msg = sbus_create_message(NULL,
|
||
|
+ SSS_FLEETCOMMANDERCLIENT_BUS,
|
||
|
+ SSS_FLEETCOMMANDERCLIENT_PATH,
|
||
|
+ SSS_FLEETCOMMANDERCLIENT_IFACE,
|
||
|
+ "ProcessSSSDFiles",
|
||
|
+ DBUS_TYPE_UINT32, &uid,
|
||
|
+ DBUS_TYPE_STRING, &user_dir,
|
||
|
+ DBUS_TYPE_UINT16, &prio);
|
||
|
+ if (msg == NULL) {
|
||
|
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create D-Bus Message!\n");
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ dbus_ret = dbus_connection_send(conn, msg, NULL);
|
||
|
+ if (dbus_ret == FALSE) {
|
||
|
+ ret = EIO;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = EOK;
|
||
|
+
|
||
|
+done:
|
||
|
+ if (msg != NULL) {
|
||
|
+ dbus_message_unref(msg);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (conn != NULL) {
|
||
|
+ dbus_connection_unref(conn);
|
||
|
+ }
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
diff --git a/src/providers/ipa/ipa_session.h b/src/providers/ipa/ipa_session.h
|
||
|
new file mode 100644
|
||
|
index 0000000000000000000000000000000000000000..aac99844df0c0d158b63ad67bd89896611891551
|
||
|
--- /dev/null
|
||
|
+++ b/src/providers/ipa/ipa_session.h
|
||
|
@@ -0,0 +1,52 @@
|
||
|
+/*
|
||
|
+ SSSD
|
||
|
+
|
||
|
+ IPA Backend Module -- Session Management
|
||
|
+
|
||
|
+ Authors:
|
||
|
+ Fabiano Fidêncio <fidencio@redhat.com>
|
||
|
+
|
||
|
+ Copyright (C) 2017 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 IPA_SESSION_H_
|
||
|
+#define IPA_SESSION_H_
|
||
|
+
|
||
|
+#include "providers/ldap/ldap_common.h"
|
||
|
+
|
||
|
+struct ipa_session_ctx {
|
||
|
+ struct sdap_id_ctx *sdap_ctx;
|
||
|
+ struct dp_option *ipa_options;
|
||
|
+ time_t last_update;
|
||
|
+
|
||
|
+ struct sdap_attr_map *host_map;
|
||
|
+ struct sdap_attr_map *hostgroup_map;
|
||
|
+ struct sdap_search_base **deskprofile_search_bases;
|
||
|
+ struct sdap_search_base **host_search_bases;
|
||
|
+};
|
||
|
+
|
||
|
+struct tevent_req *
|
||
|
+ipa_pam_session_handler_send(TALLOC_CTX *mem_ctx,
|
||
|
+ struct ipa_session_ctx *session_ctx,
|
||
|
+ struct pam_data *pd,
|
||
|
+ struct dp_req_params *params);
|
||
|
+
|
||
|
+errno_t
|
||
|
+ipa_pam_session_handler_recv(TALLOC_CTX *mem_ctx,
|
||
|
+ struct tevent_req *req,
|
||
|
+ struct pam_data **_data);
|
||
|
+
|
||
|
+#endif /* IPA_SESSION_H_ */
|
||
|
diff --git a/src/responder/ifp/ifp_components.c b/src/responder/ifp/ifp_components.c
|
||
|
index 0cd6ba59f866b30a7bb979fbf179b7043de3d5d0..a4cc649c21e4f7d35f5703886916653f8c2d5786 100644
|
||
|
--- a/src/responder/ifp/ifp_components.c
|
||
|
+++ b/src/responder/ifp/ifp_components.c
|
||
|
@@ -590,7 +590,8 @@ void ifp_backend_get_providers(struct sbus_request *dbus_req,
|
||
|
CONFDB_DOMAIN_AUTOFS_PROVIDER,
|
||
|
CONFDB_DOMAIN_SELINUX_PROVIDER,
|
||
|
CONFDB_DOMAIN_HOSTID_PROVIDER,
|
||
|
- CONFDB_DOMAIN_SUBDOMAINS_PROVIDER};
|
||
|
+ CONFDB_DOMAIN_SUBDOMAINS_PROVIDER,
|
||
|
+ CONFDB_DOMAIN_SESSION_PROVIDER};
|
||
|
int num_providers = sizeof(providers) / sizeof(providers[0]);
|
||
|
errno_t ret;
|
||
|
int i;
|
||
|
--
|
||
|
2.14.1
|
||
|
|