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

Commitb55b4da

Browse files
committed
Teach libpq to handle arbitrary-length lines in .pgpass files.
Historically there's been a hard-wired assumption here that no line ofa .pgpass file could be as long as NAMEDATALEN*5 bytes. That's a bitshaky to start off with, because (a) there's no reason to suppose thathost names fit in NAMEDATALEN, and (b) this figure fails to allow forbackslash escape characters. However, it fails completely if someonewants to use a very long password, and we're now hearing reports ofpeople wanting to use "security tokens" that can run up to severalhundred bytes. Another angle is that the file is specified to allowcomment lines, but there's no reason to assume that long comment linesaren't possible.Rather than guessing at what might be a more suitable limit, let'sreplace the fixed-size buffer with an expansible PQExpBuffer. Thatadds one malloc/free cycle to the typical use-case, but that's surelypretty cheap relative to the I/O this code has to do.Also, add TAP test cases to exercise this code, because there was notest coverage before.This reverts most of commit2eb3bc5, as there's no longer a need fora warning message about overlength .pgpass lines. (I kept the explicitcheck for comment lines, though.)In HEAD and v13, this also fixes an oversight in74a308c: there's notmuch point in explicit_bzero'ing the line buffer if we only do so in twoof the three exit paths.Back-patch to all supported branches, except that the test case onlygoes back to v10 where src/test/authentication/ was added.Discussion:https://postgr.es/m/4187382.1598909041@sss.pgh.pa.us
1 parent4ab7769 commitb55b4da

File tree

2 files changed

+79
-69
lines changed

2 files changed

+79
-69
lines changed

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

Lines changed: 52 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -6937,10 +6937,7 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
69376937
{
69386938
FILE*fp;
69396939
structstatstat_buf;
6940-
intline_number=0;
6941-
6942-
#defineLINELEN NAMEDATALEN*5
6943-
charbuf[LINELEN];
6940+
PQExpBufferDatabuf;
69446941

69456942
if (dbname==NULL||dbname[0]=='\0')
69466943
returnNULL;
@@ -6996,89 +6993,77 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
69966993
if (fp==NULL)
69976994
returnNULL;
69986995

6996+
/* Use an expansible buffer to accommodate any reasonable line length */
6997+
initPQExpBuffer(&buf);
6998+
69996999
while (!feof(fp)&& !ferror(fp))
70007000
{
7001-
char*t=buf,
7002-
*ret,
7003-
*p1,
7004-
*p2;
7005-
intlen;
7006-
intbuflen;
7001+
/* Make sure there's a reasonable amount of room in the buffer */
7002+
if (!enlargePQExpBuffer(&buf,128))
7003+
break;
70077004

7008-
if (fgets(buf,sizeof(buf),fp)==NULL)
7005+
/* Read some data, appending it to what we already have */
7006+
if (fgets(buf.data+buf.len,buf.maxlen-buf.len,fp)==NULL)
70097007
break;
7008+
buf.len+=strlen(buf.data+buf.len);
70107009

7011-
line_number++;
7012-
buflen=strlen(buf);
7013-
if (buflen >=sizeof(buf)-1&&buf[buflen-1]!='\n')
7010+
/* If we don't yet have a whole line, loop around to read more */
7011+
if (!(buf.len>0&&buf.data[buf.len-1]=='\n')&& !feof(fp))
7012+
continue;
7013+
7014+
/* ignore comments */
7015+
if (buf.data[0]!='#')
70147016
{
7015-
charrest[LINELEN];
7016-
intrestlen;
7017+
char*t=buf.data;
7018+
intlen;
70177019

7018-
/*
7019-
* Warn if this password setting line is too long, because it's
7020-
* unexpectedly truncated.
7021-
*/
7022-
if (buf[0]!='#')
7023-
fprintf(stderr,
7024-
libpq_gettext("WARNING: line %d too long in password file \"%s\"\n"),
7025-
line_number,pgpassfile);
7020+
/* strip trailing newline and carriage return */
7021+
len=pg_strip_crlf(t);
70267022

7027-
/* eat rest of the line */
7028-
while (!feof(fp)&& !ferror(fp))
7023+
if (len>0&&
7024+
(t=pwdfMatchesString(t,hostname))!=NULL&&
7025+
(t=pwdfMatchesString(t,port))!=NULL&&
7026+
(t=pwdfMatchesString(t,dbname))!=NULL&&
7027+
(t=pwdfMatchesString(t,username))!=NULL)
70297028
{
7030-
if (fgets(rest,sizeof(rest),fp)==NULL)
7031-
break;
7032-
restlen=strlen(rest);
7033-
if (restlen<sizeof(rest)-1||rest[restlen-1]=='\n')
7034-
break;
7035-
}
7036-
}
7037-
7038-
/* ignore comments */
7039-
if (buf[0]=='#')
7040-
continue;
7041-
7042-
/* strip trailing newline and carriage return */
7043-
len=pg_strip_crlf(buf);
7029+
/* Found a match. */
7030+
char*ret,
7031+
*p1,
7032+
*p2;
70447033

7045-
if (len==0)
7046-
continue;
7034+
ret=strdup(t);
70477035

7048-
if ((t=pwdfMatchesString(t,hostname))==NULL||
7049-
(t=pwdfMatchesString(t,port))==NULL||
7050-
(t=pwdfMatchesString(t,dbname))==NULL||
7051-
(t=pwdfMatchesString(t,username))==NULL)
7052-
continue;
7036+
fclose(fp);
7037+
explicit_bzero(buf.data,buf.maxlen);
7038+
termPQExpBuffer(&buf);
70537039

7054-
/* Found a match. */
7055-
ret=strdup(t);
7056-
fclose(fp);
7040+
if (!ret)
7041+
{
7042+
/* Out of memory. XXX: an error message would be nice. */
7043+
returnNULL;
7044+
}
70577045

7058-
if (!ret)
7059-
{
7060-
/* Out of memory. XXX: an error message would be nice. */
7061-
explicit_bzero(buf,sizeof(buf));
7062-
returnNULL;
7063-
}
7046+
/* De-escape password. */
7047+
for (p1=p2=ret;*p1!=':'&&*p1!='\0';++p1,++p2)
7048+
{
7049+
if (*p1=='\\'&&p1[1]!='\0')
7050+
++p1;
7051+
*p2=*p1;
7052+
}
7053+
*p2='\0';
70647054

7065-
/* De-escape password. */
7066-
for (p1=p2=ret;*p1!=':'&&*p1!='\0';++p1,++p2)
7067-
{
7068-
if (*p1=='\\'&&p1[1]!='\0')
7069-
++p1;
7070-
*p2=*p1;
7055+
returnret;
7056+
}
70717057
}
7072-
*p2='\0';
70737058

7074-
returnret;
7059+
/* No match, reset buffer to prepare for next line. */
7060+
buf.len=0;
70757061
}
70767062

70777063
fclose(fp);
7078-
explicit_bzero(buf,sizeof(buf));
7064+
explicit_bzero(buf.data,buf.maxlen);
7065+
termPQExpBuffer(&buf);
70797066
returnNULL;
7080-
7081-
#undef LINELEN
70827067
}
70837068

70847069

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

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
}
1818
else
1919
{
20-
plantests=>10;
20+
plantests=>13;
2121
}
2222

2323

@@ -45,7 +45,9 @@ sub test_role
4545

4646
$status_string ='success'if ($expected_reseq 0);
4747

48-
my$res =$node->psql('postgres',undef,extra_params=> ['-U',$role ]);
48+
local$Test::Builder::Level =$Test::Builder::Level + 1;
49+
50+
my$res =$node->psql('postgres',undef,extra_params=> ['-U',$role,'-w' ]);
4951
is($res,$expected_res,
5052
"authentication$status_string for method$method, role$role");
5153
return;
@@ -96,3 +98,26 @@ sub test_role
9698
reset_pg_hba($node,'scram-sha-256');
9799
$ENV{"PGCHANNELBINDING"} ='require';
98100
test_role($node,'scram_role','scram-sha-256', 2);
101+
102+
# Test .pgpass processing; but use a temp file, don't overwrite the real one!
103+
my$pgpassfile ="${TestLib::tmp_check}/pgpass";
104+
105+
delete$ENV{"PGPASSWORD"};
106+
delete$ENV{"PGCHANNELBINDING"};
107+
$ENV{"PGPASSFILE"} =$pgpassfile;
108+
109+
append_to_file($pgpassfile,qq!
110+
# This very long comment is just here to exercise handling of long lines in the file. This very long comment is just here to exercise handling of long lines in the file. This very long comment is just here to exercise handling of long lines in the file. This very long comment is just here to exercise handling of long lines in the file. This very long comment is just here to exercise handling of long lines in the file.
111+
*:*:postgres:scram_role:pass:this is not part of the password.
112+
!);
113+
chmod 0600,$pgpassfileordie;
114+
115+
reset_pg_hba($node,'password');
116+
test_role($node,'scram_role','password from pgpass', 0);
117+
test_role($node,'md5_role','password from pgpass', 2);
118+
119+
append_to_file($pgpassfile,qq!
120+
*:*:*:md5_role:p\\ass
121+
!);
122+
123+
test_role($node,'md5_role','password from pgpass', 0);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp