Integrating Cyrus SASL

Ryan Saunders jediry01 at yahoo.com
Tue Dec 30 22:39:34 PST 2008


Hello,

I am a software engineer, with an interest in improving DBus's authentication implementation. In particular, my goals are: (a) to use username/password authentication to allow a remote machine full access to the session bus via TCP (without requiring access to the cookie file), and (b) to be able to to make DBus calls to a Linux machine from a Windows machine. This is part of a personal project, to let me remote-control Amarok from my Vista-based touchscreen laptop.

After slogging through dbus-auth.c, as well as the Cyrus SASL documentation (and occasionally, the source code), I have succeeded in hacking together a rough integration of Cyrus SASL 2.1.22 into DBus 1.2.3. The implementation is quite hacky in places, but I am now able to make a few DBus calls across a TCP link using PLAIN authentication. Now that it works, my next step is to polish it up, so that it's worthy of being submitted as a patch to DBus.

However, there are a few design issues that I need to solve before I can do this. I'd like to get some guidance from y'all on some of these, before I go to the trouble of doing the work. Better to do it right the first time. :-)

Issue #1: How should libsasl2 fit into the auth mechanism handlers?
---------------------------------------------------------------------------------------
As I started to implement a DBus auth mechanism wrapping libsasl2, I very quickly ran into a multiplicity issue: whereas DBus wants each auth mech to have its own handler, stored statically in a global table, libsasl2 is a wrapper around an arbitrary number of mechanisms, which are dynamically loaded from plugin libraries at runtime. This means that the list of available mechanisms can only be known at runtime, which is incompatible with the static table. Thus, there is a mismatch between how DBus wants auth mechs to be implemented and how libsasl2 packages them up. I can think of several possible approaches to addressing this:
  1. Integrate libsasl2 using the current set of auth mech handler callbacks, in a similar fashion to how the existing mechanisms are coded. The main challenge here is to make the list of mechanisms be generated at runtime, based on what plugins libsasl2 has available. Because libsasl2 is plugin-based, the set of supported mechanisms is dynamic, and thus cannot be global data in a static table. Instead, I would need to come up with some way of merging the existing mechanism list with the dynamically generated list from libsasl2.
  2. Put libsasl2 in charge of *all* authentication mechanisms, and then repackage the existing "external" and "dbus cookie" mechanisms as libsasl2 plugins. This is more work, but I think it might be cleaner overall, because dbus-auth.c would then contain only the generic auth code, with all of the mechanism-specific stuff located elsewhere (and thus, would be a _lot_ shorter). The DBusAuth structure could also get a bit smaller, since some of the fields it contains are specific to the existing mechanisms; these fields would instead move inside of those plugins. The main disadvantage of this (besides the extra work) is that we would incurr whatever additional overhead libsasl2 imposes. On the other hand, we have to boot up libsasl2 in order to interrogate it for its available plugins anyway, so perhaps this is no worse.

My inclination is to go with option #2.


Issue #2: How to expose the auth conversation on the client slide?
---------------------------------------------------------------------------------------
Because the various auth mechs (plain text, kerberos, etc.) supported by libsasl2 require different kinds of credentials from the user, a SASL-enabled app cannot simply throw up a "username/password" dialog...it needs to be able to customize the set of things that it asks the user for, based on the current auth mechanism. libsasl2 enables this with an "interaction" interface, which the app must implement in order to get the needed information from the user (the app could do this with a dialog, a command-line prompt, whatever). This means that, in order to take full advantage of libsasl2, DBus must expose similar functionality on the client side. I can think of two main options:
  1. Allow client to specify libsasl2 callbacks and interaction structures directly.
  2. Wrap the libsasl2 interactivity stuff with a (probably very similar) DBus interface, and require DBus clients to implement that instead. The DBus interface would probably do little more than forward calls from libsasl2 out to the client.

The first option is attractive because it is less work. The main drawback that I can see with approach #1 is that it makes the layering less clean (i.e., instead of client apps working only with DBus interfaces, this would be a place where client code would interact directly with a lower-level API that DBus depends on). Because of this, it would be harder to make libsasl2 an _optional_ dependency, because client code would need the SASL interaction API in order to compile. Of course, if we promote libsasl2 to become an essential part of the auth negotiation process (see Issue #1), then this doesn't matter, because libsasl2 would be a hard dependency anyway.

My inclination is to go with option #1.


Opinions? Other considerations that I might've missed? Was any of that unclear?

R



      


More information about the dbus mailing list