Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol
On Fri, Feb 3, 2017 at 9:52 PM, Heikki Linnakangaswrote: > On 12/20/2016 03:47 AM, Michael Paquier wrote: >> >> The first thing is to be able to understand in the SCRAM code if a >> string is UTF-8 or not, and this code is in src/common/. pg_wchar.c >> offers a set of routines exactly for this purpose, which is built with >> libpq but that's not available for src/common/. So instead of moving >> all the file, I'd like to create a new file in src/common/utf8.c which >> includes pg_utf_mblen() and pg_utf8_islegal(). > > Sounds reasonable. They're short functions, might also be ok to just > copy-paste them to scram-common.c. Having a separate file makes the most sense to me I think, if we can avoid code duplication that's better. >> The second thing is the normalization itself. Per RFC4013, NFKC needs >> to be applied to the string. The operation is described in [1] >> completely, and it is named as doing 1) a compatibility decomposition >> of the bytes of the string, followed by 2) a canonical composition. >> >> About 1). The compatibility decomposition is defined in [2], "by >> recursively applying the canonical and compatibility mappings, then >> applying the canonical reordering algorithm". Canonical and >> compatibility mapping are some data available in UnicodeData.txt, the >> 6th column of the set defined in [3] to be precise. The meaning of the >> decomposition mappings is defined in [2] as well. The canonical >> decomposition is basically to look for a given UTF-8 character, and >> then apply the multiple characters resulting in its new shape. The >> compatibility mapping should as well be applied, but [5], a perl tool >> called charlint.pl doing this normalization work, does not care about > > Not sure. We need to do whatever the "right thing" is, according to the RFC. > I would assume that the spec is not ambiguous this, but I haven't looked > into the details. If it's ambiguous, then I think we need to look at some > popular implementations to see what they do. The spec defines quite correctly what should be done. The implementations are sometimes quite loose on some points though (see charlint.pl). >> So what we need from Postgres side is a mapping table to, having the >> following fields: >> 1) Hexa sequence of UTF8 character. >> 2) Its canonical combining class. >> 3) The kind of decomposition mapping if defined. >> 4) The decomposition mapping, in hexadecimal format. >> Based on what I looked at, either perl or python could be used to >> process UnicodeData.txt and to generate a header file that would be >> included in the tree. There are 30k entries in UnicodeData.txt, 5k of >> them have a mapping, so that will result in many tables. One thing to >> improve performance would be to store the length of the table in a >> static variable, order the entries by their hexadecimal keys and do a >> dichotomy lookup to find an entry. We could as well use more fancy >> things like a set of tables using a Radix tree using decomposed by >> bytes. We should finish by just doing one lookup of the table for each >> character sets anyway. > > Ok. I'm not too worried about the performance of this. It's only used for > passwords, which are not that long, and it's only done when connecting. I'm > more worried about the disk/memory usage. How small can we pack the tables? > 10kB? 100kB? Even a few MB would probably not be too bad in practice, but > I'd hate to bloat up libpq just for this. Indeed. I think I'll develop first a small utility able to do operation. There is likely some knowledge in mb/Unicode that we can use here. The radix tree patch would perhaps help? >> 3) The shape of the mapping table, which depends on how many >> operations we want to support in the normalization of the strings. >> The decisions for those items will drive the implementation in one >> sense or another. > > Let's aim for small disk/memory footprint. OK, I'll try to give it a shot in a couple of days in the shape of an extention or something like that. Thanks for the feedback. -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On 12/20/2016 03:47 AM, Michael Paquier wrote: The first thing is to be able to understand in the SCRAM code if a string is UTF-8 or not, and this code is in src/common/. pg_wchar.c offers a set of routines exactly for this purpose, which is built with libpq but that's not available for src/common/. So instead of moving all the file, I'd like to create a new file in src/common/utf8.c which includes pg_utf_mblen() and pg_utf8_islegal(). Sounds reasonable. They're short functions, might also be ok to just copy-paste them to scram-common.c. On top of that I think that having a routine able to check a full string would be useful for many users, as pg_utf8_islegal() can only check one set of characters. If the password string is found to be of UTF-8 format, SASLprepare is applied. If not, the string is copied as-is with perhaps unexpected effects for the client But he's in trouble already if client is not using UTF-8. Yeah. The second thing is the normalization itself. Per RFC4013, NFKC needs to be applied to the string. The operation is described in [1] completely, and it is named as doing 1) a compatibility decomposition of the bytes of the string, followed by 2) a canonical composition. About 1). The compatibility decomposition is defined in [2], "by recursively applying the canonical and compatibility mappings, then applying the canonical reordering algorithm". Canonical and compatibility mapping are some data available in UnicodeData.txt, the 6th column of the set defined in [3] to be precise. The meaning of the decomposition mappings is defined in [2] as well. The canonical decomposition is basically to look for a given UTF-8 character, and then apply the multiple characters resulting in its new shape. The compatibility mapping should as well be applied, but [5], a perl tool called charlint.pl doing this normalization work, does not care about this phase... Do we? Not sure. We need to do whatever the "right thing" is, according to the RFC. I would assume that the spec is not ambiguous this, but I haven't looked into the details. If it's ambiguous, then I think we need to look at some popular implementations to see what they do. About 2)... Once the decomposition has been applied, those bytes need to be recomposed using the Canonical_Combining_Class field of UnicodeData.txt in [3], which is the 3rd column of the set. Its values are defined in [4]. An other interesting thing, charlint.pl [5] does not care about this phase. I am wondering if we should as well not just drop this part as well... Once 1) and 2) are done, NKFC is complete, and so is SASLPrepare. Ok. So what we need from Postgres side is a mapping table to, having the following fields: 1) Hexa sequence of UTF8 character. 2) Its canonical combining class. 3) The kind of decomposition mapping if defined. 4) The decomposition mapping, in hexadecimal format. Based on what I looked at, either perl or python could be used to process UnicodeData.txt and to generate a header file that would be included in the tree. There are 30k entries in UnicodeData.txt, 5k of them have a mapping, so that will result in many tables. One thing to improve performance would be to store the length of the table in a static variable, order the entries by their hexadecimal keys and do a dichotomy lookup to find an entry. We could as well use more fancy things like a set of tables using a Radix tree using decomposed by bytes. We should finish by just doing one lookup of the table for each character sets anyway. Ok. I'm not too worried about the performance of this. It's only used for passwords, which are not that long, and it's only done when connecting. I'm more worried about the disk/memory usage. How small can we pack the tables? 10kB? 100kB? Even a few MB would probably not be too bad in practice, but I'd hate to bloat up libpq just for this. In conclusion, at this point I am looking for feedback regarding the following items: 1) Where to put the UTF8 check routines and what to move. Covered that above. 2) How to generate the mapping table using UnicodeData.txt. I'd think that using perl would be better. Agreed, it needs to be in Perl. That's what we require to be present when building PostgreSQL, it's what we use for generating other tables and functions. 3) The shape of the mapping table, which depends on how many operations we want to support in the normalization of the strings. The decisions for those items will drive the implementation in one sense or another. Let's aim for small disk/memory footprint. - Heikki [1]: http://www.unicode.org/reports/tr15/#Description_Norm [2]: http://www.unicode.org/Public/5.1.0/ucd/UCD.html#Character_Decomposition_Mappings [3]: http://www.unicode.org/Public/5.1.0/ucd/UCD.html#UnicodeData.txt [4]: http://www.unicode.org/Public/5.1.0/ucd/UCD.html#Canonical_Combining_Class_Values [5]: https://www.w3.org/International/charlint/ -- Sent via pgsql-hackers mailing list
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 02/02/2017 05:50 AM, David Rowley wrote: On 2 February 2017 at 00:13, Heikki Linnakangaswrote: Ok, I'll drop the second patch for now. I committed the first patch after fixing the things you and Michael pointed out. Thanks for the review! dbd69118 caused small compiler warning for me. The attached fixed it. Fixed, thanks! - 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: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 2 February 2017 at 00:13, Heikki Linnakangaswrote: > Ok, I'll drop the second patch for now. I committed the first patch after > fixing the things you and Michael pointed out. Thanks for the review! dbd69118 caused small compiler warning for me. The attached fixed it. -- David Rowley http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Training & Services encrypt_password_warning_fix.patch Description: Binary data -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 01/17/2017 11:51 PM, Peter Eisentraut wrote: On 1/3/17 9:09 AM, Heikki Linnakangas wrote: Since not everyone agrees with this approach, I split this patch into two. The first patch refactors things, replacing the isMD5() function with get_password_type(), without changing the representation of pg_authid.rolpassword. That is hopefully uncontroversial. I have checked these patches. The refactoring in the first patch seems sensible. As Michael pointed out, there is still a reference to "plain:" in the first patch. Fixed. The commit message needs to be updated, because the function plain_crypt_verify() was already added in a previous patch. Fixed. I'm not fond of this kind of coding password = encrypt_password(password_type, stmt->role, password); where the 'password' variable has a different meaning before and after. Added a new local variable to avoid the confusion. This error message might be a mistake: elog(ERROR, "unrecognized password type conversion"); I rephrased the error as "cannot encrypt password to requested type", and added a comment explaining that it cannot happen. I hope that helped, I'm not sure why you thought it might've been a mistake. I think some pieces from the second patch could be included in the first patch, e.g., the parts for passwordcheck.c and user.c. I refrained from doing that for now. It would've changed the passwordcheck hook API in an incompatible way. Breaking the API explicitly would be a good thing, if we added the "plain:" prefix, because modules would need to deal with the prefix anyway. But until we do that, better to not break the API for no good reason. And the second patch adds the "plain:" prefix, which not everyone agrees on. The code also gets a little bit dubious, as it introduces an "unknown" password type, which is sometimes treated as plaintext and sometimes as an error. I think this is going be messy. I would skip this patch for now at least. Too much controversy, and we don't know how the rest of the patches for this feature will look like to be able to know if it's worth it. Ok, I'll drop the second patch for now. I committed the first patch after fixing the things you and Michael pointed out. Thanks for the review! - 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] Password identifiers, protocol aging and SCRAM protocol
On Wed, Jan 18, 2017 at 2:46 PM, Michael Paquierwrote: > FWIW, this patch is on a "waiting on author" state and that's right. > As the discussion on SASLprepare() and the decisions regarding the way > to implement it, or at least have it, are still pending, I am not > planning to move on with any implementation until we have a plan about > what to do. Just using libidn (LGPL) for a first shot is rather > painless but... I am not alone here. With decisions on this matter pending, I am marking this patch as "returned with feedback". If there is a consensus on what to do, I'll be happy to do the implementation with the last CF in March in sight. If no, that would mean that this feature will not be part of PG 10. -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On Thu, Jan 19, 2017 at 6:17 PM, Simon Riggswrote: > We seem to be caught between adding lots of new things as parameters > and adding new detail into pg_hba.conf. > > Parameters like password_encryption are difficult here because they > essentially repeat what has already been said in the pg_hba.conf. If > we have two entries in pg_hba.conf, one saying md5 and the other > saying "scram" (or whatever), what would we set password_encryption > to? It seems clear to me that if the pg_hba.conf says md5 then > password_encryption should be md5 and if pg_hba.conf says scram then > it should be scram. > > I'd like to float another idea, as a way of finding a way forwards > that will last over time > > * pg_hba.conf entry would say sasl='methodX' (no spaces) > * we have a new catalog called pg_sasl that allows us to add new > methods, with appropriate function calls This would make sense if we support a mountain of protocols and that we want to have a handler with a set of APIs used for authentication. This is a grade higher than simple SCRAM, and this basically requires to design a set of generic routines that are fine for covering *any* protocol with this handler. I'd think this is rather hard per the slight differences in SASL exchanges for different protocols. > * remove password_encryption parameter and always use default > encryption as specified for that session in pg_hba.conf So if user X creates user Y with a password (defined by CREATE USER PASSWORD) it should by default follow what pg_hba.conf dictates, which could be pam or gss? That does not look very intuitive to me. The advantage with the current system is that password creation and protocol allowed for an authentication are two separate, independent things, password_encryption being basically a wrapper for CREATE USER. Mixing both makes things more confusing. If you are willing to move away from password_encryption, one thing that could be used is just to extend CREATE USER to be able to enforce the password protocol associated, that's what the patches on this thread do with PASSWORD (val USING protocol). > Which sounds nice, but many users will wish to upgrade their current > mechanisms from using md5 to scram. How will we update passwords > slowly, so that different users change from md5 to scram at different > times? Having to specify the mechanism in the pg_hba.conf makes that > almost impossible, forcing a big bang approach which subsequently may > never happen. At this point comes the possibility to define multiple password types for one single user instead of rolling multiple roles and renaming htem. > As a way of solving that problem, another idea would be to make the > mechanism session specific depending upon what is stored for a > particular user. That allows us to have a single pg_hba.conf entry of > "sasl", and then use md5, scram-256 or future-mechanism on a per user > basis. Isn't that specifying multiple users in a single sasl entry in pg_hba.conf? Once a user is updated, you could just move him from one line to the other of pg_hba.conf, or use a @file in the hba entry. > I'm not sure I see a clear way forwards yet, these are just ideas and > questions to help the discussion. Thanks, I find the catalog idea interesting. That's hard though per the potential range of SASL protocols that have likely different needs in the way messages are exchanged. -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On 19 January 2017 at 06:32, Noah Mischwrote: > On Wed, Jan 18, 2017 at 02:30:38PM +0900, Michael Paquier wrote: >> On Wed, Jan 18, 2017 at 2:23 PM, Noah Misch wrote: >> > The latest versions document this precisely, but I agree with Peter's >> > concern >> > about plain "scram". Suppose it's 2025 and PostgreSQL support SASL >> > mechanisms >> > OAUTHBEARER, SCRAM-SHA-256, SCRAM-SHA-256-PLUS, and SCRAM-SHA3-512. What >> > should the pg_hba.conf options look like at that time? I don't think >> > having a >> > single "scram" option fits in such a world. >> >> Sure. >> >> > I see two strategies that fit: >> > >> > 1. Single "sasl" option, with a GUC, similar to ssl_ciphers, controlling >> > the >> >mechanisms to offer. >> > 2. Separate options "scram_sha_256", "scram_sha3_512", "oauthbearer", etc. >> >> Or we could have a sasl option, with a mandatory array of mechanisms >> to define one or more items, so method entries in pg_hba.conf would >> look llke that: >> sasl mechanism=scram_sha_256,scram_sha3_512 > > I like that. Michael, I support your good work on this patch and its certainly shaping up. Noah's general point is that we need to have a general, futureproof design for the UI and I agree. We seem to be caught between adding lots of new things as parameters and adding new detail into pg_hba.conf. Parameters like password_encryption are difficult here because they essentially repeat what has already been said in the pg_hba.conf. If we have two entries in pg_hba.conf, one saying md5 and the other saying "scram" (or whatever), what would we set password_encryption to? It seems clear to me that if the pg_hba.conf says md5 then password_encryption should be md5 and if pg_hba.conf says scram then it should be scram. I'd like to float another idea, as a way of finding a way forwards that will last over time * pg_hba.conf entry would say sasl='methodX' (no spaces) * we have a new catalog called pg_sasl that allows us to add new methods, with appropriate function calls * remove password_encryption parameter and always use default encryption as specified for that session in pg_hba.conf Which sounds nice, but many users will wish to upgrade their current mechanisms from using md5 to scram. How will we update passwords slowly, so that different users change from md5 to scram at different times? Having to specify the mechanism in the pg_hba.conf makes that almost impossible, forcing a big bang approach which subsequently may never happen. As a way of solving that problem, another idea would be to make the mechanism session specific depending upon what is stored for a particular user. That allows us to have a single pg_hba.conf entry of "sasl", and then use md5, scram-256 or future-mechanism on a per user basis. I'm not sure I see a clear way forwards yet, these are just ideas and questions to help the discussion. -- Simon Riggshttp://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services -- 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] Password identifiers, protocol aging and SCRAM protocol
On Wed, Jan 18, 2017 at 02:30:38PM +0900, Michael Paquier wrote: > On Wed, Jan 18, 2017 at 2:23 PM, Noah Mischwrote: > > The latest versions document this precisely, but I agree with Peter's > > concern > > about plain "scram". Suppose it's 2025 and PostgreSQL support SASL > > mechanisms > > OAUTHBEARER, SCRAM-SHA-256, SCRAM-SHA-256-PLUS, and SCRAM-SHA3-512. What > > should the pg_hba.conf options look like at that time? I don't think > > having a > > single "scram" option fits in such a world. > > Sure. > > > I see two strategies that fit: > > > > 1. Single "sasl" option, with a GUC, similar to ssl_ciphers, controlling the > >mechanisms to offer. > > 2. Separate options "scram_sha_256", "scram_sha3_512", "oauthbearer", etc. > > Or we could have a sasl option, with a mandatory array of mechanisms > to define one or more items, so method entries in pg_hba.conf would > look llke that: > sasl mechanism=scram_sha_256,scram_sha3_512 I like that. -- 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] Password identifiers, protocol aging and SCRAM protocol
On Tue, Dec 20, 2016 at 10:47 AM, Michael Paquierwrote: > And Heikki has mentioned me that he'd prefer not having an extra > dependency for the normalization, which is LGPL-licensed by the way. > So I have looked at the SASLprep business to see what should be done > to get a complete implementation in core, completely independent of > anything known. > > The first thing is to be able to understand in the SCRAM code if a > string is UTF-8 or not, and this code is in src/common/. pg_wchar.c > offers a set of routines exactly for this purpose, which is built with > libpq but that's not available for src/common/. So instead of moving > all the file, I'd like to create a new file in src/common/utf8.c which > includes pg_utf_mblen() and pg_utf8_islegal(). On top of that I think > that having a routine able to check a full string would be useful for > many users, as pg_utf8_islegal() can only check one set of characters. > If the password string is found to be of UTF-8 format, SASLprepare is > applied. If not, the string is copied as-is with perhaps unexpected > effects for the client But he's in trouble already if client is not > using UTF-8. > > Then comes the real business... Note that's my first time touching > encoding, particularly UTF-8 in depth, so please be nice. I may write > things that are incorrect or sound so from here :) > > The second thing is the normalization itself. Per RFC4013, NFKC needs > to be applied to the string. The operation is described in [1] > completely, and it is named as doing 1) a compatibility decomposition > of the bytes of the string, followed by 2) a canonical composition. > > About 1). The compatibility decomposition is defined in [2], "by > recursively applying the canonical and compatibility mappings, then > applying the canonical reordering algorithm". Canonical and > compatibility mapping are some data available in UnicodeData.txt, the > 6th column of the set defined in [3] to be precise. The meaning of the > decomposition mappings is defined in [2] as well. The canonical > decomposition is basically to look for a given UTF-8 character, and > then apply the multiple characters resulting in its new shape. The > compatibility mapping should as well be applied, but [5], a perl tool > called charlint.pl doing this normalization work, does not care about > this phase... Do we? > > About 2)... Once the decomposition has been applied, those bytes need > to be recomposed using the Canonical_Combining_Class field of > UnicodeData.txt in [3], which is the 3rd column of the set. Its values > are defined in [4]. An other interesting thing, charlint.pl [5] does > not care about this phase. I am wondering if we should as well not > just drop this part as well... > > Once 1) and 2) are done, NKFC is complete, and so is SASLPrepare. > > So what we need from Postgres side is a mapping table to, having the > following fields: > 1) Hexa sequence of UTF8 character. > 2) Its canonical combining class. > 3) The kind of decomposition mapping if defined. > 4) The decomposition mapping, in hexadecimal format. > Based on what I looked at, either perl or python could be used to > process UnicodeData.txt and to generate a header file that would be > included in the tree. There are 30k entries in UnicodeData.txt, 5k of > them have a mapping, so that will result in many tables. One thing to > improve performance would be to store the length of the table in a > static variable, order the entries by their hexadecimal keys and do a > dichotomy lookup to find an entry. We could as well use more fancy > things like a set of tables using a Radix tree using decomposed by > bytes. We should finish by just doing one lookup of the table for each > character sets anyway. > > In conclusion, at this point I am looking for feedback regarding the > following items: > 1) Where to put the UTF8 check routines and what to move. > 2) How to generate the mapping table using UnicodeData.txt. I'd think > that using perl would be better. > 3) The shape of the mapping table, which depends on how many > operations we want to support in the normalization of the strings. > The decisions for those items will drive the implementation in one > sense or another. > > [1]: http://www.unicode.org/reports/tr15/#Description_Norm > [2]: > http://www.unicode.org/Public/5.1.0/ucd/UCD.html#Character_Decomposition_Mappings > [3]: http://www.unicode.org/Public/5.1.0/ucd/UCD.html#UnicodeData.txt > [4]: > http://www.unicode.org/Public/5.1.0/ucd/UCD.html#Canonical_Combining_Class_Values > [5]: https://www.w3.org/International/charlint/ > > Heikki, others, thoughts? FWIW, this patch is on a "waiting on author" state and that's right. As the discussion on SASLprepare() and the decisions regarding the way to implement it, or at least have it, are still pending, I am not planning to move on with any implementation until we have a plan about what to do. Just using libidn (LGPL) for a first shot is rather painless
Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol
On Wed, Jan 18, 2017 at 2:23 PM, Noah Mischwrote: > The latest versions document this precisely, but I agree with Peter's concern > about plain "scram". Suppose it's 2025 and PostgreSQL support SASL mechanisms > OAUTHBEARER, SCRAM-SHA-256, SCRAM-SHA-256-PLUS, and SCRAM-SHA3-512. What > should the pg_hba.conf options look like at that time? I don't think having a > single "scram" option fits in such a world. Sure. > I see two strategies that fit: > > 1. Single "sasl" option, with a GUC, similar to ssl_ciphers, controlling the >mechanisms to offer. > 2. Separate options "scram_sha_256", "scram_sha3_512", "oauthbearer", etc. Or we could have a sasl option, with a mandatory array of mechanisms to define one or more items, so method entries in pg_hba.conf would look llke that: sasl mechanism=scram_sha_256,scram_sha3_512 Users could define different methods in each hba line once a user and a database map. I am not sure if many people would care about that though. -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On Tue, Nov 15, 2016 at 07:52:06AM +0900, Michael Paquier wrote: > On Sat, Nov 5, 2016 at 9:36 PM, Michael Paquier> wrote: > > On Sat, Nov 5, 2016 at 12:58 AM, Peter Eisentraut > > wrote: > > pg_hba.conf uses "scram" as keyword, but scram refers to a family of > > authentication methods. There is as well SCRAM-SHA-1, SCRAM-SHA-256 > > (what this patch does). Hence wouldn't it make sense to use > > scram_sha256 in pg_hba.conf instead? If for example in the future > > there is a SHA-512 version of SCRAM we could switch easily to that and > > define scram_sha512. > > OK, I have added more docs regarding the use of scram in pg_hba.conf, > particularly in client-auth.sgml to describe what scram is better than > md5 in terms of protection, and also completed the data of pg_hba.conf > about the new keyword used in it. The latest versions document this precisely, but I agree with Peter's concern about plain "scram". Suppose it's 2025 and PostgreSQL support SASL mechanisms OAUTHBEARER, SCRAM-SHA-256, SCRAM-SHA-256-PLUS, and SCRAM-SHA3-512. What should the pg_hba.conf options look like at that time? I don't think having a single "scram" option fits in such a world. I see two strategies that fit: 1. Single "sasl" option, with a GUC, similar to ssl_ciphers, controlling the mechanisms to offer. 2. Separate options "scram_sha_256", "scram_sha3_512", "oauthbearer", etc. -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 1/3/17 9:09 AM, Heikki Linnakangas wrote: > Since not everyone agrees with this approach, I split this patch into > two. The first patch refactors things, replacing the isMD5() function > with get_password_type(), without changing the representation of > pg_authid.rolpassword. That is hopefully uncontroversial. I have checked these patches. The refactoring in the first patch seems sensible. As Michael pointed out, there is still a reference to "plain:" in the first patch. The commit message needs to be updated, because the function plain_crypt_verify() was already added in a previous patch. I'm not fond of this kind of coding password = encrypt_password(password_type, stmt->role, password); where the 'password' variable has a different meaning before and after. This error message might be a mistake: elog(ERROR, "unrecognized password type conversion"); I think some pieces from the second patch could be included in the first patch, e.g., the parts for passwordcheck.c and user.c. > And the second > patch adds the "plain:" prefix, which not everyone agrees on. The code also gets a little bit dubious, as it introduces an "unknown" password type, which is sometimes treated as plaintext and sometimes as an error. I think this is going be messy. I would skip this patch for now at least. Too much controversy, and we don't know how the rest of the patches for this feature will look like to be able to know if it's worth it. -- Peter Eisentraut http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Thu, Jan 5, 2017 at 10:31 PM, Peter Eisentrautwrote: > On 1/3/17 9:09 AM, Heikki Linnakangas wrote: >> Since not everyone agrees with this approach, I split this patch into >> two. The first patch refactors things, replacing the isMD5() function >> with get_password_type(), without changing the representation of >> pg_authid.rolpassword. That is hopefully uncontroversial. And the second >> patch adds the "plain:" prefix, which not everyone agrees on. >> >> Barring objections I'm going to at least commit the first patch. I think >> we should commit the second one too, but it's not as critical, and the >> first patch matters more for the SCRAM patch, too. > > Is there currently anything to review here for the commit fest? The patches sent here make sense as part of the SCRAM set: https://www.postgresql.org/message-id/6831df67-7641-1a66-4985-268609a48...@iki.fi I was just waiting for Heikki to fix the split of the patches before moving on with an extra lookup though. -- Michael -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 1/3/17 9:09 AM, Heikki Linnakangas wrote: > Since not everyone agrees with this approach, I split this patch into > two. The first patch refactors things, replacing the isMD5() function > with get_password_type(), without changing the representation of > pg_authid.rolpassword. That is hopefully uncontroversial. And the second > patch adds the "plain:" prefix, which not everyone agrees on. > > Barring objections I'm going to at least commit the first patch. I think > we should commit the second one too, but it's not as critical, and the > first patch matters more for the SCRAM patch, too. Is there currently anything to review here for the commit fest? -- Peter Eisentraut http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Tue, Jan 3, 2017 at 11:09 PM, Heikki Linnakangaswrote: > Since not everyone agrees with this approach, I split this patch into two. > The first patch refactors things, replacing the isMD5() function with > get_password_type(), without changing the representation of > pg_authid.rolpassword. That is hopefully uncontroversial. And the second > patch adds the "plain:" prefix, which not everyone agrees on. > > Barring objections I'm going to at least commit the first patch. I think we > should commit the second one too, but it's not as critical, and the first > patch matters more for the SCRAM patch, too. The split does not look correct to me. 0001 has references to the prefix "plain:". -- Michael -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 12/21/2016 04:09 AM, Michael Paquier wrote: Thanks for having a look! Attached is a new version, with that bug fixed. I have been able more advanced testing without the crash and things seem to work properly. The attached set of tests is also able to pass for all the combinations of hba configurations and password formats. And looking at the code I don't have more comments. Thanks! Since not everyone agrees with this approach, I split this patch into two. The first patch refactors things, replacing the isMD5() function with get_password_type(), without changing the representation of pg_authid.rolpassword. That is hopefully uncontroversial. And the second patch adds the "plain:" prefix, which not everyone agrees on. Barring objections I'm going to at least commit the first patch. I think we should commit the second one too, but it's not as critical, and the first patch matters more for the SCRAM patch, too. - Heikki 0001-Replace-isMD5-with-a-more-future-proof-way-to-check-.patch Description: invalid/octet-stream 0002-Use-plain-prefix-for-plaintext-passwords-stored-in-p.patch Description: invalid/octet-stream -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 12/14/2016 01:33 PM, Heikki Linnakangas wrote: I just noticed that the manual for CREATE ROLE says: Note that older clients might lack support for the MD5 authentication mechanism that is needed to work with passwords that are stored encrypted. That's is incorrect. The alternative to MD5 authentication is plain 'password' authentication, and that works just fine with MD5-hashed passwords. I think that sentence is a leftover from when we still supported "crypt" authentication (so I actually get to blame you for that ;-), commit 53a5026b). Back then, it was true that if an MD5 hash was stored in pg_authid, you couldn't do "crypt" authentication. That might have left old clients out in the cold. Now that we're getting SCRAM authentication, we'll need a similar notice there again, for the incompatibility of a SCRAM verifier with MDD5 authentication and vice versa. I went ahead and removed the current bogus notice from the docs. We might need to put back something like it, with the SCRAM patch, but it needs to be rewritten anyway. - 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: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Tue, Dec 20, 2016 at 9:23 PM, Heikki Linnakangaswrote: > On 12/16/2016 03:31 AM, Michael Paquier wrote: > Actually, it does still perform that check. There's a new function, > plain_crypt_verify, that passwordcheck uses now. plain_crypt_verify() is > intended to work with any future hash formats we might introduce in the > future (including SCRAM), so that passwordcheck doesn't need to know about > all the hash formats. Bah. I have misread the first version of the patch, and it is indeed keeping the username checks. Now that things don't crash that behaves as expected: =# load 'passwordcheck'; LOAD =# alter role mpaquier password 'mpaquier'; ERROR: 22023: password must not contain user name LOCATION: check_password, passwordcheck.c:101 =# alter role mpaquier password 'md58349d3a1bc8f4f7399b1ff9dea493b15'; ERROR: 22023: password must not contain user name LOCATION: check_password, passwordcheck.c:82 With the patch: >> +case PASSWORD_TYPE_PLAINTEXT: >> +shadow_pass = _pass[strlen("plain:")]; >> +break; >> It would be a good idea to have a generic routine able to get the plain >> password value. In short I think that we should reduce the amount of >> locations where "plain:" prefix is hardcoded. > > There is such a function included in the patch, get_plain_password(char > *shadow_pass), actually. Contrib/passwordcheck uses it. I figured that in > crypt.c itself, it's OK to do the above directly, but get_plain_password() > is intended to be used elsewhere. The idea would be to have the function not return an allocated string, just a position to it. That would be useful in plain_crypt_verify() for example, for a total of 4 places, including get_plain_password() where the new string allocation is done. Well, it's not like this prefix "plain:" would change anyway in the future nor that it is going to spread much. > Thanks for having a look! Attached is a new version, with that bug fixed. I have been able more advanced testing without the crash and things seem to work properly. The attached set of tests is also able to pass for all the combinations of hba configurations and password formats. And looking at the code I don't have more comments. -- Michael 009_authentication.pl Description: Perl program -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
David, * David Fetter (da...@fetter.org) wrote: > On Tue, Dec 20, 2016 at 06:14:40PM -0500, Stephen Frost wrote: > > * David Fetter (da...@fetter.org) wrote: > > > On Tue, Dec 20, 2016 at 08:34:19AM -0500, Stephen Frost wrote: > > > > * Heikki Linnakangas (hlinn...@iki.fi) wrote: > > > > > Even if you have a separate "verifier type" column, it's not fully > > > > > normalized, because there's still a dependency between the > > > > > verifier and verifier type columns. You will always need to look > > > > > at the verifier type to make sense of the verifier itself. > > > > > > > > That's true- but you don't need to look at the verifier, or even > > > > have *access* to the verifier, to look at the verifier type. > > > > > > Would a view that shows only what's to the left of the first semicolon > > > suit this purpose? > > > > Obviously a (security barrier...) view or a (security definer) function > > could be used, but I don't believe either is actually a good idea. > > Would you be so kind as to help me understand what's wrong with that idea? For starters, it doubles-down on the assumption that we'll always be happy with that particular separator and implies to anyone watching that they'll be able to trust it. Further, it's additional complication which, at least to my eyes, is entirely in the wrong direction. We could push everything in pg_authid into a single colon-separated text field and call it simpler because we don't have to deal with those silly column things, and we'd have something a lot closer to a unix passwd file too!, but it wouldn't make it a terribly smart thing to do. We aren't a bunch of individual C programs having to parse out things out of flat text files, after all. Thanks! Stephen signature.asc Description: Digital signature
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Tue, Dec 20, 2016 at 06:14:40PM -0500, Stephen Frost wrote: > David, > > * David Fetter (da...@fetter.org) wrote: > > On Tue, Dec 20, 2016 at 08:34:19AM -0500, Stephen Frost wrote: > > > * Heikki Linnakangas (hlinn...@iki.fi) wrote: > > > > Even if you have a separate "verifier type" column, it's not fully > > > > normalized, because there's still a dependency between the > > > > verifier and verifier type columns. You will always need to look > > > > at the verifier type to make sense of the verifier itself. > > > > > > That's true- but you don't need to look at the verifier, or even > > > have *access* to the verifier, to look at the verifier type. > > > > Would a view that shows only what's to the left of the first semicolon > > suit this purpose? > > Obviously a (security barrier...) view or a (security definer) function > could be used, but I don't believe either is actually a good idea. Would you be so kind as to help me understand what's wrong with that idea? Best, David. -- David Fetterhttp://fetter.org/ Phone: +1 415 235 3778 AIM: dfetter666 Yahoo!: dfetter Skype: davidfetter XMPP: david(dot)fetter(at)gmail(dot)com Remember to vote! Consider donating to Postgres: http://www.postgresql.org/about/donate -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
David, * David Fetter (da...@fetter.org) wrote: > On Tue, Dec 20, 2016 at 08:34:19AM -0500, Stephen Frost wrote: > > * Heikki Linnakangas (hlinn...@iki.fi) wrote: > > > Even if you have a separate "verifier type" column, it's not fully > > > normalized, because there's still a dependency between the > > > verifier and verifier type columns. You will always need to look > > > at the verifier type to make sense of the verifier itself. > > > > That's true- but you don't need to look at the verifier, or even > > have *access* to the verifier, to look at the verifier type. > > Would a view that shows only what's to the left of the first semicolon > suit this purpose? Obviously a (security barrier...) view or a (security definer) function could be used, but I don't believe either is actually a good idea. Thanks! Stephen signature.asc Description: Digital signature
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Wed, Dec 21, 2016 at 1:08 AM, David Fetterwrote: > Would a view that shows only what's to the left of the first semicolon > suit this purpose? Of course it would, you would just need to make the routines now checking the shape of MD5 and SCRAM identifiers available at SQL level and feed the strings into them. Now I am not sure that it's worth having a new superuser view for that. pg_roles and pg_shadow hide the information about verifiers. -- Michael -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Tue, Dec 20, 2016 at 08:34:19AM -0500, Stephen Frost wrote: > Heikki, > > * Heikki Linnakangas (hlinn...@iki.fi) wrote: > > Even if you have a separate "verifier type" column, it's not fully > > normalized, because there's still a dependency between the > > verifier and verifier type columns. You will always need to look > > at the verifier type to make sense of the verifier itself. > > That's true- but you don't need to look at the verifier, or even > have *access* to the verifier, to look at the verifier type. Would a view that shows only what's to the left of the first semicolon suit this purpose? Best, David. -- David Fetterhttp://fetter.org/ Phone: +1 415 235 3778 AIM: dfetter666 Yahoo!: dfetter Skype: davidfetter XMPP: david(dot)fetter(at)gmail(dot)com Remember to vote! Consider donating to Postgres: http://www.postgresql.org/about/donate -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
Heikki, * Heikki Linnakangas (hlinn...@iki.fi) wrote: > Even if you have a separate "verifier type" column, it's not fully > normalized, because there's still a dependency between the verifier > and verifier type columns. You will always need to look at the > verifier type to make sense of the verifier itself. That's true- but you don't need to look at the verifier, or even have *access* to the verifier, to look at the verifier type. That is actually very useful when you start thinking about the downstream side of this- what about the monitoring tool which will want to check and make sure there are only certain verifier types being used? It'll have to be a superuser, or have access to some superuser security defined function, and that really sucks. I'm not saying that we would necessairly want the verifier type to be publicly visible, but being able to see it without being a superuser would be good, imv. > It's more convenient to carry the type information with the verifier > itself, in backend code, in pg_dump, etc. Sure, you could have a > separate "transfer" text format that has the prefix, and strip it > out when the datum enters the system. But it is even simpler to have > only one format, with the prefix, and use that everywhere. It's more convenient when you need to look at both- it's not more convenient when you only wish to look at the verifier type. Further, it means that we have to have a construct that assumes things about the verifier type and verifier- what if a verifier type came along that used a colon? We'd have to do some special magic to handle that correctly, and that just sucks, and anyone who is writing code to generically deal with these fields will end up writing that same code (or forgetting to, and not handling the case correctly). > It might make sense to add a separate column, to e.g. make it easier > to e.g. query for users that have an MD5 verifier. You could do > "WHERE rolverifiertype = 'md5'", instead of "WHERE rolpassword LIKE > 'md5%'". It's not a big difference, though. But even if we did that, > I would still love to have the type information *also* included with > the verifier itself, for convenience. And if we include it in the > verifier itself, adding a separate type column seems more trouble > than it's worth. I don't agree that it's "not a big difference." As I argue above- your approach also assumes that anyone who would like to investigate the verifier type should have access to the verifier itself, which I do not agree with. I also have a hard time buying the argument that it's really so much more convenient to have the verifier type included in the same string as the verifier that we should duplicate that information and then run the risk that we end up with the two not matching or that we won't ever run into complications down the road when our chosen separator causes us difficulties. Thanks! Stephen signature.asc Description: Digital signature
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Tue, Dec 20, 2016 at 6:37 AM, Heikki Linnakangaswrote: > It's more convenient to carry the type information with the verifier itself, > in backend code, in pg_dump, etc. Sure, you could have a separate "transfer" > text format that has the prefix, and strip it out when the datum enters the > system. But it is even simpler to have only one format, with the prefix, and > use that everywhere. I see your point. -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 12/16/2016 03:31 AM, Michael Paquier wrote: On Thu, Dec 15, 2016 at 9:48 PM, Heikki Linnakangaswrote: The only way to distinguish, is to know about every verifier kind there is, and check whether rolpassword looks valid as anything else than a plaintext password. And we already got tripped by a bug-of-omission on that once. If we add more verifier formats in the future, it's bound to happen again. Let's nip that source of bugs in the bud. Attached is a patch to implement what I have in mind. OK, I had a look at the patch proposed. -if (!pg_md5_encrypt(username, username, namelen, encrypted)) -elog(ERROR, "password encryption failed"); -if (strcmp(password, encrypted) == 0) -ereport(ERROR, -(errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("password must not contain user name"))); This patch removes the only possible check for MD5 hashes that it has never been done in passwordcheck. It may be fine to remove it, but I would think that it is a good source of example regarding what could be done with MD5 hashes, though limited. So it seems to me that this check should involve as well pg_md5_encrypt on the username and compare if with the MD5 hash given by the caller. Actually, it does still perform that check. There's a new function, plain_crypt_verify, that passwordcheck uses now. plain_crypt_verify() is intended to work with any future hash formats we might introduce in the future (including SCRAM), so that passwordcheck doesn't need to know about all the hash formats. A simple ALTER USER role PASSWORD 'foo' causes a crash: Ah, fixed. +case PASSWORD_TYPE_PLAINTEXT: +shadow_pass = _pass[strlen("plain:")]; +break; It would be a good idea to have a generic routine able to get the plain password value. In short I think that we should reduce the amount of locations where "plain:" prefix is hardcoded. There is such a function included in the patch, get_plain_password(char *shadow_pass), actually. Contrib/passwordcheck uses it. I figured that in crypt.c itself, it's OK to do the above directly, but get_plain_password() is intended to be used elsewhere. Thanks for having a look! Attached is a new version, with that bug fixed. - Heikki 0001-Use-plain-prefix-for-plaintext-passwords-stored-in-p-2.patch Description: invalid/octet-stream -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 12/16/2016 05:48 PM, Robert Haas wrote: On Thu, Dec 15, 2016 at 8:40 AM, Stephen Frostwrote: * Heikki Linnakangas (hlinn...@iki.fi) wrote: On 12/14/2016 04:57 PM, Stephen Frost wrote: * Peter Eisentraut (peter.eisentr...@2ndquadrant.com) wrote: On 12/14/16 5:15 AM, Michael Paquier wrote: I would be tempted to suggest adding the verifier type as a new column of pg_authid Yes please. This discussion seems to continue to come up and I don't entirely understand why we keep trying to shove more things into pg_authid, or worse, into rolpassword. I understand the relational beauty of having a separate column for the verifier type, but I don't think it would be practical. I disagree. Me, too. I think the idea of moving everything into a separate table that allows multiple verifiers is probably not a good thing to do just right now, because that introduces a bunch of additional issues above and beyond what we need to do to get SCRAM implemented. There are administration and policy decisions to be made there that we should not conflate with SCRAM proper. However, Heikki's proposal seems to be that it's reasonable to force rolpassword to be of the form 'type:verifier' in all cases but not reasonable to have separate columns for type and verifier. Eh? I fear we'll just have to agree to disagree here, but I'll try to explain myself one more time. Even if you have a separate "verifier type" column, it's not fully normalized, because there's still a dependency between the verifier and verifier type columns. You will always need to look at the verifier type to make sense of the verifier itself. It's more convenient to carry the type information with the verifier itself, in backend code, in pg_dump, etc. Sure, you could have a separate "transfer" text format that has the prefix, and strip it out when the datum enters the system. But it is even simpler to have only one format, with the prefix, and use that everywhere. It might make sense to add a separate column, to e.g. make it easier to e.g. query for users that have an MD5 verifier. You could do "WHERE rolverifiertype = 'md5'", instead of "WHERE rolpassword LIKE 'md5%'". It's not a big difference, though. But even if we did that, I would still love to have the type information *also* included with the verifier itself, for convenience. And if we include it in the verifier itself, adding a separate type column seems more trouble than it's worth. For comparison, imagine that we added a column to pg_authid for a picture of the user, stored as a bytea. The picture can be in JPEG or PNG format. Looking at the first few bytes of the image, you can tell which one it is. Would it make sense to add a separate "type" column, to tell what format the image is in? I think it would be more convenient and robust to rely on the first bytes of the image data instead. - 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: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Sat, Dec 17, 2016 at 5:48 PM, Michael Paquierwrote: > On Sun, Dec 18, 2016 at 3:59 AM, Robert Haas wrote: >> On Fri, Dec 16, 2016 at 5:30 PM, Michael Paquier >> wrote: >>> From the discussions of last year on -hackers, it was decided to *not* >>> have an additional column per complains from a couple of hackers >>> (Robert you were in this set at this point), ... >> >> Hmm, I don't recall taking that position, but then there are a lot of >> things that I ought to recall and don't. (Ask my wife!) > > [... digging objects of the past ...] > From the past thread: > https://www.postgresql.org/message-id/ca+tgmoy790rphhbogxmbtg6mzsendoxdbxebekaet9zpz8g...@mail.gmail.com > The complain is directed directly to multiple verifiers per users > though, not to have the type in a separate column. Yes, I rather like the separate column. But since Heikki is doing the work (or if he is) I'm not going to gripe too much. -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company -- 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] Password identifiers, protocol aging and SCRAM protocol
On Thu, Dec 15, 2016 at 3:17 PM, Michael Paquierwrote: > In the case where the binaries are *not* built with libidn, I think > that we had better reject valid UTF-8 string directly and just allow > ASCII? SASLprep is a no-op on ASCII characters. > > Thoughts about this approach? And Heikki has mentioned me that he'd prefer not having an extra dependency for the normalization, which is LGPL-licensed by the way. So I have looked at the SASLprep business to see what should be done to get a complete implementation in core, completely independent of anything known. The first thing is to be able to understand in the SCRAM code if a string is UTF-8 or not, and this code is in src/common/. pg_wchar.c offers a set of routines exactly for this purpose, which is built with libpq but that's not available for src/common/. So instead of moving all the file, I'd like to create a new file in src/common/utf8.c which includes pg_utf_mblen() and pg_utf8_islegal(). On top of that I think that having a routine able to check a full string would be useful for many users, as pg_utf8_islegal() can only check one set of characters. If the password string is found to be of UTF-8 format, SASLprepare is applied. If not, the string is copied as-is with perhaps unexpected effects for the client But he's in trouble already if client is not using UTF-8. Then comes the real business... Note that's my first time touching encoding, particularly UTF-8 in depth, so please be nice. I may write things that are incorrect or sound so from here :) The second thing is the normalization itself. Per RFC4013, NFKC needs to be applied to the string. The operation is described in [1] completely, and it is named as doing 1) a compatibility decomposition of the bytes of the string, followed by 2) a canonical composition. About 1). The compatibility decomposition is defined in [2], "by recursively applying the canonical and compatibility mappings, then applying the canonical reordering algorithm". Canonical and compatibility mapping are some data available in UnicodeData.txt, the 6th column of the set defined in [3] to be precise. The meaning of the decomposition mappings is defined in [2] as well. The canonical decomposition is basically to look for a given UTF-8 character, and then apply the multiple characters resulting in its new shape. The compatibility mapping should as well be applied, but [5], a perl tool called charlint.pl doing this normalization work, does not care about this phase... Do we? About 2)... Once the decomposition has been applied, those bytes need to be recomposed using the Canonical_Combining_Class field of UnicodeData.txt in [3], which is the 3rd column of the set. Its values are defined in [4]. An other interesting thing, charlint.pl [5] does not care about this phase. I am wondering if we should as well not just drop this part as well... Once 1) and 2) are done, NKFC is complete, and so is SASLPrepare. So what we need from Postgres side is a mapping table to, having the following fields: 1) Hexa sequence of UTF8 character. 2) Its canonical combining class. 3) The kind of decomposition mapping if defined. 4) The decomposition mapping, in hexadecimal format. Based on what I looked at, either perl or python could be used to process UnicodeData.txt and to generate a header file that would be included in the tree. There are 30k entries in UnicodeData.txt, 5k of them have a mapping, so that will result in many tables. One thing to improve performance would be to store the length of the table in a static variable, order the entries by their hexadecimal keys and do a dichotomy lookup to find an entry. We could as well use more fancy things like a set of tables using a Radix tree using decomposed by bytes. We should finish by just doing one lookup of the table for each character sets anyway. In conclusion, at this point I am looking for feedback regarding the following items: 1) Where to put the UTF8 check routines and what to move. 2) How to generate the mapping table using UnicodeData.txt. I'd think that using perl would be better. 3) The shape of the mapping table, which depends on how many operations we want to support in the normalization of the strings. The decisions for those items will drive the implementation in one sense or another. [1]: http://www.unicode.org/reports/tr15/#Description_Norm [2]: http://www.unicode.org/Public/5.1.0/ucd/UCD.html#Character_Decomposition_Mappings [3]: http://www.unicode.org/Public/5.1.0/ucd/UCD.html#UnicodeData.txt [4]: http://www.unicode.org/Public/5.1.0/ucd/UCD.html#Canonical_Combining_Class_Values [5]: https://www.w3.org/International/charlint/ Heikki, others, thoughts? -- Michael -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Sun, Dec 18, 2016 at 3:59 AM, Robert Haaswrote: > On Fri, Dec 16, 2016 at 5:30 PM, Michael Paquier > wrote: >> From the discussions of last year on -hackers, it was decided to *not* >> have an additional column per complains from a couple of hackers >> (Robert you were in this set at this point), ... > > Hmm, I don't recall taking that position, but then there are a lot of > things that I ought to recall and don't. (Ask my wife!) [... digging objects of the past ...] >From the past thread: https://www.postgresql.org/message-id/ca+tgmoy790rphhbogxmbtg6mzsendoxdbxebekaet9zpz8g...@mail.gmail.com The complain is directed directly to multiple verifiers per users though, not to have the type in a separate column. -- Michael -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Fri, Dec 16, 2016 at 5:30 PM, Michael Paquierwrote: > On Sat, Dec 17, 2016 at 5:42 AM, Stephen Frost wrote: >> * Peter Eisentraut (peter.eisentr...@2ndquadrant.com) wrote: >>> On 12/15/16 8:40 AM, Stephen Frost wrote: >>> > I don't follow why we can't change the syntax for CREATE USER to allow >>> > specifying the verifier type independently. >>> >>> That's what the last patch set I looked at actually does. >> >> Well, same here, but it was quite a while ago and things have progressed >> since then wrt SCRAM, as I understand it... > > From the discussions of last year on -hackers, it was decided to *not* > have an additional column per complains from a couple of hackers > (Robert you were in this set at this point), ... Hmm, I don't recall taking that position, but then there are a lot of things that I ought to recall and don't. (Ask my wife!) -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Sat, Dec 17, 2016 at 10:23 AM, Stephen Frostwrote: > * Michael Paquier (michael.paqu...@gmail.com) wrote: >> (Robert you were in this set at this point), and the same thing was >> concluded during the informal lunch meeting at PGcon. The point is, >> the existing SCRAM patch set can survive without touching at *all* the >> format of pg_authid. We could block SCRAM authentication when >> "password" is used in pg_hba.conf and as well as when "scram" is used >> with a plain password stored in pg_authid. Or look at the format of >> the string in the catalog if "password" is defined and decide the >> authentication protocol to follow based on that. > > As I mentioned up-thread, moving forward with minimal changes to get > SCRAM in certainly makes sense, but I do think we should be open to > (and, ideally, encouraging people to work towards) having a seperate > table for verifiers with independent columns for type and verifier. Definitely, and you know my position on the matter or I would not have written last year's patch series. Both things are just orthogonal IMO at this point. And it would be good to focus just on one problem at the moment to get it out. -- Michael -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
Michael, * Michael Paquier (michael.paqu...@gmail.com) wrote: > On Sat, Dec 17, 2016 at 5:42 AM, Stephen Frostwrote: > > * Peter Eisentraut (peter.eisentr...@2ndquadrant.com) wrote: > >> On 12/15/16 8:40 AM, Stephen Frost wrote: > >> > I don't follow why we can't change the syntax for CREATE USER to allow > >> > specifying the verifier type independently. > >> > >> That's what the last patch set I looked at actually does. > > > > Well, same here, but it was quite a while ago and things have progressed > > since then wrt SCRAM, as I understand it... > > From the discussions of last year on -hackers, it was decided to *not* > have an additional column per complains from a couple of hackers It seems that, at best, we didn't have consensus on it. Hopefully we are moving in a direction of consensus. > (Robert you were in this set at this point), and the same thing was > concluded during the informal lunch meeting at PGcon. The point is, > the existing SCRAM patch set can survive without touching at *all* the > format of pg_authid. We could block SCRAM authentication when > "password" is used in pg_hba.conf and as well as when "scram" is used > with a plain password stored in pg_authid. Or look at the format of > the string in the catalog if "password" is defined and decide the > authentication protocol to follow based on that. As I mentioned up-thread, moving forward with minimal changes to get SCRAM in certainly makes sense, but I do think we should be open to (and, ideally, encouraging people to work towards) having a seperate table for verifiers with independent columns for type and verifier. Thanks! Stephen signature.asc Description: Digital signature
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Sat, Dec 17, 2016 at 5:42 AM, Stephen Frostwrote: > * Peter Eisentraut (peter.eisentr...@2ndquadrant.com) wrote: >> On 12/15/16 8:40 AM, Stephen Frost wrote: >> > I don't follow why we can't change the syntax for CREATE USER to allow >> > specifying the verifier type independently. >> >> That's what the last patch set I looked at actually does. > > Well, same here, but it was quite a while ago and things have progressed > since then wrt SCRAM, as I understand it... >From the discussions of last year on -hackers, it was decided to *not* have an additional column per complains from a couple of hackers (Robert you were in this set at this point), and the same thing was concluded during the informal lunch meeting at PGcon. The point is, the existing SCRAM patch set can survive without touching at *all* the format of pg_authid. We could block SCRAM authentication when "password" is used in pg_hba.conf and as well as when "scram" is used with a plain password stored in pg_authid. Or look at the format of the string in the catalog if "password" is defined and decide the authentication protocol to follow based on that. -- Michael -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
* Peter Eisentraut (peter.eisentr...@2ndquadrant.com) wrote: > On 12/15/16 8:40 AM, Stephen Frost wrote: > > I don't follow why we can't change the syntax for CREATE USER to allow > > specifying the verifier type independently. > > That's what the last patch set I looked at actually does. Well, same here, but it was quite a while ago and things have progressed since then wrt SCRAM, as I understand it... Thanks! Stephen signature.asc Description: Digital signature
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 12/15/16 8:40 AM, Stephen Frost wrote: > I don't follow why we can't change the syntax for CREATE USER to allow > specifying the verifier type independently. That's what the last patch set I looked at actually does. -- Peter Eisentraut http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Thu, Dec 15, 2016 at 8:40 AM, Stephen Frostwrote: > * Heikki Linnakangas (hlinn...@iki.fi) wrote: >> On 12/14/2016 04:57 PM, Stephen Frost wrote: >> >* Peter Eisentraut (peter.eisentr...@2ndquadrant.com) wrote: >> >>On 12/14/16 5:15 AM, Michael Paquier wrote: >> >>>I would be tempted to suggest adding the verifier type as a new column >> >>>of pg_authid >> >> >> >>Yes please. >> > >> >This discussion seems to continue to come up and I don't entirely >> >understand why we keep trying to shove more things into pg_authid, or >> >worse, into rolpassword. >> >> I understand the relational beauty of having a separate column for >> the verifier type, but I don't think it would be practical. > > I disagree. Me, too. I think the idea of moving everything into a separate table that allows multiple verifiers is probably not a good thing to do just right now, because that introduces a bunch of additional issues above and beyond what we need to do to get SCRAM implemented. There are administration and policy decisions to be made there that we should not conflate with SCRAM proper. However, Heikki's proposal seems to be that it's reasonable to force rolpassword to be of the form 'type:verifier' in all cases but not reasonable to have separate columns for type and verifier. Eh? >> For >> starters, we'd still like to have a self-identifying string format >> like "scram-sha-256:", so that you can conveniently pass the >> verifier as a string to CREATE USER. > > I don't follow why we can't change the syntax for CREATE USER to allow > specifying the verifier type independently. Generally speaking, I don't > expect *users* to be providing actual encoded *verifiers* very often, so > it seems like a bit of extra syntax that pg_dump has to use isn't that > big of a deal. We don't have to change the CREATE USER syntax at all. It could just split on the first colon and put the two halves of the string in different places. Of course, changing the syntax might be a good idea anyway -- or not --- but the point is, right now, when you look at rolpassword, there's not a clear rule for what kind of thing you've got in there. That's absolutely terrible design and has got to be fixed. Heikki's proposal of prefixing every entry with a type and a ':' will solve that problem and I'm not going to roll over in my grave if we do it that way, but there is such a thing as normalization and that technique could be applied here. -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Thu, Dec 15, 2016 at 9:48 PM, Heikki Linnakangaswrote: > The only way to distinguish, is to know about every verifier kind there is, > and check whether rolpassword looks valid as anything else than a plaintext > password. And we already got tripped by a bug-of-omission on that once. If > we add more verifier formats in the future, it's bound to happen again. > Let's nip that source of bugs in the bud. Attached is a patch to implement > what I have in mind. OK, I had a look at the patch proposed. -if (!pg_md5_encrypt(username, username, namelen, encrypted)) -elog(ERROR, "password encryption failed"); -if (strcmp(password, encrypted) == 0) -ereport(ERROR, -(errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("password must not contain user name"))); This patch removes the only possible check for MD5 hashes that it has never been done in passwordcheck. It may be fine to remove it, but I would think that it is a good source of example regarding what could be done with MD5 hashes, though limited. So it seems to me that this check should involve as well pg_md5_encrypt on the username and compare if with the MD5 hash given by the caller. The new code is being careful about trying to pass down a plain password, but it is possible to load MD5 hashes directly as well, aka pg_dumpall. A simple ALTER USER role PASSWORD 'foo' causes a crash: #0 0x004764d7 in heap_compute_data_size (tupleDesc=0x277f090, values=0x27504b8, isnull=0x2750550 "") at heaptuple.c:106 106 VARATT_CAN_MAKE_SHORT(DatumGetPointer(val))) (gdb) bt #0 0x004764d7 in heap_compute_data_size (tupleDesc=0x277f090, values=0x27504b8, isnull=0x2750550 "") at heaptuple.c:106 #1 0x004781e9 in heap_form_tuple (tupleDescriptor=0x277f090, values=0x27504b8, isnull=0x2750550 "") at heaptuple.c:736 #2 0x004784d0 in heap_modify_tuple (tuple=0x277adc8, tupleDesc=0x277f090, replValues=0x7fff1369d030, replIsnull=0x7fff1369d020 "", doReplace=0x7fff1369d010 "") at heaptuple.c:833 #3 0x00673788 in AlterRole (stmt=0x27a4f78) at user.c:845 #4 0x0082aa49 in standard_ProcessUtility (parsetree=0x27a4f78, queryString=0x27a43e8 "alter role ioltas password 'toto';", context=PROCESS_UTILITY_TOPLEVEL, params=0x0, dest=0x27a5300, completionTag=0x7fff1369d5b0 "") at utility.c:711 +case PASSWORD_TYPE_PLAINTEXT: +shadow_pass = _pass[strlen("plain:")]; +break; It would be a good idea to have a generic routine able to get the plain password value. In short I think that we should reduce the amount of locations where "plain:" prefix is hardcoded. > Alternatively, you could argue that we should forbid storing passwords in > plaintext altogether. I'm OK with that, too, if that's what people prefer. > Then you cannot have a user that can log in with both MD5 and SCRAM > authentication, but it's certainly more secure, and it's easier to document. At the end this may prove to be a bad idea for some developers. In local deployments when working on a backend application with Postgres as backend, it is actually useful to have plain passwords. At least I have found that useful in some stuff I did many years ago. -- Michael -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
* Heikki Linnakangas (hlinn...@iki.fi) wrote: > On 12/14/2016 04:57 PM, Stephen Frost wrote: > >* Peter Eisentraut (peter.eisentr...@2ndquadrant.com) wrote: > >>On 12/14/16 5:15 AM, Michael Paquier wrote: > >>>I would be tempted to suggest adding the verifier type as a new column > >>>of pg_authid > >> > >>Yes please. > > > >This discussion seems to continue to come up and I don't entirely > >understand why we keep trying to shove more things into pg_authid, or > >worse, into rolpassword. > > I understand the relational beauty of having a separate column for > the verifier type, but I don't think it would be practical. I disagree. > For > starters, we'd still like to have a self-identifying string format > like "scram-sha-256:", so that you can conveniently pass the > verifier as a string to CREATE USER. I don't follow why we can't change the syntax for CREATE USER to allow specifying the verifier type independently. Generally speaking, I don't expect *users* to be providing actual encoded *verifiers* very often, so it seems like a bit of extra syntax that pg_dump has to use isn't that big of a deal. > I think it'll be much better to > stick to one format, than try to split the verifier into type and > the string, when it enters the catalog table. Apparently, multiple people disagree with this approach. I don't think history is really on your side here either. > >We should have an independent table for the verifiers, which has a > >different column for the verifier type, and either starts off supporting > >multiple verifiers per role or at least gives us the ability to add that > >easily later. We should also move rolvaliduntil to that new table. > > I agree we'll probably need a new table for verifiers. Or turn > rolpassword into an array or something. We discussed that before, > however, and it didn't really go anywhere, so right now I'd like to > get SCRAM in with minimal changes to the rest of the system. There > is a lot of room for improvement once it's in. Using an array strikes me as an absolutely terrible idea- how are you going to handle having different valid_until times then? I do agree with trying to get SCRAM in without changing too much of the rest of the system, but I wanted to make it clear that it's the only point that I agree with for continuing down this path and that we should absolutely be looking to change the CREATE USER syntax to specify the verifier independently, plan to use a different table for the verifiers with an independent column for the verifier type, support multiple verifiers per role, etc, in the (hopefully very near...) future. Thanks! Stephen signature.asc Description: Digital signature
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 12/15/2016 03:00 AM, Michael Paquier wrote: On Wed, Dec 14, 2016 at 8:33 PM, Heikki Linnakangaswrote: But, a password stored in plaintext works with either MD5 or SCRAM, or any future authentication mechanism. So as soon as we have SCRAM authentication, it becomes somewhat useful again. In a nutshell: auth / stored MD5 SCRAM plaintext - passwordY Y Y md5 Y N Y scram N Y Y If a password is stored in plaintext, it can be used with any authentication mechanism. And the plaintext 'password' authentication mechanism works with any kind of a stored password. But an MD5 hash cannot be used with SCRAM authentication, or vice versa. So.. I have been thinking about this portion of the thread. And what I find the most scary is not the fact that we use plain passwords for SCRAM authentication, it is the fact that we would need to do a catalog lookup earlier in the connection workflow to decide what is the connection protocol to use depending on the username provided in the startup packet if the pg_hba.conf entry matching the user and database names uses "password". I don't see why we would need to do a catalog lookup any earlier. With "password" authentication, the server can simply request the client to send its password. When it receives it, it performs the catalog lookup to get pg_authid.rolpassword. If it's in plaintext, just compare it, if it's an MD5 hash, hash the client's password and compare, and if it's a SCRAM verifier, build a verifier with the same salt and iteration count and compare. And, honestly, why do we actually need to have a support table that spread? SCRAM is designed to be secure, so it seems to me that it would on the contrary a bad idea to encourage the use of plain passwords if we actually think that they should never be used (they are actually useful for located, development instances, not production ones). I agree we should not encourage bad password practices. But as long as we support passwords to be stored in plaintext at all, it makes no sense to not allow them to be used with SCRAM. The fact that you can use a password stored in plaintext with both MD5 and SCRAM is literally the only reason you would store a password in plaintext, so if we don't want to allow that, we should disallow storing passwords in plaintext altogether. So what I would suggest would be to have a support table like that: auth / stored MD5 SCRAM plaintext - passwordY Y N md5 Y N Y scram N N Y I was using 'Y' to indicate that the combination works, and 'N' to indicate that it does not. Assuming you're using the same notation, the above doesn't make any sense. So here is an idea for things to do now: 1) do not change the format of the existing passwords 2) do not change pg_authid 3) block access to instances if "password" or "md5" are used in pg_hba.conf if the user have a SCRAM verifier. 4) block access if "scram" is used and if user has a plain or md5 verifier. 5) Allow access if "scram" is used and if user has a SCRAM verifier. We had a similar discussion regarding verifier/password formats last year but that did not end well. It would be sad to fall back again into this discussion and get no result. If somebody wants to support access to SCRAM with plain password entries, why not. But that would gain a -1 from me regarding the earlier lookup of pg_authid needed to do the decision making on the protocol to use. And I think that we want SCRAM to be designed to be a maximum stable and secure. The bottom line is that at the moment, when plaintext passwords are stored as is, without any indicator that it's a plaintext password, it's ambiguous whether a password is a SCRAM verifier, or if it's a plaintext password that just happens to begin with the word "scram:". That is completely unrelated to which combinations of stored passwords and authentication mechanisms we actually support or allow to work. The only way to distinguish, is to know about every verifier kind there is, and check whether rolpassword looks valid as anything else than a plaintext password. And we already got tripped by a bug-of-omission on that once. If we add more verifier formats in the future, it's bound to happen again. Let's nip that source of bugs in the bud. Attached is a patch to implement what I have in mind. Alternatively, you could argue that we should forbid storing passwords in plaintext altogether. I'm OK with that, too, if that's what people prefer. Then you cannot have a user that can log in with both MD5 and SCRAM authentication, but it's certainly more secure, and it's easier to document. - Heikki 0001-Use-plain-prefix-for-plaintext-passwords-stored-in-p.patch Description: invalid/octet-stream -- Sent via pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 12/14/2016 04:57 PM, Stephen Frost wrote: * Peter Eisentraut (peter.eisentr...@2ndquadrant.com) wrote: On 12/14/16 5:15 AM, Michael Paquier wrote: I would be tempted to suggest adding the verifier type as a new column of pg_authid Yes please. This discussion seems to continue to come up and I don't entirely understand why we keep trying to shove more things into pg_authid, or worse, into rolpassword. I understand the relational beauty of having a separate column for the verifier type, but I don't think it would be practical. For starters, we'd still like to have a self-identifying string format like "scram-sha-256:", so that you can conveniently pass the verifier as a string to CREATE USER. I think it'll be much better to stick to one format, than try to split the verifier into type and the string, when it enters the catalog table. We should have an independent table for the verifiers, which has a different column for the verifier type, and either starts off supporting multiple verifiers per role or at least gives us the ability to add that easily later. We should also move rolvaliduntil to that new table. I agree we'll probably need a new table for verifiers. Or turn rolpassword into an array or something. We discussed that before, however, and it didn't really go anywhere, so right now I'd like to get SCRAM in with minimal changes to the rest of the system. There is a lot of room for improvement once it's in. - 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] Password identifiers, protocol aging and SCRAM protocol
On Tue, Dec 13, 2016 at 2:44 PM, Michael Paquierwrote: > SASLPrep is defined here: > https://tools.ietf.org/html/rfc4013 > And stringprep is here: > https://tools.ietf.org/html/rfc3454 > So that's roughly applying a conversion from the mapping table, taking > into account prohibited, bi-directional, mapping characters, etc. The > spec says that the password should be in unicode. But we cannot be > sure of that, right? Those mapping tables should be likely a separated > thing.. (perl has Unicode::Stringprep::Mapping for example). OK. I have look at that and I have bumped into libidn, that offers a couple of APIs that could be used directly for this purpose. Particularly, what has caught my eyes is stringprep_profile(): https://www.gnu.org/software/libidn/manual/html_node/Stringprep-Functions.html res = stringprep_profile (input, output, "SASLprep", STRINGPREP_NO_UNASSIGNED); libidn can be installed on Windows, and I have found packages for cygwin, mingw, linux, freebsd and macos via brew. In the case where libidn is not installed, I think that the safest path would be to check if the input string has any high bits set (0x80) and bail out because that would mean that it is a UTF-8 string that we cannot change. Any thoughts about using libidn? Also, after discussion with Heikki, here are the things that we need to do: 1) In libpq, we need to check if the string is valid utf-8. If that's valid utf-8, apply SASLprep. if not, copy the string as-is. We could error as well in this case... Perhaps a WARNING could be more adapted, that's the most tricky case, and if the client does not use utf-8 that may lead to unexpected behavior. 2) In server, when the password verifier is created. If client_encoding is utf-8, but not server_encoding, convert the password to utf-8 and build the verifier after applying SASLprep. In the case where the binaries are *not* built with libidn, I think that we had better reject valid UTF-8 string directly and just allow ASCII? SASLprep is a no-op on ASCII characters. Thoughts about this approach? -- Michael -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Wed, Dec 14, 2016 at 8:33 PM, Heikki Linnakangaswrote: > But, a password stored in plaintext works with either MD5 or SCRAM, or any > future authentication mechanism. So as soon as we have SCRAM authentication, > it becomes somewhat useful again. > > In a nutshell: > > auth / stored MD5 SCRAM plaintext > - > passwordY Y Y > md5 Y N Y > scram N Y Y > > If a password is stored in plaintext, it can be used with any authentication > mechanism. And the plaintext 'password' authentication mechanism works with > any kind of a stored password. But an MD5 hash cannot be used with SCRAM > authentication, or vice versa. So.. I have been thinking about this portion of the thread. And what I find the most scary is not the fact that we use plain passwords for SCRAM authentication, it is the fact that we would need to do a catalog lookup earlier in the connection workflow to decide what is the connection protocol to use depending on the username provided in the startup packet if the pg_hba.conf entry matching the user and database names uses "password". And, honestly, why do we actually need to have a support table that spread? SCRAM is designed to be secure, so it seems to me that it would on the contrary a bad idea to encourage the use of plain passwords if we actually think that they should never be used (they are actually useful for located, development instances, not production ones). So what I would suggest would be to have a support table like that: auth / stored MD5 SCRAM plaintext - passwordY Y N md5 Y N Y scram N N Y So here is an idea for things to do now: 1) do not change the format of the existing passwords 2) do not change pg_authid 3) block access to instances if "password" or "md5" are used in pg_hba.conf if the user have a SCRAM verifier. 4) block access if "scram" is used and if user has a plain or md5 verifier. 5) Allow access if "scram" is used and if user has a SCRAM verifier. We had a similar discussion regarding verifier/password formats last year but that did not end well. It would be sad to fall back again into this discussion and get no result. If somebody wants to support access to SCRAM with plain password entries, why not. But that would gain a -1 from me regarding the earlier lookup of pg_authid needed to do the decision making on the protocol to use. And I think that we want SCRAM to be designed to be a maximum stable and secure. -- Michael -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 12/14/2016 11:41 AM, Stephen Frost wrote: * Heikki Linnakangas (hlinn...@iki.fi) wrote: On 14 December 2016 20:12:05 EET, Bruce Momjianwrote: On Wed, Dec 14, 2016 at 11:27:15AM +0100, Magnus Hagander wrote: Storing plaintext passwords has been bad form for just about forever and I wouldn't be sad to see our support of it go. At the least, as was discussed somewhere, but I'm not sure where it ended up, we should give administrators the ability to control what ways a password can be stored. In particular, once a user has migrated all of their users to SCRAM, they should be able to say "don't let new passwords be in any format other than SCRAM-SHA-256". It isn't as bad as it used to be. I remember with PASSWORD was the default. I agree that we should be able to set a policy that says, "we only allow X for password storage". JD Thanks! Stephen -- Command Prompt, Inc. http://the.postgres.company/ +1-503-667-4564 PostgreSQL Centered full stack support, consulting and development. Everyone appreciates your honesty, until you are honest with them. -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
* Heikki Linnakangas (hlinn...@iki.fi) wrote: > On 14 December 2016 20:12:05 EET, Bruce Momjianwrote: > >On Wed, Dec 14, 2016 at 11:27:15AM +0100, Magnus Hagander wrote: > >> I would so like to just drop support for plain passwords completely > >:) But > >> there's a backwards compatibility issue to think about of course. > >> > >> But -- is there any actual usecase for them anymore? > > > >I thought we recommended 'password' for SSL connections because if you > >use MD5 passwords the password text layout is known and that simplifies > >cryptanalysis. > > No, that makes no sense. And whether you use 'password' or 'md5' > authentication is a different question than whether you store passwords in > plaintext or as md5 hashes. Magnus was asking whether it ever makes sense to > *store* passwords in plaintext. Right. > Since you brought it up, there is a legitimate argument to be made that > 'password' authentication is more secure than 'md5', when SSL is used. > Namely, if an attacker can acquire contents of pg_authid e.g. by stealing a > backup tape, with 'md5' authentication he can log in as any user, using just > the stolen hashes. But with 'password', he needs to reverse the hash first. > It's not a great difference, but it's something. Tunnelled passwords which are stored as hashes is also well understood and comparable to SSH with passwords in /etc/passwd. Storing plaintext passwords has been bad form for just about forever and I wouldn't be sad to see our support of it go. At the least, as was discussed somewhere, but I'm not sure where it ended up, we should give administrators the ability to control what ways a password can be stored. In particular, once a user has migrated all of their users to SCRAM, they should be able to say "don't let new passwords be in any format other than SCRAM-SHA-256". Thanks! Stephen signature.asc Description: Digital signature
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 14 December 2016 20:12:05 EET, Bruce Momjianwrote: >On Wed, Dec 14, 2016 at 11:27:15AM +0100, Magnus Hagander wrote: >> I would so like to just drop support for plain passwords completely >:) But >> there's a backwards compatibility issue to think about of course. >> >> But -- is there any actual usecase for them anymore? > >I thought we recommended 'password' for SSL connections because if you >use MD5 passwords the password text layout is known and that simplifies >cryptanalysis. No, that makes no sense. And whether you use 'password' or 'md5' authentication is a different question than whether you store passwords in plaintext or as md5 hashes. Magnus was asking whether it ever makes sense to *store* passwords in plaintext. Since you brought it up, there is a legitimate argument to be made that 'password' authentication is more secure than 'md5', when SSL is used. Namely, if an attacker can acquire contents of pg_authid e.g. by stealing a backup tape, with 'md5' authentication he can log in as any user, using just the stolen hashes. But with 'password', he needs to reverse the hash first. It's not a great difference, but it's something. - 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: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Wed, Dec 14, 2016 at 11:27:15AM +0100, Magnus Hagander wrote: > I would so like to just drop support for plain passwords completely :) But > there's a backwards compatibility issue to think about of course. > > But -- is there any actual usecase for them anymore? I thought we recommended 'password' for SSL connections because if you use MD5 passwords the password text layout is known and that simplifies cryptanalysis. -- Bruce Momjianhttp://momjian.us EnterpriseDB http://enterprisedb.com + As you are, so once was I. As I am, so you will be. + + Ancient Roman grave inscription + -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
* Peter Eisentraut (peter.eisentr...@2ndquadrant.com) wrote: > On 12/14/16 5:15 AM, Michael Paquier wrote: > > I would be tempted to suggest adding the verifier type as a new column > > of pg_authid > > Yes please. This discussion seems to continue to come up and I don't entirely understand why we keep trying to shove more things into pg_authid, or worse, into rolpassword. We should have an independent table for the verifiers, which has a different column for the verifier type, and either starts off supporting multiple verifiers per role or at least gives us the ability to add that easily later. We should also move rolvaliduntil to that new table. No, I am specifically *not* concerned with "backwards compatibility" of that table- we continually add to it and change it and applications which are so closely tied to PG that they look at pg_authid need to be updated with nearly every release anyway. What we *do* need to make sure we get correct is what pg_dump/pg_upgrade do, but that's entirely within our control to manage and shouldn't be that much of an issue to implement. Thanks! Stephen signature.asc Description: Digital signature
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 12/14/16 5:15 AM, Michael Paquier wrote: > I would be tempted to suggest adding the verifier type as a new column > of pg_authid Yes please. -- Peter Eisentraut http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 12/14/2016 12:27 PM, Magnus Hagander wrote: I would so like to just drop support for plain passwords completely :) But there's a backwards compatibility issue to think about of course. But -- is there any actual usecase for them anymore? Hmm. At the moment, I don't think there is. But, a password stored in plaintext works with either MD5 or SCRAM, or any future authentication mechanism. So as soon as we have SCRAM authentication, it becomes somewhat useful again. In a nutshell: auth / stored MD5 SCRAM plaintext - passwordY Y Y md5 Y N Y scram N Y Y If a password is stored in plaintext, it can be used with any authentication mechanism. And the plaintext 'password' authentication mechanism works with any kind of a stored password. But an MD5 hash cannot be used with SCRAM authentication, or vice versa. I just noticed that the manual for CREATE ROLE says: Note that older clients might lack support for the MD5 authentication mechanism that is needed to work with passwords that are stored encrypted. That's is incorrect. The alternative to MD5 authentication is plain 'password' authentication, and that works just fine with MD5-hashed passwords. I think that sentence is a leftover from when we still supported "crypt" authentication (so I actually get to blame you for that ;-), commit 53a5026b). Back then, it was true that if an MD5 hash was stored in pg_authid, you couldn't do "crypt" authentication. That might have left old clients out in the cold. Now that we're getting SCRAM authentication, we'll need a similar notice there again, for the incompatibility of a SCRAM verifier with MDD5 authentication and vice versa. If not, another option could be to just specifically check that it's *not* "md5" or "scram-:". That would invalidate plaintext passwords that have those texts in them of course, but what's the likelyhood of that in reality? Hmm, we have dismissed that risk for the MD5 hashes (and we also have a length check for them), but as we get new hash formats, the risk increases. Someone might well want to use "plain:of:jars" as password. Perhaps we should use a more complicated pattern. I googled around for how others store SCRAM and other password hashes. Many other systems seem to have similar naming schemes. The closest thing to a standard I could find was: https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md Perhaps we should also use something like "$plain$" or "$scram-sha-256"? There's also https://tools.ietf.org/html/rfc5803, which specifies how to store SCRAM verifiers in LDAP. I don't understand enough of LDAP to understand what those actually look like, though, and there were no examples in the RFC. I wonder if we should also worry about storing multiple verifiers in rolpassword? We don't support that now, but we might in the future. It might come handy, if you could easily store multiple hashes in a single string, separated by commas for example. - 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: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 12/14/2016 12:15 PM, Michael Paquier wrote: This work is definitely something that should be done before anything else. Need a patch or are you on it? I'm on it.. - 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: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Wed, Dec 14, 2016 at 9:51 AM, Heikki Linnakangaswrote: > On 12/09/2016 10:19 AM, Michael Paquier wrote: > >> On Fri, Dec 9, 2016 at 5:11 PM, Heikki Linnakangas >> wrote: >> >>> Couple of things I should write down before I forget: >>> >>> 1. It's a bit cumbersome that the scram verifiers stored in >>> pg_authid.rolpassword don't have any clear indication that they're scram >>> verifiers. MD5 hashes are readily identifiable by the "md5" prefix. I >>> think >>> we should use a "scram-sha-256:" for scram verifiers. >>> >> >> scram-sha-256 would make the most sense to me. >> >> Actually, I think it'd be awfully nice to also prefix plaintext passwords >>> with "plain:", but I'm not sure it's worth breaking the compatibility, if >>> there are tools out there that peek into rolpassword. Thoughts? >>> >> >> pgbouncer is the only thing coming up in mind. It looks at pg_shadow >> for password values. pg_dump'ing data from pre-10 instances will also >> need to adapt. I see tricky the compatibility with the exiting CREATE >> USER PASSWORD command though, so I am wondering if that's worth the >> complication. >> >> 2. It's currently not possible to use the plaintext "password" >>> authentication method, for a user that has a SCRAM verifier in >>> rolpassword. >>> That seems like an oversight. We can't do MD5 authentication with a SCRAM >>> verifier, but "password" we could. >>> >> >> Yeah, that should be possible... >> > > The tip of the work branch can now do SCRAM authentication, when a user > has a plaintext password in pg_authid.rolpassword. The reverse doesn't > work, however: you cannot do plain "password" authentication, when the user > has a SCRAM verifier in pg_authid.rolpassword. It gets worse: plain > "password" authentication doesn't check if the string stored in > pg_authid.rolpassword is a SCRAM authenticator, and treats it as a > plaintext password, so you can do this: > > PGPASSWORD="scram-sha-256:mDBuqO1mEekieg==:4096:17dc259499c1 > a184c26ee5b19715173d9354195f510b4d3af8be585acb39ae33:d3d7131 > 49c6becbbe56bae259aafe4e95b79ab7e3b50f2fbd850ea7d7b7c114f" psql > postgres -h localhost -U scram_user > > I think we're going to have a more bugs like this, if we don't start to > explicitly label plaintext passwords as such. > > So, let's add "plain:" prefix to plaintext passwords, in > pg_authid.rolpassword. With that, these would be valid values in > pg_authid.rolpassword: > > plain:foo > md55a962ce7a24371a10e85627a484cac28 > scram-sha-256:mDBuqO1mEekieg==:4096:17dc259499c1a184c26ee5b1 > 9715173d9354195f510b4d3af8be585acb39ae33:d3d713149c6becbbe56 > bae259aafe4e95b79ab7e3b50f2fbd850ea7d7b7c114f > I would so like to just drop support for plain passwords completely :) But there's a backwards compatibility issue to think about of course. But -- is there any actual usecase for them anymore? If not, another option could be to just specifically check that it's *not* "md5" or "scram-:". That would invalidate plaintext passwords that have those texts in them of course, but what's the likelyhood of that in reality? Though I guess that might at least in theory be more bug-prone, so going with a "plain:" prefix seems like a good idea as well. > But anything that doesn't begin with "plain:", "md5", or "scram-sha-256:" > would be invalid. You shouldn't have invalid values in the column, but if > you do, all the authentication mechanisms would reject it. > > It would be nice to also change the format of MD5 passwords to have a > colon, as in "md5:", but that's probably not worth breaking > compatibility for. Almost no-one stores passwords in plaintext, so changing > the format of that wouldn't affect many people, but there might well be > tools out there that peek into MD5 hashes. There are definitely tools that do that, so +1 on leaving that alone. -- Magnus Hagander Me: http://www.hagander.net/ Work: http://www.redpill-linpro.com/
Re: pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On Wed, Dec 14, 2016 at 5:51 PM, Heikki Linnakangaswrote: > The tip of the work branch can now do SCRAM authentication, when a user has > a plaintext password in pg_authid.rolpassword. The reverse doesn't work, > however: you cannot do plain "password" authentication, when the user has a > SCRAM verifier in pg_authid.rolpassword. It gets worse: plain "password" > authentication doesn't check if the string stored in pg_authid.rolpassword > is a SCRAM authenticator, and treats it as a plaintext password, so you can > do this: > > PGPASSWORD="scram-sha-256:mDBuqO1mEekieg==:4096:17dc259499c1a184c26ee5b19715173d9354195f510b4d3af8be585acb39ae33:d3d713149c6becbbe56bae259aafe4e95b79ab7e3b50f2fbd850ea7d7b7c114f" > psql postgres -h localhost -U scram_user This one's fun. > I think we're going to have a more bugs like this, if we don't start to > explicitly label plaintext passwords as such. > > So, let's add "plain:" prefix to plaintext passwords, in > pg_authid.rolpassword. With that, these would be valid values in > pg_authid.rolpassword: > > [...] > > But anything that doesn't begin with "plain:", "md5", or "scram-sha-256:" > would be invalid. You shouldn't have invalid values in the column, but if > you do, all the authentication mechanisms would reject it. I would be tempted to suggest adding the verifier type as a new column of pg_authid, but as CREATE USER PASSWORD accepts strings with md5 prefix as-is for ages using the "plain:" prefix is definitely a better plan. My opinion on the matter has changed compared to a couple of months back. > It would be nice to also change the format of MD5 passwords to have a colon, > as in "md5:", but that's probably not worth breaking compatibility > for. Almost no-one stores passwords in plaintext, so changing the format of > that wouldn't affect many people, but there might well be tools out there > that peek into MD5 hashes. Yes, let's not take this road. This work is definitely something that should be done before anything else. Need a patch or are you on it? -- Michael -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
pg_authid.rolpassword format (was Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol)
On 12/09/2016 10:19 AM, Michael Paquier wrote: On Fri, Dec 9, 2016 at 5:11 PM, Heikki Linnakangaswrote: Couple of things I should write down before I forget: 1. It's a bit cumbersome that the scram verifiers stored in pg_authid.rolpassword don't have any clear indication that they're scram verifiers. MD5 hashes are readily identifiable by the "md5" prefix. I think we should use a "scram-sha-256:" for scram verifiers. scram-sha-256 would make the most sense to me. Actually, I think it'd be awfully nice to also prefix plaintext passwords with "plain:", but I'm not sure it's worth breaking the compatibility, if there are tools out there that peek into rolpassword. Thoughts? pgbouncer is the only thing coming up in mind. It looks at pg_shadow for password values. pg_dump'ing data from pre-10 instances will also need to adapt. I see tricky the compatibility with the exiting CREATE USER PASSWORD command though, so I am wondering if that's worth the complication. 2. It's currently not possible to use the plaintext "password" authentication method, for a user that has a SCRAM verifier in rolpassword. That seems like an oversight. We can't do MD5 authentication with a SCRAM verifier, but "password" we could. Yeah, that should be possible... The tip of the work branch can now do SCRAM authentication, when a user has a plaintext password in pg_authid.rolpassword. The reverse doesn't work, however: you cannot do plain "password" authentication, when the user has a SCRAM verifier in pg_authid.rolpassword. It gets worse: plain "password" authentication doesn't check if the string stored in pg_authid.rolpassword is a SCRAM authenticator, and treats it as a plaintext password, so you can do this: PGPASSWORD="scram-sha-256:mDBuqO1mEekieg==:4096:17dc259499c1a184c26ee5b19715173d9354195f510b4d3af8be585acb39ae33:d3d713149c6becbbe56bae259aafe4e95b79ab7e3b50f2fbd850ea7d7b7c114f" psql postgres -h localhost -U scram_user I think we're going to have a more bugs like this, if we don't start to explicitly label plaintext passwords as such. So, let's add "plain:" prefix to plaintext passwords, in pg_authid.rolpassword. With that, these would be valid values in pg_authid.rolpassword: plain:foo md55a962ce7a24371a10e85627a484cac28 scram-sha-256:mDBuqO1mEekieg==:4096:17dc259499c1a184c26ee5b19715173d9354195f510b4d3af8be585acb39ae33:d3d713149c6becbbe56bae259aafe4e95b79ab7e3b50f2fbd850ea7d7b7c114f But anything that doesn't begin with "plain:", "md5", or "scram-sha-256:" would be invalid. You shouldn't have invalid values in the column, but if you do, all the authentication mechanisms would reject it. It would be nice to also change the format of MD5 passwords to have a colon, as in "md5:", but that's probably not worth breaking compatibility for. Almost no-one stores passwords in plaintext, so changing the format of that wouldn't affect many people, but there might well be tools out there that peek into MD5 hashes. - 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] Password identifiers, protocol aging and SCRAM protocol
On Tue, Dec 13, 2016 at 10:43 AM, Michael Paquierwrote: > On Mon, Dec 12, 2016 at 11:39 PM, Heikki Linnakangas wrote: >> A few couple more things that caught my eye while hacking on this: Looking at what we have now, in the branch... >> * Use SASLPrep for passwords. SASLPrep is defined here: https://tools.ietf.org/html/rfc4013 And stringprep is here: https://tools.ietf.org/html/rfc3454 So that's roughly applying a conversion from the mapping table, taking into account prohibited, bi-directional, mapping characters, etc. The spec says that the password should be in unicode. But we cannot be sure of that, right? Those mapping tables should be likely a separated thing.. (perl has Unicode::Stringprep::Mapping for example). >> * Check nonces, etc. to not contain invalid characters. Fixed this one. >> * Derive mock SCRAM verifier for non-existent users deterministically from >> username. You have put in place the facility to allow that. The only thing that comes in mind to generate something per-cluster is to have BootStrapXLOG() generate an "authentication secret identifier" with a uint64 and add that in the control file. Using pg_backend_random() would be a good idea here. >> * Allow plain 'password' authentication for users with a SCRAM verifier in >> rolpassword. Done. >> * Throw an error if an "authorization identity" is given. ATM, we just >> ignore it, but seems better to reject the attempt than do something that >> might not be what the client expects. Done. >> * Add "scram-sha-256" prefix to SCRAM verifiers stored in >> pg_authid.rolpassword. You did it. -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On Mon, Dec 12, 2016 at 11:39 PM, Heikki Linnakangaswrote: > A few couple more things that caught my eye while hacking on this: > > 1. We don't use SASLPrep to scrub username's and passwords. That's by > choice, for usernames, because historically in PostgreSQL usernames can be > stored in any encoding, but SASLPrep assumes UTF-8. We dodge that by passing > an empty username in the authentication exchange anyway, because we always > use the username we got from the startup packet. But for passwords, I think > we need to fix that. The spec is very clear on that: > >> Note that implementations MUST either implement SASLprep or disallow >> use of non US-ASCII Unicode codepoints in "str". > > 2. I think we should check nonces, etc. more carefully, to not contain > invalid characters. For example, in the server, we use the read_attr_value() > function to read the client's nonce. Per the spec, the nonce should consist > of ASCII printable characters, but we will accept anything except the comma. > That's no trouble to the server, but let's be strict. > > To summarize, here's the overall TODO list so far: > > * Use SASLPrep for passwords. > > * Check nonces, etc. to not contain invalid characters. > > * Derive mock SCRAM verifier for non-existent users deterministically from > username. > > * Allow plain 'password' authentication for users with a SCRAM verifier in > rolpassword. > > * Throw an error if an "authorization identity" is given. ATM, we just > ignore it, but seems better to reject the attempt than do something that > might not be what the client expects. > > * Add "scram-sha-256" prefix to SCRAM verifiers stored in > pg_authid.rolpassword. > > Anything else I'm missing? > > I've created a wiki page, mostly to host that TODO list, while we hack this > to completion: https://wiki.postgresql.org/wiki/SCRAM_authentication. Feel > free to add stuff that comes to mind, and remove stuff as you push patches > to the branch on github. Based on the current code, I think you have the whole list. I'll try to look once again at the code to see I have anything else in mind. Improving the TAP regression tests is also an item, with SCRAM authentication support when a plain password is stored. -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On 12 December 2016 at 22:39, Heikki Linnakangaswrote: > * Throw an error if an "authorization identity" is given. ATM, we just > ignore it, but seems better to reject the attempt than do something that > might not be what the client expects. Yeah. That might be an opportunity to make admins' and connection poolers' lives much happier down the track, but first we'd need a way of specifying a mapping for the other users a given user is permitted to masquerade as (like we have for roles and role membership). We have SET SESSION AUTHORIZATION already, which has all the same benefits and security problems as allowing connect-time selection of authorization identity without such a framework. And we have SET ROLE. ERRORing is the right thing to do here, so we can safely use this protocol functionality later if we want to allow user masquerading. -- Craig Ringer http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Training & Services -- 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] Password identifiers, protocol aging and SCRAM protocol
A few couple more things that caught my eye while hacking on this: 1. We don't use SASLPrep to scrub username's and passwords. That's by choice, for usernames, because historically in PostgreSQL usernames can be stored in any encoding, but SASLPrep assumes UTF-8. We dodge that by passing an empty username in the authentication exchange anyway, because we always use the username we got from the startup packet. But for passwords, I think we need to fix that. The spec is very clear on that: Note that implementations MUST either implement SASLprep or disallow use of non US-ASCII Unicode codepoints in "str". 2. I think we should check nonces, etc. more carefully, to not contain invalid characters. For example, in the server, we use the read_attr_value() function to read the client's nonce. Per the spec, the nonce should consist of ASCII printable characters, but we will accept anything except the comma. That's no trouble to the server, but let's be strict. To summarize, here's the overall TODO list so far: * Use SASLPrep for passwords. * Check nonces, etc. to not contain invalid characters. * Derive mock SCRAM verifier for non-existent users deterministically from username. * Allow plain 'password' authentication for users with a SCRAM verifier in rolpassword. * Throw an error if an "authorization identity" is given. ATM, we just ignore it, but seems better to reject the attempt than do something that might not be what the client expects. * Add "scram-sha-256" prefix to SCRAM verifiers stored in pg_authid.rolpassword. Anything else I'm missing? I've created a wiki page, mostly to host that TODO list, while we hack this to completion: https://wiki.postgresql.org/wiki/SCRAM_authentication. Feel free to add stuff that comes to mind, and remove stuff as you push patches to the branch on github. - 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] Password identifiers, protocol aging and SCRAM protocol
On 12/09/2016 01:10 PM, Michael Paquier wrote: On Fri, Dec 09, 2016 at 11:51:45AM +0200, Heikki Linnakangas wrote: On 12/09/2016 05:58 AM, Michael Paquier wrote: One thing is: when do we look up at pg_authid? After receiving the first message from client or before beginning the exchange? As the first message from client has the user name, it would make sense to do the lookup after receiving it, but from PG prospective it would just make sense to use the data already present in the startup packet. The current patch does the latter. What do you think? While hacking on this, I came up with the attached refactoring, against current master. I think it makes the current code more readable, anyway, and it provides a get_role_password() function that SCRAM can use, to look up the stored password. (This is essentially the same refactoring that was included in the SCRAM patch set, that introduced the get_role_details() function.) Barring objections, I'll go ahead and commit this first. Ok, committed. - shadow_pass = TextDatumGetCString(datum); + *shadow_pass = TextDatumGetCString(datum); datum = SysCacheGetAttr(AUTHNAME, roleTup, Anum_pg_authid_rolvaliduntil, ); @@ -83,100 +83,146 @@ md5_crypt_verify(const char *role, char *client_pass, { *logdetail = psprintf(_("User \"%s\" has an empty password."), role); + *shadow_pass = NULL; return STATUS_ERROR;/* empty password */ } Here the password is allocated by text_to_cstring(), that's only 1 byte but it should be free()'d. Fixed. Thanks, good catch! It doesn't matter in practice as we'll disconnect shortly afterwards anyway, but given that the callers pfree() other things on error, let's be tidy. - 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] Password identifiers, protocol aging and SCRAM protocol
On Fri, Dec 09, 2016 at 11:51:45AM +0200, Heikki Linnakangas wrote: > On 12/09/2016 05:58 AM, Michael Paquier wrote: > > > > One thing is: when do we look up at pg_authid? After receiving the > > first message from client or before beginning the exchange? As the > > first message from client has the user name, it would make sense to do > > the lookup after receiving it, but from PG prospective it would just > > make sense to use the data already present in the startup packet. The > > current patch does the latter. What do you think? > > While hacking on this, I came up with the attached refactoring, against > current master. I think it makes the current code more readable, anyway, and > it provides a get_role_password() function that SCRAM can use, to look up > the stored password. (This is essentially the same refactoring that was > included in the SCRAM patch set, that introduced the get_role_details() > function.) > > Barring objections, I'll go ahead and commit this first. Here are some comments. > @@ -720,12 +721,16 @@ CheckMD5Auth(Port *port, char **logdetail) > sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4); > > passwd = recv_password_packet(port); > - > if (passwd == NULL) > return STATUS_EOF; /* client wouldn't send > password */ This looks like useless noise. > - shadow_pass = TextDatumGetCString(datum); > + *shadow_pass = TextDatumGetCString(datum); > > datum = SysCacheGetAttr(AUTHNAME, roleTup, > > Anum_pg_authid_rolvaliduntil, ); > @@ -83,100 +83,146 @@ md5_crypt_verify(const char *role, char *client_pass, > { > *logdetail = psprintf(_("User \"%s\" has an empty password."), > role); > + *shadow_pass = NULL; > return STATUS_ERROR;/* empty password */ > } Here the password is allocated by text_to_cstring(), that's only 1 byte but it should be free()'d. -- Michael signature.asc Description: PGP signature
Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol
On 12/09/2016 05:58 AM, Michael Paquier wrote: One thing is: when do we look up at pg_authid? After receiving the first message from client or before beginning the exchange? As the first message from client has the user name, it would make sense to do the lookup after receiving it, but from PG prospective it would just make sense to use the data already present in the startup packet. The current patch does the latter. What do you think? While hacking on this, I came up with the attached refactoring, against current master. I think it makes the current code more readable, anyway, and it provides a get_role_password() function that SCRAM can use, to look up the stored password. (This is essentially the same refactoring that was included in the SCRAM patch set, that introduced the get_role_details() function.) Barring objections, I'll go ahead and commit this first. - Heikki >From 30be98cf09e8807d477827257a1e55c979dbe877 Mon Sep 17 00:00:00 2001 From: Heikki LinnakangasDate: Fri, 9 Dec 2016 11:49:36 +0200 Subject: [PATCH 1/1] Refactor the code for verifying user's password. Split md5_crypt_verify() into three functions: * get_role_password() to fetch user's password from pg_authid, and check its expiration. * md5_crypt_verify() to check an MD5 authentication challenge * plain_crypt_verify() to check a plaintext password. get_role_password() will be needed as a separate function by the upcoming SCRAM authentication patch set. Most of the remaining functionality in md5_crypt_verify() was different for MD5 and plaintext authentication, so split that for readability. While we're at it, simplify the *_crypt_verify functions by using stack-allocated buffers to hold the temporary MD5 hashes, instead of pallocing. --- src/backend/libpq/auth.c | 18 +++- src/backend/libpq/crypt.c | 214 -- src/include/libpq/crypt.h | 9 +- 3 files changed, 151 insertions(+), 90 deletions(-) diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index f8bffe3..5c9ee06 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -707,6 +707,7 @@ CheckMD5Auth(Port *port, char **logdetail) { char md5Salt[4]; /* Password salt */ char *passwd; + char *shadow_pass; int result; if (Db_user_namespace) @@ -720,12 +721,16 @@ CheckMD5Auth(Port *port, char **logdetail) sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4); passwd = recv_password_packet(port); - if (passwd == NULL) return STATUS_EOF; /* client wouldn't send password */ - result = md5_crypt_verify(port->user_name, passwd, md5Salt, 4, logdetail); + result = get_role_password(port->user_name, _pass, logdetail); + if (result == STATUS_OK) + result = md5_crypt_verify(port->user_name, shadow_pass, passwd, + md5Salt, 4, logdetail); + if (shadow_pass) + pfree(shadow_pass); pfree(passwd); return result; @@ -741,16 +746,21 @@ CheckPasswordAuth(Port *port, char **logdetail) { char *passwd; int result; + char *shadow_pass; sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0); passwd = recv_password_packet(port); - if (passwd == NULL) return STATUS_EOF; /* client wouldn't send password */ - result = md5_crypt_verify(port->user_name, passwd, NULL, 0, logdetail); + result = get_role_password(port->user_name, _pass, logdetail); + if (result == STATUS_OK) + result = plain_crypt_verify(port->user_name, shadow_pass, passwd, + logdetail); + if (shadow_pass) + pfree(shadow_pass); pfree(passwd); return result; diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c index b4ca174..fb6d1af 100644 --- a/src/backend/libpq/crypt.c +++ b/src/backend/libpq/crypt.c @@ -30,28 +30,28 @@ /* - * Check given password for given user, and return STATUS_OK or STATUS_ERROR. + * Fetch stored password for a user, for authentication. * - * 'client_pass' is the password response given by the remote user. If - * 'md5_salt' is not NULL, it is a response to an MD5 authentication - * challenge, with the given salt. Otherwise, it is a plaintext password. + * Returns STATUS_OK on success. On error, returns STATUS_ERROR, and stores + * a palloc'd string describing the reason, for the postmaster log, in + * *logdetail. The error reason should *not* be sent to the client, to avoid + * giving away user information! * - * In the error case, optionally store a palloc'd string at *logdetail - * that will be sent to the postmaster log (but not the client). + * If the password is expired, it is still returned in *shadow_pass, but the + * return code is STATUS_ERROR. On other errors, *shadow_pass is set to + * NULL. */ int -md5_crypt_verify(const char *role, char *client_pass, - char *md5_salt, int md5_salt_len, char **logdetail) +get_role_password(const char *role, char **shadow_pass, char **logdetail) { int retval = STATUS_ERROR; - char *shadow_pass, - *crypt_pwd; TimestampTz vuntil
Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol
On Fri, Dec 9, 2016 at 5:11 PM, Heikki Linnakangaswrote: > Couple of things I should write down before I forget: > > 1. It's a bit cumbersome that the scram verifiers stored in > pg_authid.rolpassword don't have any clear indication that they're scram > verifiers. MD5 hashes are readily identifiable by the "md5" prefix. I think > we should use a "scram-sha-256:" for scram verifiers. scram-sha-256 would make the most sense to me. > Actually, I think it'd be awfully nice to also prefix plaintext passwords > with "plain:", but I'm not sure it's worth breaking the compatibility, if > there are tools out there that peek into rolpassword. Thoughts? pgbouncer is the only thing coming up in mind. It looks at pg_shadow for password values. pg_dump'ing data from pre-10 instances will also need to adapt. I see tricky the compatibility with the exiting CREATE USER PASSWORD command though, so I am wondering if that's worth the complication. > 2. It's currently not possible to use the plaintext "password" > authentication method, for a user that has a SCRAM verifier in rolpassword. > That seems like an oversight. We can't do MD5 authentication with a SCRAM > verifier, but "password" we could. Yeah, that should be possible... -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
Couple of things I should write down before I forget: 1. It's a bit cumbersome that the scram verifiers stored in pg_authid.rolpassword don't have any clear indication that they're scram verifiers. MD5 hashes are readily identifiable by the "md5" prefix. I think we should use a "scram-sha-256:" for scram verifiers. Actually, I think it'd be awfully nice to also prefix plaintext passwords with "plain:", but I'm not sure it's worth breaking the compatibility, if there are tools out there that peek into rolpassword. Thoughts? 2. It's currently not possible to use the plaintext "password" authentication method, for a user that has a SCRAM verifier in rolpassword. That seems like an oversight. We can't do MD5 authentication with a SCRAM verifier, but "password" we could. - 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] Password identifiers, protocol aging and SCRAM protocol
On 12/09/2016 05:58 AM, Michael Paquier wrote: On Thu, Dec 8, 2016 at 10:05 PM, Michael Paquierwrote: On Thu, Dec 8, 2016 at 5:55 PM, Heikki Linnakangas wrote: Actually, we don't give away that information currently. If you try to log in with password or MD5 authentication, and the user doesn't exist, you get the same error as with an incorrect password. So, I think we do need to give the client a made-up salt and iteration count in that case, to hide the fact that the user doesn't exist. Furthermore, you can't just generate random salt and iteration count, because then you could simply try connecting twice, and see if you get the same salt and iteration count. We need to deterministically derive the salt from the username, so that you get the same salt/iteration count every time you try connecting with that username. But it needs indistinguishable from a random salt, to the client. Perhaps a SHA hash of the username and some per-cluster secret value, created by initdb. There must be research papers out there on how to do this.. A simple idea would be to use the system ID when generating this fake salt? That's generated by initdb, once per cluster. I am wondering if it would be risky to use it for the salt. For the number of iterations the default number could be used. I think I'd feel better with a completely separate randomly-generated value for this. System ID is not too difficult to guess, and there's no need to skimp on this. Yes, default number of iterations makes sense. We cannot completely avoid leaking information through this, unfortunately. For example, if you have a user with a non-default number of iterations, and an attacker probes that, he'll know that the username was valid, because he got back a non-default number of iterations. But let's do our best. I have been thinking more about this part quite a bit, and here is the most simple thing that we could do while respecting the protocol. That's more or less what I think you have in mind by re-reading upthread, but it does not hurt to rewrite the whole flow to be clear: 1) Server gets the startup packet, maps pg_hba.conf and moves on to the scram authentication code path. 2) Server sends back sendAuthRequest() to request user to provide a password. This maps to the plain/md5 behavior as no errors would be issued to user until he has provided a password. 3) Client sends back the password, and the first message with the user name. 4) Server receives it, and checks the data. If a failure happens at this stage, just ERROR on PG-side without sending back a e= message. This includes the username-mismatch, empty password and end of password validity. So we would never use e=unknown-user. This sticks with what you quoted upthread that the server may end the exchange before sending the final message. If we want to mimic the current behavior with MD5 authentication, I think we need to follow through with the challenge, and only fail in the last step, even if we know the password was empty or expired. MD5 authentication doesn't currently give away that information to the user. But it's OK to bail out early on OOM, or if the client sends an outright broken message. Those don't give away any information on the user account. 5) Server sends back the challenge, and client answers back with its reply to it. Then enters the final stage of the exchange, at which point the server would issue its final message that would be e= in case of errors. If something like an OOM happens, no message would be sent so failing on an OOM ERROR on PG side would be fine as well. 6) Read final message from client and validate. 7) issue final message of server. On failure at steps 6) or 7), an e= message is returned instead of the final message. Does that look right? Yep. One thing is: when do we look up at pg_authid? After receiving the first message from client or before beginning the exchange? As the first message from client has the user name, it would make sense to do the lookup after receiving it, but from PG prospective it would just make sense to use the data already present in the startup packet. The current patch does the latter. What do you think? Let's see what fits the program flow best. Probably best to do it before beginning the exchange. I'm hacking on this right now... By the way, I have pushed the extra patches you sent into this branch: https://github.com/michaelpq/postgres/tree/scram Thanks! We had a quick chat with Michael, and agreed that we'd hack together on that github repository, to avoid stepping on each other's toes, and cut rebased patch sets from there to pgsql-hackers every now and then. - 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] Password identifiers, protocol aging and SCRAM protocol
On Thu, Dec 8, 2016 at 10:05 PM, Michael Paquierwrote: > On Thu, Dec 8, 2016 at 5:55 PM, Heikki Linnakangas wrote: >> On 12/08/2016 10:18 AM, Michael Paquier wrote: >>> Hmmm. How do we handle the case where the user name does not match >>> then? The spec gives an error message e= specifically for this case. >> >> Hmm, interesting. I wonder how/when they imagine that error message to be >> used. I suppose you could send a dummy server-first message, with a made-up >> salt and iteration count, if the user is not found, so that you can report >> that in the server-final message. But that seems unnecessarily complicated, >> compared to just sending the error immediately. I could imagine using a >> dummy server-first message to hide whether the user exists, but that >> argument doesn't hold water if you're going to report an "unknown-user" >> error, anyway. > > Using directly an error message would map with MD5 and plain, but > that's definitely a new protocol piece so I'd rather think that using > e= once the client has sent its first message in the exchange should > be answered with an appropriate SASL error... > >> Actually, we don't give away that information currently. If you try to log >> in with password or MD5 authentication, and the user doesn't exist, you get >> the same error as with an incorrect password. So, I think we do need to give >> the client a made-up salt and iteration count in that case, to hide the fact >> that the user doesn't exist. Furthermore, you can't just generate random >> salt and iteration count, because then you could simply try connecting >> twice, and see if you get the same salt and iteration count. We need to >> deterministically derive the salt from the username, so that you get the >> same salt/iteration count every time you try connecting with that username. >> But it needs indistinguishable from a random salt, to the client. Perhaps a >> SHA hash of the username and some per-cluster secret value, created by >> initdb. There must be research papers out there on how to do this.. > > A simple idea would be to use the system ID when generating this fake > salt? That's generated by initdb, once per cluster. I am wondering if > it would be risky to use it for the salt. For the number of iterations > the default number could be used. I have been thinking more about this part quite a bit, and here is the most simple thing that we could do while respecting the protocol. That's more or less what I think you have in mind by re-reading upthread, but it does not hurt to rewrite the whole flow to be clear: 1) Server gets the startup packet, maps pg_hba.conf and moves on to the scram authentication code path. 2) Server sends back sendAuthRequest() to request user to provide a password. This maps to the plain/md5 behavior as no errors would be issued to user until he has provided a password. 3) Client sends back the password, and the first message with the user name. 4) Server receives it, and checks the data. If a failure happens at this stage, just ERROR on PG-side without sending back a e= message. This includes the username-mismatch, empty password and end of password validity. So we would never use e=unknown-user. This sticks with what you quoted upthread that the server may end the exchange before sending the final message. 5) Server sends back the challenge, and client answers back with its reply to it. Then enters the final stage of the exchange, at which point the server would issue its final message that would be e= in case of errors. If something like an OOM happens, no message would be sent so failing on an OOM ERROR on PG side would be fine as well. 6) Read final message from client and validate. 7) issue final message of server. On failure at steps 6) or 7), an e= message is returned instead of the final message. Does that look right? One thing is: when do we look up at pg_authid? After receiving the first message from client or before beginning the exchange? As the first message from client has the user name, it would make sense to do the lookup after receiving it, but from PG prospective it would just make sense to use the data already present in the startup packet. The current patch does the latter. What do you think? By the way, I have pushed the extra patches you sent into this branch: https://github.com/michaelpq/postgres/tree/scram -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On Thu, Dec 8, 2016 at 5:55 PM, Heikki Linnakangaswrote: > On 12/08/2016 10:18 AM, Michael Paquier wrote: >> Hmmm. How do we handle the case where the user name does not match >> then? The spec gives an error message e= specifically for this case. > > Hmm, interesting. I wonder how/when they imagine that error message to be > used. I suppose you could send a dummy server-first message, with a made-up > salt and iteration count, if the user is not found, so that you can report > that in the server-final message. But that seems unnecessarily complicated, > compared to just sending the error immediately. I could imagine using a > dummy server-first messaage to hide whether the user exists, but that > argument doesn't hold water if you're going to report an "unknown-user" > error, anyway. Using directly an error message would map with MD5 and plain, but that's definitely a new protocol piece so I'd rather think that using e= once the client has sent its first message in the exchange should be answered with an appropriate SASL error... > Actually, we don't give away that information currently. If you try to log > in with password or MD5 authentication, and the user doesn't exist, you get > the same error as with an incorrect password. So, I think we do need to give > the client a made-up salt and iteration count in that case, to hide the fact > that the user doesn't exist. Furthermore, you can't just generate random > salt and iteration count, because then you could simply try connecting > twice, and see if you get the same salt and iteration count. We need to > deterministically derive the salt from the username, so that you get the > same salt/iteration count every time you try connecting with that username. > But it needs indistinguishable from a random salt, to the client. Perhaps a > SHA hash of the username and some per-cluster secret value, created by > initdb. There must be research papers out there on how to do this.. A simple idea would be to use the system ID when generating this fake salt? That's generated by initdb, once per cluster. I am wondering if it would be risky to use it for the salt. For the number of iterations the default number could be used. > To be really pedantic about that, we should also ward off timing attacks, by > making sure that the dummy authentication is no faster/slower than a real > one.. There is one catalog lookup when extracting the verifier from pg_authid, I'd guess that if we generate a fake verifier things should get pretty close. >> If this is taken into account we need to perform sanity checks at >> initialization phase I am afraid as the number of iterations and the >> salt are part of the verifier. So you mean that just sending out a >> normal ERROR message is fine at an earlier step (with *logdetails >> filled for the backend)? I just want to be sure I understand what you >> mean here. > > That's right, we can send a normal ERROR message. (But not for the > "user-not-found" case, as discussed above.) I'd think that the cases where the password is empty and the password has passed valid duration should be returned with e=other-error. If the caller sends a SCRAM request that would be impolite (?) to just throw up an error once the exchange has begun. > Although, currently, the whole pg_hba.conf file in that example is a valid > file that someone might have on a real server. With the above addition, it > would not be. You would never have the two lines with the same > host/database/user combination in pg_hba.conf. Okay. -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On 12/08/2016 10:18 AM, Michael Paquier wrote: On Thu, Dec 8, 2016 at 5:54 AM, Heikki Linnakangaswrote: Attached those here, as add-on patches to your latest patch set. Thanks for looking at it! I'll continue reviewing, but a couple of things caught my eye that you may want to jump on, in the meanwhile: On error messages, the spec says: o e: This attribute specifies an error that occurred during authentication exchange. It is sent by the server in its final message and can help diagnose the reason for the authentication exchange failure. On failed authentication, the entire server- final-message is OPTIONAL; specifically, a server implementation MAY conclude the SASL exchange with a failure without sending the server-final-message. This results in an application-level error response without an extra round-trip. If the server-final-message is sent on authentication failure, then the "e" attribute MUST be included. Note that it says that the server can send the error message with the e= attribute, in the *final message*. It's not a valid response in the earlier state, before sending server-first-message. I think we need to change the INIT state handling in pg_be_scram_exchange() to not send e= messages to the client. On an error at that state, it needs to just bail out without a message. The spec allows that. We can always log the detailed reason in the server log, anyway. Hmmm. How do we handle the case where the user name does not match then? The spec gives an error message e= specifically for this case. Hmm, interesting. I wonder how/when they imagine that error message to be used. I suppose you could send a dummy server-first message, with a made-up salt and iteration count, if the user is not found, so that you can report that in the server-final message. But that seems unnecessarily complicated, compared to just sending the error immediately. I could imagine using a dummy server-first messaage to hide whether the user exists, but that argument doesn't hold water if you're going to report an "unknown-user" error, anyway. Actually, we don't give away that information currently. If you try to log in with password or MD5 authentication, and the user doesn't exist, you get the same error as with an incorrect password. So, I think we do need to give the client a made-up salt and iteration count in that case, to hide the fact that the user doesn't exist. Furthermore, you can't just generate random salt and iteration count, because then you could simply try connecting twice, and see if you get the same salt and iteration count. We need to deterministically derive the salt from the username, so that you get the same salt/iteration count every time you try connecting with that username. But it needs indistinguishable from a random salt, to the client. Perhaps a SHA hash of the username and some per-cluster secret value, created by initdb. There must be research papers out there on how to do this.. To be really pedantic about that, we should also ward off timing attacks, by making sure that the dummy authentication is no faster/slower than a real one.. If this is taken into account we need to perform sanity checks at initialization phase I am afraid as the number of iterations and the salt are part of the verifier. So you mean that just sending out a normal ERROR message is fine at an earlier step (with *logdetails filled for the backend)? I just want to be sure I understand what you mean here. That's right, we can send a normal ERROR message. (But not for the "user-not-found" case, as discussed above.) As Peter E pointed out earlier, the documentation is lacking, on how to configure MD5 and/or SCRAM. If you put "scram" as the authentication method in pg_hba.conf, what does it mean? If you have a line for both "scram" and "md5" in pg_hba.conf, with the same database/user/hostname combo, what does that mean? Answer: The first one takes effect, the second one has no effect. Yet the example in the docs now has that, which is nonsense :-). Hopefully we'll have some kind of a "both" option, before the release, but in the meanwhile, we need describe how this works now in the docs. OK, it would be better to add a paragraph in client-auth.sgml regarding the mapping of the two settings. For the example of file in postgresql.conf, I would have really thought that adding directly a line with "scram" listed was enough though. Perhaps a comment to say that if md5 and scram are specified the first one wins where a user and database name map? So, I think this makes no sense: # Allow any user from host 192.168.12.10 to connect to database -# "postgres" if the user's password is correctly supplied. +# "postgres" if the user's password is correctly supplied and is +# using the correct password method. # # TYPE DATABASEUSERADDRESS METHOD hostpostgres
Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol
On Thu, Dec 8, 2016 at 5:54 AM, Heikki Linnakangaswrote: > Attached those here, as add-on patches to your latest patch set. Thanks for looking at it! > I'll continue reviewing, but a couple of things caught my eye that you may > want > to jump on, in the meanwhile: > > On error messages, the spec says: > >> o e: This attribute specifies an error that occurred during >> authentication exchange. It is sent by the server in its final >> message and can help diagnose the reason for the authentication >> exchange failure. On failed authentication, the entire server- >> final-message is OPTIONAL; specifically, a server implementation >> MAY conclude the SASL exchange with a failure without sending the >> server-final-message. This results in an application-level error >> response without an extra round-trip. If the server-final-message >> is sent on authentication failure, then the "e" attribute MUST be >> included. > > > Note that it says that the server can send the error message with the e= > attribute, in the *final message*. It's not a valid response in the earlier > state, before sending server-first-message. I think we need to change the > INIT state handling in pg_be_scram_exchange() to not send e= messages to the > client. On an error at that state, it needs to just bail out without a > message. The spec allows that. We can always log the detailed reason in the > server log, anyway. Hmmm. How do we handle the case where the user name does not match then? The spec gives an error message e= specifically for this case. If this is taken into account we need to perform sanity checks at initialization phase I am afraid as the number of iterations and the salt are part of the verifier. So you mean that just sending out a normal ERROR message is fine at an earlier step (with *logdetails filled for the backend)? I just want to be sure I understand what you mean here. > As Peter E pointed out earlier, the documentation is lacking, on how to > configure MD5 and/or SCRAM. If you put "scram" as the authentication method > in pg_hba.conf, what does it mean? If you have a line for both "scram" and > "md5" in pg_hba.conf, with the same database/user/hostname combo, what does > that mean? Answer: The first one takes effect, the second one has no effect. > Yet the example in the docs now has that, which is nonsense :-). Hopefully > we'll have some kind of a "both" option, before the release, but in the > meanwhile, we need describe how this works now in the docs. OK, it would be better to add a paragraph in client-auth.sgml regarding the mapping of the two settings. For the example of file in postgresql.conf, I would have really thought that adding directly a line with "scram" listed was enough though. Perhaps a comment to say that if md5 and scram are specified the first one wins where a user and database name map? -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On 12/07/2016 08:39 AM, Michael Paquier wrote: On Tue, Nov 29, 2016 at 1:36 PM, Michael Paquierwrote: Nothing more will likely happen in this CF, so I have moved it to 2017-01 with the same status of "Needs Review". Attached is a new set of patches using the new routines pg_backend_random() and pg_strong_random() to handle the randomness in SCRAM: - 0001 refactors the SHA2 routines. pgcrypto uses raw files from src/common when compiling with this patch. That works on any platform, and this is the simplified version of upthread. - 0002 adds base64 routines to src/common. - 0003 does some refactoring regarding the password encryption in ALTER/CREATE USER queries. - 0004 adds the clause PASSWORD (val USING method) in CREATE/ALTER USER. - 0005 is the code patch for SCRAM. Note that this switches pgcrypto to link to libpgcommon as SHA2 routines are used by the backend. - 0006 adds some regression tests for passwords. - 0007 adds some TAP tests for authentication. This is added to the upcoming CF. I spent a little time reading through this once again. Steady progress, did some small fixes: * Rewrote the nonce generation. In the server-side, it first generated a string of ascii-printable characters, then base64-encoded them, which is superfluous. Also, avoid calling pg_strong_random() one byte at a time, for performance reasons. * Added a more sophisticated fallback implementation in libpq, for the --disable-strong-random cases, similar to pg_backend_random(). * No need to disallow SCRAM with db_user_namespace. It doesn't include the username in the salt like MD5 does. Attached those here, as add-on patches to your latest patch set. I'll continue reviewing, but a couple of things caught my eye that you may want to jump on, in the meanwhile: On error messages, the spec says: o e: This attribute specifies an error that occurred during authentication exchange. It is sent by the server in its final message and can help diagnose the reason for the authentication exchange failure. On failed authentication, the entire server- final-message is OPTIONAL; specifically, a server implementation MAY conclude the SASL exchange with a failure without sending the server-final-message. This results in an application-level error response without an extra round-trip. If the server-final-message is sent on authentication failure, then the "e" attribute MUST be included. Note that it says that the server can send the error message with the e= attribute, in the *final message*. It's not a valid response in the earlier state, before sending server-first-message. I think we need to change the INIT state handling in pg_be_scram_exchange() to not send e= messages to the client. On an error at that state, it needs to just bail out without a message. The spec allows that. We can always log the detailed reason in the server log, anyway. As Peter E pointed out earlier, the documentation is lacking, on how to configure MD5 and/or SCRAM. If you put "scram" as the authentication method in pg_hba.conf, what does it mean? If you have a line for both "scram" and "md5" in pg_hba.conf, with the same database/user/hostname combo, what does that mean? Answer: The first one takes effect, the second one has no effect. Yet the example in the docs now has that, which is nonsense :-). Hopefully we'll have some kind of a "both" option, before the release, but in the meanwhile, we need describe how this works now in the docs. - Heikki >From 4d3a59ae1cb5742499c71b0c1e048d30dcef6836 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Wed, 7 Dec 2016 15:24:55 +0200 Subject: [PATCH 08/11] Rewrite nonce generation. In the server, the nonce was generated using only ASCII-printable characters, and the result was base64-encoded. The base64 encoding is pointless, if we use only ASCII-printable chars to begin with. Calling pg_strong_random() can be somewhat expensive, as with the /dev/urandom implementation, it has to open the device, read the bytes, and close, on every call. So avoid calling it in a loop, generating only one byte in each call. I went back to using base64-encoding method of turning the raw bytes into the final nonce. That was more convenient than writing something that encodes to the whole ASCII-printable range. That means that we're not using the whole range of chars allowed in the nonce, but I believe that doesn't make any difference. (Both the frontend and backend will still accept the full range from the other side of the connection). --- src/backend/libpq/auth-scram.c | 52 --- src/include/common/scram-common.h| 6 +++- src/include/libpq/libpq-be.h | 2 -- src/interfaces/libpq/fe-auth-scram.c | 60 ++-- 4 files changed, 34 insertions(+), 86 deletions(-) diff --git a/src/backend/libpq/auth-scram.c
Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol
On Fri, Nov 18, 2016 at 2:51 AM, Michael Paquierwrote: > On Thu, Nov 17, 2016 at 8:12 AM, Robert Haas wrote: >> So, the problem isn't Darwin-specific. I experimented with this on >> Linux and found Linux does the same thing with libpgcommon_srv.a that >> macOS does: a file in the archive that is totally unused is omitted >> from the postgres binary. In Linux, however, that doesn't prevent >> pgcrypto from compiling anyway. It does, however, prevent it from >> working. Instead of failing at compile time with a complaint about >> missing symbols, it fails at load time. I think that's because macOS >> has -bundle-loader and we use it; without that, I think we'd get the >> same behavior on macOS that we get on Windows. > > Yes, right. I recall seeing the regression tests failing with pgcrypto > when doing that. Though I did not recall if this was specific to macos > or Linux when I looked again at this patch yesterday. When testing > again yesterday I was able to make the tests of pgcrypto to pass, but > perhaps my build was not in a clean state... > >> 1. Rejigger things so that we don't build libpgcommon_srv.a in the >> first place, and instead add $(top_builddir)/src/common to >> src/backend/Makefile's value of SUBDIRS. With appropriate adjustments >> to src/common/Makefile, this should allow us to include all of the >> object files on the linker command line individually instead of >> building an archive library that is then used only for the postgres >> binary itself anyway. Then, things wouldn't get dropped. >> >> 2. Just postpone committing this patch until we're ready to use the >> new code in the backend someplace (or add a dummy reference to it >> someplace). > > At the end this refactoring makes sense because it will be used in the > backend with the SCRAM engine, so we could just wait for 2 instead of > having some workarounds. This is dropping the ball for later and there > will be already a lot of work for the SCRAM core part, though I don't > think that the SHA2 refactoring will change much going forward. > > Option 3 would be to do things the patch does it, aka just compiling > pgcrypto using the source files directly and put a comment to revert > that once the APIs are used in the backend. I can guess that you don't > like that. Nothing more will likely happen in this CF, so I have moved it to 2017-01 with the same status of "Needs Review". -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On Thu, Nov 17, 2016 at 8:12 AM, Robert Haaswrote: > So, the problem isn't Darwin-specific. I experimented with this on > Linux and found Linux does the same thing with libpgcommon_srv.a that > macOS does: a file in the archive that is totally unused is omitted > from the postgres binary. In Linux, however, that doesn't prevent > pgcrypto from compiling anyway. It does, however, prevent it from > working. Instead of failing at compile time with a complaint about > missing symbols, it fails at load time. I think that's because macOS > has -bundle-loader and we use it; without that, I think we'd get the > same behavior on macOS that we get on Windows. Yes, right. I recall seeing the regression tests failing with pgcrypto when doing that. Though I did not recall if this was specific to macos or Linux when I looked again at this patch yesterday. When testing again yesterday I was able to make the tests of pgcrypto to pass, but perhaps my build was not in a clean state... > 1. Rejigger things so that we don't build libpgcommon_srv.a in the > first place, and instead add $(top_builddir)/src/common to > src/backend/Makefile's value of SUBDIRS. With appropriate adjustments > to src/common/Makefile, this should allow us to include all of the > object files on the linker command line individually instead of > building an archive library that is then used only for the postgres > binary itself anyway. Then, things wouldn't get dropped. > > 2. Just postpone committing this patch until we're ready to use the > new code in the backend someplace (or add a dummy reference to it > someplace). At the end this refactoring makes sense because it will be used in the backend with the SCRAM engine, so we could just wait for 2 instead of having some workarounds. This is dropping the ball for later and there will be already a lot of work for the SCRAM core part, though I don't think that the SHA2 refactoring will change much going forward. Option 3 would be to do things the patch does it, aka just compiling pgcrypto using the source files directly and put a comment to revert that once the APIs are used in the backend. I can guess that you don't like that. -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On Wed, Nov 16, 2016 at 11:28 PM, Michael Paquierwrote: > On Wed, Nov 16, 2016 at 8:04 PM, Michael Paquier > wrote: >> In the current set of patches, the sha2 functions would not get used >> until the main patch for SCRAM gets committed so that's a couple of >> steps and many months ahead.. And --as-needed/--no-as-needed are not >> supported in macos. So I would believe that the best route is just to >> use this patch with the way it does things, and once SCRAM gets in we >> could switch the build into more appropriate linking. At least that's >> far less ugly than having fake objects in the backend code. Of course >> a comment in pgcrypo's Makefile would be appropriate. > > Or a comment with a "ifeq ($(PORTNAME), darwin)" containing the > additional objects to make clear that this is proper to only OSX. > Other ideas are welcome. So, the problem isn't Darwin-specific. I experimented with this on Linux and found Linux does the same thing with libpgcommon_srv.a that macOS does: a file in the archive that is totally unused is omitted from the postgres binary. In Linux, however, that doesn't prevent pgcrypto from compiling anyway. It does, however, prevent it from working. Instead of failing at compile time with a complaint about missing symbols, it fails at load time. I think that's because macOS has -bundle-loader and we use it; without that, I think we'd get the same behavior on macOS that we get on Windows. The fundamental problem here is that the archive-member-dropping behavior that we're getting here is not really what we want, and I think that's going to happen on most or all architectures. For GNU ld, we could add -Wl,--whole-archive, and macOS has -all_load, but I that this is just a nest of portability problems waiting to happen. I think there are two things we can do here that are far simpler: 1. Rejigger things so that we don't build libpgcommon_srv.a in the first place, and instead add $(top_builddir)/src/common to src/backend/Makefile's value of SUBDIRS. With appropriate adjustments to src/common/Makefile, this should allow us to include all of the object files on the linker command line individually instead of building an archive library that is then used only for the postgres binary itself anyway. Then, things wouldn't get dropped. 2. Just postpone committing this patch until we're ready to use the new code in the backend someplace (or add a dummy reference to it someplace). -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company -- 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] Password identifiers, protocol aging and SCRAM protocol
On Wed, Nov 16, 2016 at 8:04 PM, Michael Paquierwrote: > In the current set of patches, the sha2 functions would not get used > until the main patch for SCRAM gets committed so that's a couple of > steps and many months ahead.. And --as-needed/--no-as-needed are not > supported in macos. So I would believe that the best route is just to > use this patch with the way it does things, and once SCRAM gets in we > could switch the build into more appropriate linking. At least that's > far less ugly than having fake objects in the backend code. Of course > a comment in pgcrypo's Makefile would be appropriate. Or a comment with a "ifeq ($(PORTNAME), darwin)" containing the additional objects to make clear that this is proper to only OSX. Other ideas are welcome. -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On Wed, Nov 16, 2016 at 6:51 PM, Robert Haaswrote: > So, it seems that the linker is willing to drop archive members if the > entire .o file is used, but not individual symbols. That explains why > Michael thinks we need to do something special here, because with his > 0001 patch, nothing in the new sha2(_openssl).c file would immediately > be used in the backend. And indeed I see now that my earlier testing > was done incorrectly, and pgcrypto does in fact fail to build under my > proposal. Oops. Ah, thanks! I did not notice that before in configure.in: if test "$PORTNAME" = "darwin"; then PGAC_PROG_CC_LDFLAGS_OPT([-Wl,-dead_strip_dylibs], $link_test_func) elif test "$PORTNAME" = "openbsd"; then PGAC_PROG_CC_LDFLAGS_OPT([-Wl,-Bdynamic], $link_test_func) else PGAC_PROG_CC_LDFLAGS_OPT([-Wl,--as-needed], $link_test_func) fi In the current set of patches, the sha2 functions would not get used until the main patch for SCRAM gets committed so that's a couple of steps and many months ahead.. And --as-needed/--no-as-needed are not supported in macos. So I would believe that the best route is just to use this patch with the way it does things, and once SCRAM gets in we could switch the build into more appropriate linking. At least that's far less ugly than having fake objects in the backend code. Of course a comment in pgcrypo's Makefile would be appropriate. -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On Wed, Nov 16, 2016 at 7:36 PM, Andres Freundwrote: > With -Wl,--as-neeeded the linker will dismiss unused symbols found in a > static library. Maybe that's the difference? The man page --as-needed says that --as-needed modifies the behavior of dynamic libraries, not static ones. If there is any such effect, it is undocumented. Here is the text: LD> This option affects ELF DT_NEEDED tags for dynamic libraries mentioned LD> on the command line after the --as-needed option. Normally the linker will LD> add a DT_NEEDED tag for each dynamic library mentioned on the LD> command line, regardless of whether the library is actually needed or not. LD> --as-needed causes a DT_NEEDED tag to only be emitted for a library LD> that at that point in the link satisfies a non-weak undefined symbol reference LD> from a regular object file or, if the library is not found in the DT_NEEDED LD> lists of other needed libraries, a non-weak undefined symbol reference LD> from another needed dynamic library. Object files or libraries appearing LD> on the command line after the library in question do not affect whether the LD> library is seen as needed. This is similar to the rules for extraction of object LD> files from archives. --no-as-needed restores the default behaviour. Some experimentation on my Mac reveals that my previous statement about how this works was incorrect. See attached patch for what I tried. What I find is: 1. If I create an additional source file in src/common containing a completely unused symbol (wunk) it appears in the nm output for libpgcommon_srv.a but not in the nm output for the postgres binary. 2. If I add an additional function to an existing source file in src/common containing a completely unused symbol (quux) it appears in the nm output for both libpgcommon_srv.a and also in the nm output for the postgres binary. 3. If I create an additional source file in src/backend containing a completely unused symbol (blarfle) it appears in the nm output for the postgres binary. So, it seems that the linker is willing to drop archive members if the entire .o file is used, but not individual symbols. That explains why Michael thinks we need to do something special here, because with his 0001 patch, nothing in the new sha2(_openssl).c file would immediately be used in the backend. And indeed I see now that my earlier testing was done incorrectly, and pgcrypto does in fact fail to build under my proposal. Oops. But I think that's a temporary thing. As soon as the backend is using the sha2 routines for anything (which is the point, right?) the build changes become unnecessary. For example, if I apply this patch: --- a/src/backend/lib/binaryheap.c +++ b/src/backend/lib/binaryheap.c @@ -305,3 +305,7 @@ sift_down(binaryheap *heap, int node_off) node_off = swap_off; } } + +#include "common/sha2.h" +extern void ugh(void); +void ugh(void) { pg_sha224_init(NULL); } ...then the backend ends up sucking in everything in sha2.c and the pgcrypto build works again. -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company diff --git a/src/common/Makefile b/src/common/Makefile index 03dfaa1..f84264a 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -46,7 +46,7 @@ OBJS_COMMON = config_info.o controldata_utils.o exec.o ip.o keywords.o \ OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o file_utils.o restricted_token.o -OBJS_SRV = $(OBJS_COMMON:%.o=%_srv.o) +OBJS_SRV = $(OBJS_COMMON:%.o=%_srv.o) wunk.o all: libpgcommon.a libpgcommon_srv.a diff --git a/src/common/ip.c b/src/common/ip.c index 797d910..d517802 100644 --- a/src/common/ip.c +++ b/src/common/ip.c @@ -258,3 +258,11 @@ getnameinfo_unix(const struct sockaddr_un * sa, int salen, return 0; } #endif /* HAVE_UNIX_SOCKETS */ + +extern void quux(void); + +void +quux(void) +{ + /* quux */ +} diff --git a/src/common/wunk.c b/src/common/wunk.c new file mode 100644 index 000..2db667c --- /dev/null +++ b/src/common/wunk.c @@ -0,0 +1,7 @@ +extern void wunk(void); + +void +wunk(void) +{ + /* wunk */ +} -- 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] Password identifiers, protocol aging and SCRAM protocol
Hi, On 2016-11-16 19:29:41 -0500, Robert Haas wrote: > On Wed, Nov 16, 2016 at 6:56 PM, Michael Paquier >wrote: > > On Wed, Nov 16, 2016 at 11:24 AM, Robert Haas wrote: > >> diff --git a/contrib/pgcrypto/Makefile b/contrib/pgcrypto/Makefile > >> index 805db76..ddb0183 100644 > >> --- a/contrib/pgcrypto/Makefile > >> +++ b/contrib/pgcrypto/Makefile > >> @@ -1,6 +1,6 @@ > >> # contrib/pgcrypto/Makefile > >> > >> -INT_SRCS = md5.c sha1.c sha2.c internal.c internal-sha2.c blf.c > >> rijndael.c \ > >> +INT_SRCS = md5.c sha1.c internal.c internal-sha2.c blf.c rijndael.c \ > >> fortuna.c random.c pgp-mpi-internal.c imath.c > >> INT_TESTS = sha2 > > > > I would like to do so. And while Linux is happy with that, macOS is > > not, this results in linking resolution errors when compiling the > > library. > > Well, I'm running macOS and it worked for me. TBH, I don't even quite > understand how it could NOT work. What makes the symbols provided by > libpgcommon any different from any other symbols that are part of the > binary? How could one set work and the other set fail? I can > understand how there might be some problem if the backend were > dynamically linked libpgcommon, but it's not. It's doing this: With -Wl,--as-neeeded the linker will dismiss unused symbols found in a static library. Maybe that's the difference? Andres -- 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] Password identifiers, protocol aging and SCRAM protocol
On Wed, Nov 16, 2016 at 6:56 PM, Michael Paquierwrote: > On Wed, Nov 16, 2016 at 11:24 AM, Robert Haas wrote: >> diff --git a/contrib/pgcrypto/Makefile b/contrib/pgcrypto/Makefile >> index 805db76..ddb0183 100644 >> --- a/contrib/pgcrypto/Makefile >> +++ b/contrib/pgcrypto/Makefile >> @@ -1,6 +1,6 @@ >> # contrib/pgcrypto/Makefile >> >> -INT_SRCS = md5.c sha1.c sha2.c internal.c internal-sha2.c blf.c rijndael.c \ >> +INT_SRCS = md5.c sha1.c internal.c internal-sha2.c blf.c rijndael.c \ >> fortuna.c random.c pgp-mpi-internal.c imath.c >> INT_TESTS = sha2 > > I would like to do so. And while Linux is happy with that, macOS is > not, this results in linking resolution errors when compiling the > library. Well, I'm running macOS and it worked for me. TBH, I don't even quite understand how it could NOT work. What makes the symbols provided by libpgcommon any different from any other symbols that are part of the binary? How could one set work and the other set fail? I can understand how there might be some problem if the backend were dynamically linked libpgcommon, but it's not. It's doing this: gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -g -O2 -Wall -Werror -L../../src/port -L../../src/common -Wl,-dead_strip_dylibs -Wall -Werror access/brin/brin.o [many more .o files omitted for brevity] utils/fmgrtab.o ../../src/timezone/localtime.o ../../src/timezone/strftime.o ../../src/timezone/pgtz.o ../../src/port/libpgport_srv.a ../../src/common/libpgcommon_srv.a -lm -o postgres As I understand it, listing the .a file on the linker command line like that is exactly equivalent to listing out each individual .o file that is part of that static library. There shouldn't be any difference in how a symbol that's provided by one of the .o files looks vs. how a symbol that's provided by one of the .a files looks. Let's test it. [rhaas pgsql]$ nm src/backend/postgres | grep -E 'GetUserIdAndContext|psprintf' 0001003d71d0 T _GetUserIdAndContext 00010040f160 T _psprintf So... how would the dynamic loader know that it was supposed to find the first one and fail to find the second one? More to the point, it's clear that it DOES find the second one on every platform in the buildfarm, because adminpack, dblink, pageinspect, and pgstattuple all use psprintf without the push-ups you are proposing to undertake here. pg_md5_encrypt is used by passwordcheck, and forkname_to_number is used by pageinspect and pg_prewarm. It all just works. No special magic required. > Yes we could do that for consistency with the other nix platforms. But > is that really necessary as libpgcommon already has those objects? The point is that *postgres* already has those objects. You don't need to include them twice. -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company -- 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] Password identifiers, protocol aging and SCRAM protocol
On Wed, Nov 16, 2016 at 11:24 AM, Robert Haaswrote: > diff --git a/contrib/pgcrypto/Makefile b/contrib/pgcrypto/Makefile > index 805db76..ddb0183 100644 > --- a/contrib/pgcrypto/Makefile > +++ b/contrib/pgcrypto/Makefile > @@ -1,6 +1,6 @@ > # contrib/pgcrypto/Makefile > > -INT_SRCS = md5.c sha1.c sha2.c internal.c internal-sha2.c blf.c rijndael.c \ > +INT_SRCS = md5.c sha1.c internal.c internal-sha2.c blf.c rijndael.c \ > fortuna.c random.c pgp-mpi-internal.c imath.c > INT_TESTS = sha2 I would like to do so. And while Linux is happy with that, macOS is not, this results in linking resolution errors when compiling the library. > And for Mkvcbuild.pm I think you could just do this: > > diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm > index de764dd..1993764 100644 > --- a/src/tools/msvc/Mkvcbuild.pm > +++ b/src/tools/msvc/Mkvcbuild.pm > @@ -114,6 +114,15 @@ sub mkvcbuild >md5.c pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c >string.c username.c wait_error.c); > > +if ($solution->{options}->{openssl}) > +{ > +push(@pgcommonallfiles, 'sha2_openssl.c'); > +} > +else > +{ > +push(@pgcommonallfiles, 'sha2.c'); > +} > + > our @pgcommonfrontendfiles = ( > @pgcommonallfiles, qw(fe_memutils.c file_utils.c >restricted_token.c)); > @@ -422,7 +431,7 @@ sub mkvcbuild > { > $pgcrypto->AddFiles( > 'contrib/pgcrypto', 'md5.c', > -'sha1.c', 'sha2.c', > +'sha1.c', > 'internal.c', 'internal-sha2.c', > 'blf.c', 'rijndael.c', > 'fortuna.c', 'random.c', > > Is there some reason that won't work? Yes we could do that for consistency with the other nix platforms. But is that really necessary as libpgcommon already has those objects? -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On Wed, Nov 16, 2016 at 1:53 PM, Michael Paquierwrote: >> Yeah, I don't see a point to that. > > OK, by doing so here is what I have. The patch generated by > format-patch, as well as diffs generated by git diff -M are reduced > and the patch gets half in size. They could be reduced more by adding > at the top of sha2.c a couple of defined to map the old SHAXXX_YYY > variables with their PG_ equivalents, but that does not seem worth it > to me, and diffs are listed line by line. All right, this version is much easier to review. I am a bit puzzled, though. It looks like src/common will include sha2.o if built without OpenSSL and sha2_openssl.o if built with OpenSSL. So far, so good. One would think, then, that pgcrypto would not need to worry about these functions any more because libpgcommon_srv.a is linked into the server, so any references to those symbols would presumably just work. However, that's not what you did. On Windows, you added a dependency on libpgcommon which I think is unnecessary because that stuff is already linked into the server. On non-Windows systems, however, you have instead taught pgcrypto to copy the source file it needs from src/common and recompile it. I don't understand why you need to do any of that, or why it should be different on Windows vs. non-Windows. So I think that the changes for the pgcrypto Makefile could just look like this: diff --git a/contrib/pgcrypto/Makefile b/contrib/pgcrypto/Makefile index 805db76..ddb0183 100644 --- a/contrib/pgcrypto/Makefile +++ b/contrib/pgcrypto/Makefile @@ -1,6 +1,6 @@ # contrib/pgcrypto/Makefile -INT_SRCS = md5.c sha1.c sha2.c internal.c internal-sha2.c blf.c rijndael.c \ +INT_SRCS = md5.c sha1.c internal.c internal-sha2.c blf.c rijndael.c \ fortuna.c random.c pgp-mpi-internal.c imath.c INT_TESTS = sha2 And for Mkvcbuild.pm I think you could just do this: diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index de764dd..1993764 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -114,6 +114,15 @@ sub mkvcbuild md5.c pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c string.c username.c wait_error.c); +if ($solution->{options}->{openssl}) +{ +push(@pgcommonallfiles, 'sha2_openssl.c'); +} +else +{ +push(@pgcommonallfiles, 'sha2.c'); +} + our @pgcommonfrontendfiles = ( @pgcommonallfiles, qw(fe_memutils.c file_utils.c restricted_token.c)); @@ -422,7 +431,7 @@ sub mkvcbuild { $pgcrypto->AddFiles( 'contrib/pgcrypto', 'md5.c', -'sha1.c', 'sha2.c', +'sha1.c', 'internal.c', 'internal-sha2.c', 'blf.c', 'rijndael.c', 'fortuna.c', 'random.c', Is there some reason that won't work? -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company -- 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] Password identifiers, protocol aging and SCRAM protocol
On Wed, Nov 16, 2016 at 4:46 AM, Robert Haaswrote: > On Tue, Nov 15, 2016 at 5:12 PM, Michael Paquier > wrote: >> On Tue, Nov 15, 2016 at 12:40 PM, Robert Haas wrote: >>> On Tue, Nov 15, 2016 at 2:24 PM, Michael Paquier >>> wrote: How do you plug in that with OpenSSL? Are you suggesting to use a set of undef definitions in the new header in the same way as pgcrypto is doing, which is rather ugly? Because that's what the deal is about in this patch. >>> >>> Perhaps that justifies renaming them -- although I would think the >>> fact that they are static would prevent conflicts -- but why reorder >>> them and change variable names? >> >> Yeah... Perhaps I should not have done that, which was just for >> consistency's sake, and even if the new reordering makes more sense >> actually... > > Yeah, I don't see a point to that. OK, by doing so here is what I have. The patch generated by format-patch, as well as diffs generated by git diff -M are reduced and the patch gets half in size. They could be reduced more by adding at the top of sha2.c a couple of defined to map the old SHAXXX_YYY variables with their PG_ equivalents, but that does not seem worth it to me, and diffs are listed line by line. -- Michael From 3171c40390703e9b12f97e25914f31accf480a52 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Wed, 16 Nov 2016 10:48:42 -0800 Subject: [PATCH] Refactor SHA2 functions and move them to src/common/ This way both frontend and backends can refer to them if needed. Those functions are taken from pgcrypto, which now fetches directly the source files it needs from src/common/ when compiling its library. A new interface, which is more PG-like is designed for those SHA2 functions, allowing to link to either OpenSSL or the in-core stuff taken from KAME as need be, which is the most flexible solution. --- contrib/pgcrypto/.gitignore | 4 + contrib/pgcrypto/Makefile | 5 +- contrib/pgcrypto/fortuna.c | 12 +-- contrib/pgcrypto/internal-sha2.c| 82 +++ contrib/pgcrypto/sha2.h | 100 -- src/common/Makefile | 6 ++ {contrib/pgcrypto => src/common}/sha2.c | 174 +--- src/common/sha2_openssl.c | 102 +++ src/include/common/sha2.h | 115 + src/tools/msvc/Mkvcbuild.pm | 22 ++-- 10 files changed, 388 insertions(+), 234 deletions(-) delete mode 100644 contrib/pgcrypto/sha2.h rename {contrib/pgcrypto => src/common}/sha2.c (82%) create mode 100644 src/common/sha2_openssl.c create mode 100644 src/include/common/sha2.h diff --git a/contrib/pgcrypto/.gitignore b/contrib/pgcrypto/.gitignore index 5dcb3ff..30619bf 100644 --- a/contrib/pgcrypto/.gitignore +++ b/contrib/pgcrypto/.gitignore @@ -1,3 +1,7 @@ +# Source file copied from src/common +/sha2.c +/sha2_openssl.c + # Generated subdirectories /log/ /results/ diff --git a/contrib/pgcrypto/Makefile b/contrib/pgcrypto/Makefile index 805db76..4085abb 100644 --- a/contrib/pgcrypto/Makefile +++ b/contrib/pgcrypto/Makefile @@ -4,7 +4,7 @@ INT_SRCS = md5.c sha1.c sha2.c internal.c internal-sha2.c blf.c rijndael.c \ fortuna.c random.c pgp-mpi-internal.c imath.c INT_TESTS = sha2 -OSSL_SRCS = openssl.c pgp-mpi-openssl.c +OSSL_SRCS = openssl.c pgp-mpi-openssl.c sha2_openssl.c OSSL_TESTS = sha2 des 3des cast5 ZLIB_TST = pgp-compression @@ -59,6 +59,9 @@ SHLIB_LINK += $(filter -leay32, $(LIBS)) SHLIB_LINK += -lws2_32 endif +sha2.c sha2_openssl.c: % : $(top_srcdir)/src/common/% + rm -f $@ && $(LN_S) $< . + rijndael.o: rijndael.tbl rijndael.tbl: diff --git a/contrib/pgcrypto/fortuna.c b/contrib/pgcrypto/fortuna.c index 5028203..ba74db6 100644 --- a/contrib/pgcrypto/fortuna.c +++ b/contrib/pgcrypto/fortuna.c @@ -34,9 +34,9 @@ #include #include +#include "common/sha2.h" #include "px.h" #include "rijndael.h" -#include "sha2.h" #include "fortuna.h" @@ -112,7 +112,7 @@ #define CIPH_BLOCK 16 /* for internal wrappers */ -#define MD_CTX SHA256_CTX +#define MD_CTX pg_sha256_ctx #define CIPH_CTX rijndael_ctx struct fortuna_state @@ -154,22 +154,22 @@ ciph_encrypt(CIPH_CTX * ctx, const uint8 *in, uint8 *out) static void md_init(MD_CTX * ctx) { - SHA256_Init(ctx); + pg_sha256_init(ctx); } static void md_update(MD_CTX * ctx, const uint8 *data, int len) { - SHA256_Update(ctx, data, len); + pg_sha256_update(ctx, data, len); } static void md_result(MD_CTX * ctx, uint8 *dst) { - SHA256_CTX tmp; + pg_sha256_ctx tmp; memcpy(, ctx, sizeof(*ctx)); - SHA256_Final(dst, ); + pg_sha256_final(, dst); px_memset(, 0, sizeof(tmp)); } diff --git a/contrib/pgcrypto/internal-sha2.c b/contrib/pgcrypto/internal-sha2.c index 55ec7e1..e06f554 100644 ---
Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol
On Tue, Nov 15, 2016 at 5:12 PM, Michael Paquierwrote: > On Tue, Nov 15, 2016 at 12:40 PM, Robert Haas wrote: >> On Tue, Nov 15, 2016 at 2:24 PM, Michael Paquier >> wrote: >>> How do you plug in that with OpenSSL? Are you suggesting to use a set >>> of undef definitions in the new header in the same way as pgcrypto is >>> doing, which is rather ugly? Because that's what the deal is about in >>> this patch. >> >> Perhaps that justifies renaming them -- although I would think the >> fact that they are static would prevent conflicts -- but why reorder >> them and change variable names? > > Yeah... Perhaps I should not have done that, which was just for > consistency's sake, and even if the new reordering makes more sense > actually... Yeah, I don't see a point to that. -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company -- 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] Password identifiers, protocol aging and SCRAM protocol
On Tue, Nov 15, 2016 at 12:40 PM, Robert Haaswrote: > On Tue, Nov 15, 2016 at 2:24 PM, Michael Paquier > wrote: >> How do you plug in that with OpenSSL? Are you suggesting to use a set >> of undef definitions in the new header in the same way as pgcrypto is >> doing, which is rather ugly? Because that's what the deal is about in >> this patch. > > Perhaps that justifies renaming them -- although I would think the > fact that they are static would prevent conflicts -- but why reorder > them and change variable names? Yeah... Perhaps I should not have done that, which was just for consistency's sake, and even if the new reordering makes more sense actually... -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On Tue, Nov 15, 2016 at 2:24 PM, Michael Paquierwrote: > How do you plug in that with OpenSSL? Are you suggesting to use a set > of undef definitions in the new header in the same way as pgcrypto is > doing, which is rather ugly? Because that's what the deal is about in > this patch. Perhaps that justifies renaming them -- although I would think the fact that they are static would prevent conflicts -- but why reorder them and change variable names? -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company -- 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] Password identifiers, protocol aging and SCRAM protocol
On Tue, Nov 15, 2016 at 10:40 AM, Robert Haaswrote: > On Fri, Nov 4, 2016 at 11:58 AM, Peter Eisentraut > wrote: >> The organization of these patches makes sense to me. >> >> On 10/20/16 1:14 AM, Michael Paquier wrote: >>> - 0001, moving all the SHA2 functions to src/common/ and introducing a >>> PG-like interface. No actual changes here. >> >> That's probably alright, although the patch contains a lot more changes >> than I would imagine for a simple file move. I'll still have to review >> that in detail. > > Even with git diff -M, reviewing 0001 is very difficult. It does > things that are considerably in excess of what is needed to move these > files from point A to point B, such as: > > - Renaming static functions to have a "pg" prefix. > - Changing the order of the functions in the file. > - Renaming an argument called "context" to "cxt". > > I think that is a bad plan. I think we should insist that 0001 > content itself with a minimal move of the files changing no more than > is absolutely necessary. If refactoring is needed, those changes can > be submitted separately, which will be much easier to review. My > preliminary judgement is that most of this change is pointless and > should be reverted. How do you plug in that with OpenSSL? Are you suggesting to use a set of undef definitions in the new header in the same way as pgcrypto is doing, which is rather ugly? Because that's what the deal is about in this patch. -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On Fri, Nov 4, 2016 at 11:58 AM, Peter Eisentrautwrote: > The organization of these patches makes sense to me. > > On 10/20/16 1:14 AM, Michael Paquier wrote: >> - 0001, moving all the SHA2 functions to src/common/ and introducing a >> PG-like interface. No actual changes here. > > That's probably alright, although the patch contains a lot more changes > than I would imagine for a simple file move. I'll still have to review > that in detail. Even with git diff -M, reviewing 0001 is very difficult. It does things that are considerably in excess of what is needed to move these files from point A to point B, such as: - Renaming static functions to have a "pg" prefix. - Changing the order of the functions in the file. - Renaming an argument called "context" to "cxt". I think that is a bad plan. I think we should insist that 0001 content itself with a minimal move of the files changing no more than is absolutely necessary. If refactoring is needed, those changes can be submitted separately, which will be much easier to review. My preliminary judgement is that most of this change is pointless and should be reverted. -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company -- 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] Password identifiers, protocol aging and SCRAM protocol
On Wed, 9 Nov 2016 15:23:11 +0900 Michael Paquierwrote: > > (This is about patch 0007, not 0001) > Thanks, you are right. That's not good as-is. So this basically means > that the characters here should be from 32 to 127 included. Really, most important is to exclude comma from the list of allowed characters. And this prevents us from using a range. I'd do something like: char prinables="0123456789ABCDE...xyz!@#*&+"; unsigned int r; for (i=0;i generate_nonce needs just to be made smarter in the way it selects the > character bytes. -- 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] Password identifiers, protocol aging and SCRAM protocol
On Wed, Nov 9, 2016 at 3:13 PM, Victor Wagnerwrote: > On Tue, 18 Oct 2016 16:35:27 +0900 > Michael Paquier wrote: > > Hi >> Attached is a rebased patch set for SCRAM, with the following things: >> - 0001, moving all the SHA2 functions to src/common/ and introducing a >> PG-like interface. No actual changes here. > > It seems, that client nonce generation in this patch is not > RFC-compliant. > > RFC 5802 states that SCRAM nonce should be > > a sequence of random printable ASCII > characters excluding ',' > > while this patch uses sequence of random bytes from pg_strong_random > function with zero byte appended. (This is about patch 0007, not 0001) Thanks, you are right. That's not good as-is. So this basically means that the characters here should be from 32 to 127 included. generate_nonce needs just to be made smarter in the way it selects the character bytes. -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On Tue, 18 Oct 2016 16:35:27 +0900 Michael Paquierwrote: Hi > Attached is a rebased patch set for SCRAM, with the following things: > - 0001, moving all the SHA2 functions to src/common/ and introducing a > PG-like interface. No actual changes here. It seems, that client nonce generation in this patch is not RFC-compliant. RFC 5802 states that SCRAM nonce should be a sequence of random printable ASCII characters excluding ',' while this patch uses sequence of random bytes from pg_strong_random function with zero byte appended. It could cause following problems 1. If zero byte happens inside random sequence, nonce would be shorter than expected, or even empty. 2. If one of bytes happens to be ASCII Code of comma, than server to the client-first message, which includes copy of client nonce, appended by server nonce, as one of unquoted comman-separated field, would be parsed incorrectly. Regards, Victor -- -- 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] Password identifiers, protocol aging and SCRAM protocol
On Sat, Nov 5, 2016 at 12:58 AM, Peter Eisentrautwrote: > The organization of these patches makes sense to me. > > On 10/20/16 1:14 AM, Michael Paquier wrote: >> - 0001, moving all the SHA2 functions to src/common/ and introducing a >> PG-like interface. No actual changes here. > > That's probably alright, although the patch contains a lot more changes > than I would imagine for a simple file move. I'll still have to review > that in detail. The main point is to know if people are happy of having an interface of the type pg_sha256_[init|update|finish] to tackle the fact that core code contains a set of routines that map with some of the OpenSSL APIs... >> - 0002, replacing PostmasterRandom by pg_strong_random(), with a fix >> for the cancel key problem. >> - 0003, adding for pg_strong_random() a fallback for any nix platform >> not having /dev/random. This should be grouped with 0002, but I split >> it for clarity. > > Also makes sense, but will need more detailed review. I did not follow > the previous PostmasterRandom issues closely. pademelon does not have /dev/random and /dev/urandom, so the issue is related to having a fallback method... But Heikki feels that having a method producing potentially weak keys should not be in pg_strong_random(). I'd suggest to control that with a ./configure switch and call it a day. Platforms without any of the four randomness methods pg_strong_random includes play a dangerous game but... >> - 0004, Add encoding routines for base64 without whitespace in >> src/common/. I improved the error handling here by making them return >> -1 in case of error and let the caller handle the error. > > I don't think we want to have two different copies of base64 routines. > Surely we can make the existing routines do what we want with a > parameter or two about whitespace and line length. We could. Though after hacking on that I find cleaner copying the code from encoding.c after removing the whitespace handling, as Heikki has suggested. >> - 0005, Refactor decision-making of password encryption into a single >> routine. > > It makes sense to factor this out. We probably don't need the pstrdup > if we just keep the string as is. (You could make an argument for it if > the input values were const char *.) We probably also don't need the > pfree. The Assert(0) can probably be done better. We usually use > elog() in such cases. Hm, OK. Agreed with that. >> - 0006, Add clause PASSWORD val USING protocol to CREATE/ALTER ROLE. > > "protocol" is a weird choice here. Maybe something like "method" is > better. The way the USING clause is placed can be confusing. It's not > clear that it belongs to PASSWORD. If someone wants to augment another > clause in CREATE ROLE with a secondary argument, then it could get > really confusing. I'd suggest something to group things together, like > PASSWORD (val USING method). The method could be an identifier instead > of a string. Why not. > Please add an example to the documentation and explain better how this > interacts with the existing ENCRYPTED PASSWORD clause. Sure. >> - 0007, the SCRAM implementation. > > No documentation about pg_hba.conf changes, so I don't know how to use > this. ;-) Oops. I have focused on the code a lot during last rewrite of the patch and forgot that. I'll think about something. > This implements SASL and SCRAM and SHA256. We need to be clear about > which term we advertise to users. An explanation in the missing > documentation would probably be a good start. pg_hba.conf uses "scram" as keyword, but scram refers to a family of authentication methods. There is as well SCRAM-SHA-1, SCRAM-SHA-256 (what this patch does). Hence wouldn't it make sense to use scram_sha256 in pg_hba.conf instead? If for example in the future there is a SHA-512 version of SCRAM we could switch easily to that and define scram_sha512. There is also the channel binding to think about... So we could have a list of keywords perhaps associated with SASL? Imagine for example: sasl$algo,$channel_binding Giving potentially: saslscram_sha256 saslscram_sha256,channel saslscram_sha512 saslscram_sha512,channel In the case of the patch of this thread just the first entry would make sense, once channel binding support is added a second keyword/option could be added. And there are of course other methods that could replace SCRAM.. > I would also like to see a test suite that covers the authentication > specifically. What you have in mind is a TAP test with a couple of roles and pg_hba.conf getting rewritten then reloaded? Adding it in src/test/recovery/ is the first place that comes in mind but that's not really something related to recovery... Any ideas? -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
The organization of these patches makes sense to me. On 10/20/16 1:14 AM, Michael Paquier wrote: > - 0001, moving all the SHA2 functions to src/common/ and introducing a > PG-like interface. No actual changes here. That's probably alright, although the patch contains a lot more changes than I would imagine for a simple file move. I'll still have to review that in detail. > - 0002, replacing PostmasterRandom by pg_strong_random(), with a fix > for the cancel key problem. > - 0003, adding for pg_strong_random() a fallback for any nix platform > not having /dev/random. This should be grouped with 0002, but I split > it for clarity. Also makes sense, but will need more detailed review. I did not follow the previous PostmasterRandom issues closely. > - 0004, Add encoding routines for base64 without whitespace in > src/common/. I improved the error handling here by making them return > -1 in case of error and let the caller handle the error. I don't think we want to have two different copies of base64 routines. Surely we can make the existing routines do what we want with a parameter or two about whitespace and line length. > - 0005, Refactor decision-making of password encryption into a single routine. It makes sense to factor this out. We probably don't need the pstrdup if we just keep the string as is. (You could make an argument for it if the input values were const char *.) We probably also don't need the pfree. The Assert(0) can probably be done better. We usually use elog() in such cases. > - 0006, Add clause PASSWORD val USING protocol to CREATE/ALTER ROLE. "protocol" is a weird choice here. Maybe something like "method" is better. The way the USING clause is placed can be confusing. It's not clear that it belongs to PASSWORD. If someone wants to augment another clause in CREATE ROLE with a secondary argument, then it could get really confusing. I'd suggest something to group things together, like PASSWORD (val USING method). The method could be an identifier instead of a string. Please add an example to the documentation and explain better how this interacts with the existing ENCRYPTED PASSWORD clause. > - 0007, the SCRAM implementation. No documentation about pg_hba.conf changes, so I don't know how to use this. ;-) This implements SASL and SCRAM and SHA256. We need to be clear about which term we advertise to users. An explanation in the missing documentation would probably be a good start. I would also like to see a test suite that covers the authentication specifically. -- Peter Eisentraut http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services -- 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] Password identifiers, protocol aging and SCRAM protocol
On 10/17/2016 12:27 PM, Heikki Linnakangas wrote: On 10/17/2016 12:18 PM, Michael Paquier wrote: You removed the part of pgcrypto in charge of randomness, nice move. I was wondering about how to do with the perfc and the unix_std at some point, and ripping them off as you did is fine for me. Yeah. I didn't understand the need for the perfc stuff. Are there Windows systems that don't have the Crypto APIs? I doubt it, but the buildfarm will tell us in a moment if there are. And if we don't have a good source of randomness like /dev/random, I think it's better to fail, than try to collect entropy ourselves (which is what unix_std did). If there's a platform where that doesn't work, someone will hopefully send us a patch, rather than silently fall back to an iffy implementation. Looks like Tom's old HP-UX box, pademelon, is not happy about this. Does (that version of) HP-UX not have /dev/urandom? I think we're going to need a bit more logging if no randomness source is available. What we have now is just "could not generate random query cancel key", which isn't very informative. Perhaps we should also call pg_strong_random() once at postmaster startup, to check that it works, instead of starting up but not accepting any connections. - 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] Password identifiers, protocol aging and SCRAM protocol
On 10/17/2016 12:18 PM, Michael Paquier wrote: You removed the part of pgcrypto in charge of randomness, nice move. I was wondering about how to do with the perfc and the unix_std at some point, and ripping them off as you did is fine for me. Yeah. I didn't understand the need for the perfc stuff. Are there Windows systems that don't have the Crypto APIs? I doubt it, but the buildfarm will tell us in a moment if there are. And if we don't have a good source of randomness like /dev/random, I think it's better to fail, than try to collect entropy ourselves (which is what unix_std did). If there's a platform where that doesn't work, someone will hopefully send us a patch, rather than silently fall back to an iffy implementation. - 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] Password identifiers, protocol aging and SCRAM protocol
On Mon, Oct 17, 2016 at 5:55 PM, Heikki Linnakangaswrote: > On 10/15/2016 04:26 PM, Michael Paquier wrote: >>> >>> * Now that we don't call random() in postmaster anymore, is there any >>> point >>> in calling srandom() there (i.e. where the above incorrect comment was)? >>> Should we remove it? random() might be used by pre-loaded extensions, >>> though. (Hopefully not for cryptographic purposes.) >> >> >> That's the business of the maintainers such modules, so my heart is >> telling me to rip it off, but my mind tells me that there is no point >> in making them unhappy either if they rely on it. I'd trust my mind on >> this one, other opinions are welcome. > > > I kept it for now. Doesn't do any harm either, even if it's unnecessary. > >>> * Should we backport this? Sorry if we discussed that already, but I >>> don't >>> remember. >> >> >> I think that we discussed quickly the point at last PGCon during the >> SCRAM-committee-unofficial meeting, and that we talked about doing >> that only for HEAD. > > > Ok, committed to HEAD. You removed the part of pgcrypto in charge of randomness, nice move. I was wondering about how to do with the perfc and the unix_std at some point, and ripping them off as you did is fine for me. -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
On 10/15/2016 04:26 PM, Michael Paquier wrote: * Now that we don't call random() in postmaster anymore, is there any point in calling srandom() there (i.e. where the above incorrect comment was)? Should we remove it? random() might be used by pre-loaded extensions, though. (Hopefully not for cryptographic purposes.) That's the business of the maintainers such modules, so my heart is telling me to rip it off, but my mind tells me that there is no point in making them unhappy either if they rely on it. I'd trust my mind on this one, other opinions are welcome. I kept it for now. Doesn't do any harm either, even if it's unnecessary. * Should we backport this? Sorry if we discussed that already, but I don't remember. I think that we discussed quickly the point at last PGCon during the SCRAM-committee-unofficial meeting, and that we talked about doing that only for HEAD. Ok, committed to HEAD. Thanks! - 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] Password identifiers, protocol aging and SCRAM protocol
On Fri, Oct 14, 2016 at 9:08 PM, Heikki Linnakangaswrote: > On 10/12/2016 11:11 AM, Michael Paquier wrote: > * Changed pg_strong_random() to return false on error, and let the callers > handle errors. That's more error-prone than throwing an error in the > function itself, as it's an easy mistake to forget to check for the return > value, but we can't just "exit(1)" if called in the frontend. If it gets > called from libpq during authentication, as it will with SCRAM, we want to > close the connection and report an error, not exit the whole user > application. Likewise, in postmaster, if we fail to generate a query cancel > key when forking a backend, we don't want to FATAL and shut down the whole > postmaster. Okay for this one. Indeed that's a cleaner interface. > This is pretty much ready for commit now, IMO, but please do review one more > time. OK, I had an extra lookup and the patch looks in pretty good shape seen from here. - MyCancelKey = PostmasterRandom(); + if (!pg_strong_random(, sizeof(MyCancelKey))) + { + rw->rw_crashed_at = GetCurrentTimestamp(); + return false; + } It would be nice to LOG an entry here for bgworkers. + /* +* fork failed, fall through to report -- actual error message was +* logged by StartAutoVacWorker +*/ Since you created a new block, the first line gets longer than 80 characters. > * We now open and close /dev/(u)random on every pg_strong_random() call. > Should we be worried about performance of that? Actually I have hacked up a small program that can be used to compare using /dev/urandom with random() calls (this emulates RandomSalt), and opening/closing /dev/urandom causes a performance hit, but the difference becomes noticeable with loop calls higher than 10k on my Linux laptop. I recall that /dev/urandom is quite slow on Linux compared to other platforms still... So for a single call per connection attempt we won't actually notice it much. I am just attaching that if you want to play with it, and you can use it as follows: ./calc [dev|random] nbytes loops That's really a quick hack but it does the job if you worry about the performance. > * Now that we don't call random() in postmaster anymore, is there any point > in calling srandom() there (i.e. where the above incorrect comment was)? > Should we remove it? random() might be used by pre-loaded extensions, > though. (Hopefully not for cryptographic purposes.) That's the business of the maintainers such modules, so my heart is telling me to rip it off, but my mind tells me that there is no point in making them unhappy either if they rely on it. I'd trust my mind on this one, other opinions are welcome. > * Should we backport this? Sorry if we discussed that already, but I don't > remember. I think that we discussed quickly the point at last PGCon during the SCRAM-committee-unofficial meeting, and that we talked about doing that only for HEAD. -- Michael #include #include #include #include #include #include #include static int nbytes = 20; static char *method = NULL; static char *progname = NULL; static int loops = 100; static void help(void) { printf("%s [dev|random] nbytes loops\n", progname); } static void calc_dev(void) { int i, f; char *data = malloc(nbytes); for (i = 0; i < loops; i++) { f = open("/dev/urandom", O_RDONLY, 0); if (f == -1) { fprintf(stderr, "Failed to open /dev/urandom\n"); exit(1); } (void) read(f, data, nbytes); close(f); } free(data); } static void calc_random(void) { long rand; int i, j; char data; for (i = 0; i < loops; i++) { for (j = 0; j < nbytes; j++) { rand = random(); data = (rand % 255) + 1; } } } int main(int argc, char **argv) { progname = strdup(argv[0]); if (argc != 4) { fprintf(stderr, "Meh\n"); exit(1); } nbytes = atoi(argv[2]); loops = atoi(argv[3]); printf("nbytes = %d, loops = %d\n", nbytes, loops); if (strcmp(argv[1], "dev") == 0) calc_dev(); else if (strcmp(argv[1], "random") == 0) calc_random(); else { fprintf(stderr, "Incorrect method\n"); exit(1); } } -- 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] Password identifiers, protocol aging and SCRAM protocol
On 10/14/2016 03:08 PM, Heikki Linnakangas wrote: I spent some time whacking that around: Sigh, forgot attachment. Here you go. - Heikki >From 4b3000df3dc71ad41018a6606c92bc4a0adeb8f5 Mon Sep 17 00:00:00 2001 From: Heikki LinnakangasDate: Fri, 14 Oct 2016 14:58:44 +0300 Subject: [PATCH 1/1] Replace PostmasterRandom() with a stronger way of generating randomness. This adds a new routine, pg_strong_random() for generating random bytes, for use in both frontend and backend. At the moment, it's only used in the backend, but the upcoming SCRAM authentication patches need strong random numbers in libpq as well. pg_strong_random() can acquire strong random numbers from a number of sources, depending on what's available: - OpenSSL RAND_bytes(), if built with OpenSSL - On Windows, the native cryptographic functions are used - /dev/urandom - /dev/random Original patch by Magnus Hagander, with further tweaks by Michael Paquier and me. Discussion: --- src/backend/libpq/auth.c| 21 - src/backend/postmaster/postmaster.c | 153 ++-- src/include/port.h | 3 + src/port/Makefile | 2 +- src/port/pg_strong_random.c | 148 ++ src/tools/msvc/Mkvcbuild.pm | 2 +- 6 files changed, 212 insertions(+), 117 deletions(-) create mode 100644 src/port/pg_strong_random.c diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 0ba8530..e617ac6 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -45,6 +45,12 @@ static void auth_failed(Port *port, int status, char *logdetail); static char *recv_password_packet(Port *port); static int recv_and_check_password_packet(Port *port, char **logdetail); +/* + * MD5 authentication + * + */ +static int CheckMD5Auth(Port *port, char **logdetail); + /* * Ident authentication @@ -535,9 +541,7 @@ ClientAuthentication(Port *port) ereport(FATAL, (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled"))); - /* include the salt to use for computing the response */ - sendAuthRequest(port, AUTH_REQ_MD5, port->md5Salt, 4); - status = recv_and_check_password_packet(port, ); + status = CheckMD5Auth(port, ); break; case uaPassword: @@ -696,6 +700,17 @@ recv_password_packet(Port *port) * */ +static int +CheckMD5Auth(Port *port, char **logdetail) +{ + /* include the salt to use for computing the response */ + pg_strong_random(port->md5Salt, sizeof(port->md5Salt)); + + sendAuthRequest(port, AUTH_REQ_MD5, port->md5Salt, 4); + return recv_and_check_password_packet(port, logdetail); +} + + /* * Called when we have sent an authorization request for a password. * Get the response and check it. diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 2d43506..d646692 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -358,14 +358,6 @@ static volatile bool avlauncher_needs_signal = false; static volatile bool StartWorkerNeeded = true; static volatile bool HaveCrashedWorker = false; -/* - * State for assigning random salts and cancel keys. - * Also, the global MyCancelKey passes the cancel key assigned to a given - * backend from the postmaster to that backend (via fork). - */ -static unsigned int random_seed = 0; -static struct timeval random_start_time; - #ifdef USE_BONJOUR static DNSServiceRef bonjour_sdref = NULL; #endif @@ -403,8 +395,6 @@ static void processCancelRequest(Port *port, void *pkt); static int initMasks(fd_set *rmask); static void report_fork_failure_to_client(Port *port, int errnum); static CAC_state canAcceptConnections(void); -static long PostmasterRandom(void); -static void RandomSalt(char *salt, int len); static void signal_child(pid_t pid, int signal); static bool SignalSomeChildren(int signal, int targets); static void TerminateChildren(int signal); @@ -579,9 +569,11 @@ PostmasterMain(int argc, char *argv[]) * Initialize random(3) so we don't get the same values in every run. * * Note: the seed is pretty predictable from externally-visible facts such - * as postmaster start time, so avoid using random() for security-critical - * random values during postmaster startup. At the time of first - * connection, PostmasterRandom will select a hopefully-more-random seed. + * as postmaster start time, so don't use random() for security-critical + * random values (use pg_strong_random() instead). At the time of first + * connection,
Re: [HACKERS] Password identifiers, protocol aging and SCRAM protocol
On 10/12/2016 11:11 AM, Michael Paquier wrote: And so we are back on that, with a new set: Great! I'm looking at this first one for now: - 0001, introducing pg_strong_random() in src/port/ to have the backend portion of SCRAM use it instead of random(). This patch is from Magnus who has kindly sent is to me, so the authorship goes to him. This patch replaces at the same time PostmasterRandom() with it, this way once SCRAM gets integrated both the frontend and the backend finish using the same facility. I think that's good for consistency. Compared to the version Magnus has sent me, I have changed two things: -- Reading from /dev/urandom and /dev/random is not influenced by EINTR. read() handling is also made better in case of partial reads from a given source. -- Win32 Crypto routines use MS_DEF_PROV instead of NULL. I think that's a better idea to not let the user the choice of the encryption source here. I spent some time whacking that around: * Renamed the file to src/port/pg_strong_random.c "pgsrandom" makes me think of srandom(), which this isn't. * Changed pg_strong_random() to return false on error, and let the callers handle errors. That's more error-prone than throwing an error in the function itself, as it's an easy mistake to forget to check for the return value, but we can't just "exit(1)" if called in the frontend. If it gets called from libpq during authentication, as it will with SCRAM, we want to close the connection and report an error, not exit the whole user application. Likewise, in postmaster, if we fail to generate a query cancel key when forking a backend, we don't want to FATAL and shut down the whole postmaster. * There used to be this: /* -* Precompute password salt values to use for this connection. It's -* slightly annoying to do this long in advance of knowing whether we'll -* need 'em or not, but we must do the random() calls before we fork, not -* after. Else the postmaster's random sequence won't get advanced, and -* all backends would end up using the same salt... -*/ - RandomSalt(port->md5Salt, sizeof(port->md5Salt)); But that whole business of advancing postmaster's random sequence is moot now. So I moved the generation of md5 salt from postmaster to where MD5 authentication is performed. * This comment in postmaster.c was wrong: @@ -581,7 +571,7 @@ PostmasterMain(int argc, char *argv[]) * Note: the seed is pretty predictable from externally-visible facts such * as postmaster start time, so avoid using random() for security-critical * random values during postmaster startup. At the time of first -* connection, PostmasterRandom will select a hopefully-more-random seed. +* connection, pg_strong_random will select a hopefully-more-random seed. */ srandom((unsigned int) (MyProcPid ^ MyStartTime)); We don't use pg_strong_random() for that, the same PID+timestamp method is still used as before. Adjusted the comment to reflect reality. * Added "#include ", for the CryptAcquireContext and CryptGenRandom functions? It compiled OK without that, so I guess it got pulled in via some other header file, but seems more clear and future-proof to #include it directly. * random comment kibitzing (no pun intended). This is pretty much ready for commit now, IMO, but please do review one more time. And I do have some small questions still: * We now open and close /dev/(u)random on every pg_strong_random() call. Should we be worried about performance of that? * Now that we don't call random() in postmaster anymore, is there any point in calling srandom() there (i.e. where the above incorrect comment was)? Should we remove it? random() might be used by pre-loaded extensions, though. (Hopefully not for cryptographic purposes.) * Should we backport this? Sorry if we discussed that already, but I don't remember. - 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] Password identifiers, protocol aging and SCRAM protocol
On Wed, Sep 28, 2016 at 8:55 PM, Michael Paquierwrote: >> Our b64_encode routine does use whitespace, so we can't use it as is for >> SCRAM. As the patch stands, we might never output anything long enough to >> create linefeeds, but let's be tidy. The base64 implementation is about 100 >> lines of code, so perhaps we should just leave src/backend/utils/encode.c >> alone, and make a new copy of the base64 routines in src/common. > > OK, I'll refresh that tomorrow with the rest. Thanks for the commit to > extend password_encryption. OK, so after more chatting with Heikki, here is a list of TODO items and a summary of the state of things: - base64 encoding routines should drop whitespace (' ', \r, \t), and it would be better to just copy those from the backend's encode.c to src/common/. No need to move escape and binary things, nor touch backend's base64 routines. - No need to move sha1.c to src/common/. Better to just get sha2.c into src/common/ as we aim at SCRAM-SHA-256. - random() called in the client is no good. We need something better here. - The error handling needs to be reworked and should follow the protocol presented by RFC5802, by sending back e= messages. This needs a bit of work, not much I think though as the infra is in place in the core patch. - Let's discard the md5-or-scram optional thing in pg_hba.conf. This complicates the error handling protocol. I am marking this patch as returned with feedback for current CF and will post a new set soon, moving it to the next CF once I have the new set of patches ready for posting. -- Michael -- 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] Password identifiers, protocol aging and SCRAM protocol
Heikki, Michael, Magnus, * Michael Paquier (michael.paqu...@gmail.com) wrote: > On Tue, Sep 27, 2016 at 10:42 PM, Heikki Linnakangaswrote: > > The libpq-side is not. Just calling random() won't do. We haven't needed for > > random numbers in libpq before, but now we do. Is the pgcrypto solution > > portable enough that we can use it in libpq? > > Do you think that urandom would be enough then? The last time I took a > look at that, I saw urandom on all modern platforms even those ones: > OpenBSD, NetBSD, Solaris, SunOS. For Windows the CryptGen stuff would > be nice enough I guess.. Magnus had been working on a patch that, as I recall, he thought was portable and I believe could be used on both sides. Magnus, would what you were working on be helpful here...? Thanks! Stephen signature.asc Description: Digital signature