Subject: Re: Implementing SASL PLAIN servers

From: Sam Hartman <[email-masked]>
Date: Sun, 16 Jan 2005 13:38:24 -0500

>>>>> "Simon" == Simon Josefsson <[email-masked]> writes:

    >>> 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.
    >>  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.

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

First I'm sorry it has taken me so long to respond to this.

Apparently I seem to be the only one who believes that we're doing
something wrong.  Let me explain where I'm coming from and make sure
the group understands my position.  If people still believe that
forbidding unassigned codepoints is wrong, I'll withdraw my objection.

First, the ideal goal is to make sure that at some point when we are
storing a password or username, we forbid unassigned codepoints.  We'd
like that to happen.  If the IETF ever writes change password or
account creation protocols, we can make sure that happens for those
protocols.

However plain does not include a change password or account creation
protocol; the credentials are established out of band.  We explain to
people that they should normalize with saslprep and they should forbid
unassigned codepoints when establishing credentials.

We know about a lot of cases where people won't.  For example the unix
passwd command neither normalizes nor forbids unassigned codepoints.
Windows active directory passwords don't normalize although at least
they have a well defined character set.

If passwords are hashed, there's not really much you can do.  One
thing you can try is to try both the saslpreped and non-saslpreped
version of the string, hash both and see if one works.

My concern comes about when we think about what to do if it happens
you have access to the plaintext credential.  That is, the credential
establishment protocol actually stores the password.

Remember this credential establishment protocol is outside our
control.  I would like to take a look at the case where it neither
normalizes nor forbids unassigned codepoints.

It seems like the easiest thing to do in an implementation of plain
for this situation is to saslprep the two strings (one from user; one
from database) and compare.  My question is what do you do if the
database string contains unassigned codepoints.

If you allow unassigned codepoints you may improve interoperability.
This is true in the case where the codepoints end up being assigned to
normalize to themselves in a future saslprep.

What is the cost of allowing unassigned codepoints in this case.
Well, normally the cost of unassigned codepoints is that you don't
want to store long-term strings that may end up having the wrong
normalization.  However in this instance, that has already happened:
completely outside our control this string has already been placed in
the database.  The only cost I can see is that if some of the
unassigned codepoints end up generating forbidden output in a new
saslprep, upgrading a server to support that new saslprep will cause
passwords that used to work to stop working.  If we forbid unassigned
codepoints then these passwords never would have worked.  In either
case we cannot prevent the password from being established.  

It seems to boil down to two possible attitudes.  Option one (allowing
unassigned codepoints) means that users may be able to log in today
even though a server upgrade may stop the login process from working
in the future.  The second option is that we prevent users from
logging in today in order to guarantee that they will not be surprised
by a future server upgrade.

--Sam

---

From: Simon Josefsson <[email-masked]>
Date: Sun, 16 Jan 2005 20:39:00 +0100

Sam Hartman <[email-masked]> writes:

> the group understands my position.

Thanks for explaining, I now understand your approach.  While it
appear to go against the spirit of the following paragraph in
StringPrep, I think you make a good case for choosing another
strategy.

   The goal of the requirements in this section is to prevent
   comparisons between two strings that were both permitted to contain
   unassigned code points.  When two strings X and Y are compared and
   string Y was prepared in a way that permits unassigned code points, a
   negative result to the comparison is not definitive; it's possible
   that the strings don't match even though they would match if a more
   recent version of the profile were used for Y.  However, if both X
   and Y were prepared in a way that permits unassigned code points,
   something worse can happen: even a positive result for the comparison
   is not definitive.  It is possible that the strings do match even
   though they would not match if a more recent version of the profile
   were used (one that prohibits a code point appearing in both X and
   Y).

> If people still believe that forbidding unassigned codepoints is
> wrong, I'll withdraw my objection.

I didn't follow this.  Was the logic reversed here?  s/wrong/right/?
I and (I believe) Kurt has suggested that unassigned code points
should be forbidden, and you are suggesting to permit them, when
taking a string from an external database.

> by a future server upgrade.

You could also explain it as two possible attitudes toward StringPrep.
Either follow its spirit closely, and never compare strings with
unassigned code points, or realize it may be useful to violate the
StringPrep spirit.

Perhaps some input from people more familiar with StringPrep would be
useful, to see if anyone is bothered by breaking this rule.  Or if
they see other potential pitfalls in doing so.

