serverauth-requirepeer.patch
text/x-patch
Filename: serverauth-requirepeer.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| doc/src/sgml/libpq.sgml | 32 | 0 |
| src/interfaces/libpq/fe-connect.c | 45 | 0 |
| src/interfaces/libpq/libpq-int.h | 1 | 0 |
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index be788e9..400a6ae 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -449,6 +449,28 @@
</listitem>
</varlistentry>
+ <varlistentry id="libpq-connect-requirepeer" xreflabel="requirepeer">
+ <term><literal>requirepeer</literal></term>
+ <listitem>
+ <para>
+ For Unix-domain socket connections, if this parameter is
+ set, the client checks at the beginning of the connection
+ that the server process runs under the specified user name,
+ otherwise the connection is aborted with an error. This
+ parameter can be used to achieve the kind of server
+ authentication that SSL certificates achieve on TCP/IP
+ connections. (Note that if the Unix-domain socket is
+ in <filename>/tmp</filename> or another publically writable
+ location, any user could start a server there. Use this
+ parameter to ensure that you are connected to a server run
+ by a trusted user,
+ e.g., <literal>requirepeer=postgres</literal>.) This
+ option is only supported on some platforms, currently
+ Linux, FreeBSD, NetBSD, OpenBSD, BSD/OS, and Solaris.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry id="libpq-connect-krbsrvname" xreflabel="krbsrvname">
<term><literal>krbsrvname</literal></term>
<listitem>
@@ -6082,6 +6104,16 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
<listitem>
<para>
<indexterm>
+ <primary><envar>PGREQUIREPEER</envar></primary>
+ </indexterm>
+ <envar>PGREQUIREPEER</envar> behaves the same as the <xref
+ linkend="libpq-connect-requirepeer"> connection parameter.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <indexterm>
<primary><envar>PGKRBSRVNAME</envar></primary>
</indexterm>
<envar>PGKRBSRVNAME</envar> behaves the same as the <xref
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index ab6cc08..9b8de26 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -214,6 +214,9 @@ static const PQconninfoOption PQconninfoOptions[] = {
{"sslcrl", "PGSSLCRL", NULL, NULL,
"SSL-Revocation-List", "", 64},
+ {"requirepeer", "PGREQUIREPEER", NULL, NULL,
+ "Require-Peer", "", 10},
+
#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
/* Kerberos and GSSAPI authentication support specifying the service name */
{"krbsrvname", "PGKRBSRVNAME", PG_KRB_SRVNAM, NULL,
@@ -572,6 +575,8 @@ fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
conn->sslmode = strdup("require");
}
#endif
+ tmp = conninfo_getval(connOptions, "requirepeer");
+ conn->requirepeer = tmp ? strdup(tmp) : NULL;
#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
tmp = conninfo_getval(connOptions, "krbsrvname");
conn->krbsrvname = tmp ? strdup(tmp) : NULL;
@@ -1501,6 +1506,44 @@ keep_going: /* We will come back to here until there is
char *startpacket;
int packetlen;
+ // TODO: currently Linux-only code, needs to be made
+ // portable; see backend/libpq/auth.c
+ if (conn->requirepeer)
+ {
+ struct ucred peercred;
+ ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
+ struct passwd *pass;
+
+ errno = 0;
+ if (getsockopt(conn->sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
+ so_len != sizeof(peercred))
+ {
+ /* We didn't get a valid credentials struct. */
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not get peer credentials: %s\n"),
+ SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
+ goto error_return;
+ }
+
+ pass = getpwuid(peercred.uid);
+
+ if (pass == NULL)
+ {
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("local user with ID %d does not exist\n"),
+ (int) peercred.uid);
+ goto error_return;
+ }
+
+ if (strcmp(pass->pw_name, conn->requirepeer) != 0)
+ {
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("requirepeer failed (actual: %s != required: %s)\n"),
+ pass->pw_name, conn->requirepeer);
+ goto error_return;
+ }
+ }
+
#ifdef USE_SSL
/*
@@ -2300,6 +2343,8 @@ freePGconn(PGconn *conn)
free(conn->sslrootcert);
if (conn->sslcrl)
free(conn->sslcrl);
+ if (conn->requirepeer)
+ free(conn->requirepeer);
#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
if (conn->krbsrvname)
free(conn->krbsrvname);
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index e88b3ec..afb15f0 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -305,6 +305,7 @@ struct pg_conn
char *sslcert; /* client certificate filename */
char *sslrootcert; /* root certificate filename */
char *sslcrl; /* certificate revocation list filename */
+ char *requirepeer; /* required peer credentials for local sockets */
#if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
char *krbsrvname; /* Kerberos service name */