On Mon, 3 Nov 2014 16:08:16 +0100
Jakub Hrozek <jhrozek(a)redhat.com> wrote:
On Sat, Nov 01, 2014 at 05:21:51PM -0400, Simo Sorce wrote:
> On Sat, 1 Nov 2014 17:24:53 +0100
> Jakub Hrozek <jhrozek(a)redhat.com> wrote:
>
> > 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?
>
> Are we sure we will be able to meaningfully separate "privileged
> initialization" from non-privileged items ?
Right now we've identified the places that need root access during
initialization because we crawled the whole SSSD codebase while making
it rootless -- they're the keytab processing after startup of IPA and
AD providers and reading the ccaches of users when initializing the
renewal. In general, the only access where we might fail unprivileged
atm is keytab access or ccache access.
I can't guarantee other problems in the future, true, but that's not a
problem limited to initialization, but we might run into a similar
problem during runtime as well.
Given keytabs can be rotated during the lifetime of sssd I think we
should rather have a suid helper (or use gss-proxy in conjuction with
sssd) to access the keytab, or sssd_be will fail to handle keyroation
in future.
> My fear is that we complicate the init system and end up having
all
> initialization in privileged_*_init() anyway, and *_init() become
> empty shells.
>
> I am comfortable with keeping the whole init privileged TBH.
Right, the initialization is a small window, at least time-wise,
compared to the code that runs during regular SSSD execution.
Separating the privileged init would have two benefits from my point
of view. 1) Making the surface of the code that runs as root smaller
in general. This is mostly interested in downstream groups that aim at
limiting the root code.
This sounds like it would be better served by a helper though.
2) Being able to separate the code that we know is required to
run
privileged and be able to unit test SSSD as a whole during make
check, using wrappers.
Same as above.
With 1) we can wait for some feedback from downstream. 2) is more of
a
convenience -- in order for SSSD to run as a completely different
user, we need to do changes in the monitor (like stop requiring that
monitor runs as root)
Hopefully this will not cause issues in monitoring network or
resolv.conf and other files that is done there.
In conclusion, for now maybe we can file a ticket describing the
privileged init, defer it and wait for downstream feedback as well as
see how our testing with a custom destdir goes. Revive this ticket if
we see a need and keep the backend init privileged now.
+1
Simo.
--
Simo Sorce * Red Hat, Inc * New York