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

Commit080eabe

Browse files
committed
Fix libpq's behavior when /etc/passwd isn't readable.
Some users run their applications in chroot environments that lack an/etc/passwd file. This means that the current UID's user name and homedirectory are not obtainable. libpq used to be all right with that,so long as the database role name to use was specified explicitly.But commita4c8f14 broke such cases bycausing any failure of pg_fe_getauthname() to be treated as a hard error.In any case it did little to advance its nominal goal of causing errorsin pg_fe_getauthname() to be reported better. So revert that and insteadput some real error-reporting code in place. This requires changes to theAPIs of pg_fe_getauthname() and pqGetpwuid(), since the latter haddeparted from the POSIX-specified API of getpwuid_r() in a way that madeit impossible to distinguish actual lookup errors from "no such user".To allow such failures to be reported, while not failing if the callersupplies a role name, add a second call of pg_fe_getauthname() inconnectOptions2(). This is a tad ugly, and could perhaps be avoided withsome refactoring of PQsetdbLogin(), but I'll leave that idea for later.(Note that the complained-of misbehavior only occurs in PQsetdbLogin,not when using the PQconnect functions, because in the latter we willnever bother to call pg_fe_getauthname() if the user gives a role name.)In passing also clean up the Windows-side usage of GetUserName(): therecommended buffer size is 257 bytes, the passed buffer length shouldbe the buffer size not buffer size less 1, and any error is reportedby GetLastError() not errno.Per report from Christoph Berg. Back-patch to 9.4 where the chrootfailure case was introduced. The generally poor reporting of errorshere is of very long standing, of course, but given the lack of fieldcomplaints about it we won't risk changing these APIs further back(even though they're theoretically internal to libpq).
1 parentde6429a commit080eabe

File tree

7 files changed

+97
-43
lines changed

7 files changed

+97
-43
lines changed

‎src/common/username.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
#include"common/username.h"
2727

2828
/*
29-
* Returns the current user name in a static buffer, or NULL on error and
30-
* sets errstr
29+
* Returns the current user name in a static buffer
30+
*On error, returns NULL andsets*errstr to point to a palloc'd message
3131
*/
3232
constchar*
3333
get_user_name(char**errstr)
@@ -50,15 +50,17 @@ get_user_name(char **errstr)
5050

5151
returnpw->pw_name;
5252
#else
53-
/* UNLEN = 256, 'static' variable remains after function exit */
53+
/* Microsoft recommends buffer size of UNLEN+1, where UNLEN = 256 */
54+
/* "static" variable remains after function exit */
5455
staticcharusername[256+1];
55-
DWORDlen=sizeof(username)-1;
56+
DWORDlen=sizeof(username);
5657

5758
*errstr=NULL;
5859

5960
if (!GetUserName(username,&len))
6061
{
61-
*errstr=psprintf(_("user name lookup failure: %s"),strerror(errno));
62+
*errstr=psprintf(_("user name lookup failure: error code %lu"),
63+
GetLastError());
6264
returnNULL;
6365
}
6466

‎src/include/port.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ extern void srandom(unsigned int seed);
433433
/* thread.h */
434434
externchar*pqStrerror(interrnum,char*strerrbuf,size_tbuflen);
435435

