Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb577743

Browse files
Make SCRAM iteration count configurable
Replace the hardcoded value with a GUC such that the iterationcount can be raised in order to increase protection againstbrute-force attacks. The hardcoded value for SCRAM iterationcount was defined to be 4096, which is taken from RFC 7677, soset the default for the GUC to 4096 to match. In RFC 7677 therecommendation is at least 15000 iterations but 4096 is listedas a SHOULD requirement given that it's estimated to yield a0.5s processing time on a mobile handset of the time of RFCwriting (late 2015).Raising the iteration count of SCRAM will make stored passwordsmore resilient to brute-force attacks at a higher computationalcost during connection establishment. Lowering the count willreduce computational overhead during connections at the tradeoffof reducing strength against brute-force attacks.There are however platforms where even a modest iteration countyields a too high computational overhead, with weaker passwordencryption schemes chosen as a result. In these situations,SCRAM with a very low iteration count still gives benefits overweaker schemes like md5, so we allow the iteration count to beset to one at the low end.The new GUC is intentionally generically named such that it canbe made to support future SCRAM standards should they emerge.At that point the value can be made into key:value pairs withan undefined key as a default which will be backwards compatiblewith this.Reviewed-by: Michael Paquier <michael@paquier.xyz>Reviewed-by: Jonathan S. Katz <jkatz@postgresql.org>Discussion:https://postgr.es/m/F72E7BC7-189F-4B17-BF47-9735EB72C364@yesql.se
1 parentc15631f commitb577743

File tree

16 files changed

+94
-10
lines changed

16 files changed

+94
-10
lines changed

‎doc/src/sgml/config.sgml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,26 @@ include_dir 'conf.d'
11321132
</listitem>
11331133
</varlistentry>
11341134

1135+
<varlistentry>
1136+
<term><varname>scram_iterations</varname> (<type>integer</type>)
1137+
<indexterm>
1138+
<primary><varname>scram_iterations</varname> configuration parameter</primary>
1139+
</indexterm>
1140+
</term>
1141+
<listitem>
1142+
<para>
1143+
The number of computational iterations to be performed when encrypting
1144+
a password using SCRAM-SHA-256. The default is <literal>4096</literal>.
1145+
A higher number of iterations provides additional protection against
1146+
brute-force attacks on stored passwords, but makes authentication
1147+
slower. Changing the value has no effect on existing passwords
1148+
encrypted with SCRAM-SHA-256 as the iteration count is fixed at the
1149+
time of encryption. In order to make use of a changed value, a new
1150+
password must be set.
1151+
</para>
1152+
</listitem>
1153+
</varlistentry>
1154+
11351155
<varlistentry id="guc-krb-server-keyfile" xreflabel="krb_server_keyfile">
11361156
<term><varname>krb_server_keyfile</varname> (<type>string</type>)
11371157
<indexterm>

‎src/backend/libpq/auth-scram.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,11 @@ static char *scram_mock_salt(const char *username,
191191
pg_cryptohash_typehash_type,
192192
intkey_length);
193193

194+
/*
195+
* The number of iterations to use when generating new secrets.
196+
*/
197+
intscram_sha_256_iterations=SCRAM_SHA_256_DEFAULT_ITERATIONS;
198+
194199
/*
195200
* Get a list of SASL mechanisms that this module supports.
196201
*
@@ -496,7 +501,7 @@ pg_be_scram_build_secret(const char *password)
496501

497502
result=scram_build_secret(PG_SHA256,SCRAM_SHA_256_KEY_LEN,
498503
saltbuf,SCRAM_DEFAULT_SALT_LEN,
499-
SCRAM_DEFAULT_ITERATIONS,password,
504+
scram_sha_256_iterations,password,
500505
&errstr);
501506

502507
if (prep_password)
@@ -717,7 +722,7 @@ mock_scram_secret(const char *username, pg_cryptohash_type *hash_type,
717722
encoded_salt[encoded_len]='\0';
718723

719724
*salt=encoded_salt;
720-
*iterations=SCRAM_DEFAULT_ITERATIONS;
725+
*iterations=SCRAM_SHA_256_DEFAULT_ITERATIONS;
721726

722727
/* StoredKey and ServerKey are not used in a doomed authentication */
723728
memset(stored_key,0,SCRAM_MAX_KEY_LEN);

