Thread: [HACKERS] scram and \password

[HACKERS] scram and \password

From
Jeff Janes
Date:
Should the \password tool in psql inspect password_encryption and act on it being 'scram'?

I didn't see this issue discussed, but the ability to search the archives for backslashes is rather limited.

Cheers,

Jeff

Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Sat, Mar 11, 2017 at 2:53 AM, Jeff Janes <jeff.janes@gmail.com> wrote:
> Should the \password tool in psql inspect password_encryption and act on it
> being 'scram'?

Not sure if it is wise to change the default fot this release.

> I didn't see this issue discussed, but the ability to search the archives
> for backslashes is rather limited.

I'll save you some time: it has not been discussed. Nor has
PQencryptPassword been mentioned. Changing to SCRAM is not that
complicated, just call scram_build_verifier() and you are good to go.

Instead of changing the default, I think that we should take this
occasion to rename PQencryptPassword to something like
PQhashPassword(), and extend it with a method argument to support both
md5 and scram. PQencryptPassword could also be marked as deprecated,
or let as-is for some time. For \password, we could have another
meta-command but that sounds grotty, or just extend \password with a
--method argument. Switching the default could happen in another
release.

A patch among those lines would be a simple, do people feel that this
should be part of PG 10?
-- 
Michael



Re: [HACKERS] scram and \password

From
Joe Conway
Date:
On 03/10/2017 02:43 PM, Michael Paquier wrote:
> On Sat, Mar 11, 2017 at 2:53 AM, Jeff Janes <jeff.janes@gmail.com> wrote:
>> Should the \password tool in psql inspect password_encryption and act on it
>> being 'scram'?
>
> Not sure if it is wise to change the default fot this release.
>
>> I didn't see this issue discussed, but the ability to search the archives
>> for backslashes is rather limited.
>
> I'll save you some time: it has not been discussed. Nor has
> PQencryptPassword been mentioned. Changing to SCRAM is not that
> complicated, just call scram_build_verifier() and you are good to go.
>
> Instead of changing the default, I think that we should take this
> occasion to rename PQencryptPassword to something like
> PQhashPassword(), and extend it with a method argument to support both
> md5 and scram. PQencryptPassword could also be marked as deprecated,
> or let as-is for some time. For \password, we could have another
> meta-command but that sounds grotty, or just extend \password with a
> --method argument. Switching the default could happen in another
> release.
>
> A patch among those lines would be a simple, do people feel that this
> should be part of PG 10?

Seems like it should work in an analogous way to CREATE/ALTER ROLE.
According to the docs:

8<----
ENCRYPTED
UNENCRYPTED
   These key words control whether the password is stored encrypted in
the system catalogs. (If neither is specified, the default behavior is
determined by the configuration parameter password_encryption.) If the
presented password string is already in MD5-encrypted or SCRAM-encrypted
format, then it is stored encrypted as-is, regardless of whether
ENCRYPTED or UNENCRYPTED is specified (since the system cannot decrypt
the specified encrypted password string). This allows reloading of
encrypted passwords during dump/restore.
8<----

So if the password is not already set, \password uses
password_encryption to determine which format to use, and if the
password is already set, then the current method is assumed.

Joe

--
Crunchy Data - http://crunchydata.com
PostgreSQL Support for Secure Enterprises
Consulting, Training, & Open Source Development


Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Sun, Mar 12, 2017 at 5:35 AM, Joe Conway <mail@joeconway.com> wrote:
> On 03/10/2017 02:43 PM, Michael Paquier wrote:
>> Instead of changing the default, I think that we should take this
>> occasion to rename PQencryptPassword to something like
>> PQhashPassword(), and extend it with a method argument to support both
>> md5 and scram. PQencryptPassword could also be marked as deprecated,
>> or let as-is for some time. For \password, we could have another
>> meta-command but that sounds grotty, or just extend \password with a
>> --method argument. Switching the default could happen in another
>> release.
>>
>> A patch among those lines would be a simple, do people feel that this
>> should be part of PG 10?
>
> Seems like it should work in an analogous way to CREATE/ALTER ROLE.
> According to the docs:
>
> 8<----
> ENCRYPTED
> UNENCRYPTED
>
>     These key words control whether the password is stored encrypted in
> the system catalogs. (If neither is specified, the default behavior is
> determined by the configuration parameter password_encryption.) If the
> presented password string is already in MD5-encrypted or SCRAM-encrypted
> format, then it is stored encrypted as-is, regardless of whether
> ENCRYPTED or UNENCRYPTED is specified (since the system cannot decrypt
> the specified encrypted password string). This allows reloading of
> encrypted passwords during dump/restore.
> 8<----
>
> So if the password is not already set, \password uses
> password_encryption to determine which format to use, and if the
> password is already set, then the current method is assumed.

Yeah, the problem here being that this routine does not need a live
connection to work, and we surely don't want to make that mandatory,
that's why I am suggesting something like the above. Another approach
would be to switch to SCRAM once password_encryption does this switch
as well... There is no perfect scenario here.
-- 
Michael



Re: [HACKERS] scram and \password

From
Joe Conway
Date:
On 03/11/2017 02:21 PM, Michael Paquier wrote:
> On Sun, Mar 12, 2017 at 5:35 AM, Joe Conway <mail@joeconway.com> wrote:
>> So if the password is not already set, \password uses
>> password_encryption to determine which format to use, and if the
>> password is already set, then the current method is assumed.
>
> Yeah, the problem here being that this routine does not need a live
> connection to work, and we surely don't want to make that mandatory,
> that's why I am suggesting something like the above. Another approach
> would be to switch to SCRAM once password_encryption does this switch
> as well... There is no perfect scenario here.

You might extend PQencryptPassword() to take a method. Or create a new
function that does? Certainly psql has a connection available to run the
ALTER ROLE command that it crafts.

I guess a related problem might be, do we have a SQL visible way to
determine what method is used by the current password for a given role?

Joe

--
Crunchy Data - http://crunchydata.com
PostgreSQL Support for Secure Enterprises
Consulting, Training, & Open Source Development


Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Sun, Mar 12, 2017 at 8:04 AM, Joe Conway <mail@joeconway.com> wrote:
> On 03/11/2017 02:21 PM, Michael Paquier wrote:
>> On Sun, Mar 12, 2017 at 5:35 AM, Joe Conway <mail@joeconway.com> wrote:
>>> So if the password is not already set, \password uses
>>> password_encryption to determine which format to use, and if the
>>> password is already set, then the current method is assumed.
>>
>> Yeah, the problem here being that this routine does not need a live
>> connection to work, and we surely don't want to make that mandatory,
>> that's why I am suggesting something like the above. Another approach
>> would be to switch to SCRAM once password_encryption does this switch
>> as well... There is no perfect scenario here.
>
> You might extend PQencryptPassword() to take a method. Or create a new
> function that does? Certainly psql has a connection available to run the
> ALTER ROLE command that it crafts.

Yeah but it can be called as well while the application is calling
PQgetResult() and still looping until it gets a NULL result. Not sure
if this is a use-case to worry about, but sending a query to the
server in PQencryptPassword() could as well break some applications.

PQencryptPassword() is used for CREATE/ALTER ROLE commands, so
actually wouldn't it make sense to just switch PQencryptPassword to
handle SCRAM if at some point we decide to switch the default from md5
to scram? So many questions.

> I guess a related problem might be, do we have a SQL visible way to
> determine what method is used by the current password for a given role?

Nope. We are simply looking at a function doing a lookup at pg_authid
and then use get_password_type() to check which type of verifier is
used... Or have the type of verifier as a new column of pg_authid,
information that could be made visible to any users with column
privileges.
-- 
Michael



Re: [HACKERS] scram and \password

From
Joe Conway
Date:
On 03/11/2017 03:15 PM, Michael Paquier wrote:
> Yeah but it can be called as well while the application is calling
> PQgetResult() and still looping until it gets a NULL result. Not sure
> if this is a use-case to worry about, but sending a query to the
> server in PQencryptPassword() could as well break some applications.

I was suggesting sending the query outside of PQencryptPassword() in
order to determine what method should be passed as a new argument to
PQencryptPassword().

> PQencryptPassword() is used for CREATE/ALTER ROLE commands, so
> actually wouldn't it make sense to just switch PQencryptPassword to
> handle SCRAM if at some point we decide to switch the default from md5
> to scram? So many questions.

As long as we support more than one method it would seem to me we need a
way to determine which one we want to use and not only default it, don't
we? Apologies if this has already been discussed -- I was not able to
follow the lengthy threads on SCRAM in any detail.

>> I guess a related problem might be, do we have a SQL visible way to
>> determine what method is used by the current password for a given role?
>
> Nope. We are simply looking at a function doing a lookup at pg_authid
> and then use get_password_type() to check which type of verifier is
> used... Or have the type of verifier as a new column of pg_authid,
> information that could be made visible to any users with column
> privileges.

What happens if the user does not have privs for pg_authid? E.g. if I
want to change my own password what happens if the default is one
method, and my password uses the other -- now I cannot change my own
password using \password?

Joe

--
Crunchy Data - http://crunchydata.com
PostgreSQL Support for Secure Enterprises
Consulting, Training, & Open Source Development


Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Sun, Mar 12, 2017 at 9:10 AM, Joe Conway <mail@joeconway.com> wrote:
> On 03/11/2017 03:15 PM, Michael Paquier wrote:
>> Yeah but it can be called as well while the application is calling
>> PQgetResult() and still looping until it gets a NULL result. Not sure
>> if this is a use-case to worry about, but sending a query to the
>> server in PQencryptPassword() could as well break some applications.
>
> I was suggesting sending the query outside of PQencryptPassword() in
> order to determine what method should be passed as a new argument to
> PQencryptPassword().

Why not. Our thoughts don't overlap, I thought about having
PQencryptPassword() call itself the server for the value of
password_encryption, and force the type depending on what the server
answers.

>> PQencryptPassword() is used for CREATE/ALTER ROLE commands, so
>> actually wouldn't it make sense to just switch PQencryptPassword to
>> handle SCRAM if at some point we decide to switch the default from md5
>> to scram? So many questions.
>
> As long as we support more than one method it would seem to me we need a
> way to determine which one we want to use and not only default it, don't
> we? Apologies if this has already been discussed -- I was not able to
> follow the lengthy threads on SCRAM in any detail.

Definitely, the most simple solution would be just to extend
PQencryptPassword() with a method value, to allow a user to do what he
wants...

>>> I guess a related problem might be, do we have a SQL visible way to
>>> determine what method is used by the current password for a given role?
>>
>> Nope. We are simply looking at a function doing a lookup at pg_authid
>> and then use get_password_type() to check which type of verifier is
>> used... Or have the type of verifier as a new column of pg_authid,
>> information that could be made visible to any users with column
>> privileges.
>
> What happens if the user does not have privs for pg_authid? E.g. if I
> want to change my own password what happens if the default is one
> method, and my password uses the other -- now I cannot change my own
> password using \password?

You can now. However it would be a problem for a user having a SCRAM
verifier using an application that changes the password with
PQencryptPassword() as it would change it back to MD5 on an update.
Having a RLS on pg_authid to allow a user to look at its own password
type is an idea. With multiple verifier types per role such class of
bugs can be also completely discarded.
-- 
Michael



Re: [HACKERS] scram and \password

From
Joe Conway
Date:
On 03/11/2017 11:07 PM, Michael Paquier wrote:
> Having a RLS on pg_authid to allow a user to look at its own password
> type is an idea.

Given that that is not likely at this stage of the dev cycle, what about
a special purpose SQL function that returns the password type for the
current user? Or is it a security issue of some sort to allow a user to
know their own password type?

Joe

--
Crunchy Data - http://crunchydata.com
PostgreSQL Support for Secure Enterprises
Consulting, Training, & Open Source Development


Re: [HACKERS] scram and \password

From
Robert Haas
Date:
On Fri, Mar 10, 2017 at 5:43 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:
> On Sat, Mar 11, 2017 at 2:53 AM, Jeff Janes <jeff.janes@gmail.com> wrote:
>> Should the \password tool in psql inspect password_encryption and act on it
>> being 'scram'?
>
> Not sure if it is wise to change the default fot this release.

Seems like an odd way to phrase it.  Aren't we talking about making a
feature that worked in previous releases continue to work?

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Mon, Mar 13, 2017 at 12:48 AM, Joe Conway <mail@joeconway.com> wrote:
> On 03/11/2017 11:07 PM, Michael Paquier wrote:
>> Having a RLS on pg_authid to allow a user to look at its own password
>> type is an idea.
>
> Given that that is not likely at this stage of the dev cycle, what about
> a special purpose SQL function that returns the password type for the
> current user?

OK, so what about doing the following then:
1) Create pg_role_password_type(oid), taking a role OID in input and
returning the type.
2) Extend PQencryptPassword with a method, and document. Plaintext is forbidden.
3) Extend \password in psql with a similar -method=scram|md5 argument,
and forbid the use of "plain" format.
After thinking about it, extending PQencryptPassword() would lead to
future breakage, which makes it clear to not fall into the trap of
having password_encryption set to scram in the server's as well as in
pg_hba.conf and PQencryptPassword() enforcing things to md5.

