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

Commitdbd6911

Browse files
committed
Replace isMD5() with a more future-proof way to check if pw is encrypted.
The rule is that if pg_authid.rolpassword begins with "md5" and has theright length, it's an MD5 hash, otherwise it's a plaintext password. Theidiom has been to use isMD5() to check for that, but that gets awkward,when we add new kinds of verifiers, like the verifiers for SCRAMauthentication in the pending SCRAM patch set. Replace isMD5() with a newget_password_type() function, so that when new verifier types are added, wedon't need to remember to modify every place that currently calls isMD5(),to also recognize the new kinds of verifiers.Also, use the new plain_crypt_verify function in passwordcheck, so that itdoesn't need to know about MD5, or in the future, about other kinds ofhashes or password verifiers.Reviewed by Michael Paquier and Peter Eisentraut.Discussion:https://www.postgresql.org/message-id/2d07165c-1793-e243-a2a9-e45b624c7580@iki.fi
1 parent7ac4a38 commitdbd6911

File tree

6 files changed

+220
-159
lines changed

6 files changed

+220
-159
lines changed

‎contrib/passwordcheck/passwordcheck.c

Lines changed: 63 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#endif
2222

2323
#include"commands/user.h"
24-
#include"common/md5.h"
24+
#include"libpq/crypt.h"
2525
#include"fmgr.h"
2626

2727
PG_MODULE_MAGIC;
@@ -50,87 +50,77 @@ extern void _PG_init(void);
5050
*/
5151
staticvoid
5252
check_password(constchar*username,
53-
constchar*password,
54-
intpassword_type,
53+
constchar*shadow_pass,
54+
PasswordTypepassword_type,
5555
Datumvaliduntil_time,
5656
boolvaliduntil_null)
5757
{
58-
intnamelen=strlen(username);
59-
intpwdlen=strlen(password);
60-
charencrypted[MD5_PASSWD_LEN+1];
61-
inti;
62-
boolpwd_has_letter,
63-
pwd_has_nonletter;
64-
65-
switch (password_type)
58+
if (password_type!=PASSWORD_TYPE_PLAINTEXT)
6659
{
67-
casePASSWORD_TYPE_MD5:
68-
69-
/*
70-
* Unfortunately we cannot perform exhaustive checks on encrypted
71-
* passwords - we are restricted to guessing. (Alternatively, we
72-
* could insist on the password being presented non-encrypted, but
73-
* that has its own security disadvantages.)
74-
*
75-
* We only check for username = password.
76-
*/
77-
if (!pg_md5_encrypt(username,username,namelen,encrypted))
78-
elog(ERROR,"password encryption failed");
79-
if (strcmp(password,encrypted)==0)
80-
ereport(ERROR,
81-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
82-
errmsg("password must not contain user name")));
83-
break;
84-
85-
casePASSWORD_TYPE_PLAINTEXT:
86-
60+
/*
61+
* Unfortunately we cannot perform exhaustive checks on encrypted
62+
* passwords - we are restricted to guessing. (Alternatively, we could
63+
* insist on the password being presented non-encrypted, but that has
64+
* its own security disadvantages.)
65+
*
66+
* We only check for username = password.
67+
*/
68+
char*logdetail;
69+
70+
if (plain_crypt_verify(username,shadow_pass,username,&logdetail)==STATUS_OK)
71+
ereport(ERROR,
72+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
73+
errmsg("password must not contain user name")));
74+
}
75+
else
76+
{
77+
/*
78+
* For unencrypted passwords we can perform better checks
79+
*/
80+
constchar*password=shadow_pass;
81+
intpwdlen=strlen(password);
82+
inti;
83+
boolpwd_has_letter,
84+
pwd_has_nonletter;
85+
86+
/* enforce minimum length */
87+
if (pwdlen<MIN_PWD_LENGTH)
88+
ereport(ERROR,
89+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
90+
errmsg("password is too short")));
91+
92+
/* check if the password contains the username */
93+
if (strstr(password,username))
94+
ereport(ERROR,
95+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
96+
errmsg("password must not contain user name")));
97+
98+
/* check if the password contains both letters and non-letters */
99+
pwd_has_letter= false;
100+
pwd_has_nonletter= false;
101+
for (i=0;i<pwdlen;i++)
102+
{
87103
/*
88-
* For unencrypted passwords we can perform better checks
104+
* isalpha() does not work for multibyte encodings but let's
105+
* consider non-ASCII characters non-letters
89106
*/
90-
91-
/* enforce minimum length */
92-
if (pwdlen<MIN_PWD_LENGTH)
93-
ereport(ERROR,
94-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
95-
errmsg("password is too short")));
96-
97-
/* check if the password contains the username */
98-
if (strstr(password,username))
99-
ereport(ERROR,
100-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
101-
errmsg("password must not contain user name")));
102-
103-
/* check if the password contains both letters and non-letters */
104-
pwd_has_letter= false;
105-
pwd_has_nonletter= false;
106-
for (i=0;i<pwdlen;i++)
107-
{
108-
/*
109-
* isalpha() does not work for multibyte encodings but let's
110-
* consider non-ASCII characters non-letters
111-
*/
112-
if (isalpha((unsignedchar)password[i]))
113-
pwd_has_letter= true;
114-
else
115-
pwd_has_nonletter= true;
116-
}
117-
if (!pwd_has_letter|| !pwd_has_nonletter)
118-
ereport(ERROR,
119-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
120-
errmsg("password must contain both letters and nonletters")));
107+
if (isalpha((unsignedchar)password[i]))
108+
pwd_has_letter= true;
109+
else
110+
pwd_has_nonletter= true;
111+
}
112+
if (!pwd_has_letter|| !pwd_has_nonletter)
113+
ereport(ERROR,
114+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
115+
errmsg("password must contain both letters and nonletters")));
121116

122117
#ifdefUSE_CRACKLIB
123-
/* call cracklib to check password */
124-
if (FascistCheck(password,CRACKLIB_DICTPATH))
125-
ereport(ERROR,
126-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
127-
errmsg("password is easily cracked")));
118+
/* call cracklib to check password */
119+
if (FascistCheck(password,CRACKLIB_DICTPATH))
120+
ereport(ERROR,
121+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
122+
errmsg("password is easily cracked")));
128123
#endif
129-
break;
130-
131-
default:
132-
elog(ERROR,"unrecognized password type: %d",password_type);
133-
break;
134124
}
135125

136126
/* all checks passed, password is ok */

‎src/backend/commands/user.c

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#include"commands/dbcommands.h"
3030
#include"commands/seclabel.h"
3131
#include"commands/user.h"
32-
#include"common/md5.h"
32+
#include"libpq/crypt.h"
3333
#include"miscadmin.h"
3434
#include"storage/lmgr.h"
3535
#include"utils/acl.h"
@@ -81,7 +81,6 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
8181
ListCell*option;
8282
char*password=NULL;/* user password */
8383
intpassword_type=Password_encryption;
84-
charencrypted_password[MD5_PASSWD_LEN+1];
8584
boolissuper= false;/* Make the user a superuser? */
8685
boolinherit= true;/* Auto inherit privileges? */
8786
boolcreaterole= false;/* Can this user create roles? */
@@ -370,7 +369,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
370369
if (check_password_hook&&password)
371370
(*check_password_hook) (stmt->role,
372371
password,
373-
isMD5(password) ?PASSWORD_TYPE_MD5 :PASSWORD_TYPE_PLAINTEXT,
372+
get_password_type(password),
374373
validUntil_datum,
375374
validUntil_null);
376375

@@ -393,17 +392,12 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
393392

394393
if (password)
395394
{
396-
if (password_type==PASSWORD_TYPE_PLAINTEXT||isMD5(password))
397-
new_record[Anum_pg_authid_rolpassword-1]=
398-
CStringGetTextDatum(password);
399-
else
400-
{
401-
if (!pg_md5_encrypt(password,stmt->role,strlen(stmt->role),
402-
encrypted_password))
403-
elog(ERROR,"password encryption failed");
404-
new_record[Anum_pg_authid_rolpassword-1]=
405-
CStringGetTextDatum(encrypted_password);
406-
}
395+
/* Encrypt the password to the requested format. */
396+
char*shadow_pass;
397+
398+
shadow_pass=encrypt_password(password_type,stmt->role,password);
399+
new_record[Anum_pg_authid_rolpassword-1]=
400+
CStringGetTextDatum(shadow_pass);
407401
}
408402
else
409403
new_record_nulls[Anum_pg_authid_rolpassword-1]= true;
@@ -505,7 +499,6 @@ AlterRole(AlterRoleStmt *stmt)
505499
char*rolename=NULL;
506500
char*password=NULL;/* user password */
507501
intpassword_type=Password_encryption;
508-
charencrypted_password[MD5_PASSWD_LEN+1];
509502
intissuper=-1;/* Make the user a superuser? */
510503
intinherit=-1;/* Auto inherit privileges? */
511504
intcreaterole=-1;/* Can this user create roles? */
@@ -744,7 +737,7 @@ AlterRole(AlterRoleStmt *stmt)
744737
if (check_password_hook&&password)
745738
(*check_password_hook) (rolename,
746739
password,
747-
isMD5(password) ?PASSWORD_TYPE_MD5 :PASSWORD_TYPE_PLAINTEXT,
740+
get_password_type(password),
748741
validUntil_datum,
749742
validUntil_null);
750743

@@ -803,17 +796,12 @@ AlterRole(AlterRoleStmt *stmt)
803796
/* password */
804797
if (password)
805798
{
806-
if (password_type==PASSWORD_TYPE_PLAINTEXT||isMD5(password))
807-
new_record[Anum_pg_authid_rolpassword-1]=
808-
CStringGetTextDatum(password);
809-
else
810-
{
811-
if (!pg_md5_encrypt(password,rolename,strlen(rolename),
812-
encrypted_password))
813-
elog(ERROR,"password encryption failed");
814-
new_record[Anum_pg_authid_rolpassword-1]=
815-
CStringGetTextDatum(encrypted_password);
816-
}
799+
/* Encrypt the password to the requested format. */
800+
char*shadow_pass;
801+
802+
shadow_pass=encrypt_password(password_type,rolename,password);
803+
new_record[Anum_pg_authid_rolpassword-1]=
804+
CStringGetTextDatum(shadow_pass);
817805
new_record_repl[Anum_pg_authid_rolpassword-1]= true;
818806
}
819807

@@ -1228,7 +1216,7 @@ RenameRole(const char *oldname, const char *newname)
12281216

12291217
datum=heap_getattr(oldtuple,Anum_pg_authid_rolpassword,dsc,&isnull);
12301218

1231-
if (!isnull&&isMD5(TextDatumGetCString(datum)))
1219+
if (!isnull&&get_password_type(TextDatumGetCString(datum))==PASSWORD_TYPE_MD5)
12321220
{
12331221
/* MD5 uses the username as salt, so just clear it on a rename */
12341222
repl_repl[Anum_pg_authid_rolpassword-1]= true;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp