Multiple-Mechanism Sample Code?
Ken Hornstein
kenh at cmf.nrl.navy.mil
Mon Jan 1 00:41:34 EST 2007
>>> The client starts iterating through the ordered list, starting from
>>> the strongest mechanism. It tries the mechanism. If authentication
>>> succeeds - success. If not, the client may retry the mechanism (e.g.
>>> if the server returned an indication that the password is incorrect)
>>> several times, say 3 times. After that the client should move on to
>>> the next strongest SASL mechanism and so on.
I wasn't able to reply to your original note, but since it got brought up
again ... I just wanted to offer my $0.02. I personally think this advice
is wrong. I am speaking from the perspective of someone who uses (or at
least tries to use) the SASL GSSAPI mechanism as much as possible, and
I've written code that uses the Cyrus-SASL library as well as my own
lightweight GSSAPI-SASL library code (I had my reasons for not using
Cyrus-SASL for that one). Here are my reasons:
- Doing this is complicated.
As people have already noted, doing this right is a lot of work. If you
try to use the Cyrus-SASL library, you have to duplicate the list
parsing yourself, which just increases the complexity. Complexity means
more bugs, and it also decreases the likelihood people will even bother
to implement SASL in their products (other than the default CRAM-MD5
mechanism).
If you want to do this _right_, it also requires mechanism-specific
knowledge. Maybe redoing CRAM-MD5 attempts is correct, because
the user's password could be wrong. But redoing GSSAPI is almost
certainly wrong (although I guess retrying it isn't harmful).
But I recall one recent app (I want to say Thunderbird, but I
could be wrong) that if GSSAPI failed, it prompted you for a
password ... THAT everyone would agree is wrong, and is just
confusing for users.
- It makes things more complicated for users.
In your scenario, what kind of error message should be returned to
a user? All of the errors from all of the mechanisms? Just the
last one? None? I ask because getting the error message back from
a failed SASL-GSSAPI authentication exchange is _crucial_ to debugging
users problems. Like I said above, at least one recent SASL app just
gave you a new password prompt for every error, even with GSSAPI.
Debugging THAT issue was a whole lot of fun (I think I ended up using
a system call tracer; I could have saved myself an hour's worth of
work if the damn program just spit out a useful message).
Also, it's sometimes rather difficult to determine if an application
supports the mechanism I am interested in. I don't mean to bash on
Simon's fine work at GSSAPI-ing the world; I've had many chats with
him and I know the problems he's faced. It's just that it's not always
clear to me with some of the programs I've run into how you're supposed
to turn GSSAPI authentication on. I guess the idea is that it's
"magically" supposed to work ... but when it doesn't, I'm sitting
around scratching my head going, "Well, does this version even
_support_ it? Do I need to enable some wacky registry key?" I
like to consider myself pretty Kerberos savvy, but _none_ of these
automagic SASL-GSSAPI programs ever work for me on the first try.
I will contrast this with Apple's Mail.app. It has a very clear
UI element to select between different SASL mechanisms, and one
of them is "Kerberos V (GSSAPI)". I know that when I select that,
it's going to use the mechanism I want, and none of the others.
I will confess that I don't know if it returns useful error messages,
because it's always worked on the first try for me.
- Not all mechanisms are created the same.
Aside from the issue of attacks, in general don't want my users to
be using any random mechanism; I want them to be using GSSAPI in all
but a few cases. If we get other SASL mechanisms that use some
kind of infrastructure, I imagine the users of those mechanisms will
feel the same way. If GSSAPI is failing, I consider that a serious
problem and I want to know about it, _now_. I don't want users falling
back to CRAM-MD5 (okay, I prevent that on the server, but I can't
think of a situation where trying a bunch of mechanisms is preferrable
to explicit mechanism selection on the client).
Now, my suggestions? I think a SASL client should do the following:
- Allow (and perhaps even enforce) the selection of a specific SASL
mechanism.
- If a mechanism is not specifically selected, pick the "best" one
(I'm sure we could get into massive arguments about what the "best"
mechanism is). You could use some intelligence here; if you don't
have a Kerberos credential cache, for example, don't try GSSAPI.
- If authentication fails with the chosen mechanism, error out and
return the error text to the user.
--Ken
More information about the Cyrus-sasl
mailing list