> Or is it a security issue of some sort to allow a user to
> know their own password type?

Don't think so. Any user has access to the value of
password_encryption. So one can guess what will be the format of a
password hashed.
-- 
Michael



Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Mon, Mar 13, 2017 at 9:15 AM, Robert Haas <robertmhaas@gmail.com> wrote:
> On Fri, Mar 10, 2017 at 5:43 PM, Michael Paquier
> <michael.paquier@gmail.com> wrote:
>> On Sat, Mar 11, 2017 at 2:53 AM, Jeff Janes <jeff.janes@gmail.com> wrote:
>>> Should the \password tool in psql inspect password_encryption and act on it
>>> being 'scram'?
>>
>> Not sure if it is wise to change the default fot this release.
>
> Seems like an odd way to phrase it.  Aren't we talking about making a
> feature that worked in previous releases continue to work?

Considering how fresh scram is, it seems clear to me that we do not
want to just switch the default values of password_encryption, the
default behaviors of PQencryptPassword() and \password only to scram,
but have something else. Actually if we change nothing for default
deployments of Postgres using md5, PQencryptPassword() and \password
would still work properly.
-- 
Michael



Re: [HACKERS] scram and \password

From
Jeff Janes
Date:
On Fri, Mar 10, 2017 at 2:43 PM, Michael Paquier <michael.paquier@gmail.com> wrote:
On Sat, Mar 11, 2017 at 2:53 AM, Jeff Janes <jeff.janes@gmail.com> wrote:
> Should the \password tool in psql inspect password_encryption and act on it
> being 'scram'?

Not sure if it is wise to change the default fot this release.

I'm not proposing that we change the default value of password_encryption, only that \password respect whatever value it currently finds there.  But after thinking about it a bit more, I reached the same conclusion that Joe did, that it should use the same hashing method as the current password does, and only consult password_encryption if there is no password currently set.


A patch among those lines would be a simple, do people feel that this
should be part of PG 10?
 
I think it is pretty important to have some way of setting the password that doesn't risk it ending up in the server log file, or .psql_history, or having someone shoulder-surf it.

Cheers,

Jeff

Re: [HACKERS] scram and \password

From
Joe Conway
Date:
On 03/12/2017 08:10 PM, Michael Paquier wrote:
> OK, so what about doing the following then:
> 1) Create pg_role_password_type(oid), taking a role OID in input and
> returning the type.

That version would make sense for administrative use. I still think we
might want a version of this that takes no argument, works on the
current_user, and is executable by anyone.

> 2) Extend PQencryptPassword with a method, and document. Plaintext is forbidden.

Check, although if "plain" were allowed as a method for the sake of
consistency/completeness the function could just immediately return the
argument.

> 3) Extend \password in psql with a similar -method=scram|md5 argument,
> and forbid the use of "plain" format.

Not sure why we would forbid "plain" here unless we remove it entirely
elsewhere.

> After thinking about it, extending PQencryptPassword() would lead to
> future breakage, which makes it clear to not fall into the trap of
> having password_encryption set to scram in the server's as well as in
> pg_hba.conf and PQencryptPassword() enforcing things to md5.

I'm not grokking this statement

Joe

--
Crunchy Data - http://crunchydata.com
PostgreSQL Support for Secure Enterprises
Consulting, Training, & Open Source Development


Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Tue, Mar 14, 2017 at 9:54 AM, Joe Conway <mail@joeconway.com> wrote:
> On 03/12/2017 08:10 PM, Michael Paquier wrote:
>> OK, so what about doing the following then:
>> 1) Create pg_role_password_type(oid), taking a role OID in input and
>> returning the type.
>
> That version would make sense for administrative use. I still think we
> might want a version of this that takes no argument, works on the
> current_user, and is executable by anyone.

Sure.

>> 2) Extend PQencryptPassword with a method, and document. Plaintext is forbidden.
>
> Check, although if "plain" were allowed as a method for the sake of
> consistency/completeness the function could just immediately return the
> argument.
>
>> 3) Extend \password in psql with a similar -method=scram|md5 argument,
>> and forbid the use of "plain" format.
>
> Not sure why we would forbid "plain" here unless we remove it entirely
> elsewhere.

OK. I don't mind about those two, as long as documentation is clear
enough about what using plain leads to.

>> After thinking about it, extending PQencryptPassword() would lead to
>> future breakage, which makes it clear to not fall into the trap of
>> having password_encryption set to scram in the server's as well as in
>> pg_hba.conf and PQencryptPassword() enforcing things to md5.
>
> I'm not grokking this statement

To grok: "To understand profoundly through intuition or empathy.".
Learning a new thing everyday.
-- 
Michael



Re: [HACKERS] scram and \password

From
Robert Haas
Date:
On Sun, Mar 12, 2017 at 11:14 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:
> On Mon, Mar 13, 2017 at 9:15 AM, Robert Haas <robertmhaas@gmail.com> wrote:
>> On Fri, Mar 10, 2017 at 5:43 PM, Michael Paquier
>> <michael.paquier@gmail.com> wrote:
>>> On Sat, Mar 11, 2017 at 2:53 AM, Jeff Janes <jeff.janes@gmail.com> wrote:
>>>> Should the \password tool in psql inspect password_encryption and act on it
>>>> being 'scram'?
>>>
>>> Not sure if it is wise to change the default fot this release.
>>
>> Seems like an odd way to phrase it.  Aren't we talking about making a
>> feature that worked in previous releases continue to work?
>
> Considering how fresh scram is, it seems clear to me that we do not
> want to just switch the default values of password_encryption, the
> default behaviors of PQencryptPassword() and \password only to scram,
> but have something else. Actually if we change nothing for default
> deployments of Postgres using md5, PQencryptPassword() and \password
> would still work properly.

I'm not talking about changing the default, just having it be possible
to use \password with the new system as it was with the old, whatever
exactly we think that means.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: [HACKERS] scram and \password

From
Tom Lane
Date:
Robert Haas <robertmhaas@gmail.com> writes:
> I'm not talking about changing the default, just having it be possible
> to use \password with the new system as it was with the old, whatever
> exactly we think that means.

Seems to me the intended behavior of \password is to use the best
available practice.  So my guess is that it ought to use SCRAM when
talking to a >= 10.0 server.  What the previous password was ought
to be irrelevant, even if it could find that out which it shouldn't
be able to IMO.
        regards, tom lane



Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Tue, Mar 14, 2017 at 11:47 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Robert Haas <robertmhaas@gmail.com> writes:
>> I'm not talking about changing the default, just having it be possible
>> to use \password with the new system as it was with the old, whatever
>> exactly we think that means.

I think that this means looking at password_encryption within
PQencryptPassword(), something that could silently break some
applications. That's why with Joe we are mentioning upthread to extend
PQencryptPassword() with a hashing method, and have a function to
allow retrieval of the password type for a given user.

> Seems to me the intended behavior of \password is to use the best
> available practice.  So my guess is that it ought to use SCRAM when
> talking to a >= 10.0 server.  What the previous password was ought
> to be irrelevant, even if it could find that out which it shouldn't
> be able to IMO.

And in a release or two? SCRAM being a fresh feature, switching the
hashing now is not much a conservative approach.
-- 
Michael



Re: [HACKERS] scram and \password

From
Tom Lane
Date:
Michael Paquier <michael.paquier@gmail.com> writes:
> On Tue, Mar 14, 2017 at 11:47 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> Seems to me the intended behavior of \password is to use the best
>> available practice.  So my guess is that it ought to use SCRAM when
>> talking to a >= 10.0 server.  What the previous password was ought
>> to be irrelevant, even if it could find that out which it shouldn't
>> be able to IMO.

> And in a release or two? SCRAM being a fresh feature, switching the
> hashing now is not much a conservative approach.

If some other practice becomes better in v12, then we teach it about that
one.  It's not like psql hasn't got many other server-version-dependent
behaviors.

Alternatively, if what you mean by that is you don't trust SCRAM at all,
maybe we'd better revert the feature as not being ready for prime time.
        regards, tom lane



Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Tue, Mar 14, 2017 at 12:34 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Michael Paquier <michael.paquier@gmail.com> writes:
> If some other practice becomes better in v12, then we teach it about that
> one.  It's not like psql hasn't got many other server-version-dependent
> behaviors.

Okay. Looking at the code, scram_build_verifier is only available on
the backend side, so if we need to rethink it a bit to be able to have
libpq build a SCRAM verifier:
- The allocation of the verifier buffer needs to happen outside it,
and the caller needs to provide an allocated buffer. Its size had
better be calculated a macro.
- The routine needs to be moved to scram-common.c.
- a copy of hex_encode, say pg_hex_encode added in its own file in
src/common/, needs to be provided. That's 6 lines of code, we could
just have that in scram-common.c.
Does that sound correct?

> Alternatively, if what you mean by that is you don't trust SCRAM at all,
> maybe we'd better revert the feature as not being ready for prime time.

FWIW, I am confident about the code. Based on years watching this
mailing list, switching long-term behaviors is usually done in a less
faster pace, that's the only reason on which my opinion is based.
-- 
Michael



Re: [HACKERS] scram and \password

From
Heikki Linnakangas
Date:
On 03/14/2017 04:47 AM, Tom Lane wrote:
> Robert Haas <robertmhaas@gmail.com> writes:
>> I'm not talking about changing the default, just having it be possible
>> to use \password with the new system as it was with the old, whatever
>> exactly we think that means.
>
> Seems to me the intended behavior of \password is to use the best
> available practice.  So my guess is that it ought to use SCRAM when
> talking to a >= 10.0 server.  What the previous password was ought
> to be irrelevant, even if it could find that out which it shouldn't
> be able to IMO.

If the server isn't set up to do SCRAM authentication, i.e. there are no 
"scram" entries in pg_hba.conf, and you set yourself a SCRAM verifier, 
you have just locked yourself out of the system. I think that's a 
non-starter. There needs to be some more intelligence in the decision.

It would be a lot more sensible, if there was a way to specify in 
pg_hba.conf, "scram-or-md5". We punted on that for PostgreSQL 10, but 
perhaps we should try to cram that in, after all.

- Heikki




Re: [HACKERS] scram and \password

From
Joe Conway
Date:
On 03/14/2017 03:15 AM, Heikki Linnakangas wrote:
> On 03/14/2017 04:47 AM, Tom Lane wrote:
>> Robert Haas <robertmhaas@gmail.com> writes:
>>> I'm not talking about changing the default, just having it be possible
>>> to use \password with the new system as it was with the old, whatever
>>> exactly we think that means.
>>
>> Seems to me the intended behavior of \password is to use the best
>> available practice.  So my guess is that it ought to use SCRAM when
>> talking to a >= 10.0 server.  What the previous password was ought
>> to be irrelevant, even if it could find that out which it shouldn't
>> be able to IMO.
>
> If the server isn't set up to do SCRAM authentication, i.e. there are no
> "scram" entries in pg_hba.conf, and you set yourself a SCRAM verifier,
> you have just locked yourself out of the system. I think that's a
> non-starter. There needs to be some more intelligence in the decision.


Yes, this was exactly my concern.

> It would be a lot more sensible, if there was a way to specify in
> pg_hba.conf, "scram-or-md5". We punted on that for PostgreSQL 10, but
> perhaps we should try to cram that in, after all.


I was also thinking about that. Basically a primary method and a
fallback. If that were the case, a gradual transition could happen, and
if we want \password to enforce best practice it would be ok.

Joe

--
Crunchy Data - http://crunchydata.com
PostgreSQL Support for Secure Enterprises
Consulting, Training, & Open Source Development


Re: [HACKERS] scram and \password

From
Tom Lane
Date:
Joe Conway <mail@joeconway.com> writes:
> On 03/14/2017 03:15 AM, Heikki Linnakangas wrote:
>> If the server isn't set up to do SCRAM authentication, i.e. there are no
>> "scram" entries in pg_hba.conf, and you set yourself a SCRAM verifier,
>> you have just locked yourself out of the system. I think that's a
>> non-starter. There needs to be some more intelligence in the decision.

> Yes, this was exactly my concern.

This seems like a serious usability fail.


>> It would be a lot more sensible, if there was a way to specify in
>> pg_hba.conf, "scram-or-md5". We punted on that for PostgreSQL 10, but
>> perhaps we should try to cram that in, after all.

> I was also thinking about that. Basically a primary method and a
> fallback. If that were the case, a gradual transition could happen, and
> if we want \password to enforce best practice it would be ok.

Why exactly would anyone want "md5 only"?  I should think that "scram
only" is a sensible pg_hba setting, if the DBA feels that md5 is too
insecure, but I do not see the point of "md5 only" in 2017.  I think
we should just start interpreting that as "md5 or better".
        regards, tom lane



Re: [HACKERS] scram and \password