Concluding, I don't have any objections to either solution, if it is
clear from the document which is used.

Thanks,
Simon

---

From: Sam Hartman <[email-masked]>
Date: Sun, 16 Jan 2005 14:48:08 -0500

Simon> Sam Hartman <[email-masked]> writes:
    >> If people still believe that forbidding unassigned codepoints
    >> is wrong, I'll withdraw my objection.

    Simon> I didn't follow this.  Was the logic reversed here?
    Simon> s/wrong/right/?  I and (I believe) Kurt has suggested that

You are correct, s/wrong/right.

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Sun, 16 Jan 2005 15:57:54 -0800

Sam,

Since SASLprep is a profile of the Stringprep algorithm, it
simply does not provide the option you desire....  to allow
both strings to contain unassigned code points.  So, instead
of SASLprep, you recommend we use some other algorithm which
allows both strings to contain unassigned code points.
This algorithm would not be a profile of Stringprep.

I do not support this for a number of reasons.

First, I think it important to leverage Stringprep and
SASLprep in PLAIN.

Second, I think Stringprep has it right from an interoperability
standpoint.  Both strings should not contain unassigned code points.

Lastly, operationally, I think it better to fail authentication
for stored passwords which contain unassigned code points and,
in doing so, forcing stored password to consist only of
assigned code points.  I would suspect, even if you were to
allow them in PLAIN, use of such passwords in other systems
would be quite problematic.

So, in short, I think PLAIN (and SASLprep (and Stringprep))
should not be changed in this regard.

Kurt (with Editor and Chair hats off)

---

From: Sam Hartman <[email-masked]>
Date: Mon, 17 Jan 2005 11:09:40 -0500

>>>>> "Kurt" == Kurt D Zeilenga <[email-masked]> writes:

    Kurt> Sam, Since SASLprep is a profile of the Stringprep
    Kurt> algorithm, it simply does not provide the option you
    Kurt> desire....  to allow both strings to contain unassigned code
    Kurt> points.  So, instead of SASLprep, you recommend we use some
    Kurt> other algorithm which allows both strings to contain
    Kurt> unassigned code points.  

I don't believe that is true.  Stringprep defines a preparation step,
not a comparison step.  I believe the text in section 7 of stringprep
is liberal enough to allow what I am talking about, although it is not
liberal enough to allow for an IETF protocol that would ever get into
the situation I'm discussing.

In particular, I believe it is consistent with the definition of query
string presented in section 7 to argue that a string pulled out of a
database is a query string.  If stringprep is used when that string is
stored in the database, it needs to be a storage string.  However
under the case we are discussing that storage operation is not under
the control of an IETf protocol.

I cannot find normative text forbidding a query string being compared
with another query string.  I can find explanatory text in section 7
motivating the normative guidelines in this section.  That text says
section 7 is designed to prevent the comparison of two strings that
both contain unassigned codepoints.  These guidelines are in fact
sufficient to achieve that goal when both strings are transported
through IETF protocols that use stringprep.  I don't think the
guidelines are sufficient (nor should they be) to prevent comparison
of two query strings in other situations.

    Kurt> oThis algorithm would 
not be a
    Kurt> profile of Stringprep.

Disagree because I'm talking about using stringprep.
I do agree with your reasons for requiring a stringprep algorithm, but do not think they apply to my argument.

    Kurt> Lastly, operationally, I think it better to fail
    Kurt> authentication for stored passwords which contain unassigned
    Kurt> code points and, in doing so, forcing stored password to
    Kurt> consist only of assigned code points.  I would suspect, even
    Kurt> if you were to allow them in PLAIN, use of such passwords in
    Kurt> other systems would be quite problematic.

First, keep in mind that these passwords are allowed in plain; we no
longer require any particular normalization.

My assumption is that people using these sorts of passwords will
continue using these passwords because they already have
infrastructure that works that way.  Examples of such infrastructure
include Windows Active Directory, PAM on Unix, and a variety of
SQL-backed password stores.

I assume that if plain doesn't support these passwords it will be a
problem for applications that use plain, and those applications rather
than the password store will be blamed.  If it actually turns out that
forbidding unassigned codepoints when saslprep is used with plain will
significantly reduce their use, then they should be forbidden.

--Sam

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Mon, 17 Jan 2005 08:49:04 -0800

