Subject: Implementing SASL PLAIN servers

From: Simon Josefsson <[email-masked]>
Date: Thu, 09 Dec 2004 04:59:38 +0100

Hello.  I believe sasl-plain-05 would benefit from being more clear on
how servers should be implemented.  I'll try to describe the perceived
problem, and propose a solution.  I'd like for people to decide
whether the problem is real before thinking about whether the proposed
solution is the right one or not.

Section 2 says:

  The presented authentication identity and password strings are not
  to be compared directly with stored strings.  The server SHALL first
  prepare authentication identity and password strings using the
  [SASLPrep] profile of the [StringPrep] algorithm.  Per Section 7 of
  [StringPrep], unassigned code points may appear in prepared
  presented (query) strings but are prohibited in stored strings.  If
  preparation fails or results in an empty string, verification SHALL
  fail.  If the server stores only the hash of expected string, the
  string MUST be prepared before generation of the hash.

What I believe is missing, or is too unclear, here, is how the server
would prepare a password received from an external database, or
generally, a password that is not already be in prepared form.

What I'd like to see is explicit text that says whether SASLprep
should be invoked with the unassigned code point flag on or off, for
each of the strings.  That is, name each input string explicitly.  The
strings include: the client authid/passwd (i.e., data received over
the network from the client) and the server passwd (i.e., data
received from a database).  Depending on the server design, the
strings may also include a server authid (i.e., data received from a
database).

The current text only talk about this matter in an indirect way, a'la
"The server SHALL first prepare the strings using ... SASLPrep".  That
does not say HOW to use SASLPrep on those strings.

To understand whether there is a problem, the following question might
be useful: how would you prepare and compare an unprepared password
received from an external database, in the SASL PLAIN server?  I don't
believe the answer follows from the above description.

What I propose:

In the above paragraph, the first sentence is misleading, because it
imply there are always stored strings on the server.  That may not be
the case, for several reasons.  One reason may be that the server uses
an external database with unprepared passwords.  Another is that
passwords are generated on the fly.  I propose:

OLD:

  The presented authentication identity and password strings are not to
  be compared directly with stored strings.

NEW:

  The presented authentication identity and password strings need to
  be prepared before they are used in the verification process.

Proceeding with the next sentence:

  The server SHALL first prepare authentication identity and password
  strings using the [SASLPrep] profile of the [StringPrep] algorithm.
  Per Section 7 of [StringPrep], unassigned code points may appear in
  prepared presented (query) strings but are prohibited in stored
  strings.

I believe it would be clearer to state explicitly how each string
should be prepared.

I believe it was Sam who proposed to treat all strings as query
strings.  I'm not fully convinced it is the only way to see things,
but I cannot find a problem with his view now, so it appears to be the
best clarification that I can come up with.  So from that we get the
modifications below.  The first sentence is correct, and can stay:

OLD:
  The server SHALL first prepare authentication identity and password
  strings using the [SASLPrep] profile of the [StringPrep] algorithm.

To clarify that this means both the client-provided and the
server-known strings, I propose to add:

NEW:
  Both the strings received from the client, and the strings known to
  the server, MUST be prepared.

The next sentence is currently:

OLD:
  Per Section 7 of [StringPrep], unassigned code points may appear in
  prepared presented (query) strings but are prohibited in stored
  strings.

I believe it is the most troubling part, and that it doesn't convey
any useful information.  I propose to replace it with the following:

NEW:
  The server prepare the authentication identity and password received
  from the client ("client strings") using SASLprep, allowing
  unassigned code points in the output (see Section 7 of
  [StringPrep]).

  If the server store unprepared passwords and authentication
  identities ("server strings"), the server prepare these using
  SASLprep, allowing unassigned code points in the output.  The server
  verify the authentication by comparing the prepared client strings
  with the prepared server strings.

  If the server store a non-reversible transformation (i.e., a hash)
  of the authentication identity or password, the input strings to
  that transformation MUST have been prepared and unassigned code
  points MUST NOT be part of the prepared output.  Strings that are
  not used as input to the transformation (i.e., strings used to look
  up data in the database) MUST be prepared so that unassigned code
  points are permitted in the output.

  Verification when a non-reversible transformation is stored in the
  database is more complex.  We have several cases, that differ in
  what is being used as input to the transformation.  For example, in
  some designs the database is keyed on the authentication identity,
  and store a transformation of the password.  In some design, the
  database is keyed on the authentication identity, and store a
  transformation of the password and the authentication identity.
  Conceivable, some designs could key the database on a transformation
  of the password and authentication identity, and storing the
  authentication identity.  However, which mode is used does not
  matter, as long as the earlier rules are followed.

Then there is one old sentence that still apply:

OLD:
  If preparation fails or results in an empty string, verification
  SHALL fail.

The following current sentence has been superseded by earlier text,
and should be removed.

OLD:
  If the server stores only the hash of expected string, the string
  MUST be prepared before generation of the hash.

Thanks,
Simon