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

Commit3a0cced

Browse files
committed
Improve error handling of cryptohash computations
The existing cryptohash facility was causing problems in some code pathsrelated to MD5 (frontend and backend) that relied on the fact that theonly type of error that could happen would be an OOM, as the MD5implementation used in PostgreSQL ~13 (the in-core implementation isused when compiling with or without OpenSSL in those older versions),could fail only under this circumstance.The new cryptohash facilities can fail for reasons other than OOMs, likeattempting MD5 when FIPS is enabled (upstream OpenSSL allows that up to1.0.2, Fedora and Photon patch OpenSSL 1.1.1 to allow that), so thiswould cause incorrect reports to show up.This commit extends the cryptohash APIs so as callers of those routinescan fetch more context when an error happens, by using a new routinecalled pg_cryptohash_error(). The error states are stored within eachimplementation's internal context data, so as it is possible to extendthe logic depending on what's suited for an implementation. The defaultimplementation requires few error states, but OpenSSL could reportvarious issues depending on its internal state so more is needed incryptohash_openssl.c, and the code is shaped so as we are always able tograb the necessary information.The core code is changed to adapt to the new error routine, paintingmore "const" across the call stack where the static errors are stored,particularly in authentication code paths on variables that providelog details. This way, any future changes would warn if attempting tofree these strings. The MD5 authentication code was also a bit blurryabout the handling of "logdetail" (LOG sent to the postmaster), soimprove the comments related that, while on it.The origin of the problem is87ae969, that introduced the centralizedcryptohash facility. Extra changes are done for pgcrypto in v14 for thenon-OpenSSL code path to cope with the improvements done by thiscommit.Reported-by: Michael MühlbeyerAuthor: Michael PaquierReviewed-by: Tom LaneDiscussion:https://postgr.es/m/89B7F072-5BBE-4C92-903E-D83E865D9367@trivadis.comBackpatch-through: 14
1 parent05cdda6 commit3a0cced

File tree

19 files changed

+290
-84
lines changed

19 files changed

+290
-84
lines changed

‎contrib/passwordcheck/passwordcheck.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ check_password(const char *username,
7474
*
7575
* We only check for username = password.
7676
*/
77-
char*logdetail;
77+
constchar*logdetail=NULL;
7878

7979
if (plain_crypt_verify(username,shadow_pass,username,&logdetail)==STATUS_OK)
8080
ereport(ERROR,

‎contrib/pgcrypto/internal-sha2.c‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ int_sha2_update(PX_MD *h, const uint8 *data, unsigned dlen)
101101
pg_cryptohash_ctx*ctx= (pg_cryptohash_ctx*)h->p.ptr;
102102

103103
if (pg_cryptohash_update(ctx,data,dlen)<0)
104-
elog(ERROR,"could not update %s context","SHA2");
104+
elog(ERROR,"could not update %s context: %s","SHA2",
105+
pg_cryptohash_error(ctx));
105106
}
106107

107108
staticvoid
@@ -110,7 +111,8 @@ int_sha2_reset(PX_MD *h)
110111
pg_cryptohash_ctx*ctx= (pg_cryptohash_ctx*)h->p.ptr;
111112

112113
if (pg_cryptohash_init(ctx)<0)
113-
elog(ERROR,"could not initialize %s context","SHA2");
114+
elog(ERROR,"could not initialize %s context: %s","SHA2",
115+
pg_cryptohash_error(ctx));
114116
}
115117

116118
staticvoid
@@ -119,7 +121,8 @@ int_sha2_finish(PX_MD *h, uint8 *dst)
119121
pg_cryptohash_ctx*ctx= (pg_cryptohash_ctx*)h->p.ptr;
120122

121123
if (pg_cryptohash_final(ctx,dst,h->result_size(h))<0)
122-
elog(ERROR,"could not finalize %s context","SHA2");
124+
elog(ERROR,"could not finalize %s context: %s","SHA2",
125+
pg_cryptohash_error(ctx));
123126
}
124127

125128
staticvoid

‎contrib/pgcrypto/internal.c‎

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ int_md5_update(PX_MD *h, const uint8 *data, unsigned dlen)
8989
pg_cryptohash_ctx*ctx= (pg_cryptohash_ctx*)h->p.ptr;
9090

