On 12/08/2016 10:18 AM, Michael Paquier wrote:
On Thu, Dec 8, 2016 at 5:54 AM, Heikki Linnakangas <hlinn...@iki.fi> wrote:
Attached those here, as add-on patches to your latest patch set.

Thanks for looking at it!

I'll continue reviewing, but a couple of things caught my eye that you may want
to jump on, in the meanwhile:

On error messages, the spec says:

o  e: This attribute specifies an error that occurred during
      authentication exchange.  It is sent by the server in its final
      message and can help diagnose the reason for the authentication
      exchange failure.  On failed authentication, the entire server-
      final-message is OPTIONAL; specifically, a server implementation
      MAY conclude the SASL exchange with a failure without sending the
      server-final-message.  This results in an application-level error
      response without an extra round-trip.  If the server-final-message
      is sent on authentication failure, then the "e" attribute MUST be
      included.


Note that it says that the server can send the error message with the e=
attribute, in the *final message*. It's not a valid response in the earlier
state, before sending server-first-message. I think we need to change the
INIT state handling in pg_be_scram_exchange() to not send e= messages to the
client. On an error at that state, it needs to just bail out without a
message. The spec allows that. We can always log the detailed reason in the
server log, anyway.

Hmmm. How do we handle the case where the user name does not match
then? The spec gives an error message e= specifically for this case.

Hmm, interesting. I wonder how/when they imagine that error message to be used. I suppose you could send a dummy server-first message, with a made-up salt and iteration count, if the user is not found, so that you can report that in the server-final message. But that seems unnecessarily complicated, compared to just sending the error immediately. I could imagine using a dummy server-first messaage to hide whether the user exists, but that argument doesn't hold water if you're going to report an "unknown-user" error, anyway.

Actually, we don't give away that information currently. If you try to log in with password or MD5 authentication, and the user doesn't exist, you get the same error as with an incorrect password. So, I think we do need to give the client a made-up salt and iteration count in that case, to hide the fact that the user doesn't exist. Furthermore, you can't just generate random salt and iteration count, because then you could simply try connecting twice, and see if you get the same salt and iteration count. We need to deterministically derive the salt from the username, so that you get the same salt/iteration count every time you try connecting with that username. But it needs indistinguishable from a random salt, to the client. Perhaps a SHA hash of the username and some per-cluster secret value, created by initdb. There must be research papers out there on how to do this..

To be really pedantic about that, we should also ward off timing attacks, by making sure that the dummy authentication is no faster/slower than a real one..

If this is taken into account we need to perform sanity checks at
initialization phase I am afraid as the number of iterations and the
salt are part of the verifier. So you mean that just sending out a
normal ERROR message is fine at an earlier step (with *logdetails
filled for the backend)? I just want to be sure I understand what you
mean here.

That's right, we can send a normal ERROR message. (But not for the "user-not-found" case, as discussed above.)

As Peter E pointed out earlier, the documentation is lacking, on how to
configure MD5 and/or SCRAM. If you put "scram" as the authentication method
in pg_hba.conf, what does it mean? If you have a line for both "scram" and
"md5" in pg_hba.conf, with the same database/user/hostname combo, what does
that mean? Answer: The first one takes effect, the second one has no effect.
Yet the example in the docs now has that, which is nonsense :-). Hopefully
we'll have some kind of a "both" option, before the release, but in the
meanwhile, we need describe how this works now in the docs.

OK, it would be better to add a paragraph in client-auth.sgml
regarding the mapping of the two settings. For the example of file in
postgresql.conf, I would have really thought that adding directly a
line with "scram" listed was enough though. Perhaps a comment to say
that if md5 and scram are specified the first one wins where a user
and database name map?

So, I think this makes no sense:

 # Allow any user from host 192.168.12.10 to connect to database
-# "postgres" if the user's password is correctly supplied.
+# "postgres" if the user's password is correctly supplied and is
+# using the correct password method.
 #
 # TYPE  DATABASE        USER            ADDRESS                 METHOD
 host    postgres        all             192.168.12.10/32        md5
+host    postgres        all             192.168.12.10/32        scram

But this is OK:

+# Same as previous entry, except that the supplied password must be
+# encrypted with SCRAM-SHA-256.
+host    all             all             .example.com            scram
+

Although, currently, the whole pg_hba.conf file in that example is a valid file that someone might have on a real server. With the above addition, it would not be. You would never have the two lines with the same host/database/user combination in pg_hba.conf.

Overall, I think something like this would make sense in the example:

# Allow any user from hosts in the example.com domain to connect to
# any database, if the user's password is correctly supplied.
#
# Most users use SCRAM authentication, but some users use older clients
# that don't support SCRAM authentication, and need to be able to log
# in using MD5 authentication. Such users are put in the @md5users
# group, everyone else must use SCRAM.
#
# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    all             @md5users       .example.com            md5
host    all             all             .example.com            scram

- Heikki



--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to