At 08:09 AM 1/17/2005, Sam Hartman wrote:
>I do agree with your reasons for requiring a stringprep algorithm,

We don't actually require a stringprep algorithm, we recommend
one (SASLprep).

>but do not think they apply to my argument.
>

Actually, we don't require use of SASLprep... and hence its
normalization step... and, hence, its prohibit step.
   The server SHOULD prepare each of these strings using the
   [SASLPrep] profile of the [StringPrep] algorithm.

(I argue that without these steps, its no longer SASLprep.)

>infrastructure that works that way.

We already give them an escape in the above "SHOULD".  That is,
the language:
   When preparing using [SASLprep] or other [StringPrep] based
   algorithm, per Section 7 of [StringPrep], unassigned code points
   may appear in prepared presented (query) strings but are prohibited
   in prepared stored strings.  If only the output of a non-invertible
   function of expected string is stored, the string MUST be prepared
   before input to that function.

only applies to use of [SASLprep] and other [StringPrep] based
algorithms.  If an implementation chooses (after appropriately
considering the implications of doing so), to use some other
preparation algorithm, even one which is like SASLprep in
every regard except prohibition, fine.  But its not proper to
call that algorithm "SASLprep".  In SASLprep, the mandatory
prohibition step includes unassigned code point restrictions.

I argue that any algorithm which allows both strings compared
to contain unassigned code points is not a valid profile of
the StringPrep algorithm.  We can argue about the language
of RFC 3454 if you like, but I strongly believe that the
intent of RFC 3454 was to prohibit comparisons of two
strings both containing unassigned code points (from both
my talks with authors, and my lurking on the IDN list during
its development) .  If that not clear in RFC 3454, then the
IETF should address that in a revision of RFC 3454. 

But given the above SHOULD, isn't this argument moot?
Haven't we already given the implementor plenty of rope to
do whatever they please?

-- Kurt

---

From: Sam Hartman <[email-masked]>
Date: Mon, 17 Jan 2005 12:13:48 -0500

>>>>> "Kurt" == Kurt D Zeilenga <[email-masked]> writes:

    Kurt> I argue that any algorithm which allows both strings
    Kurt> compared to contain unassigned code points is not a valid
    Kurt> profile of the StringPrep algorithm.  

Again, stringprep does not address comparison, only preparation.

    Kurt> We can argue about the
    Kurt> language of RFC 3454 if you like, but I strongly believe
    Kurt> that the intent of RFC 3454 was to prohibit comparisons of
    Kurt> two strings both containing unassigned code points (from
    Kurt> both my talks with authors, and my lurking on the IDN list
    Kurt> during its development) .  

Agreed, but I also think the authors only considered the scope where
the IETF had control of either both strings or at least the storage
string.

If for example we were discussing the LDAP set password operation I'd
completely agree the password needs to be treated as a storage string.

    Kurt> If that not clear in RFC 3454,
    Kurt> then the IETF should address that in a revision of RFC 3454.

    Kurt> But given the above SHOULD, isn't this argument moot?

The question in my mind is whether we describe the problem clearly
enough that implementers will make the right decision for their
environment.  I agree that our normative text is fine.

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Mon, 17 Jan 2005 09:31:36 -0800

>environment.  I agree that our normative text is fine. 

I think we're quite clear that SASLprep SHOULD be used.  Now,
we've allowed implementors to use other preparation algorithms,
but the risk (to interoperability, security, etc.) of doing so
is all theirs.  As with going against any SHOULD, the implementor
should carefully consider the consequences of doing so.  Obviously
we cannot prevent implementors from not carefully considering the
consequences... but we should assume in our writing that they will
carefully consider the consequences.  And with that assumption, I
don't see how they could miss Section 7 of RFC 3454.

Kurt

---

From: Sam Hartman <[email-masked]>
Date: Mon, 17 Jan 2005 12:49:43 -0500

Kurt> At 09:13 AM 1/17/2005, Sam Hartman wrote:
    >> The question in my mind is whether we describe the problem
    >> clearly enough that implementers will make the right decision
    >> for their environment.  I agree that our normative text is
    >> fine.

    Kurt> I think we're quite clear that SASLprep SHOULD be used.
    Kurt> Now, we've allowed implementors to use other preparation
    Kurt> algorithms, but the risk (to interoperability, security,
    Kurt> etc.) of doing so is all theirs.  As with going against any
    Kurt> SHOULD, the implementor should carefully consider the
    Kurt> consequences of doing so.  Obviously we cannot prevent
    Kurt> implementors from not carefully considering the
    Kurt> consequences... but we should assume in our writing that
    Kurt> they will carefully consider the consequences.  And with
    Kurt> that assumption, I don't see how they could miss Section 7
    Kurt> of RFC 3454.

For the purposes of moving forward on plain, I'll drop this
discussion.

In the interests of understanding, I think I'd like to discuss this
issue with you in person because there seems to be a fairly
significant disconnect here.  However I don't think there is support
in the WG for making any changes in this regard.

If my understanding is correct, you accepted some textual changes from
Simon.  So, I should be waiting for a new plain before last calling
it?

--Sam

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Mon, 17 Jan 2005 10:21:43 -0800

>Simon.  So, I should be waiting for a new plain before last calling

As Editor, I believe the WG supports making some textual changes
based upon Simon's suggestions.  Hence, I intend to prepare
(and submit) a revised I-D for further WG consideration.  Please
hold off any AD action for now.

Kurt

---

From: Simon Josefsson <[email-masked]>
Date: Mon, 17 Jan 2005 21:29:10 +0100

> should not be changed in this regard.

I believe it should change to clarify what is intended.  The current
text:

  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 think this leave the field open to implement either your or Sam's
approach, both which seem reasonable choices to me.

The problem is the circular use of the terms "query strings" and
"stored strings".  If you consider strings pulled from a databases as
"stored", then you implement it your way, if you consider strings
pulled from a database as query strings ("queries" into the PLAIN
authorization algorithm), you will implement Sam's way.  Neither
implementation would appear to violate the above text.

To repeat what I have been trying to say all along: all specifications
must say, for each string that is going to be prepared, whether is to
be regarded a query string or a stored string.  Classifying strings
into stored strings and query strings is not a mechanic process.

Thanks,
Simon

---

From: Jeffrey Altman <[email-masked]>
Date: Mon, 17 Jan 2005 17:28:58 -0500

> implementation would appear to violate the above text.

I realize I have not been paying as much attention to this discussion
as I should be.  I apologize for the delay.

When Jeff Hutzelman and I were analyzing the Kerberos protocol to 
determine which category each string falls into, we realized that in a 
protocol such as Kerberos there are no storage strings.  We have query 
strings and display strings.  The only place a storage string exists is
in the set/change password protocol which is not part of the core
specification.

The only time a string is a "storage string" is when a string is being
written to a database.  If you are going to consider things which are
read from databases as "storage strings', then almost every string in
the protocol becomes a "storage string" and you get yourself into a lot
of trouble.  This is because a "Kerberos ticket", an "X.509 cert", a
"Kerberos keytab", etc. are all databases.  Some are used by the client
as a source of strings sent to the server; or vice versa.

A "query string" is a string which is being generated for the purpose
of comparison and not for the purpose of storage.  In fact, you can
even have two "query strings" from different sources compared with one
another.  As long as the strings are not being stored, they are not
"storage strings".

Jeffrey Altman

---

From: Jeffrey Hutzelman <[email-masked]>
Date: Mon, 17 Jan 2005 17:22:44 -0500

On Monday, January 17, 2005 11:09:40 -0500 Sam Hartman 
<[email-masked]> wrote:

> stored in the database, it needs to be a storage string.

I agree with this interpretation.  As I understand it, the theory is that 
you want to prevent the storage into the database of a string containing a 
code point which is unassigned at the time of storage, but which in a later 
version of the profile will map to something other than itself (some other 
codepoint, or multiple code points, or the empty string) or be prohibited 
entirely.

By prohibiting unassigned code points at the time of storage, you protect 
against this problem by guaranteeing that the only mapping applied to any 
code points in the stored string is the one you know about.  And, by 
applying normalization at the same time, you guarantee that no further 
normalization will apply to the stored string, and so even if the later 
comparison is done against a string prepared against an older version of 
the profile, you know that a positive match is definitive because the older 
profile will have identity-mapped any unknown codepoints, which means they 
will match the stored string only if they map to themselves under the newer 
profile used at storage time.  (stringprep profiles are required to have 
the property that applying the transformation multiple times yields the 
same result; achieving this property is possible only if output contains 
only code points which map to themselves).

However, if you start with two unnormalized strings, normalize both of 
them, and then compare the results, you can guarantee that normalization of 
both strings was done with the same version of the profile.  In this case, 
sequences of code points which are unassigned in that version of the 
profile will match only if they are identical in both strings, since again, 
such code points are mapped to themselves.  It is true that it is possible 
to authenticate against a stored password containing a code point which 
will be prohibited in a future version of the profile; however, since we do 
not control the storage process it is beyond our power to prevent such 
passwords from being stored.

Only strings that you are going to store into a database for future use are 
storage strings.  Strings retrieved from a database are not storage 
strings, unless you are then going to store them into some other database 
(or the same one, I suppose).

In any case, it turns out that in SASL PLAIN, and in SSH password, the 
process of password comparison is out of our control.  In virtually all 
cases, the server implementation will perform whatever transformation is 
required by the backend (possibly SASLprep, possibly a noop, possibly 
conversion into some non-Unicode character set), then pass the result to 
some mechanism which does the comparison according to its own rules.  I 
think we should limit ourselves to describing what must happen on the wire 
(no normalization), and recommending behaviour for cases where the 
implementor gets to decide how passwords are handled (use SASLprep, 
prohibit unassigned codepoints when passwords are stored).

-- Jeff

---

From: Simon Josefsson <[email-masked]>
Date: Mon, 17 Jan 2005 23:52:10 +0100

Jeffrey Altman <[email-masked]> writes:

> written to a database.

Or a digitally signed structure.

I agree with your general points, however, one small comment:

> If you are going to consider things which are read from databases as
> "storage strings', then almost every string in the protocol becomes
> a "storage string" and you get yourself into a lot of trouble.  This
> is because a "Kerberos ticket", an "X.509 cert", a "Kerberos
> keytab", etc. are all databases.  Some are used by the client as a
> source of strings sent to the server; or vice versa.

I'm not sure it is a good idea to put strings with unassigned code
points inside the authenticated parts of a Kerberos ticket.  On the
other hand, I thought Kerberos principal names were restricted to
ASCII currently, so this shouldn't be a problem yet.

There is some normative text in StringPrep about this:

   Due to the way that versioning is handled in this section, stored
   strings that are embedded in structures that cannot be changed (such
   as the signed parts of digital certificates) MUST NOT contain any
   unassigned code points.

But again the use of the terminology make things confusing.  What if
you are putting a query string into a structure that cannot be
changed?  Should that be OK?

I think the StringPrep terminology was not well chosen; at least it
doesn't contribute to clarity or lean itself to simple decisions for
how to classify strings.

Perhaps it would help to avoid thinking about query vs stored.
Instead, one could focus on when unassigned code points would be
harmless vs harmful.

Thanks,
Simon

---

From: Sam Hartman <[email-masked]>
Date: Mon, 17 Jan 2005 19:01:41 -0500

>>>>> "Simon" == Simon Josefsson <[email-masked]> writes:

    Simon> I agree with your general points, however, one small
    Simon> comment:

    >> If you are going to consider things which are read from
    >> databases as "storage strings', then almost every string in the
    >> protocol becomes a "storage string" and you get yourself into a
    >> lot of trouble.  This is because a "Kerberos ticket", an "X.509
    >> cert", a "Kerberos keytab", etc. are all databases.  Some are
    >> used by the client as a source of strings sent to the server;
    >> or vice versa.

    Simon> I'm not sure it is a good idea to put strings with
    Simon> unassigned code points inside the authenticated parts of a
    Simon> Kerberos ticket.  On the other hand, I thought Kerberos
    Simon> principal names were restricted to ASCII currently, so this
    Simon> shouldn't be a problem yet.

This really belongs on another list.  However for names in the
encrypted part of a ticket, these names should be storage strings of
the administration protocol used to create the account.  At that point
you do the unassigned codepoint check.

--Sam

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Mon, 17 Jan 2005 19:15:25 -0800

At 02:28 PM 1/17/2005, Jeffrey Altman wrote:
>When Jeff Hutzelman and I were analyzing the Kerberos protocol to determine which category each string falls into,

If by category, you mean "storage" and "query", that's a mistake in
my opinion.  You should determine which of the two strings involved
in the comparison should be allowed to contain unassigned code
points.  That is, don't get wrapped about the terms "storage"
and "query".  They might as well have been called Foo and Bar
strings.  What's important is not both strings involved in the
comparison not be allowed to contain unassigned code points.

>In fact, you can
>another. 

Then maybe it makes sense to disallow unassigned code points in
both.

Kurt

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Mon, 17 Jan 2005 19:23:52 -0800

At 02:22 PM 1/17/2005, Jeffrey Hutzelman wrote:
>I think we should limit ourselves to describing what must happen on the wire (no normalization), and recommending behaviour for cases where the implementor gets to decide how passwords are handled (use SASLprep, prohibit unassigned codepoints when passwords are stored). 

So, you appear to concur with the proposed (see archives, ~
9-Dec-04) "SHOULD use SASLprep" behavior.   As I noted to Sam,
I intend to update the I-D to this end soon.

Kurt

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Mon, 17 Jan 2005 19:29:11 -0800

>Instead, one could focus on when unassigned code points would be

Precisely.  In PLAIN, when SASLprep is used, the presented
strings may contain unassigned code points and the (stored)
strings they are compared against cannot.

If SASLprep is not being used, the implementor should still
avoid allowing unassigned code points from appearing in both
strings involved in a comparison... possibly by disallowing
unassigned code points in the presented string.

Kurt

---

From: Simon Josefsson <[email-masked]>
Date: Tue, 18 Jan 2005 09:07:49 +0100

> you do the unassigned codepoint check.

It seems the situation is similar to the SASL PLAIN situation.

The strings in the database might not have been processed by SASLprep.
That's partly because there is no standardized admin protocol that
suggest SASLprep.  So whether the database contain prepared or
unprepared strings is an implementation choice.

Unless a specific database model is assumed by SASL PLAIN or Kerberos,
those specifications has to discuss how strings pulled out of the
database should be prepared, if at all.  For SASL PLAIN I think either
choice (i.e., permit or forbid unassigned code points) are reasonable,
but for Kerberos, where the string may eventually end up in an
authenticated structure, I'm not as sure.

Regards,
Simon

---

From: Sam Hartman <[email-masked]>
Date: Sun, 16 Jan 2005 13:38:24 -0500

--Sam

---

From: Simon Josefsson <[email-masked]>
Date: Sun, 16 Jan 2005 20:39:00 +0100

Thanks,
Simon

---

From: Sam Hartman <[email-masked]>
Date: Sun, 16 Jan 2005 14:48:08 -0500

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Sun, 16 Jan 2005 15:57:54 -0800

Sam,

---

From: Sam Hartman <[email-masked]>
Date: Mon, 17 Jan 2005 11:09:40 -0500

--Sam

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Mon, 17 Jan 2005 08:49:04 -0800

-- Kurt

---

From: Sam Hartman <[email-masked]>
Date: Mon, 17 Jan 2005 12:13:48 -0500

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Mon, 17 Jan 2005 09:31:36 -0800

Kurt

---

From: Sam Hartman <[email-masked]>
Date: Mon, 17 Jan 2005 12:49:43 -0500

--Sam

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Mon, 17 Jan 2005 10:21:43 -0800

Kurt

---

From: Simon Josefsson <[email-masked]>
Date: Mon, 17 Jan 2005 21:29:10 +0100

Thanks,
Simon

---

From: Jeffrey Altman <[email-masked]>
Date: Mon, 17 Jan 2005 17:28:58 -0500

Jeffrey Altman

---

From: Jeffrey Hutzelman <[email-masked]>
Date: Mon, 17 Jan 2005 17:22:44 -0500

-- Jeff

---

From: Simon Josefsson <[email-masked]>
Date: Mon, 17 Jan 2005 23:52:10 +0100

Thanks,
Simon

---

From: Sam Hartman <[email-masked]>
Date: Mon, 17 Jan 2005 19:01:41 -0500

--Sam

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Mon, 17 Jan 2005 19:15:25 -0800

Kurt

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Mon, 17 Jan 2005 19:23:52 -0800

Kurt

---

From: "Kurt D. Zeilenga" <[email-masked]>
Date: Mon, 17 Jan 2005 19:29:11 -0800

Kurt

---

From: Simon Josefsson <[email-masked]>
Date: Tue, 18 Jan 2005 09:07:49 +0100

Regards,
Simon