9191
if (pg_cryptohash_update(ctx,data,dlen)<0)
92-
elog(ERROR,"could not update %s context","MD5");
92+
elog(ERROR,"could not update %s context: %s","MD5",
93+
pg_cryptohash_error(ctx));
9394
}
9495

9596
staticvoid
@@ -98,7 +99,8 @@ int_md5_reset(PX_MD *h)
9899
pg_cryptohash_ctx*ctx= (pg_cryptohash_ctx*)h->p.ptr;
99100

100101
if (pg_cryptohash_init(ctx)<0)
101-
elog(ERROR,"could not initialize %s context","MD5");
102+
elog(ERROR,"could not initialize %s context: %s","MD5",
103+
pg_cryptohash_error(ctx));
102104
}
103105

104106
staticvoid
@@ -107,7 +109,8 @@ int_md5_finish(PX_MD *h, uint8 *dst)
107109
pg_cryptohash_ctx*ctx= (pg_cryptohash_ctx*)h->p.ptr;
108110

109111
if (pg_cryptohash_final(ctx,dst,h->result_size(h))<0)
110-
elog(ERROR,"could not finalize %s context","MD5");
112+
elog(ERROR,"could not finalize %s context: %s","MD5",
113+
pg_cryptohash_error(ctx));
111114
}
112115

113116
staticvoid
@@ -139,7 +142,8 @@ int_sha1_update(PX_MD *h, const uint8 *data, unsigned dlen)
139142
pg_cryptohash_ctx*ctx= (pg_cryptohash_ctx*)h->p.ptr;
140143

141144
if (pg_cryptohash_update(ctx,data,dlen)<0)
142-
elog(ERROR,"could not update %s context","SHA1");
145+
elog(ERROR,"could not update %s context: %s","SHA1",
146+
pg_cryptohash_error(ctx));
143147
}
144148

145149
staticvoid
@@ -148,7 +152,8 @@ int_sha1_reset(PX_MD *h)
148152
pg_cryptohash_ctx*ctx= (pg_cryptohash_ctx*)h->p.ptr;
149153

150154
if (pg_cryptohash_init(ctx)<0)
151-
elog(ERROR,"could not initialize %s context","SHA1");
155+
elog(ERROR,"could not initialize %s context: %s","SHA1",
156+
pg_cryptohash_error(ctx));
152157
}
153158

154159
staticvoid
@@ -157,7 +162,8 @@ int_sha1_finish(PX_MD *h, uint8 *dst)
157162
pg_cryptohash_ctx*ctx= (pg_cryptohash_ctx*)h->p.ptr;
158163

159164
if (pg_cryptohash_final(ctx,dst,h->result_size(h))<0)
160-
elog(ERROR,"could not finalize %s context","SHA1");
165+
elog(ERROR,"could not finalize %s context: %s","SHA1",
166+
pg_cryptohash_error(ctx));
161167
}
162168

163169
staticvoid

‎contrib/uuid-ossp/uuid-ossp.c‎

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -319,14 +319,17 @@ uuid_generate_internal(int v, unsigned char *ns, const char *ptr, int len)
319319
pg_cryptohash_ctx*ctx=pg_cryptohash_create(PG_MD5);
320320

321321
if (pg_cryptohash_init(ctx)<0)
322-
elog(ERROR,"could not initialize %s context","MD5");
322+
elog(ERROR,"could not initialize %s context: %s","MD5",
323+
pg_cryptohash_error(ctx));
323324
if (pg_cryptohash_update(ctx,ns,sizeof(uu))<0||
324325
pg_cryptohash_update(ctx, (unsignedchar*)ptr,len)<0)
325-
elog(ERROR,"could not update %s context","MD5");
326+
elog(ERROR,"could not update %s context: %s","MD5",
327+
pg_cryptohash_error(ctx));
326328
/* we assume sizeof MD5 result is 16, same as UUID size */
327329
if (pg_cryptohash_final(ctx, (unsignedchar*)&uu,
328330
sizeof(uu))<0)
329-
elog(ERROR,"could not finalize %s context","MD5");
331+
elog(ERROR,"could not finalize %s context: %s","MD5",
332+
pg_cryptohash_error(ctx));
330333
pg_cryptohash_free(ctx);
331334
}
332335
else
@@ -335,12 +338,15 @@ uuid_generate_internal(int v, unsigned char *ns, const char *ptr, int len)
335338
unsignedcharsha1result[SHA1_DIGEST_LENGTH];
336339