From
Joe Conway
Date:
On 03/14/2017 08:40 AM, Tom Lane wrote:
> Joe Conway <mail@joeconway.com> writes:
>> On 03/14/2017 03:15 AM, Heikki Linnakangas wrote:
>>> It would be a lot more sensible, if there was a way to specify in
>>> pg_hba.conf, "scram-or-md5". We punted on that for PostgreSQL 10, but
>>> perhaps we should try to cram that in, after all.
>
>> I was also thinking about that. Basically a primary method and a
>> fallback. If that were the case, a gradual transition could happen, and
>> if we want \password to enforce best practice it would be ok.
>
> Why exactly would anyone want "md5 only"?  I should think that "scram
> only" is a sensible pg_hba setting, if the DBA feels that md5 is too
> insecure, but I do not see the point of "md5 only" in 2017.  I think
> we should just start interpreting that as "md5 or better".

That certainly would work for me.

Joe

--
Crunchy Data - http://crunchydata.com
PostgreSQL Support for Secure Enterprises
Consulting, Training, & Open Source Development


Re: [HACKERS] scram and \password

From
Jeff Janes
Date:
On Tue, Mar 14, 2017 at 3:15 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
On 03/14/2017 04:47 AM, Tom Lane wrote:
Robert Haas <robertmhaas@gmail.com> writes:
I'm not talking about changing the default, just having it be possible
to use \password with the new system as it was with the old, whatever
exactly we think that means.

Seems to me the intended behavior of \password is to use the best
available practice.  So my guess is that it ought to use SCRAM when
talking to a >= 10.0 server.  What the previous password was ought
to be irrelevant, even if it could find that out which it shouldn't
be able to IMO.

If the server isn't set up to do SCRAM authentication, i.e. there are no "scram" entries in pg_hba.conf,

The method is not part of the pg_hba matching algorithm, so either the first match is scram, or it isn't.  There is no fallback to later entries, as I understand it.
 
and you set yourself a SCRAM verifier, you have just locked yourself out of the system. I think that's a non-starter. There needs to be some more intelligence in the decision.

Right.  And you can lock yourself out of the system going the other way, as well, setting a md5 password when scram is in pg_hba.  Which is how I ended up starting this thread.
 

It would be a lot more sensible, if there was a way to specify in pg_hba.conf, "scram-or-md5". We punted on that for PostgreSQL 10, but perhaps we should try to cram that in, after all.

So the backend for the incipient connection would consult the catalog pg_authid before responding back to the client with an authentication method, as opposed to merely pulling it out of pg_hba?

Cheers,

Jeff

Re: [HACKERS] scram and \password

From
Jeff Janes
Date:
On Tue, Mar 14, 2017 at 8:40 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Joe Conway <mail@joeconway.com> writes:

> I was also thinking about that. Basically a primary method and a
> fallback. If that were the case, a gradual transition could happen, and
> if we want \password to enforce best practice it would be ok.

Why exactly would anyone want "md5 only"?  I should think that "scram
only" is a sensible pg_hba setting, if the DBA feels that md5 is too
insecure, but I do not see the point of "md5 only" in 2017.  I think
we should just start interpreting that as "md5 or better".

Without md5-only, a user who uses \password to change their password from a newer client would lock themselves out of connecting again from older clients.  As a conscious decision (either of the DBA or the user) that would be OK, but to have it happen by default would be unfortunate.
 
Cheers,

Jeff

Re: [HACKERS] scram and \password

From
Tom Lane
Date:
Jeff Janes <jeff.janes@gmail.com> writes:
> On Tue, Mar 14, 2017 at 8:40 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> Why exactly would anyone want "md5 only"?  I should think that "scram
>> only" is a sensible pg_hba setting, if the DBA feels that md5 is too
>> insecure, but I do not see the point of "md5 only" in 2017.  I think
>> we should just start interpreting that as "md5 or better".

> Without md5-only, a user who uses \password to change their password from a
> newer client would lock themselves out of connecting again from older
> clients.  As a conscious decision (either of the DBA or the user) that
> would be OK, but to have it happen by default would be unfortunate.

That's a point, but what it implies is that \password needs some input
from the user about whether to generate a SCRAM or MD5-hashed password.
It would be a fatal error to try to drive that off the auth method
that had been used for the current connection, even if \password had a
way to find that out.  By definition, your concern is about clients
other than the current one, which might well be coming in from other
addresses and getting challenges based on other pg_hba entries.  So
you can't say that "I came in on a SCRAM connection" is sufficient
reason to generate a SCRAM password.

In short, I don't think that argument refutes my position that "md5"
in pg_hba.conf should be understood as allowing SCRAM passwords too.
        regards, tom lane



Re: [HACKERS] scram and \password

From
Robert Haas
Date:
On Tue, Mar 14, 2017 at 5:14 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> Without md5-only, a user who uses \password to change their password from a
>> newer client would lock themselves out of connecting again from older
>> clients.  As a conscious decision (either of the DBA or the user) that
>> would be OK, but to have it happen by default would be unfortunate.
>
> That's a point, but what it implies is that \password needs some input
> from the user about whether to generate a SCRAM or MD5-hashed password.
> It would be a fatal error to try to drive that off the auth method
> that had been used for the current connection, even if \password had a
> way to find that out.  By definition, your concern is about clients
> other than the current one, which might well be coming in from other
> addresses and getting challenges based on other pg_hba entries.  So
> you can't say that "I came in on a SCRAM connection" is sufficient
> reason to generate a SCRAM password.

To some extent that seems like a question of system policy.  Either
the DBA wants users to use SCRAM passwords, or the DBA wants users to
use MD5 passwords, or either is permissible.  In the last case, the
user can do what they like, but it seems like a fairly bad idea from a
user perspective to let the user configure a password using a system
that will lock them out.  We shouldn't assume the user even has any
knowledge of what's in pg_hba.conf, or that they would know what those
contents meant if they had them.  There ought to be something like a
PGC_SUSER GUC that sets the kinds of password verifiers that a user is
allowed to configure, and maybe \password should default to the first
one in the list (but possibly be overridable?).

> In short, I don't think that argument refutes my position that "md5"
> in pg_hba.conf should be understood as allowing SCRAM passwords too.

I'm not sure that's a bad idea, but my first reaction is not to like
it.  md5 is a funny spelling of md5-or-scram.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Wed, Mar 15, 2017 at 6:14 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Jeff Janes <jeff.janes@gmail.com> writes:
>> On Tue, Mar 14, 2017 at 8:40 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>>> Why exactly would anyone want "md5 only"?  I should think that "scram
>>> only" is a sensible pg_hba setting, if the DBA feels that md5 is too
>>> insecure, but I do not see the point of "md5 only" in 2017.  I think
>>> we should just start interpreting that as "md5 or better".
>
>> Without md5-only, a user who uses \password to change their password from a
>> newer client would lock themselves out of connecting again from older
>> clients.  As a conscious decision (either of the DBA or the user) that
>> would be OK, but to have it happen by default would be unfortunate.
>
> That's a point, but what it implies is that \password needs some input
> from the user about whether to generate a SCRAM or MD5-hashed password.
> It would be a fatal error to try to drive that off the auth method
> that had been used for the current connection, even if \password had a
> way to find that out.  By definition, your concern is about clients
> other than the current one, which might well be coming in from other
> addresses and getting challenges based on other pg_hba entries.  So
> you can't say that "I came in on a SCRAM connection" is sufficient
> reason to generate a SCRAM password.
>
> In short, I don't think that argument refutes my position that "md5"
> in pg_hba.conf should be understood as allowing SCRAM passwords too.

I have been hacking my way through this thing, and making
scram_build_verifier is requiring a bit more refactoring than I
thought first:
- stored and server keys are hex-encoded using a backend-only routine.
I think that those should be instead base64-encoded using what has
already been moved in src/common/.
- Callers of scram_build_verifier() need to allocate by themselves the
verifier, and feed it to the function similarly to MD5.
- Frontend-side random generation function is needed, so I have moved
pg_frontend_random() into its own file in src/common/.

Attached are four patches:
- 0001: Switch server and stored keys to be base64-encoded.
- 0002: Move pg_frontend_random() to src/common/
- 0003: Move scram_build_verifier() to src/common/
- 0004: Extend PQencryptPassword with a method argument, able to
handle SCRAM, MD5 and cleartext.

I have not yet done the psql portion with \password -method (too
tired), and in 0004 all the calls of PQencryptPassword use "scram" for
the purpose of the demonstration. Even if PQencryptPassword is not
extended at the end, patches 0001~0003 are necessary anyway.
-- 
Michael

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

Attachment

Re: [HACKERS] scram and \password

From
Joe Conway
Date:
On 03/15/2017 08:48 AM, Michael Paquier wrote:
> I have been hacking my way through this thing, and making
> scram_build_verifier is requiring a bit more refactoring than I
> thought first:
> - stored and server keys are hex-encoded using a backend-only routine.
> I think that those should be instead base64-encoded using what has
> already been moved in src/common/.

Or possibly make the hex routines available in the front end as well
instead?

Joe

--
Crunchy Data - http://crunchydata.com
PostgreSQL Support for Secure Enterprises
Consulting, Training, & Open Source Development


Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Thu, Mar 16, 2017 at 6:46 AM, Joe Conway <mail@joeconway.com> wrote:
> On 03/15/2017 08:48 AM, Michael Paquier wrote:
>> I have been hacking my way through this thing, and making
>> scram_build_verifier is requiring a bit more refactoring than I
>> thought first:
>> - stored and server keys are hex-encoded using a backend-only routine.
>> I think that those should be instead base64-encoded using what has
>> already been moved in src/common/.
>
> Or possibly make the hex routines available in the front end as well
> instead?

Yeah, but keeping in mind that src/common/ should be kept as small as
necessary, the base64 switch made more sense (hex_encode is really
small I know).
-- 
Michael



Re: [HACKERS] scram and \password

From
Heikki Linnakangas
Date:
On 03/14/2017 11:14 PM, Tom Lane wrote:
> In short, I don't think that argument refutes my position that "md5"
> in pg_hba.conf should be understood as allowing SCRAM passwords too.

Yeah, let's do that. Here's a patch.

I had some terminology trouble with the docs. What do you call a user 
that has "md5XXXXX" in pgauthid.rolpassword? What about someone with a 
SCRAM verifier? I used the terms "those users that have an MD5 hash set 
in the system catalog", and "users that have set their password as a 
SCRAM verifier", but it feels awkward.

The behavior when a user doesn't exist, or doesn't have a valid 
password, is a bit subtle. Previously, with 'md5' authentication, we 
would send the client an MD5 challenge, and fail with "invalid password" 
error after receiving the response. And with 'scram' authentication, we 
would perform a dummy authentication exchange, with a made-up salt. This 
is to avoid revealing to an unauthenticated client whether or not the 
user existed.

With this patch, the dummy authentication logic for 'md5' is a bit more 
complicated. I made it look at the password_encryption GUC, and send the 
client a dummy MD5 or SCRAM challenge based on that. The idea is that 
most users presumably have a password of that type, so we use that 
method for the dummy authentication, to make it look as "normal" as 
possible. It's not perfect, if password_encryption is set to 'scram', 
and you probe for a user that has an MD5 password set, you can tell that 
it's a valid user from the fact that the server sends an MD5 challenge.

In practice, I'm not sure how good this dummy authentication thing 
really is anyway. Even on older versions, I'd wager a guess that if you 
tried hard enough, you could tell if a user exists or not based on 
timing, for example. So I think this is good enough. But it's worth 
noting and discussing.

- Heikki


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

Attachment

Re: [HACKERS] scram and \password

From
Joe Conway
Date:
On 03/16/2017 06:52 AM, Heikki Linnakangas wrote:
> On 03/14/2017 11:14 PM, Tom Lane wrote:
>> In short, I don't think that argument refutes my position that "md5"
>> in pg_hba.conf should be understood as allowing SCRAM passwords too.
>
> Yeah, let's do that. Here's a patch.
>
> I had some terminology trouble with the docs. What do you call a user
> that has "md5XXXXX" in pgauthid.rolpassword? What about someone with a
> SCRAM verifier? I used the terms "those users that have an MD5 hash set
> in the system catalog", and "users that have set their password as a
> SCRAM verifier", but it feels awkward.

maybe something like:
"those users with an MD5 hashed password"
"those users with a SCRAM verifier hash"

> The behavior when a user doesn't exist, or doesn't have a valid
> password, is a bit subtle. Previously, with 'md5' authentication, we
> would send the client an MD5 challenge, and fail with "invalid password"
> error after receiving the response. And with 'scram' authentication, we
> would perform a dummy authentication exchange, with a made-up salt. This
> is to avoid revealing to an unauthenticated client whether or not the
> user existed.
>
> With this patch, the dummy authentication logic for 'md5' is a bit more
> complicated. I made it look at the password_encryption GUC, and send the
> client a dummy MD5 or SCRAM challenge based on that. The idea is that
> most users presumably have a password of that type, so we use that
> method for the dummy authentication, to make it look as "normal" as
> possible. It's not perfect, if password_encryption is set to 'scram',
> and you probe for a user that has an MD5 password set, you can tell that
> it's a valid user from the fact that the server sends an MD5 challenge.

Presumably if you are unauthenticated you don't have any way to know
what password_encryption is set to, so this seems pretty reasonable.

Joe

--
Crunchy Data - http://crunchydata.com
PostgreSQL Support for Secure Enterprises
Consulting, Training, & Open Source Development


Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Thu, Mar 16, 2017 at 10:52 PM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
> On 03/14/2017 11:14 PM, Tom Lane wrote:
>>
>> In short, I don't think that argument refutes my position that "md5"
>> in pg_hba.conf should be understood as allowing SCRAM passwords too.
>
>
> Yeah, let's do that. Here's a patch.

At least this has the merit of making \password simpler from psql
without a kind of --method option: if the backend is 9.6 or older,
just generate a MD5-hash, and SCRAM-hash for newer versions.
PQencryptPassword still needs to be extended so as it accepts a hash
method though.

> I had some terminology trouble with the docs. What do you call a user that
> has "md5XXXXX" in pgauthid.rolpassword? What about someone with a SCRAM
> verifier? I used the terms "those users that have an MD5 hash set in the
> system catalog", and "users that have set their password as a SCRAM
> verifier", but it feels awkward.

MD5-hashed values are verifiers as well, the use of the term
"password" looks weird to me.

> The behavior when a user doesn't exist, or doesn't have a valid password, is
> a bit subtle. Previously, with 'md5' authentication, we would send the
> client an MD5 challenge, and fail with "invalid password" error after
> receiving the response. And with 'scram' authentication, we would perform a
> dummy authentication exchange, with a made-up salt. This is to avoid
> revealing to an unauthenticated client whether or not the user existed.
>
> With this patch, the dummy authentication logic for 'md5' is a bit more
> complicated. I made it look at the password_encryption GUC, and send the
> client a dummy MD5 or SCRAM challenge based on that. The idea is that most
> users presumably have a password of that type, so we use that method for the
> dummy authentication, to make it look as "normal" as possible. It's not
> perfect, if password_encryption is set to 'scram', and you probe for a user
> that has an MD5 password set, you can tell that it's a valid user from the
> fact that the server sends an MD5 challenge.

No objections to that. If password_encryption is set off or plain, it
is definitely better to switch to scram as this patch does.

> In practice, I'm not sure how good this dummy authentication thing really is
> anyway. Even on older versions, I'd wager a guess that if you tried hard
> enough, you could tell if a user exists or not based on timing, for example.
> So I think this is good enough. But it's worth noting and discussing.

Regression tests are proving to be useful here (it would be nice to
get those committed first!). I am noticing that this patch breaks
connection for users with cleartext or md5-hashed verifier when
"password" is used in pg_hba.conf. The case where a user has a
scram-hashed verifier when "md5" is used in the matching hba entry
works though. The missing piece is visibly in CheckPWChallengeAuth(),
which should also be used with uaPassword.

-# 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.
+# Require SCRAM authentication for most users, but make an exception
+# for user 'mike', who uses an older client that doesn't support SCRAM
+# authentication.## TYPE  DATABASE        USER            ADDRESS                 METHOD
-host    all             @md5users       .example.com            md5
+host    all             mike            .example.com            md5
Why not still using @md5users?
-- 
Michael



Re: [HACKERS] scram and \password

From
Robert Haas
Date:
On Thu, Mar 16, 2017 at 11:38 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:
> On Thu, Mar 16, 2017 at 10:52 PM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
>> On 03/14/2017 11:14 PM, Tom Lane wrote:
>>>
>>> In short, I don't think that argument refutes my position that "md5"
>>> in pg_hba.conf should be understood as allowing SCRAM passwords too.
>>
>>
>> Yeah, let's do that. Here's a patch.
>
> At least this has the merit of making \password simpler from psql
> without a kind of --method option: if the backend is 9.6 or older,
> just generate a MD5-hash, and SCRAM-hash for newer versions.
> PQencryptPassword still needs to be extended so as it accepts a hash
> method though.

What if the user doesn't want to switch to SCRAM because they also use
some connector that hasn't been updated to support it?

I bet there will be a lot of people in that situation.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: [HACKERS] scram and \password

From
Heikki Linnakangas
Date:
On 03/17/2017 02:01 PM, Robert Haas wrote:
> On Thu, Mar 16, 2017 at 11:38 PM, Michael Paquier
> <michael.paquier@gmail.com> wrote:
>> At least this has the merit of making \password simpler from psql
>> without a kind of --method option: if the backend is 9.6 or older,
>> just generate a MD5-hash, and SCRAM-hash for newer versions.
>> PQencryptPassword still needs to be extended so as it accepts a hash
>> method though.
>
> What if the user doesn't want to switch to SCRAM because they also use
> some connector that hasn't been updated to support it?
>
> I bet there will be a lot of people in that situation.

You could use the less secure server-side ALTER USER to set the password 
in that case. Or use an older client. But I agree, it's a bit weird if 
we don't allow the user to generate an MD5 hash, if he insists. I think 
we still need a 'method' option to \password.

It would make sense to have \password obey password_encryption GUC. Then 
\password and ALTER USER would do the same thing, which would be less 
surprising. Although it's also a bit weird for a GUC to affect 
client-side behavior, so perhaps better to just document that \password 
will create a SCRAM verifier, unless you explicitly tell it to create an 
MD5 hash, and add a 'method' parameter to it.

- Heikki




Re: [HACKERS] scram and \password

From
Robert Haas
Date:
On Fri, Mar 17, 2017 at 8:32 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
> It would make sense to have \password obey password_encryption GUC. Then
> \password and ALTER USER would do the same thing, which would be less
> surprising. Although it's also a bit weird for a GUC to affect client-side
> behavior, so perhaps better to just document that \password will create a
> SCRAM verifier, unless you explicitly tell it to create an MD5 hash, and add
> a 'method' parameter to it.

Either of those would be fine with me, but I think we should do one of them.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: [HACKERS] scram and \password

From
Tom Lane
Date:
Robert Haas <robertmhaas@gmail.com> writes:
> On Fri, Mar 17, 2017 at 8:32 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
>> It would make sense to have \password obey password_encryption GUC. Then
>> \password and ALTER USER would do the same thing, which would be less
>> surprising. Although it's also a bit weird for a GUC to affect client-side
>> behavior, so perhaps better to just document that \password will create a
>> SCRAM verifier, unless you explicitly tell it to create an MD5 hash, and add
>> a 'method' parameter to it.

> Either of those would be fine with me, but I think we should do one of them.

I vote for the second one; seems much less surprising and action-at-a-
distance-y.  And I think the entire point of \password is to *not* do
exactly what a bare ALTER USER would do, but to superimpose a layer of
best practice on it.  We certainly want to define use of SCRAM as being
best practice.
        regards, tom lane



Re: [HACKERS] scram and \password

From
Heikki Linnakangas
Date:
On 03/17/2017 05:38 AM, Michael Paquier wrote:
> Regression tests are proving to be useful here (it would be nice to
> get those committed first!). I am noticing that this patch breaks
> connection for users with cleartext or md5-hashed verifier when
> "password" is used in pg_hba.conf.

Are you sure? It works for me.

Here's a slightly updated patch that includes required changes to the 
test case (now that those have been committed), and some re-wording in 
the docs, per Joe's suggestion. All the tests pass here.

> -# 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.
> +# Require SCRAM authentication for most users, but make an exception
> +# for user 'mike', who uses an older client that doesn't support SCRAM
> +# authentication.
>  #
>  # TYPE  DATABASE        USER            ADDRESS                 METHOD
> -host    all             @md5users       .example.com            md5
> +host    all             mike            .example.com            md5
> Why not still using @md5users?

The old example didn't make much sense, now that md5 means "md5 or 
scram". Could've still used @md5users, but I think this is more clear. 
The old explanation was wrong or at least misleading anyway, because 
@md5users doesn't refer to a group, but a flat file that lists roles.

- Heikki


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

Attachment

Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Wed, Mar 22, 2017 at 8:54 PM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
> On 03/17/2017 05:38 AM, Michael Paquier wrote:
>>
>> Regression tests are proving to be useful here (it would be nice to
>> get those committed first!). I am noticing that this patch breaks
>> connection for users with cleartext or md5-hashed verifier when
>> "password" is used in pg_hba.conf.
>
> Are you sure? It works for me.

Hm... All the tests of password are still broken for me on macos, but
work on Linux:
not ok 4 - authentication success for method password, role scram_role

#   Failed test 'authentication success for method password, role scram_role'
#   at t/001_password.pl line 39.
#          got: '2'
#     expected: '0'
not ok 5 - authentication success for method password, role md5_role

#   Failed test 'authentication success for method password, role md5_role'
#   at t/001_password.pl line 39.
#          got: '2'
#     expected: '0'
not ok 6 - authentication success for method password, role plain_role

[... dig ... dig ...]

And after a lookup the failure is here:
-   result = get_role_password(port->user_name, &shadow_pass, logdetail);
+   shadow_pass = get_role_password(port->user_name, logdetail);   if (result == STATUS_OK)
result is never setup in this code path, so that may crash.

And you need to do something like that, which makes the tests pass here:
@@ -721,6 +721,7 @@ CheckPasswordAuth(Port *port, char **logdetail)       return STATUS_EOF;      /* client wouldn't
sendpassword */
 
   shadow_pass = get_role_password(port->user_name, logdetail);
+   result = shadow_pass != NULL ? STATUS_OK : STATUS_ERROR;   if (result == STATUS_OK)       result =
plain_crypt_verify(port->user_name,shadow_pass, passwd,                                   logdetail);
 

> Here's a slightly updated patch that includes required changes to the test
> case (now that those have been committed), and some re-wording in the docs,
> per Joe's suggestion. All the tests pass here.

+           verifier = scram_build_verifier(username, shadow_pass, 0);
+
+           (void) parse_scram_verifier(verifier, &state->salt,
&state->iterations,
+                                       state->StoredKey, state->ServerKey);
+           pfree(verifier);
Not directly a problem of this patch, but scram_build_verifier can return NULL.

>> -# 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.
>> +# Require SCRAM authentication for most users, but make an exception
>> +# for user 'mike', who uses an older client that doesn't support SCRAM
>> +# authentication.
>>  #
>>  # TYPE  DATABASE        USER            ADDRESS                 METHOD
>> -host    all             @md5users       .example.com            md5
>> +host    all             mike            .example.com            md5
>> Why not still using @md5users?
>
> The old example didn't make much sense, now that md5 means "md5 or scram".
> Could've still used @md5users, but I think this is more clear. The old
> explanation was wrong or at least misleading anyway, because @md5users
> doesn't refer to a group, but a flat file that lists roles.

This patch introduces for the first time a non-generic user name in
pg_hba.conf, that's why, keeping in mind that users could just
copy-paste what is in the docs to make their own file, the approach of
using an @ marker looks more generic to me. But I won't insist on this
point more.

I like the move of removing the status error codes from
get_role_password(). With this support grid, only users with
MD5-hashed verifiers cannot login when the matching hba entry uses
scram.
-- 
Michael



Re: scram and \password

From
Heikki Linnakangas
Date:
On 03/23/2017 06:41 AM, Michael Paquier wrote:
> And after a lookup the failure is here:
> -   result = get_role_password(port->user_name, &shadow_pass, logdetail);
> +   shadow_pass = get_role_password(port->user_name, logdetail);
>     if (result == STATUS_OK)
> result is never setup in this code path, so that may crash.

Ah, of course. For some reason, I has -Wno-maybe-uninitialized in my 
configure command line. Without that, gcc even warns about that.

Fixed, and pushed. Thanks!

- Heikki




Re: scram and \password

From
Michael Paquier
Date:
On Fri, Mar 24, 2017 at 8:36 PM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
> On 03/23/2017 06:41 AM, Michael Paquier wrote:
>>
>> And after a lookup the failure is here:
>> -   result = get_role_password(port->user_name, &shadow_pass, logdetail);
>> +   shadow_pass = get_role_password(port->user_name, logdetail);
>>     if (result == STATUS_OK)
>> result is never setup in this code path, so that may crash.
>
> Ah, of course. For some reason, I has -Wno-maybe-uninitialized in my
> configure command line. Without that, gcc even warns about that.
>
> Fixed, and pushed. Thanks!

OK, cool.

In order to close this thread, I propose to reuse the patches I sent
here to make scram_build_verifier() available to frontends:
https://www.postgresql.org/message-id/CAB7nPqT4yc3u8wspYkWbG088Ndp6asMH3=Zb___Ck89CTvziYQ@mail.gmail.com

And on top of it modify \password so as it generates a md5 verifier
for pre-9.6 servers and a scram one for post-10 servers by looking at
the backend version of the current connection. What do you think?
-- 
Michael



Re: scram and \password

From
Heikki Linnakangas
Date:
On 03/24/2017 03:02 PM, Michael Paquier wrote:
> In order to close this thread, I propose to reuse the patches I sent
> here to make scram_build_verifier() available to frontends:
> https://www.postgresql.org/message-id/CAB7nPqT4yc3u8wspYkWbG088Ndp6asMH3=Zb___Ck89CTvziYQ@mail.gmail.com
>
> And on top of it modify \password so as it generates a md5 verifier
> for pre-9.6 servers and a scram one for post-10 servers by looking at
> the backend version of the current connection. What do you think?

Yep, sounds like a plan.

- Heikki




Re: scram and \password

From
Michael Paquier
Date:
On Fri, Mar 24, 2017 at 10:12 PM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
> On 03/24/2017 03:02 PM, Michael Paquier wrote:
>>
>> In order to close this thread, I propose to reuse the patches I sent
>> here to make scram_build_verifier() available to frontends:
>>
>> https://www.postgresql.org/message-id/CAB7nPqT4yc3u8wspYkWbG088Ndp6asMH3=Zb___Ck89CTvziYQ@mail.gmail.com
>>
>> And on top of it modify \password so as it generates a md5 verifier
>> for pre-9.6 servers and a scram one for post-10 servers by looking at
>> the backend version of the current connection. What do you think?
>
> Yep, sounds like a plan.

And attached is a set of rebased patches, with createuser and psql's
\password extended to do that.
-- 
Michael

Attachment

Re: scram and \password

From
Robert Haas
Date:
On Sat, Mar 25, 2017 at 1:10 AM, Michael Paquier
<michael.paquier@gmail.com> wrote:
> On Fri, Mar 24, 2017 at 10:12 PM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
>> On 03/24/2017 03:02 PM, Michael Paquier wrote:
>>>
>>> In order to close this thread, I propose to reuse the patches I sent
>>> here to make scram_build_verifier() available to frontends:
>>>
>>> https://www.postgresql.org/message-id/CAB7nPqT4yc3u8wspYkWbG088Ndp6asMH3=Zb___Ck89CTvziYQ@mail.gmail.com
>>>
>>> And on top of it modify \password so as it generates a md5 verifier
>>> for pre-9.6 servers and a scram one for post-10 servers by looking at
>>> the backend version of the current connection. What do you think?
>>
>> Yep, sounds like a plan.
>
> And attached is a set of rebased patches, with createuser and psql's
> \password extended to do that.

Heikki, are you going to do something about these?  We're running out of time.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: scram and \password

From
Heikki Linnakangas
Date:
On 04/05/2017 06:53 PM, Robert Haas wrote:
> On Sat, Mar 25, 2017 at 1:10 AM, Michael Paquier
> <michael.paquier@gmail.com> wrote:
>> On Fri, Mar 24, 2017 at 10:12 PM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
>>> On 03/24/2017 03:02 PM, Michael Paquier wrote:
>>>>
>>>> In order to close this thread, I propose to reuse the patches I sent
>>>> here to make scram_build_verifier() available to frontends:
>>>>
>>>> https://www.postgresql.org/message-id/CAB7nPqT4yc3u8wspYkWbG088Ndp6asMH3=Zb___Ck89CTvziYQ@mail.gmail.com
>>>>
>>>> And on top of it modify \password so as it generates a md5 verifier
>>>> for pre-9.6 servers and a scram one for post-10 servers by looking at
>>>> the backend version of the current connection. What do you think?
>>>
>>> Yep, sounds like a plan.
>>
>> And attached is a set of rebased patches, with createuser and psql's
>> \password extended to do that.
>
> Heikki, are you going to do something about these?  We're running out of time.

Sorry I've been procrastinating. I'm on it now. (We need to do something 
about this, feature freeze or not..)

At a quick glance, moving pg_frontend_random() to src/common looks like 
a non-starter. It uses pglock_thread() which is internal to libpq, so it 
won't compile as it is. I think I'm going to change 
scram_build_verifier() to take a pre-generated salt as argument, to 
avoid the need for a random number generator in src/common.

- Heikki




Re: scram and \password

From
Michael Paquier
Date:
On Thu, Apr 6, 2017 at 2:11 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
> At a quick glance, moving pg_frontend_random() to src/common looks like a
> non-starter. It uses pglock_thread() which is internal to libpq, so it won't
> compile as it is. I think I'm going to change scram_build_verifier() to take
> a pre-generated salt as argument, to avoid the need for a random number
> generator in src/common.

Oops. Need an updated set of patches?
-- 
Michael



Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Thu, Apr 6, 2017 at 8:04 AM, Michael Paquier
<michael.paquier@gmail.com> wrote:
> On Thu, Apr 6, 2017 at 2:11 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
>> At a quick glance, moving pg_frontend_random() to src/common looks like a
>> non-starter. It uses pglock_thread() which is internal to libpq, so it won't
>> compile as it is. I think I'm going to change scram_build_verifier() to take
>> a pre-generated salt as argument, to avoid the need for a random number
>> generator in src/common.
>
> Oops. Need an updated set of patches?

Attached is an updated set of patches anyway. This is similar to the
last set, except that I removed the part where pg_frontend_random() is
refactored, extending scram_build_verifier() to use a pre-generated
salt.

Hope that helps.
-- 
Michael

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

Attachment

Re: [HACKERS] scram and \password

From
Noah Misch
Date:
On Wed, Apr 05, 2017 at 08:11:25PM +0300, Heikki Linnakangas wrote:
> On 04/05/2017 06:53 PM, Robert Haas wrote:
> >On Sat, Mar 25, 2017 at 1:10 AM, Michael Paquier
> ><michael.paquier@gmail.com> wrote:
> >>On Fri, Mar 24, 2017 at 10:12 PM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
> >>>On 03/24/2017 03:02 PM, Michael Paquier wrote:
> >>>>
> >>>>In order to close this thread, I propose to reuse the patches I sent
> >>>>here to make scram_build_verifier() available to frontends:
> >>>>
> >>>>https://www.postgresql.org/message-id/CAB7nPqT4yc3u8wspYkWbG088Ndp6asMH3=Zb___Ck89CTvziYQ@mail.gmail.com
> >>>>
> >>>>And on top of it modify \password so as it generates a md5 verifier
> >>>>for pre-9.6 servers and a scram one for post-10 servers by looking at
> >>>>the backend version of the current connection. What do you think?
> >>>
> >>>Yep, sounds like a plan.
> >>
> >>And attached is a set of rebased patches, with createuser and psql's
> >>\password extended to do that.
> >
> >Heikki, are you going to do something about these?  We're running out of time.
> 
> Sorry I've been procrastinating. I'm on it now. (We need to do something
> about this, feature freeze or not..)

[Action required within three days.  This is a generic notification.]

The above-described topic is currently a PostgreSQL 10 open item.  Heikki,
since you committed the patch believed to have created it, you own this open
item.  If some other commit is more relevant or if this does not belong as a
v10 open item, please let us know.  Otherwise, please observe the policy on
open item ownership[1] and send a status update within three calendar days of
this message.  Include a date for your subsequent status update.  Testers may
discover new open items at any time, and I want to plan to get them all fixed
well in advance of shipping v10.  Consequently, I will appreciate your efforts
toward speedy resolution.  Thanks.

[1] https://www.postgresql.org/message-id/20170404140717.GA2675809%40tornado.leadboat.com



Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Mon, Apr 10, 2017 at 12:53 PM, Noah Misch <noah@leadboat.com> wrote:
> On Wed, Apr 05, 2017 at 08:11:25PM +0300, Heikki Linnakangas wrote:
>> >Heikki, are you going to do something about these?  We're running out of time.
>>
>> Sorry I've been procrastinating. I'm on it now. (We need to do something
>> about this, feature freeze or not..)

As there have been some conflicts because of the commit of SASLprep,
here is a rebased set of patches. A couple of things worth noting:
- SASLprep does an allocation of the prepared password string. It is
definitely better to do all the ground work in pg_saslprep but this
costs a free() call with a #ifdef FRONTEND at the end of
scram_build_verifier().
- Patch 0005 does that:
+           /*
+            * Hash password using SCRAM-SHA-256 when connecting to servers
+            * newer than Postgres 10, and hash with MD5 otherwise.
+            */
+           if (pset.sversion < 100000)
+               encrypted_password = PQencryptPassword(pw1, user, "md5");
+           else
+               encrypted_password = PQencryptPassword(pw1, user, "scram");
Actually I am thinking that guessing the hashing function according to
the value of password_encryption would make the most sense. Thoughts?
-- 
Michael
VMware vCenter server
www.vmware.com

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

Attachment

Re: [HACKERS] scram and \password

From
Heikki Linnakangas
Date:
On 04/10/2017 08:42 AM, Michael Paquier wrote:
> As there have been some conflicts because of the commit of SASLprep,
> here is a rebased set of patches. A couple of things worth noting:
> - SASLprep does an allocation of the prepared password string. It is
> definitely better to do all the ground work in pg_saslprep but this
> costs a free() call with a #ifdef FRONTEND at the end of
> scram_build_verifier().
> - Patch 0005 does that:
> +           /*
> +            * Hash password using SCRAM-SHA-256 when connecting to servers
> +            * newer than Postgres 10, and hash with MD5 otherwise.
> +            */
> +           if (pset.sversion < 100000)
> +               encrypted_password = PQencryptPassword(pw1, user, "md5");
> +           else
> +               encrypted_password = PQencryptPassword(pw1, user, "scram");
> Actually I am thinking that guessing the hashing function according to
> the value of password_encryption would make the most sense. Thoughts?

Thanks! I've been busy on the other thread on future-proofing the 
protocol with negotiating the SASL mechanism, I'll come back to this 
once we get that settled. By the end of the week, I presume.

Not sure about the password-encryption thing, there are good arguments 
for either behavior..

- Heikki




Re: [HACKERS] scram and \password

From
Noah Misch
Date:
On Tue, Apr 11, 2017 at 10:07:12PM +0300, Heikki Linnakangas wrote:
> On 04/10/2017 08:42 AM, Michael Paquier wrote:
> >As there have been some conflicts because of the commit of SASLprep,
> >here is a rebased set of patches. A couple of things worth noting:
> >- SASLprep does an allocation of the prepared password string. It is
> >definitely better to do all the ground work in pg_saslprep but this
> >costs a free() call with a #ifdef FRONTEND at the end of
> >scram_build_verifier().
> >- Patch 0005 does that:
> >+           /*
> >+            * Hash password using SCRAM-SHA-256 when connecting to servers
> >+            * newer than Postgres 10, and hash with MD5 otherwise.
> >+            */
> >+           if (pset.sversion < 100000)
> >+               encrypted_password = PQencryptPassword(pw1, user, "md5");
> >+           else
> >+               encrypted_password = PQencryptPassword(pw1, user, "scram");
> >Actually I am thinking that guessing the hashing function according to
> >the value of password_encryption would make the most sense. Thoughts?
> 
> Thanks! I've been busy on the other thread on future-proofing the protocol
> with negotiating the SASL mechanism, I'll come back to this once we get that
> settled. By the end of the week, I presume.

This PostgreSQL 10 open item is past due for your status update.  Kindly send
a status update within 24 hours, and include a date for your subsequent status
update.  Refer to the policy on open item ownership:
https://www.postgresql.org/message-id/20170404140717.GA2675809%40tornado.leadboat.com



Re: [HACKERS] scram and \password

From
Simon Riggs
Date:
On 14 March 2017 at 15:40, Tom Lane <tgl@sss.pgh.pa.us> wrote:

>> I was also thinking about that. Basically a primary method and a
>> fallback. If that were the case, a gradual transition could happen, and
>> if we want \password to enforce best practice it would be ok.
>
> Why exactly would anyone want "md5 only"?  I should think that "scram
> only" is a sensible pg_hba setting, if the DBA feels that md5 is too
> insecure, but I do not see the point of "md5 only" in 2017.  I think
> we should just start interpreting that as "md5 or better".

+1


As a potential open item, if we treat "md5" as ">= md5"
should we not also treat "password" as ">=password"?

It seems strange that we still support "password" and yet tell
everyonenot to use it.

I'd like PG10 to be the version where I don't have to tell people not
to use certain things, hash indexes, "password" etc.

-- 
Simon Riggs                http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services



Re: [HACKERS] scram and \password

From
Heikki Linnakangas
Date:
On 04/18/2017 11:15 AM, Simon Riggs wrote:
> As a potential open item, if we treat "md5" as ">= md5"
> should we not also treat "password" as ">=password"?
>
> It seems strange that we still support "password" and yet tell
> everyonenot to use it.
>
> I'd like PG10 to be the version where I don't have to tell people not
> to use certain things, hash indexes, "password" etc.