‎src/backend/utils/misc/guc_tables.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@
4141
#include"commands/trigger.h"
4242
#include"commands/user.h"
4343
#include"commands/vacuum.h"
44+
#include"common/scram-common.h"
4445
#include"jit/jit.h"
4546
#include"libpq/auth.h"
4647
#include"libpq/libpq.h"
48+
#include"libpq/scram.h"
4749
#include"nodes/queryjumble.h"
4850
#include"optimizer/cost.h"
4951
#include"optimizer/geqo.h"
@@ -3468,6 +3470,17 @@ struct config_int ConfigureNamesInt[] =
34683470
NULL,NULL,NULL
34693471
},
34703472

3473+
{
3474+
{"scram_iterations",PGC_USERSET,CONN_AUTH_AUTH,
3475+
gettext_noop("Sets the iteration count for SCRAM secret generation."),
3476+
NULL,
3477+
GUC_REPORT
3478+
},
3479+
&scram_sha_256_iterations,
3480+
SCRAM_SHA_256_DEFAULT_ITERATIONS,1,INT_MAX,
3481+
NULL,NULL,NULL
3482+
},
3483+
34713484
/* End-of-list marker */
34723485
{
34733486
{NULL,0,0,NULL,NULL},NULL,0,0,0,NULL,NULL,NULL

‎src/backend/utils/misc/postgresql.conf.sample

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595

9696
#authentication_timeout = 1min# 1s-600s
9797
#password_encryption = scram-sha-256# scram-sha-256 or md5
98+
#scram_iterations = 4096
9899
#db_user_namespace = off
99100

100101
# GSSAPI using Kerberos

‎src/common/scram-common.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,7 @@ scram_build_secret(pg_cryptohash_type hash_type, int key_length,
214214
/* Only this hash method is supported currently */
215215
Assert(hash_type==PG_SHA256);
216216

217-
if (iterations <=0)
218-
iterations=SCRAM_DEFAULT_ITERATIONS;
217+
Assert(iterations>0);
219218

220219
/* Calculate StoredKey and ServerKey */
221220
if (scram_SaltedPassword(password,hash_type,key_length,

‎src/include/common/scram-common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
* Default number of iterations when generating secret. Should be at least
4848
* 4096 per RFC 7677.
4949
*/
50-
#defineSCRAM_DEFAULT_ITERATIONS4096
50+
#defineSCRAM_SHA_256_DEFAULT_ITERATIONS4096
5151

5252
externintscram_SaltedPassword(constchar*password,
5353
pg_cryptohash_typehash_type,intkey_length,

‎src/include/libpq/scram.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
#include"libpq/libpq-be.h"
1919
#include"libpq/sasl.h"
2020

21+
/* Number of iterations when generating new secrets */
22+
externPGDLLIMPORTintscram_sha_256_iterations;
23+
2124
/* SASL implementation callbacks */
2225
externPGDLLIMPORTconstpg_be_sasl_mechpg_be_scram_mech;
2326

‎src/interfaces/libpq/fe-auth-scram.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -895,7 +895,7 @@ verify_server_signature(fe_scram_state *state, bool *match,
895895
* error details.
896896
*/
897897
char*
898-
pg_fe_scram_build_secret(constchar*password,constchar**errstr)
898+
pg_fe_scram_build_secret(constchar*password,intiterations,constchar**errstr)
899899
{
900900
char*prep_password;
901901
pg_saslprep_rcrc;
@@ -927,7 +927,7 @@ pg_fe_scram_build_secret(const char *password, const char **errstr)
927927

928928
result=scram_build_secret(PG_SHA256,SCRAM_SHA_256_KEY_LEN,saltbuf,
929929
SCRAM_DEFAULT_SALT_LEN,
930-
SCRAM_DEFAULT_ITERATIONS,password,
930+
iterations,password,
931931
errstr);
932932

933933
free(prep_password);

‎src/interfaces/libpq/fe-auth.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1341,7 +1341,9 @@ PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user,
13411341
{
13421342
constchar*errstr=NULL;
13431343

1344-
crypt_pwd=pg_fe_scram_build_secret(passwd,&errstr);
1344+
crypt_pwd=pg_fe_scram_build_secret(passwd,
1345+
conn->scram_sha_256_iterations,
1346+
&errstr);
13451347
if (!crypt_pwd)
13461348
libpq_append_conn_error(conn,"could not encrypt password: %s",errstr);
13471349
}

‎src/interfaces/libpq/fe-auth.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ extern char *pg_fe_getauthname(PQExpBuffer errorMessage);
2626
/* Mechanisms in fe-auth-scram.c */
2727
externconstpg_fe_sasl_mechpg_scram_mech;
2828
externchar*pg_fe_scram_build_secret(constchar*password,
29+
intiterations,
2930
constchar**errstr);
3031

3132
#endif/* FE_AUTH_H */

‎src/interfaces/libpq/fe-connect.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@ pqDropServerData(PGconn *conn)
596596
conn->std_strings= false;
597597
conn->default_transaction_read_only=PG_BOOL_UNKNOWN;
598598
conn->in_hot_standby=PG_BOOL_UNKNOWN;
599+
conn->scram_sha_256_iterations=SCRAM_SHA_256_DEFAULT_ITERATIONS;
599600
conn->sversion=0;
600601

601602
/* Drop large-object lookup data */
@@ -4182,6 +4183,7 @@ makeEmptyPGconn(void)
41824183
conn->std_strings= false;/* unless server says differently */
41834184
conn->default_transaction_read_only=PG_BOOL_UNKNOWN;
41844185
conn->in_hot_standby=PG_BOOL_UNKNOWN;
4186+
conn->scram_sha_256_iterations=SCRAM_SHA_256_DEFAULT_ITERATIONS;
41854187
conn->verbosity=PQERRORS_DEFAULT;
41864188
conn->show_context=PQSHOW_CONTEXT_ERRORS;
41874189
conn->sock=PGINVALID_SOCKET;

‎src/interfaces/libpq/fe-exec.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,10 @@ pqSaveParameterStatus(PGconn *conn, const char *name, const char *value)
11811181
conn->in_hot_standby=
11821182
(strcmp(value,"on")==0) ?PG_BOOL_YES :PG_BOOL_NO;
11831183
}
1184+
elseif (strcmp(name,"scram_iterations")==0)
1185+
{
1186+
conn->scram_sha_256_iterations=atoi(value);
1187+
}
11841188
}
11851189

11861190

‎src/interfaces/libpq/libpq-int.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,7 @@ struct pg_conn
525525
/* Assorted state for SASL, SSL, GSS, etc */
526526
constpg_fe_sasl_mech*sasl;
527527
void*sasl_state;
528+
intscram_sha_256_iterations;
528529

529530
/* SSL structures */
530531
boolssl_in_use;

‎src/test/authentication/t/001_password.pl

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,21 @@ sub test_conn
8686
q{SET password_encryption='md5'; CREATE ROLE "md5,role" LOGIN PASSWORD 'pass';}
8787
);
8888

89+
# Create a role with a non-default iteration count
90+
$node->safe_psql(
91+
'postgres',
92+
"SET password_encryption='scram-sha-256';
93+
SET scram_iterations=1024;
94+
CREATE ROLE scram_role_iter LOGIN PASSWORD 'pass';
95+
RESET scram_iterations;"
96+
);
97+
98+
my$res =$node->safe_psql('postgres',
99+
"SELECT substr(rolpassword,1,19)
100+
FROM pg_authid
101+
WHERE rolname = 'scram_role_iter'");
102+
is($res,'SCRAM-SHA-256$1024:','scram_iterations in server side ROLE');
103+
89104
# Create a database to test regular expression.
90105
$node->safe_psql('postgres',"CREATE database regex_testdb;");
91106

@@ -98,7 +113,7 @@ sub test_conn
98113
log_unlike=> [qr/connection authenticated:/]);
99114

100115
# SYSTEM_USER is null when not authenticated.
101-
my$res =$node->safe_psql('postgres',"SELECT SYSTEM_USER IS NULL;");
116+
$res =$node->safe_psql('postgres',"SELECT SYSTEM_USER IS NULL;");
102117
is($res,'t',"users with trust authentication use SYSTEM_USER = NULL");
103118

104119
# Test SYSTEM_USER with parallel workers when not authenticated.
@@ -283,6 +298,14 @@ sub test_conn
283298
log_like=> [
284299
qr/connection authenticated: identity="scram_role" method=scram-sha-256/
285300
]);
301+
test_conn(
302+
$node,
303+
'user=scram_role_iter',
304+
'scram-sha-256',
305+
0,
306+
log_like=> [
307+
qr/connection authenticated: identity="scram_role_iter" method=scram-sha-256/
308+
]);
286309
test_conn($node,'user=md5_role','scram-sha-256', 2,
287310
log_unlike=> [qr/connection authenticated:/]);
288311

‎src/test/regress/expected/password.out

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ CREATE ROLE regress_passwd6 PASSWORD 'SCRAM-SHA-256$1234';
7272
CREATE ROLE regress_passwd7 PASSWORD 'md5012345678901234567890123456789zz';
7373
-- invalid length
7474
CREATE ROLE regress_passwd8 PASSWORD 'md501234567890123456789012345678901zz';
75+
-- Changing the SCRAM iteration count
76+
SET scram_iterations = 1024;
77+
CREATE ROLE regress_passwd9 PASSWORD 'alterediterationcount';
7578
SELECT rolname, regexp_replace(rolpassword, '(SCRAM-SHA-256)\$(\d+):([a-zA-Z0-9+/=]+)\$([a-zA-Z0-9+=/]+):([a-zA-Z0-9+/=]+)', '\1$\2:<salt>$<storedkey>:<serverkey>') as rolpassword_masked
7679
FROM pg_authid
7780
WHERE rolname LIKE 'regress_passwd%'
@@ -86,7 +89,8 @@ SELECT rolname, regexp_replace(rolpassword, '(SCRAM-SHA-256)\$(\d+):([a-zA-Z0-9+
8689
regress_passwd6 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
8790
regress_passwd7 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
8891
regress_passwd8 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
89-
(8 rows)
92+
regress_passwd9 | SCRAM-SHA-256$1024:<salt>$<storedkey>:<serverkey>
93+
(9 rows)
9094

9195
-- An empty password is not allowed, in any form
9296
CREATE ROLE regress_passwd_empty PASSWORD '';
@@ -129,6 +133,7 @@ DROP ROLE regress_passwd5;
129133
DROP ROLE regress_passwd6;
130134
DROP ROLE regress_passwd7;
131135
DROP ROLE regress_passwd8;
136+
DROP ROLE regress_passwd9;
132137
DROP ROLE regress_passwd_empty;
133138
DROP ROLE regress_passwd_sha_len0;
134139
DROP ROLE regress_passwd_sha_len1;

‎src/test/regress/sql/password.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ CREATE ROLE regress_passwd7 PASSWORD 'md5012345678901234567890123456789zz';
6363
-- invalid length
6464
CREATE ROLE regress_passwd8 PASSWORD'md501234567890123456789012345678901zz';
6565

66+
-- Changing the SCRAM iteration count
67+
SET scram_iterations=1024;
68+
CREATE ROLE regress_passwd9 PASSWORD'alterediterationcount';
69+
6670
SELECT rolname, regexp_replace(rolpassword,'(SCRAM-SHA-256)\$(\d+):([a-zA-Z0-9+/=]+)\$([a-zA-Z0-9+=/]+):([a-zA-Z0-9+/=]+)','\1$\2:<salt>$<storedkey>:<serverkey>')as rolpassword_masked
6771
FROM pg_authid
6872
WHERE rolnameLIKE'regress_passwd%'
@@ -97,6 +101,7 @@ DROP ROLE regress_passwd5;
97101
DROP ROLE regress_passwd6;
98102
DROP ROLE regress_passwd7;
99103
DROP ROLE regress_passwd8;
104+
DROP ROLE regress_passwd9;
100105
DROP ROLE regress_passwd_empty;
101106
DROP ROLE regress_passwd_sha_len0;
102107
DROP ROLE regress_passwd_sha_len1;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp