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

---

From: Simon Josefsson <[email-masked]>
Date: Thu, 09 Dec 2004 05:30:58 +0100

I now realize my suggestions were made against -05, and not Kurt's
latest proposed text.  I have now reviewed the latest proposal, and
while wording changed slightly, I failed to find any significant
changes that would have any consequences for implementations.  So I
believe all my comments still apply.

Kurt's new text removed the term "hash" though.  I think that is a bad
idea.  The term "non-invertible function" could be read as referring
to SASLprep, if there is no connotation to hashes.

Thanks,
Simon

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Wed, 08 Dec 2004 22:15:07 -0800

While some of this text reads okay, some of what the text
says I find technical flawed.  I note most of these technical
issues were previously discussed by the WG.

I note that the text also doesn't reflect the apparent consensus 
that use of SASLprep be RECOMMENDED (instead of REQUIRED)
(see <http://www.imc.org/ietf-sasl/mail-archive/msg01835.html>
for latest text).  Addressing this, and making the text read well,
is a bit of a challenge.

>  unassigned code points in the output (see Section 7 of

I believe the text needs to explicitly state that these
strings are to be regarded as "query" strings.  This for
continuity with Section 7 of [StringPrep].  I think that
can be worked in without too much problem.  (Likewise for
"stored" strings.)

>  with the prepared server strings.

This behavior is counter to the specified behavior of SASLprep
and StringPrep, from Section 7 of RFC 3454.
   The goal of the requirements in this section is to prevent
   comparisons between two strings that were both permitted to
   contain unassigned code points.
Since we allowing unassigned code points in the presented
strings, we must prohibit them in the stored strings.

>  matter, as long as the earlier rules are followed.

I see this elaboration as at best extraneous and at worse
distracting.  I don't see how it clarifies any of the key
issues you raise.

Kurt

---

From: Simon Josefsson <[email-masked]>
Date: Thu, 09 Dec 2004 17:54:02 +0100

> for latest text).  Addressing this, and making the text read well,

I can try to update my proposed text.

> can be worked in without too much problem.  (Likewise for

Good point.  How about this:

The server prepare the authentication identity and password received
from the client ("client strings") using SASLprep, treating them as
query strings, i.e., unassigned code points are allowed in the output
(see Section 7 of [StringPrep]).

> strings, we must prohibit them in the stored strings.

Unless I misunderstood him, or remember incorrectly, Sam proposed this
approach.  I would have implemented it differently -- I would treat
the unprepared strings using SASLprep treating the strings as stored
strings.  I don't care which option is chosen, only that there is a
plan and that the plan is expressed in the document.

> distracting.  I don't see how it clarifies any of the key

Requirements like those in the first paragraph above are needed if
servers should use SASLprep in the same way.  Again, exactly which
approach is chosen is secondary for me, but it should be made clear
which strings are prepared using SASLprep, and which strings may
contain unassigned code points or not.  The second paragraph
illustrate that there isn't a simple answer how to prepare each
string, it depends on how the server and the user database is
designed.  The current specification is pretty focused on only one
possible implementation of stored hashes.

However, I agree that the second paragraph does not add anything to
the protocol, so if you don't believe it is useful, then it could be
dropped.  I tried to write something that would improve the document.

I think the text reads OK if MUST is replaced with SHOULD.

Thanks,
Simon

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Thu, 09 Dec 2004 09:27:17 -0800

>I can try to update my proposed text.

Appreciated. 

>(see Section 7 of [StringPrep]).

That seems fine to me.

>plan and that the plan is expressed in the document.

All "server strings" should be regarded as "stored strings",
e.g., unassigned code prohibited in them.

>servers should use SASLprep in the same way. 

My last comment was in regards only to the last paragraph of your
suggested text.

>dropped.  I tried to write something that would improve the document.

Understand.  My thoughts are that this last paragraph is a bit
distracting and that document would read better without it.

>I think the text reads OK if MUST is replaced with SHOULD.

I note that the MUST v SHOULD applies to SASLprep preparation
of ALL strings (e.g., SASLprep SHOULD be used).   If SASLprep is
used, then it is be used as detailed (e.g., unassigned code
points MUST NOT appear in prepared output of server strings).

Kurt

---

From: Simon Josefsson <[email-masked]>
Date: Mon, 20 Dec 2004 03:41:17 +0100

>>I can try to update my proposed text.

If there is consensus to change to RECOMMENDED, I believe that it
would be easier for me to suggest modifications if there was a new
document that reflect current consensus.  Otherwise most of my
suggested text would likely just rewrite other aspect of the document.

My main concern is that it should be clear, for each string, whether
it may contain unassigned code points or not.  I thought it would be
simple to add small clarifying text for each string to address this.

> e.g., unassigned code prohibited in them.

We agree.  Sam, can you live with this?

For what its worth, this is also the approach I have implemented.
http://josefsson.org/cgi-bin/viewcvs.cgi/gsasl/lib/plain/server.c?view=markup

>>>>  matter, as long as the earlier rules are followed.
...
> distracting and that document would read better without it.

Then let's drop it.

I recall that Sam suggested that the document should discuss the two
aspects of a server implementation.  I don't think it is necessary if
you consider "server strings" as "stored strings", but if you don't,
it becomes critical.  Here is some discussion:

At least two conceptual parts of a server is involved in invoking
SASLprep.

First, there is the part that store passwords in the database.  As far
as I can tell, everyone agrees that the application should validate
the user input using SASLprep, treating the input as a stored string.

There doesn't seem to be consensus about what to store in the database
(original or prepared string), but I don't think it matters; either
approach should work.  (I'm not planning to implement a database that
store prepared strings, except as possibly an optimization, if the
original string is also stored.)

The second part of the server is the online part that receives
passwords from the client, and from the database.  Kurt and I seem to
be in agreement that it should prepare all strings (i.e., both from
client and from database) treating them as stored strings.  (Of
course, if the database store prepared strings, the server need not
prepare them again.)  If I understood him (and remember) correctly,
Sam suggested the server should treat all strings as query strings.
Given the current document, I have been trying to argue that this is
an entirely reasonable interpretation, so the document must be
clarified.

Right now, I have stopped caring about which approach is adopted, as
long as some approach is adopted.

Thanks,
Simon

---

From: Simon Josefsson <[email-masked]>
Date: Thu, 09 Dec 2004 05:30:58 +0100

Thanks,
Simon

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Wed, 08 Dec 2004 22:15:07 -0800

Kurt

---

From: Simon Josefsson <[email-masked]>
Date: Thu, 09 Dec 2004 17:54:02 +0100

Thanks,
Simon

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Thu, 09 Dec 2004 09:27:17 -0800

Appreciated. 

That seems fine to me.

Kurt

---

From: Simon Josefsson <[email-masked]>
Date: Mon, 20 Dec 2004 03:41:17 +0100

...

Then let's drop it.

Thanks,
Simon