Between md5 and scram, the choice is easy, because a user can only have 
an MD5 hashed or SCRAM "hashed" password in pg_authid. So you present 
the client an MD5 challenge or a SCRAM challenge, depending on what the 
user has in pg_authid, or you error out without even trying. But 
"password" authentication can be used with any kind of a verifier in 
pg_authid. "password" authentication can be useful, for example, if a 
user has a SCRAM verifier in pg_authid, but the client doesn't support 
SCRAM.

You could argue that you shouldn't use it even in that situation, you 
should upgrade the client, or use SSL certs or an ssh tunnel or 
something else instead. But that's a very different argument than the 
one for treating "md5" as ">= md5".

Also note that LDAP and RADIUS authentication look identical to 
"password" authentication, on the wire. The only difference is that 
instead of checking the password against pg_authid, the server checks it 
against an LDAP or RADIUS server.

- Heikki




Re: [HACKERS] scram and \password

From
Heikki Linnakangas
Date:
On 04/18/2017 08:44 AM, Noah Misch wrote:
> On Tue, Apr 11, 2017 at 10:07:12PM +0300, Heikki Linnakangas wrote:
>> Thanks! I've been busy on the other thread on future-proofing the protocol
>> with negotiating the SASL mechanism, I'll come back to this once we get that
>> settled. By the end of the week, I presume.
>
> This PostgreSQL 10 open item is past due for your status update.  Kindly send
> a status update within 24 hours, and include a date for your subsequent status
> update.  Refer to the policy on open item ownership:
> https://www.postgresql.org/message-id/20170404140717.GA2675809%40tornado.leadboat.com

Took a bit longer than I predicted, but the other scram open items have 
now been resolved, and I'll start reviewing this now. I expect there 
will be 1-2 iterations on this before it's committed. I'll send another 
status update by Friday, if this isn't committed by then.

- Heikki




Re: [HACKERS] scram and \password

From
Simon Riggs
Date:
On 18 April 2017 at 09:25, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
> On 04/18/2017 11:15 AM, Simon Riggs wrote:
>>
>> As a potential open item, if we treat "md5" as ">= md5"
>> should we not also treat "password" as ">=password"?
>>
>> It seems strange that we still support "password" and yet tell
>> everyonenot to use it.
>>
>> I'd like PG10 to be the version where I don't have to tell people not
>> to use certain things, hash indexes, "password" etc.
>
>
> Between md5 and scram, the choice is easy, because a user can only have an
> MD5 hashed or SCRAM "hashed" password in pg_authid. So you present the
> client an MD5 challenge or a SCRAM challenge, depending on what the user has
> in pg_authid, or you error out without even trying. But "password"
> authentication can be used with any kind of a verifier in pg_authid.
> "password" authentication can be useful, for example, if a user has a SCRAM
> verifier in pg_authid, but the client doesn't support SCRAM.

Which would be a little strange and defeat the purpose of SCRAM.

> You could argue that you shouldn't use it even in that situation, you should
> upgrade the client, or use SSL certs or an ssh tunnel or something else
> instead. But that's a very different argument than the one for treating
> "md5" as ">= md5".
>
> Also note that LDAP and RADIUS authentication look identical to "password"
> authentication, on the wire. The only difference is that instead of checking
> the password against pg_authid, the server checks it against an LDAP or
> RADIUS server.

So the argument is multiple things are dangerous so we do nothing...

We have an opportunity to change things because its PG10, so lets not
waste the opportunity.


Thanks very much for working on SCRAM, its a good feature.

-- 
Simon Riggs                http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services



Re: [HACKERS] scram and \password

From
Heikki Linnakangas
Date:
On 04/10/2017 08:42 AM, Michael Paquier wrote:
> As there have been some conflicts because of the commit of SASLprep,
> here is a rebased set of patches.

I've committed a modified version of the first patch, to change the 
on-disk format to RFC 5803, as mentioned on the other thread 
(https://www.postgresql.org/message-id/351ba574-85ea-d9b8-9689-8c928dd0955d@iki.fi).

I'll continue reviewing the rest of the patch on Monday, but one glaring 
issue is that we cannot add an argument to the existing libpq 
PQencryptPassword() function, because that's part of the public API. It 
would break all applications that use PQencryptPassword().

What we need to do is to add a new function. What should we call that? 
We don't have a tradition of using "Ex" or such suffix to mark extended 
versions of existing functions. PQencryptPasswordWithMethod(user, pass, 
method) ?

- Heikki




Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Sat, Apr 22, 2017 at 5:04 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
> I'll continue reviewing the rest of the patch on Monday, but one glaring
> issue is that we cannot add an argument to the existing libpq
> PQencryptPassword() function, because that's part of the public API. It
> would break all applications that use PQencryptPassword().
>
> What we need to do is to add a new function. What should we call that? We
> don't have a tradition of using "Ex" or such suffix to mark extended
> versions of existing functions. PQencryptPasswordWithMethod(user, pass,
> method) ?

Do we really want to add a new function or have a hard failure? Any
application calling PQencryptPassword may trap itself silently if the
server uses scram as hba key or if the default is switched to that,
from this point of view extending the function makes sense as well.
-- 
Michael



Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Sat, Apr 22, 2017 at 7:20 AM, Michael Paquier
<michael.paquier@gmail.com> wrote:
> Do we really want to add a new function or have a hard failure? Any
> application calling PQencryptPassword may trap itself silently if the
> server uses scram as hba key or if the default is switched to that,
> from this point of view extending the function makes sense as well.

Attached is a new patch set, taking into account the new format.
-- 
Michael

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

Attachment

Re: [HACKERS] scram and \password

From
Heikki Linnakangas
Date:
On 04/22/2017 01:20 AM, Michael Paquier wrote:
> On Sat, Apr 22, 2017 at 5:04 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
>> I'll continue reviewing the rest of the patch on Monday, but one glaring
>> issue is that we cannot add an argument to the existing libpq
>> PQencryptPassword() function, because that's part of the public API. It
>> would break all applications that use PQencryptPassword().
>>
>> What we need to do is to add a new function. What should we call that? We
>> don't have a tradition of using "Ex" or such suffix to mark extended
>> versions of existing functions. PQencryptPasswordWithMethod(user, pass,
>> method) ?
>
> Do we really want to add a new function or have a hard failure? Any
> application calling PQencryptPassword may trap itself silently if the
> server uses scram as hba key or if the default is switched to that,
> from this point of view extending the function makes sense as well.

Yeah, there is that. But we simply cannot change the signature of an 
existing function. It would not only produce compile-time errors when 
building old applications, which would arguably be a good thing, but it 
would also cause old binaries to segfault when dynamically linked with 
the new libpq.

I think it's clear that we should have a new function that takes the 
algorithm as argument. But there are open decisions on what the old 
PQencryptPassword() function should do, and also what the new function 
should do by default, if you don't specify an algorithm:

A) Have PQencryptPassword() return an md5 hash.

B) Have PQencryptPassword() return a SCRAM verifier

C) Have PQencryptPassword() return a SCRAM verifier if connected to a 
v10 server, and an md5 hash otherwise. This is tricky, because 
PQencryptPassword doesn't take a PGconn argument. It could behave like 
PQescapeString() does, and choose md5/scram depending on the server 
version of the last connection that was established.

For the new function, it's probably best to pass a PGconn argument. That 
way we can use the connection to determine the default, and it seems to 
be a good idea for future-proofing too. And an extra "options" argument 
might be good, while we're at it, to e.g. specify the number of 
iterations for SCRAM. So all in all, I propose the documentation for 
these functions to be (I chose option C from above for this):

----
char *
PQencryptPasswordConn(PGconn *conn,                      const char *passwd,                      const char *user,
                const char *method,                      const char *options)
 

[this paragraph is the same as current PQencryptPassword()]
This function is intended to be used by client applications that wish to 
send commands like ALTER ROLE joe PASSWORD 'pwd'. It is good practice to 
not send the original cleartext password in such a command, because it 
might be exposed in command logs, activity displays and so on. Instead, 
use this function to convert the password to encrypted form before it is 
sent.
[end of unchanged part]

This function may execute internal queries to the server to determine 
appropriate defaults, using the given connection object. The call can 
therefore fail if the connection is busy executing another query, or the 
current transaction is aborted.

The return value is a string allocated by malloc, or NULL if out of 
memory or other error. On error, a suitable message is stored in the 
'conn' object. The caller can assume the string doesn't contain any 
special characters that would require escaping. Use PQfreemem to free 
the result when done with it.

The function arguments are:

conn  Connection object for the database where the password is to be changed.

passwd  The new password

user  Name of the role whose password is to be changed

method  Name of the password encryption method to use. Currently supported 
methods are "md5" or "scram-sha-256". If method is NULL, the default for 
the current database is used. [i.e. this looks at password_encryption]

options  Options specific to the encryption method, or NULL to use the 
defaults. (This argument is for future expansion, there are currently no 
options, and you should always pass NULL.)


char *
PQencryptPassword(const char *passwd, const char *user)

PQencryptPassword is an older, deprecated version of 
PQencryptPasswodConn. The difference is that PQencryptPassword does not 
require a connection object. The encryption method will be chosen 
depending on the server version of the last established connection, and 
built-in default options.

----

Thoughts? Unless someone has better ideas or objections, I'll go 
implement that.

- Heikki




Re: [HACKERS] scram and \password

From
Robert Haas
Date:
On Tue, Apr 25, 2017 at 11:26 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
> algorithm as argument. But there are open decisions on what the old
> PQencryptPassword() function should do, and also what the new function
> should do by default, if you don't specify an algorithm:
>
> A) Have PQencryptPassword() return an md5 hash.
>
> B) Have PQencryptPassword() return a SCRAM verifier
>
> C) Have PQencryptPassword() return a SCRAM verifier if connected to a v10
> server, and an md5 hash otherwise. This is tricky, because PQencryptPassword
> doesn't take a PGconn argument. It could behave like PQescapeString() does,
> and choose md5/scram depending on the server version of the last connection
> that was established.

I vote for A - leave PQencryptPassword() as-is, and deprecate it.
Tell people to use the new function going forward.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: [HACKERS] scram and \password

From
Tom Lane
Date:
Robert Haas <robertmhaas@gmail.com> writes:
> On Tue, Apr 25, 2017 at 11:26 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
>> A) Have PQencryptPassword() return an md5 hash.
>>
>> B) Have PQencryptPassword() return a SCRAM verifier
>>
>> C) Have PQencryptPassword() return a SCRAM verifier if connected to a v10
>> server, and an md5 hash otherwise. This is tricky, because PQencryptPassword
>> doesn't take a PGconn argument. It could behave like PQescapeString() does,
>> and choose md5/scram depending on the server version of the last connection
>> that was established.

> I vote for A - leave PQencryptPassword() as-is, and deprecate it.
> Tell people to use the new function going forward.

+1.  I never much liked that magic behavior of PQescapeString, and don't
think we should replicate it elsewhere, so I definitely don't like (C).
And I don't think we can do (B) because that will break the functionality
altogether when talking to an older server.  That leaves (A) plus invent
a new function.
        regards, tom lane



Re: [HACKERS] scram and \password

From
Magnus Hagander
Date:


On Tue, Apr 25, 2017 at 8:29 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Robert Haas <robertmhaas@gmail.com> writes:
> On Tue, Apr 25, 2017 at 11:26 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
>> A) Have PQencryptPassword() return an md5 hash.
>>
>> B) Have PQencryptPassword() return a SCRAM verifier
>>
>> C) Have PQencryptPassword() return a SCRAM verifier if connected to a v10
>> server, and an md5 hash otherwise. This is tricky, because PQencryptPassword
>> doesn't take a PGconn argument. It could behave like PQescapeString() does,
>> and choose md5/scram depending on the server version of the last connection
>> that was established.

> I vote for A - leave PQencryptPassword() as-is, and deprecate it.
> Tell people to use the new function going forward.

+1.  I never much liked that magic behavior of PQescapeString, and don't
think we should replicate it elsewhere, so I definitely don't like (C).
And I don't think we can do (B) because that will break the functionality
altogether when talking to an older server.  That leaves (A) plus invent
a new function.

+1. 


--

Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Wed, Apr 26, 2017 at 12:26 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
> Yeah, there is that. But we simply cannot change the signature of an
> existing function. It would not only produce compile-time errors when
> building old applications, which would arguably be a good thing, but it
> would also cause old binaries to segfault when dynamically linked with the
> new libpq.

Sure.

> I think it's clear that we should have a new function that takes the
> algorithm as argument. But there are open decisions on what the old
> PQencryptPassword() function should do, and also what the new function
> should do by default, if you don't specify an algorithm:
>
> A) Have PQencryptPassword() return an md5 hash.
>
> B) Have PQencryptPassword() return a SCRAM verifier
>
> C) Have PQencryptPassword() return a SCRAM verifier if connected to a v10
> server, and an md5 hash otherwise. This is tricky, because PQencryptPassword
> doesn't take a PGconn argument. It could behave like PQescapeString() does,
> and choose md5/scram depending on the server version of the last connection
> that was established.

Like the rest I vote for A, and document it as deprecated.