436-
#if !defined(WIN32)|| defined(__CYGWIN__)
436+
#ifndefWIN32
437437
externintpqGetpwuid(uid_tuid,structpasswd*resultbuf,char*buffer,
438438
size_tbuflen,structpasswd**result);
439439
#endif

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

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -714,22 +714,26 @@ pg_fe_sendauth(AuthRequest areq, PGconn *conn)
714714
/*
715715
* pg_fe_getauthname
716716
*
717-
* Returns a pointer to dynamic space containing whatever name the user
718-
* has authenticated to the system. If there is an error, return NULL.
717+
* Returns a pointer to malloc'd space containing whatever name the user
718+
* has authenticated to the system. If there is an error, return NULL,
719+
* and put a suitable error message in *errorMessage if that's not NULL.
719720
*/
720721
char*
721-
pg_fe_getauthname(void)
722+
pg_fe_getauthname(PQExpBuffererrorMessage)
722723
{
724+
char*result=NULL;
723725
constchar*name=NULL;
724-
char*authn;
725726

726727
#ifdefWIN32
727-
charusername[128];
728-
DWORDnamesize=sizeof(username)-1;
728+
/* Microsoft recommends buffer size of UNLEN+1, where UNLEN = 256 */
729+
charusername[256+1];
730+
DWORDnamesize=sizeof(username);
729731
#else
732+
uid_tuser_id=geteuid();
730733
charpwdbuf[BUFSIZ];
731734
structpasswdpwdstr;
732735
structpasswd*pw=NULL;
736+
intpwerr;
733737
#endif
734738

735739
/*
@@ -741,24 +745,42 @@ pg_fe_getauthname(void)
741745
*/
742746
pglock_thread();
743747

744-
/*
745-
* We document PQconndefaults() to return NULL for a memory allocation
746-
* failure. We don't have an API to return a user name lookup failure, so
747-
* we just assume it always succeeds.
748-
*/
749748
#ifdefWIN32
750749
if (GetUserName(username,&namesize))
751750
name=username;
751+
elseif (errorMessage)
752+
printfPQExpBuffer(errorMessage,
753+
libpq_gettext("user name lookup failure: error code %lu\n"),
754+
GetLastError());
752755
#else
753-
if (pqGetpwuid(geteuid(),&pwdstr,pwdbuf,sizeof(pwdbuf),&pw)==0)
756+
pwerr=pqGetpwuid(user_id,&pwdstr,pwdbuf,sizeof(pwdbuf),&pw);
757+
if (pw!=NULL)
754758
name=pw->pw_name;
759+
elseif (errorMessage)
760+
{
761+
if (pwerr!=0)
762+
printfPQExpBuffer(errorMessage,
763+
libpq_gettext("could not look up local user ID %d: %s\n"),
764+
(int)user_id,
765+
pqStrerror(pwerr,pwdbuf,sizeof(pwdbuf)));
766+
else
767+
printfPQExpBuffer(errorMessage,
768+
libpq_gettext("local user with ID %d does not exist\n"),
769+
(int)user_id);
770+
}
755771
#endif
756772

757-
authn=name ?strdup(name) :NULL;
773+
if (name)
774+
{
775+
result=strdup(name);
776+
if (result==NULL&&errorMessage)
777+
printfPQExpBuffer(errorMessage,
778+
libpq_gettext("out of memory\n"));
779+
}
758780

759781
pgunlock_thread();
760782

761-
returnauthn;
783+
returnresult;
762784
}
763785

764786

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@
1919

2020

2121
externintpg_fe_sendauth(AuthRequestareq,PGconn*conn);
22-
externchar*pg_fe_getauthname(void);
22+
externchar*pg_fe_getauthname(PQExpBuffererrorMessage);
2323

2424
#endif/* FE_AUTH_H */

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

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -764,11 +764,27 @@ connectOptions1(PGconn *conn, const char *conninfo)
764764
staticbool
765765
connectOptions2(PGconn*conn)
766766
{
767+
/*
768+
* If user name was not given, fetch it. (Most likely, the fetch will
769+
* fail, since the only way we get here is if pg_fe_getauthname() failed
770+
* during conninfo_add_defaults(). But now we want an error message.)
771+
*/
772+
if (conn->pguser==NULL||conn->pguser[0]=='\0')
773+
{
774+
if (conn->pguser)
775+
free(conn->pguser);
776+
conn->pguser=pg_fe_getauthname(&conn->errorMessage);
777+
if (!conn->pguser)
778+
{
779+
conn->status=CONNECTION_BAD;
780+
return false;
781+
}
782+
}
783+
767784
/*
768785
* If database name was not given, default it to equal user name
769786
*/
770-
if ((conn->dbName==NULL||conn->dbName[0]=='\0')
771-
&&conn->pguser!=NULL)
787+
if (conn->dbName==NULL||conn->dbName[0]=='\0')
772788
{
773789
if (conn->dbName)
774790
free(conn->dbName);
@@ -1967,6 +1983,7 @@ PQconnectPoll(PGconn *conn)
19671983
charpwdbuf[BUFSIZ];
19681984
structpasswdpass_buf;
19691985
structpasswd*pass;
1986+
intpasserr;
19701987
uid_tuid;
19711988
gid_tgid;
19721989

@@ -1987,13 +2004,18 @@ PQconnectPoll(PGconn *conn)
19872004
gotoerror_return;
19882005
}
19892006

1990-
pqGetpwuid(uid,&pass_buf,pwdbuf,sizeof(pwdbuf),&pass);
1991-
2007+
passerr=pqGetpwuid(uid,&pass_buf,pwdbuf,sizeof(pwdbuf),&pass);
19922008
if (pass==NULL)
19932009
{
1994-
appendPQExpBuffer(&conn->errorMessage,
1995-
libpq_gettext("local user with ID %d does not exist\n"),
1996-
(int)uid);
2010+
if (passerr!=0)
2011+
appendPQExpBuffer(&conn->errorMessage,
2012+
libpq_gettext("could not look up local user ID %d: %s\n"),
2013+
(int)uid,
2014+
pqStrerror(passerr,sebuf,sizeof(sebuf)));
2015+
else
2016+
appendPQExpBuffer(&conn->errorMessage,
2017+
libpq_gettext("local user with ID %d does not exist\n"),
2018+
(int)uid);
19972019
gotoerror_return;
19982020
}
19992021

@@ -4605,18 +4627,15 @@ conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
46054627
}
46064628

46074629
/*
4608-
* Special handling for "user" option
4630+
* Special handling for "user" option. Note that if pg_fe_getauthname
4631+
* fails, we just leave the value as NULL; there's no need for this to
4632+
* be an error condition if the caller provides a user name. The only
4633+
* reason we do this now at all is so that callers of PQconndefaults
4634+
* will see a correct default (barring error, of course).
46094635
*/
46104636
if (strcmp(option->keyword,"user")==0)
46114637
{
4612-
option->val=pg_fe_getauthname();
4613-
if (!option->val)
4614-
{
4615-
if (errorMessage)
4616-
printfPQExpBuffer(errorMessage,
4617-
libpq_gettext("out of memory\n"));
4618-
return false;
4619-
}
4638+
option->val=pg_fe_getauthname(NULL);
46204639
continue;
46214640
}
46224641
}
@@ -5843,7 +5862,8 @@ pqGetHomeDirectory(char *buf, int bufsize)
58435862
structpasswdpwdstr;
58445863
structpasswd*pwd=NULL;
58455864

5846-
if (pqGetpwuid(geteuid(),&pwdstr,pwdbuf,sizeof(pwdbuf),&pwd)!=0)
5865+
(void)pqGetpwuid(geteuid(),&pwdstr,pwdbuf,sizeof(pwdbuf),&pwd);
5866+
if (pwd==NULL)
58475867
return false;
58485868
strlcpy(buf,pwd->pw_dir,bufsize);
58495869
return true;

‎src/port/path.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,8 @@ get_home_path(char *ret_path)
777777
structpasswdpwdstr;
778778
structpasswd*pwd=NULL;
779779

780-
if (pqGetpwuid(geteuid(),&pwdstr,pwdbuf,sizeof(pwdbuf),&pwd)!=0)
780+
(void)pqGetpwuid(geteuid(),&pwdstr,pwdbuf,sizeof(pwdbuf),&pwd);
781+
if (pwd==NULL)
781782
return false;
782783
strlcpy(ret_path,pwd->pw_dir,MAXPGPATH);
783784
return true;

‎src/port/thread.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ pqStrerror(int errnum, char *strerrbuf, size_t buflen)
8383
/*
8484
* Wrapper around getpwuid() or getpwuid_r() to mimic POSIX getpwuid_r()
8585
* behaviour, if it is not available or required.
86+
*
87+
* Per POSIX, the possible cases are:
88+
* success: returns zero, *result is non-NULL
89+
* uid not found: returns zero, *result is NULL
90+
* error during lookup: returns an errno code, *result is NULL
91+
* (caller should *not* assume that the errno variable is set)
8692
*/
8793
#ifndefWIN32
8894
int
@@ -93,22 +99,25 @@ pqGetpwuid(uid_t uid, struct passwd * resultbuf, char *buffer,
9399

94100
#ifdefGETPWUID_R_5ARG
95101
/* POSIX version */
96-
getpwuid_r(uid,resultbuf,buffer,buflen,result);
102+
returngetpwuid_r(uid,resultbuf,buffer,buflen,result);
97103
#else
98104

99105
/*
100106
* Early POSIX draft of getpwuid_r() returns 'struct passwd *'.
101107
* getpwuid_r(uid, resultbuf, buffer, buflen)
102108
*/
109+
errno=0;
103110
*result=getpwuid_r(uid,resultbuf,buffer,buflen);
111+
/* paranoia: ensure we return zero on success */
112+
return (*result==NULL) ?errno :0;
104113
#endif
105114
#else
106-
107115
/* no getpwuid_r() available, just use getpwuid() */
116+
errno=0;
108117
*result=getpwuid(uid);
118+
/* paranoia: ensure we return zero on success */
119+
return (*result==NULL) ?errno :0;
109120
#endif
110-
111-
return (*result==NULL) ?-1 :0;
112121
}
113122
#endif
114123

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp