On Wed, Jul 23, 2014 at 03:38:13PM +0200, Jakub Hrozek wrote:
=== Providers ===
The providers are dynamically loadable libraries that are loaded by the
`sssd_be` process. After startup, the sssd_be process dlopens the provider
library and dlsyms the handlers. During sssd operation, the `sssd_be` process
mostly unpacks requests arriving on the SBUS and calls the provider-specific
handlers.
We have two options here - either drop the privileges in the provider library
itself or directly in the `sssd_be` process. Dropping privileges in the
`sssd_be` process has the advantage of modifying only one place and being
sure that no matter the back end, the privileges would always be dropped.
On the other hand, becoming user in the library itself might be
beneficial for scenarios where the back end requires root access for
initialization. Also, if some third-party proprietary module absolutely
requires to run as root, we shouldn't enforce the privilege drop.
If we don't care about the third party modules, we could take an approach
where the provider would drop privilege as soon as it can and after all
the initialization was completed, the sssd_be process would ensure the
privileges are indeed dropped. Because there are no third party back ends
so far and there was no attempt to write one, this is currently safe.
After some experimentation and poking at the krb5 code, I think a different
route is needed. We can't reasonably drop the privileges in the provider's
setup routines themselves, because we don't know if another provider needs
root privileges or not. For example consider a LDAP + Kerberos
combination, the LDAP ID provider can't drop privileges until Kerberos
provider initializes because the Kerberos provider might need root
privileges to check exisiting ccaches for renewal after startup.
We can drop privileges after the whole initialization finishes, but we
should strive to reduce the privileged code even further.
Michal had an idea of adding another function to the providers that
would perform privileged init, then sssd_be would drop privs and proceed
with the rest of the init.
So the initialization would change from:
id_provider = dlopen()
id_init = dlsym(id_provider)
id_init()
auth_provider = dlopen()
auth_init = dlsym(auth_provider)
auth_init()
[...]
become_user(sssd)
to something like:
id_provider = dlopen()
auth_provider = dlopen()
privileged_id_init = dlsym(id_provider)
privileged_auth_init = dlsym(auth_provider)
privileged_id_init()
privileged_auth_init()
become_user(sssd)
id_init()
auth_init()
The privileged init would initialize private data the provider needs and
pass it on to the non-privileged init code.
There are some other alternatives, like a setuid setup process or
performing the initialization in the monitor, but I like this option the
best because passing on complex data structures between processes is
tricky. This way we also keep no knowledge about provider internals
outside the provider code.
Simo, I CC-ed you directly because I know you prefer to be aware of
changes to the data_provider_be.c module. Do you agree with this plan?