> ----
> char *
> PQencryptPasswordConn(PGconn *conn,
>                       const char *passwd,
>                       const char *user,
>                       const char *method,
>                       const char *options)
>
> [...]

Good for me, I was first thinking as well about having "default" as
keyword, NULL is fine as well.

Could it be possible to name the new function as PQhashPassword
instead of PQencryptPassword? From the previous threads we agreed that
encryption makes no sense in this context.
-- 
Michael



Re: [HACKERS] scram and \password

From
Heikki Linnakangas
Date:
On 04/25/2017 06:26 PM, Heikki Linnakangas wrote:
> Thoughts? Unless someone has better ideas or objections, I'll go
> implement that.

This is what I came up with in the end. Some highlights and differences 
vs the plan I posted earlier:

* If algorithm is not given explicitly, PQencryptPasswordConn() queries 
"SHOW password_encryption", and uses that. That is documented, and it is 
also documented that it will *not* issue queries, and hence will not 
block, if the algorithm is given explicitly. That's an important 
property for some applications. If you want the default behavior without 
blocking, query "SHOW password_encryption" yourself, and pass the result 
as the 'algorithm'.

* In the previous draft, I envisioned an algorithm-specific 'options' 
argument. I left it out, on second thoughts (more on that below).

* The old PQencryptPassword() function is unchanged, and always uses 
md5. Per public opinion.


We talked about the alternative where PQencryptPasswordConn() would not 
look at password_encryption, but would always use the strongest possible 
algorithm supported by the server. That would avoid querying the server. 
But then I started thinking how this would work, if we make the number 
of iterations in the SCRAM verifier configurable in the future. The 
client would not know the desired number of iterations based only on the 
server version, it would need to query the server, and we would be back 
to square one. We could add an "options" argument to 
PQencryptPasswordConn() that the application could use to pass that 
information, but documenting how to fetch that information, if you don't 
want PQencryptPasswordConn() to block, gets tedious, and puts a lot of 
burden to applications. That is why I left out the "options" argument, 
after all.

I'm now thinking that if we add password hashing options like the 
iteration count in the future, they will be tacked on to 
password_encryption. For example, "password_encryption='scram-sha-256, 
iterations=10000". That way, "password_encryption" will always contain 
enough information to construct password verifiers.

What will happen to existing applications using PQencryptPasswordConn() 
if a new password_encryption algorithm (or options) is added in the 
future? With this scheme, the application doesn't need to know what 
algorithms exist. An application can pass algorithm=NULL, to use the 
server default, or do "show password_encryption" and pass that, for the 
non-blocking behavior. If you use an older libpq against a new server, 
so that libpq doesn't know about the algorithm used by the server, you 
get an error.

For reviewer convenience, I put up the patched docs at 
http://hlinnaka.iki.fi/temp/scram-wip-docs/libpq-misc.html#libpq-pqencryptpasswordconn.

Thoughts? Am I missing anything?

As an alternative, I considered making password_encryption GUC_REPORT, 
so that libpq would always know it without having to issue a query. But 
it feels wrong to send that option to the client on every connection, 
when it's only needed in the rare case that you use 
PQencryptPasswordConn(). And if we added new settings like the iteration 
count in the future, those would need to be GUC_REPORT too.

- Heikki


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

Attachment

Re: [HACKERS] scram and \password

From
Robert Haas
Date:
On Wed, Apr 26, 2017 at 6:22 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
> On 04/25/2017 06:26 PM, Heikki Linnakangas wrote:
>> Thoughts? Unless someone has better ideas or objections, I'll go
>> implement that.
> This is what I came up with in the end. Some highlights and differences vs
> the plan I posted earlier:
>
> * If algorithm is not given explicitly, PQencryptPasswordConn() queries
> "SHOW password_encryption", and uses that. That is documented, and it is
> also documented that it will *not* issue queries, and hence will not block,
> if the algorithm is given explicitly. That's an important property for some
> applications. If you want the default behavior without blocking, query "SHOW
> password_encryption" yourself, and pass the result as the 'algorithm'.

TBH, I'd just require the user to specify the algorithm explicitly.
Having it run SHOW on the server seems wonky.  It introduces a bunch
of failure modes for ... no real benefit, I think.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: [HACKERS] scram and \password

From
Tom Lane
Date:
Robert Haas <robertmhaas@gmail.com> writes:
> On Wed, Apr 26, 2017 at 6:22 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
>> * If algorithm is not given explicitly, PQencryptPasswordConn() queries
>> "SHOW password_encryption", and uses that. That is documented, and it is
>> also documented that it will *not* issue queries, and hence will not block,
>> if the algorithm is given explicitly. That's an important property for some
>> applications. If you want the default behavior without blocking, query "SHOW
>> password_encryption" yourself, and pass the result as the 'algorithm'.

> TBH, I'd just require the user to specify the algorithm explicitly.
> Having it run SHOW on the server seems wonky.  It introduces a bunch
> of failure modes for ... no real benefit, I think.

Yeah.  Blocking is the least of your worries --- what about being in
a failed transaction, for instance?

However, it's not entirely true that there's no real benefit.  If the
client app has to specify the algorithm then client code will need
extension every time we add another algorithm.  Maybe that's going to
happen so seldom that it's not a big deal, but it would be nice to
avoid that.

Would it be worth making password_encryption be GUC_REPORT so that
it could be guaranteed available, without a server transaction,
from any valid connection?  I'm generally resistant to adding
GUC_REPORT flags, but maybe this is a time for an exception.
        regards, tom lane



Re: [HACKERS] scram and \password

From
Robert Haas
Date:
On Wed, Apr 26, 2017 at 12:57 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Would it be worth making password_encryption be GUC_REPORT so that
> it could be guaranteed available, without a server transaction,
> from any valid connection?  I'm generally resistant to adding
> GUC_REPORT flags, but maybe this is a time for an exception.

Well, as Heikki just wrote a few messages upthread:

---
As an alternative, I considered making password_encryption GUC_REPORT,
so that libpq would always know it without having to issue a query.
But it feels wrong to send that option to the client on every
connection, when it's only needed in the rare case that you use
PQencryptPasswordConn(). And if we added new settings like the
iteration count in the future, those would need to be GUC_REPORT too.
---

I think those are both good points.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Wed, Apr 26, 2017 at 7:22 PM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
> We talked about the alternative where PQencryptPasswordConn() would not look
> at password_encryption, but would always use the strongest possible
> algorithm supported by the server. That would avoid querying the server. But
> then I started thinking how this would work, if we make the number of
> iterations in the SCRAM verifier configurable in the future. The client
> would not know the desired number of iterations based only on the server
> version, it would need to query the server, and we would be back to square
> one. We could add an "options" argument to PQencryptPasswordConn() that the
> application could use to pass that information, but documenting how to fetch
> that information, if you don't want PQencryptPasswordConn() to block, gets
> tedious, and puts a lot of burden to applications. That is why I left out
> the "options" argument, after all.

Fine for me.

> I'm now thinking that if we add password hashing options like the iteration
> count in the future, they will be tacked on to password_encryption. For
> example, "password_encryption='scram-sha-256, iterations=10000". That way,
> "password_encryption" will always contain enough information to construct
> password verifiers.

That's possible as well, adding more GUCs for sub-options of a hashing
algorithm is wrong.

> As an alternative, I considered making password_encryption GUC_REPORT, so
> that libpq would always know it without having to issue a query. But it
> feels wrong to send that option to the client on every connection, when it's
> only needed in the rare case that you use PQencryptPasswordConn(). And if we
> added new settings like the iteration count in the future, those would need
> to be GUC_REPORT too.

Agreed, PQencryptPassword is not that widely used..

Here are some comments.

+       /*
+        * Normalize the password with SASLprep.  If that doesn't work, because
+        * the password isn't valid UTF-8 or contains prohibited
characters, just
+        * proceed with the original password.  (See comments at top of file.)
+        */
+       rc = pg_saslprep(password, &prep_password);
This comment is not true, comments are at the top of auth-scram.c.

+ * The password should already have been processed with SASLprep, if necessary!
+ *
+ * If iterations is 0, default number of iterations is used.  The result is
+ * palloc'd or malloc'd, so caller is responsible for freeing it.
+ */
+char *
+scram_build_verifier(const char *salt, int saltlen, int iterations,
+                    const char *password)
+{
+   uint8       storedkeybuf[SCRAM_KEY_LEN];
+   uint8       serverkeybuf[SCRAM_KEY_LEN];
+   char       *result;
+   char       *p;
+   int         maxlen;
I think that it is a mistake to move SASLprep out of
scram_build_verifier, because pre-processing the password is not
necessary, it is normally mandatory. The BE/FE versions that you are
adding also duplicate the calls to pg_saslprep().

Using "encrypt" instead of "hash" in the function name :(

+   else if (strcmp(algorithm, "plain") == 0)
+   {
+       crypt_pwd = strdup(passwd);
+   }
This is not documented, and users should be warned about using it as well.
-- 
Michael



Re: [HACKERS] scram and \password

From
Ashesh Vashi
Date:

On Tue, Apr 25, 2017 at 8:56 PM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
On 04/22/2017 01:20 AM, Michael Paquier wrote:
On Sat, Apr 22, 2017 at 5:04 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
I'll continue reviewing the rest of the patch on Monday, but one glaring
issue is that we cannot add an argument to the existing libpq
PQencryptPassword() function, because that's part of the public API. It
would break all applications that use PQencryptPassword().

What we need to do is to add a new function. What should we call that? We
don't have a tradition of using "Ex" or such suffix to mark extended
versions of existing functions. PQencryptPasswordWithMethod(user, pass,
method) ?

Do we really want to add a new function or have a hard failure? Any
application calling PQencryptPassword may trap itself silently if the
server uses scram as hba key or if the default is switched to that,
from this point of view extending the function makes sense as well.

Yeah, there is that. But we simply cannot change the signature of an existing function. It would not only produce compile-time errors when building old applications, which would arguably be a good thing, but it would also cause old binaries to segfault when dynamically linked with the new libpq.

I think it's clear that we should have a new function that takes the algorithm as argument. But there are open decisions on what the old PQencryptPassword() function should do, and also what the new function should do by default, if you don't specify an algorithm:

A) Have PQencryptPassword() return an md5 hash.

B) Have PQencryptPassword() return a SCRAM verifier

C) Have PQencryptPassword() return a SCRAM verifier if connected to a v10 server, and an md5 hash otherwise. This is tricky, because PQencryptPassword doesn't take a PGconn argument. It could behave like PQescapeString() does, and choose md5/scram depending on the server version of the last connection that was established.

For the new function, it's probably best to pass a PGconn argument. That way we can use the connection to determine the default, and it seems to be a good idea for future-proofing too. And an extra "options" argument might be good, while we're at it, to e.g. specify the number of iterations for SCRAM. So all in all, I propose the documentation for these functions to be (I chose option C from above for this):

----
char *
PQencryptPasswordConn(PGconn *conn,
                      const char *passwd,
                      const char *user,
                      const char *method,
                      const char *options)
I was just thinking:
- Do we need to provide the method here?
We have connection object itself, it can decide from the type of connection, which method to be used.

-- Thanks, Ashesh
 

[this paragraph is the same as current PQencryptPassword()]
This function is intended to be used by client applications that wish to send commands like ALTER ROLE joe PASSWORD 'pwd'. It is good practice to not send the original cleartext password in such a command, because it might be exposed in command logs, activity displays and so on. Instead, use this function to convert the password to encrypted form before it is sent.
[end of unchanged part]

This function may execute internal queries to the server to determine appropriate defaults, using the given connection object. The call can therefore fail if the connection is busy executing another query, or the current transaction is aborted.

The return value is a string allocated by malloc, or NULL if out of memory or other error. On error, a suitable message is stored in the 'conn' object. The caller can assume the string doesn't contain any special characters that would require escaping. Use PQfreemem to free the result when done with it.

The function arguments are:

conn
  Connection object for the database where the password is to be changed.

passwd
  The new password

user
  Name of the role whose password is to be changed

method
  Name of the password encryption method to use. Currently supported methods are "md5" or "scram-sha-256". If method is NULL, the default for the current database is used. [i.e. this looks at password_encryption]

options
  Options specific to the encryption method, or NULL to use the defaults. (This argument is for future expansion, there are currently no options, and you should always pass NULL.)


char *
PQencryptPassword(const char *passwd, const char *user)

PQencryptPassword is an older, deprecated version of PQencryptPasswodConn. The difference is that PQencryptPassword does not require a connection object. The encryption method will be chosen depending on the server version of the last established connection, and built-in default options.

----

Thoughts? Unless someone has better ideas or objections, I'll go implement that.

- Heikki




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

Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Thu, Apr 27, 2017 at 1:25 PM, Ashesh Vashi
<ashesh.vashi@enterprisedb.com> wrote:
> - Do we need to provide the method here?
> We have connection object itself, it can decide from the type of connection,
> which method to be used.

Providing the method is not mandatory. If you look upthread... If the
caller of this routine specified method = NULL, then the value of
password_encryption on the server is queried automatically and that
will be the method used to hash the password.
-- 
Michael



Re: [HACKERS] scram and \password

From
Ashesh Vashi
Date:

On Thu, Apr 27, 2017 at 9:57 AM, Michael Paquier <michael.paquier@gmail.com> wrote:
On Thu, Apr 27, 2017 at 1:25 PM, Ashesh Vashi
<ashesh.vashi@enterprisedb.com> wrote:
> - Do we need to provide the method here?
> We have connection object itself, it can decide from the type of connection,
> which method to be used.

Providing the method is not mandatory. If you look upthread... If the
caller of this routine specified method = NULL, then the value of
password_encryption on the server is queried automatically and that
will be the method used to hash the password.
I missed that. Sorry.

Thanks.

--Thanks, Ashesh
--
Michael

Re: [HACKERS] scram and \password

From
Heikki Linnakangas
Date:
On 04/26/2017 07:57 PM, Tom Lane wrote:
> Robert Haas <robertmhaas@gmail.com> writes:
>> On Wed, Apr 26, 2017 at 6:22 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
>>> * If algorithm is not given explicitly, PQencryptPasswordConn() queries
>>> "SHOW password_encryption", and uses that. That is documented, and it is
>>> also documented that it will *not* issue queries, and hence will not block,
>>> if the algorithm is given explicitly. That's an important property for some
>>> applications. If you want the default behavior without blocking, query "SHOW
>>> password_encryption" yourself, and pass the result as the 'algorithm'.
>
>> TBH, I'd just require the user to specify the algorithm explicitly.
>> Having it run SHOW on the server seems wonky.  It introduces a bunch
>> of failure modes for ... no real benefit, I think.
>
> Yeah.  Blocking is the least of your worries --- what about being in
> a failed transaction, for instance?

Well, the "ALTER USER" command that you will surely run next, using the 
same connection, would fail anyway. I don't think running a query is a 
problem, as long as it's documented, and there's a documented way to 
avoid it.

You could argue, that since we need to document how to avoid the query 
and the blocking, we might as well always require the application to run 
the "show password_encryption" query before calling 
PQencryptPasswordConn(). But I'd like to offer the convenience for the 
majority of applications that don't mind blocking.

> However, it's not entirely true that there's no real benefit.  If the
> client app has to specify the algorithm then client code will need
> extension every time we add another algorithm.  Maybe that's going to
> happen so seldom that it's not a big deal, but it would be nice to
> avoid that.

Yeah, I'd like to be prepared. Hopefully we don't need to add another 
algorithm any time soon, but maybe we will, or maybe we want to add an 
option for the SCRAM iteration count, for example.

- Heikki




Re: [HACKERS] scram and \password

From
Noah Misch
Date:
On Fri, Apr 21, 2017 at 11:04:14PM +0300, Heikki Linnakangas wrote:
> I'll continue reviewing the rest of the patch on Monday, but [...]

This PostgreSQL 10 open item is past due for your status update.  Kindly send
a status update within 24 hours, and include a date for your subsequent status
update.  Moreover, this open item has been in progress for 17 days, materially
longer than the 1-2 week RMT non-intervention period.  Refer to the policy on
open item ownership:
https://www.postgresql.org/message-id/20170404140717.GA2675809%40tornado.leadboat.com



Re: [HACKERS] scram and \password

From
Heikki Linnakangas
Date:
On 04/28/2017 07:49 AM, Noah Misch wrote:
> On Fri, Apr 21, 2017 at 11:04:14PM +0300, Heikki Linnakangas wrote:
>> I'll continue reviewing the rest of the patch on Monday, but [...]
>
> This PostgreSQL 10 open item is past due for your status update.  Kindly send
> a status update within 24 hours, and include a date for your subsequent status
> update.  Moreover, this open item has been in progress for 17 days, materially
> longer than the 1-2 week RMT non-intervention period.  Refer to the policy on
> open item ownership:
> https://www.postgresql.org/message-id/20170404140717.GA2675809%40tornado.leadboat.com

I just pushed some little cleanups that caught my eye while working on 
this. I need to rebase the patch set I sent earlier, and fix the little 
things that Michael pointed out, but that shouldn't take long. I plan to 
push a fix for this on Tuesday (Monday is a national holiday here).

- Heikki




Re: [HACKERS] scram and \password

From
Robert Haas
Date:
On Thu, Apr 27, 2017 at 3:22 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
> You could argue, that since we need to document how to avoid the query and
> the blocking, we might as well always require the application to run the
> "show password_encryption" query before calling PQencryptPasswordConn(). But
> I'd like to offer the convenience for the majority of applications that
> don't mind blocking.

I still think that's borrowing trouble.  It just seems like too
critical of a thing to have a default -- if the convenience logic gets
it wrong and encrypts the password in a manner not intended by the
user, that could (a) amount to a security vulnerability or (b) lock
you out of your account.  If you ask your significant other "where do
you want to go to dinner?" and can't get a clear answer out of them
after some period of time, it's probably OK to assume they don't care
that much and you can just pick something.  If you ask the
commander-in-chief "which country should we fire the missiles at?" and
you don't get a clear and unambiguous answer, just picking something
is not a very good idea.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: [HACKERS] scram and \password

From
Heikki Linnakangas
Date:
On 05/01/2017 07:04 PM, Robert Haas wrote:
> On Thu, Apr 27, 2017 at 3:22 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
>> You could argue, that since we need to document how to avoid the query and
>> the blocking, we might as well always require the application to run the
>> "show password_encryption" query before calling PQencryptPasswordConn(). But
>> I'd like to offer the convenience for the majority of applications that
>> don't mind blocking.
>
> I still think that's borrowing trouble.  It just seems like too
> critical of a thing to have a default -- if the convenience logic gets
> it wrong and encrypts the password in a manner not intended by the
> user, that could (a) amount to a security vulnerability or (b) lock
> you out of your account.

That's true for a lot of things. The logic isn't complicated; it runs 
"SHOW password_encryption", and uses the value of that as the algorithm.

There's going to be a default, one way or another. The default is going 
to come from password_encryption, or it's going to be a hard-coded value 
or logic based on server-version in PQencryptPasswordConn(). Or it's 
going to be a hard-coded value or logic implemented in every application 
that uses PQencryptPasswordConn(). I think looking at 
password_encryption makes the most sense. The application is not in a 
good position to make the decision, and forcing the end-user to choose 
every time they change a password is too onerous.

>  If you ask your significant other "where do
> you want to go to dinner?" and can't get a clear answer out of them
> after some period of time, it's probably OK to assume they don't care
> that much and you can just pick something.  If you ask the
> commander-in-chief "which country should we fire the missiles at?" and
> you don't get a clear and unambiguous answer, just picking something
> is not a very good idea.

I don't understand the analogy. If the application explicitly passes an 
algorithm, we use that. If the application passes NULL, it means "you 
decide, based on the documented rules". If the application passes 
"mumble-mumble", you get an error. If the "SHOW password_encryption" 
query fails or libpq doesn't understand the result, you also get an error.

What do you think we should do here, then? Make password_encryption 
GUC_REPORT? Hard-code an algorithm in every application? Remove the 
convenience logic from PQencryptionPasswordConn(), and document that for 
a sensible default, the application should first run "SHOW 
password_encryption", and use the result of that as the algorithm? Or go 
with the current patch?

- Heikki




Re: [HACKERS] scram and \password

From
Robert Haas
Date:
On Tue, May 2, 2017 at 3:42 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
> There's going to be a default, one way or another. The default is going to
> come from password_encryption, or it's going to be a hard-coded value or
> logic based on server-version in PQencryptPasswordConn(). Or it's going to
> be a hard-coded value or logic implemented in every application that uses
> PQencryptPasswordConn(). I think looking at password_encryption makes the
> most sense. The application is not in a good position to make the decision,
> and forcing the end-user to choose every time they change a password is too
> onerous.

I think there should be no default, and the caller should have to pass
the algorithm explicitly.  If they want to determine what default to
pass by running 'SHOW password_encryption', that's their choice.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: [HACKERS] scram and \password

From
Heikki Linnakangas
Date:
On 05/02/2017 07:47 PM, Robert Haas wrote:
> On Tue, May 2, 2017 at 3:42 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
>> There's going to be a default, one way or another. The default is going to
>> come from password_encryption, or it's going to be a hard-coded value or
>> logic based on server-version in PQencryptPasswordConn(). Or it's going to
>> be a hard-coded value or logic implemented in every application that uses
>> PQencryptPasswordConn(). I think looking at password_encryption makes the
>> most sense. The application is not in a good position to make the decision,
>> and forcing the end-user to choose every time they change a password is too
>> onerous.
>
> I think there should be no default, and the caller should have to pass
> the algorithm explicitly.  If they want to determine what default to
> pass by running 'SHOW password_encryption', that's their choice.

Ok, gotcha. I disagree, I think we should provide a default. Libpq is in 
a better position to make a good choice than most applications.

I've committed the new PQencryptPasswordConn function, with the default 
behavior of doing "show password_encryption", and the changes to use it 
in psql and createuser. This closes the open issue with \password.

On 04/27/2017 07:03 AM, Michael Paquier wrote:
> I think that it is a mistake to move SASLprep out of
> scram_build_verifier, because pre-processing the password is not
> necessary, it is normally mandatory. The BE/FE versions that you are
> adding also duplicate the calls to pg_saslprep().

I played with that a little bit, but decided to keep pg_saslprep() out 
of scram_build_verifier() after all. It would seem asymmetric to have 
scram_build_verifier() call pg_saslprep(), but require callers of 
scram_SaltedPassword() to call it. So for consistency, I think 
scram_SaltedPassword() should also call pg_saslprep(). That would 
complicated the scram_SaltedPassword() function, however. It would need 
to report an OOM error somehow, for starters. Not an insurmountable 
issue, of course, but it felt cleaner this way, after all, despite the 
duplication.

> Using "encrypt" instead of "hash" in the function name :(

Yeah. For better or worse, I've kept the "encrypt" nomenclature 
everywhere, for consistency.

Thanks!

- Heikki




Re: [HACKERS] scram and \password

From
Magnus Hagander
Date:


On Wed, May 3, 2017 at 10:26 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
On 05/02/2017 07:47 PM, Robert Haas wrote:
On Tue, May 2, 2017 at 3:42 AM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
There's going to be a default, one way or another. The default is going to
come from password_encryption, or it's going to be a hard-coded value or
logic based on server-version in PQencryptPasswordConn(). Or it's going to
be a hard-coded value or logic implemented in every application that uses
PQencryptPasswordConn(). I think looking at password_encryption makes the
most sense. The application is not in a good position to make the decision,
and forcing the end-user to choose every time they change a password is too
onerous.

I think there should be no default, and the caller should have to pass
the algorithm explicitly.  If they want to determine what default to
pass by running 'SHOW password_encryption', that's their choice.

Ok, gotcha. I disagree, I think we should provide a default. Libpq is in a better position to make a good choice than most applications.

I've committed the new PQencryptPasswordConn function, with the default behavior of doing "show password_encryption", and the changes to use it in psql and createuser. This closes the open issue with \password.

If we're basically just telling people to call SHOW manually, we might as well do it in the default case. I think the wording you put into the docs there is good, as it tells people exactly what happens and how to reproduce it locally. 

For the security perspective, perhaps we should have a link to the part of the docs that discusses the different algorithms?

--

Re: [HACKERS] scram and \password

From
Michael Paquier
Date:
On Wed, May 3, 2017 at 5:26 PM, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
> Ok, gotcha. I disagree, I think we should provide a default. Libpq is in a
> better position to make a good choice than most applications.
>
> I've committed the new PQencryptPasswordConn function, with the default
> behavior of doing "show password_encryption", and the changes to use it in
> psql and createuser. This closes the open issue with \password.

Well, there is always the counter argument that applications can check
for password_encryption by themselves and complete
PQencryptPasswordConn and that would be a couple of extra lines in any
applications. But honestly, people will appreciate a way to rely on
what the backend uses automatically.

> On 04/27/2017 07:03 AM, Michael Paquier wrote:
>> I think that it is a mistake to move SASLprep out of
>> scram_build_verifier, because pre-processing the password is not
>> necessary, it is normally mandatory. The BE/FE versions that you are
>> adding also duplicate the calls to pg_saslprep().
>
> I played with that a little bit, but decided to keep pg_saslprep() out of
> scram_build_verifier() after all. It would seem asymmetric to have
> scram_build_verifier() call pg_saslprep(), but require callers of
> scram_SaltedPassword() to call it. So for consistency, I think
> scram_SaltedPassword() should also call pg_saslprep(). That would
> complicated the scram_SaltedPassword() function, however. It would need to
> report an OOM error somehow, for starters. Not an insurmountable issue, of
> course, but it felt cleaner this way, after all, despite the duplication.

Okay, I won't fight on that further.
-- 
Michael