337340
if (pg_cryptohash_init(ctx)<0)
338-
elog(ERROR,"could not initialize %s context","SHA1");
341+
elog(ERROR,"could not initialize %s context: %s","SHA1",
342+
pg_cryptohash_error(ctx));
339343
if (pg_cryptohash_update(ctx,ns,sizeof(uu))<0||
340344
pg_cryptohash_update(ctx, (unsignedchar*)ptr,len)<0)
341-
elog(ERROR,"could not update %s context","SHA1");
345+
elog(ERROR,"could not update %s context: %s","SHA1",
346+
pg_cryptohash_error(ctx));
342347
if (pg_cryptohash_final(ctx,sha1result,sizeof(sha1result))<0)
343-
elog(ERROR,"could not finalize %s context","SHA1");
348+
elog(ERROR,"could not finalize %s context: %s","SHA1",
349+
pg_cryptohash_error(ctx));
344350
pg_cryptohash_free(ctx);
345351

346352
memcpy(&uu,sha1result,sizeof(uu));

‎src/backend/commands/user.c‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
393393
if (password)
394394
{
395395
char*shadow_pass;
396-
char*logdetail;
396+
constchar*logdetail=NULL;
397397

398398
/*
399399
* Don't allow an empty password. Libpq treats an empty password the
@@ -835,7 +835,7 @@ AlterRole(AlterRoleStmt *stmt)
835835
if (password)
836836
{
837837
char*shadow_pass;
838-
char*logdetail;
838+
constchar*logdetail=NULL;
839839

840840
/* Like in CREATE USER, don't allow an empty password. */
841841
if (password[0]=='\0'||

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ pg_be_scram_init(Port *port,
327327
*/
328328
int
329329
pg_be_scram_exchange(void*opaq,constchar*input,intinputlen,
330-
char**output,int*outputlen,char**logdetail)
330+
char**output,int*outputlen,constchar**logdetail)
331331
{
332332
scram_state*state= (scram_state*)opaq;
333333
intresult;

‎src/backend/libpq/auth.c‎

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
*/
4848
staticvoidsendAuthRequest(Port*port,AuthRequestareq,constchar*extradata,
4949
intextralen);
50-
staticvoidauth_failed(Port*port,intstatus,char*logdetail);
50+
staticvoidauth_failed(Port*port,intstatus,constchar*logdetail);
5151
staticchar*recv_password_packet(Port*port);
5252
staticvoidset_authn_id(Port*port,constchar*id);
5353

@@ -56,11 +56,11 @@ static void set_authn_id(Port *port, const char *id);
5656
* Password-based authentication methods (password, md5, and scram-sha-256)
5757
*----------------------------------------------------------------
5858
*/
59-
staticintCheckPasswordAuth(Port*port,char**logdetail);
60-
staticintCheckPWChallengeAuth(Port*port,char**logdetail);
59+
staticintCheckPasswordAuth(Port*port,constchar**logdetail);
60+
staticintCheckPWChallengeAuth(Port*port,constchar**logdetail);
6161

62-
staticintCheckMD5Auth(Port*port,char*shadow_pass,char**logdetail);
63-
staticintCheckSCRAMAuth(Port*port,char*shadow_pass,char**logdetail);
62+
staticintCheckMD5Auth(Port*port,char*shadow_pass,constchar**logdetail);
63+
staticintCheckSCRAMAuth(Port*port,char*shadow_pass,constchar**logdetail);
6464

6565

6666
/*----------------------------------------------------------------
@@ -258,7 +258,7 @@ ClientAuthentication_hook_type ClientAuthentication_hook = NULL;
258258
* particular, if logdetail isn't NULL, we send that string to the log.
259259
*/
260260
staticvoid
261-
auth_failed(Port*port,intstatus,char*logdetail)
261+
auth_failed(Port*port,intstatus,constchar*logdetail)
262262
{
263263
constchar*errstr;
264264
char*cdetail;
@@ -394,7 +394,7 @@ void
394394
ClientAuthentication(Port*port)
395395
{
396396
intstatus=STATUS_ERROR;
397-
char*logdetail=NULL;
397+
constchar*logdetail=NULL;
398398

399399
/*
400400
* Get the authentication method to use for this frontend/database
@@ -780,7 +780,7 @@ recv_password_packet(Port *port)
780780
* Plaintext password authentication.
781781
*/
782782
staticint
783-
CheckPasswordAuth(Port*port,char**logdetail)
783+
CheckPasswordAuth(Port*port,constchar**logdetail)
784784
{
785785
char*passwd;
786786
intresult;
@@ -815,7 +815,7 @@ CheckPasswordAuth(Port *port, char **logdetail)
815815
* MD5 and SCRAM authentication.
816816
*/
817817
staticint
818-
CheckPWChallengeAuth(Port*port,char**logdetail)
818+
CheckPWChallengeAuth(Port*port,constchar**logdetail)
819819
{
820820
intauth_result;
821821
char*shadow_pass;
@@ -875,7 +875,7 @@ CheckPWChallengeAuth(Port *port, char **logdetail)
875875
}
876876

877877
staticint
878-
CheckMD5Auth(Port*port,char*shadow_pass,char**logdetail)
878+
CheckMD5Auth(Port*port,char*shadow_pass,constchar**logdetail)
879879
{
880880
charmd5Salt[4];/* Password salt */
881881
char*passwd;
@@ -912,7 +912,7 @@ CheckMD5Auth(Port *port, char *shadow_pass, char **logdetail)
912912
}
913913

914914
staticint
915-
CheckSCRAMAuth(Port*port,char*shadow_pass,char**logdetail)
915+
CheckSCRAMAuth(Port*port,char*shadow_pass,constchar**logdetail)
916916
{
917917
StringInfoDatasasl_mechs;
918918
intmtype;
@@ -3240,6 +3240,8 @@ PerformRadiusTransaction(const char *server, const char *secret, const char *por
32403240
md5trailer=packet->vector;
32413241
for (i=0;i<encryptedpasswordlen;i+=RADIUS_VECTOR_LENGTH)
32423242
{
3243+
constchar*errstr=NULL;
3244+
32433245
memcpy(cryptvector+strlen(secret),md5trailer,RADIUS_VECTOR_LENGTH);
32443246

32453247
/*
@@ -3248,10 +3250,12 @@ PerformRadiusTransaction(const char *server, const char *secret, const char *por
32483250
*/
32493251
md5trailer=encryptedpassword+i;
32503252

3251-
if (!pg_md5_binary(cryptvector,strlen(secret)+RADIUS_VECTOR_LENGTH,encryptedpassword+i))
3253+
if (!pg_md5_binary(cryptvector,strlen(secret)+RADIUS_VECTOR_LENGTH,
3254+
encryptedpassword+i,&errstr))
32523255
{
32533256
ereport(LOG,
3254-
(errmsg("could not perform MD5 encryption of password")));
3257+
(errmsg("could not perform MD5 encryption of password: %s",
3258+
errstr)));
32553259
pfree(cryptvector);
32563260
pg_freeaddrinfo_all(hint.ai_family,serveraddrs);
32573261
returnSTATUS_ERROR;
@@ -3336,6 +3340,7 @@ PerformRadiusTransaction(const char *server, const char *secret, const char *por
33363340
structtimevaltimeout;
33373341
structtimevalnow;
33383342
int64timeoutval;
3343+
constchar*errstr=NULL;
33393344

33403345
gettimeofday(&now,NULL);
33413346
timeoutval= (endtime.tv_sec*1000000+endtime.tv_usec)- (now.tv_sec*1000000+now.tv_usec);
@@ -3454,10 +3459,11 @@ PerformRadiusTransaction(const char *server, const char *secret, const char *por
34543459

34553460
if (!pg_md5_binary(cryptvector,
34563461
packetlength+strlen(secret),
3457-
encryptedpassword))
3462+
encryptedpassword,&errstr))
34583463
{
34593464
ereport(LOG,
3460-
(errmsg("could not perform MD5 encryption of received packet")));
3465+
(errmsg("could not perform MD5 encryption of received packet: %s",
3466+
errstr)));
34613467
pfree(cryptvector);
34623468
continue;
34633469
}

‎src/backend/libpq/crypt.c‎

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
* sent to the client, to avoid giving away user information!
3535
*/
3636
char*
37-
get_role_password(constchar*role,char**logdetail)
37+
get_role_password(constchar*role,constchar**logdetail)
3838
{
3939
TimestampTzvuntil=0;
4040
HeapTupleroleTup;
@@ -116,6 +116,7 @@ encrypt_password(PasswordType target_type, const char *role,
116116
{
117117
PasswordTypeguessed_type=get_password_type(password);
118118
char*encrypted_password;
119+
constchar*errstr=NULL;
119120

120121
if (guessed_type!=PASSWORD_TYPE_PLAINTEXT)
121122
{
@@ -132,8 +133,8 @@ encrypt_password(PasswordType target_type, const char *role,
132133
encrypted_password=palloc(MD5_PASSWD_LEN+1);
133134

134135
if (!pg_md5_encrypt(password,role,strlen(role),
135-
encrypted_password))
136-
elog(ERROR,"password encryption failed");
136+
encrypted_password,&errstr))
137+
elog(ERROR,"password encryption failed: %s",errstr);
137138
returnencrypted_password;
138139

139140
casePASSWORD_TYPE_SCRAM_SHA_256:
@@ -159,17 +160,18 @@ encrypt_password(PasswordType target_type, const char *role,
159160
* 'client_pass' is the response given by the remote user to the MD5 challenge.
160161
* 'md5_salt' is the salt used in the MD5 authentication challenge.
161162
*
162-
* In the error case,optionally store a palloc'dstring at *logdetail
163-
*that will be sent to thepostmaster log (but not the client).
163+
* In the error case,save astring at *logdetail that will be sent to the
164+
* postmaster log (but not the client).
164165
*/
165166
int
166167
md5_crypt_verify(constchar*role,constchar*shadow_pass,
167168
constchar*client_pass,
168169
constchar*md5_salt,intmd5_salt_len,
169-
char**logdetail)
170+
constchar**logdetail)
170171
{
171172
intretval;
172173
charcrypt_pwd[MD5_PASSWD_LEN+1];
174+
constchar*errstr=NULL;
173175

174176
Assert(md5_salt_len>0);
175177

@@ -183,16 +185,13 @@ md5_crypt_verify(const char *role, const char *shadow_pass,
183185

184186
/*
185187
* Compute the correct answer for the MD5 challenge.
186-
*
187-
* We do not bother setting logdetail for any pg_md5_encrypt failure
188-
* below: the only possible error is out-of-memory, which is unlikely, and
189-
* if it did happen adding a psprintf call would only make things worse.
190188
*/
191189
/* stored password already encrypted, only do salt */
192190
if (!pg_md5_encrypt(shadow_pass+strlen("md5"),
193191
md5_salt,md5_salt_len,
194-
crypt_pwd))
192+
crypt_pwd,&errstr))
195193
{
194+
*logdetail=errstr;
196195
returnSTATUS_ERROR;
197196
}
198197

@@ -215,15 +214,16 @@ md5_crypt_verify(const char *role, const char *shadow_pass,
215214
* pg_authid.rolpassword.
216215
* 'client_pass' is the password given by the remote user.
217216
*
218-
* In the error case,optionallystore apalloc'dstring at *logdetail
219-
*that will be sent to thepostmaster log (but not the client).
217+
* In the error case, store a string at *logdetail that will be sent to the
218+
* postmaster log (but not the client).
220219
*/
221220
int
222221
plain_crypt_verify(constchar*role,constchar*shadow_pass,
223222
constchar*client_pass,
224-
char**logdetail)
223+
constchar**logdetail)
225224
{
226225
charcrypt_client_pass[MD5_PASSWD_LEN+1];
226+
constchar*errstr=NULL;
227227

228228
/*
229229
* Client sent password in plaintext. If we have an MD5 hash stored, hash
@@ -251,14 +251,10 @@ plain_crypt_verify(const char *role, const char *shadow_pass,
251251
if (!pg_md5_encrypt(client_pass,
252252
role,
253253
strlen(role),
254-
crypt_client_pass))
254+
crypt_client_pass,
255+
&errstr))
255256
{
256-
/*
257-
* We do not bother setting logdetail for pg_md5_encrypt
258-
* failure: the only possible error is out-of-memory, which is
259-
* unlikely, and if it did happen adding a psprintf call would
260-
* only make things worse.
261-
*/
257+
*logdetail=errstr;
262258
returnSTATUS_ERROR;
263259
}
264260
if (strcmp(crypt_client_pass,shadow_pass)==0)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp