Where it does not exists use SO_PEERCRED or getpeerucred().
AC_SYS_LARGEFILE
dnl Checks for library functions.
-AC_CHECK_FUNCS(strlcpy strlcat)
+AC_CHECK_FUNCS(strlcpy strlcat getpeereid getpeerucred)
AC_SEARCH_LIBS(crypt, crypt, [], AC_MSG_ERROR([crypt not found]))
dnl Find libevent
*/
bool admin_pre_login(PgSocket *client)
{
- uid_t peer_uid = 0;
- bool res;
+ uid_t peer_uid = -1;
+ gid_t peer_gid = -1;
+ int res;
const char *username = client->auth_user->name;
client->admin_user = 0;
/* tag same uid as special */
if (client->addr.is_unix) {
- res = get_unix_peer_uid(sbuf_socket(&client->sbuf), &peer_uid);
- if (res && peer_uid == getuid()
+ res = getpeereid(sbuf_socket(&client->sbuf), &peer_uid, &peer_gid);
+ if (res >= 0 && peer_uid == getuid()
&& strcmp("pgbouncer", username) == 0)
{
client->own_user = 1;
log_debug("P: new unix client");
{
uid_t uid;
+ gid_t gid;
log_noise("getuid(): %d", (int)getuid());
- if (get_unix_peer_uid(fd, &uid))
+ if (getpeereid(fd, &uid, &gid) >= 0)
log_noise("unix peer uid: %d", (int)uid);
else
- log_noise("unix peer uid failed");
+ log_warning("unix peer uid failed: %s", strerror(errno));
}
accept_client(fd, NULL, true);
} else {
}
/*
- * get other side's uid.
+ * Get other side's uid for UNIX socket.
+ *
+ * Standardise on getpeereid() from BSDs.
*/
-bool get_unix_peer_uid(int fd, uid_t *uid_p)
+#ifndef HAVE_GETPEEREID
+int getpeereid(int fd, uid_t *uid_p, gid_t *gid_p)
{
- int res = -1;
#ifdef SO_PEERCRED
struct ucred cred;
socklen_t len = sizeof(cred);
- res = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len);
- if (res >= 0)
+ if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) >= 0) {
*uid_p = cred.uid;
- else
- log_error("getsockopt(SO_PEERCRED): %s", strerror(errno));
+ *gid_p = cred.gid;
+ return 0;
+ }
#else /* !SO_PEERCRED */
-#ifdef LOCAL_PEERCRED
- struct xucred cred;
- socklen_t len = sizeof(cred);
- res = getsockopt(fd, AF_UNIX, LOCAL_PEERCRED, &cred, &len);
- if (res >= 0)
- *uid_p = cred.cr_uid;
- else
- log_error("getsockopt(LOCAL_PEERCRED): %s", strerror(errno));
-#endif /* !LOCAL_PEERCRED */
+#ifdef HAVE_GETPEERUCRED
+ ucred_t *cred = NULL;
+ if (getpeerucred(fd, &cred) >= 0) {
+ *uid_p = ucred_geteuid(cred);
+ *gid_p = ucred_getegid(cred);
+ ucred_free(cred);
+ if (*uid_p >= 0 && *gid_p >= 0)
+ return 0;
+ }
+#endif /* HAVE_GETPEERUCRED */
#endif /* !SO_PEERCRED */
- return (res >= 0);
+ return -1;
}
+#endif /* !HAVE_GETPEEREID */
void socket_set_nonblocking(int fd, int val)
{
/*
* socket option handling
*/
-bool get_unix_peer_uid(int fd, uid_t *uid_p);
+#ifndef HAVE_GETPEEREID
+int getpeereid(int fd, uid_t *uid_p, gid_t *gid_p);
+#endif
+
void socket_set_nonblocking(int fd, int val);
void tune_socket(int sock, bool is_unix);