Re: [HACKERS] server authentication over Unix-domain sockets

2010-07-08 Thread KaiGai Kohei
(2010/07/03 1:39), Andrew Dunstan wrote:
 
 
 Peter Eisentraut wrote:
 Is there any possibilities that both WIN32 and HAVE_UNIX_SOCKETS are
 set concurrently? If possible, the libpq may try to call undefined
 function, then build will be failed.
 Win32 never has HAVE_UNIX_SOCKET.

 Cygwin might though, I recall some old discussion about that - can't
 remember the outcome though, and I can't find it right now.

 Cygwin doesn't define WIN32 anyway.

 
 Indeed, and we've been very careful to keep it that way.
 

Sorry for the late responding.

I marked this patch 'ready for committer'.

Thanks,
-- 
KaiGai Kohei kai...@ak.jp.nec.com

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] server authentication over Unix-domain sockets

2010-07-02 Thread KaiGai Kohei
(2010/07/01 11:30), Peter Eisentraut wrote:
 On tis, 2010-06-22 at 09:37 +0900, KaiGai Kohei wrote:
 As you described at the source code comments as follows,
 it is not portable except for Linux due to the getsockopt() API.

 +   // TODO: currently Linux-only code, needs to be made
 +   // portable; see backend/libpq/auth.c

 I expect it shall be fixed (using the code come from ident_unix()?)
 before committing.
 
 Updated patch attached.
 
 Note that the code that gets the user ID from the other end of a socket
 appears to have two different modes of operation.  On some platforms
 (Linux, OpenBSD, Solaris), you call a function and get the answer.  On
 some other platforms (other BSDs?), you need to send a packet and read
 the answer.  I don't have any possibility to test the latter approach,
 and it seemed a bit complicated to code blindly.  So I have omitted
 support for that, but if someone else wants to do the porting, that is
 of course possible.
 
I checked the revised patch.
The part to obtain user id of the peer is identical with ident_unix()
on the backend, so I believe it will work well, although I don't have
test environment except for Linux.

 I'd like to point out one other point.
 It uses getpwuid() to translate a user identifier into a user name,
 but it returns a pointer of the static variable within glibc.
 So, it is not thread-safe. I recommend to use getpwnam_r() instead.
 
 Good catch.  pqGetpwuid() was actually the right function to use.
 
I have a question.

The pqGetpwuid() is enclosed by #ifndef WIN32 ... #endif, although
this patch encloses the section to obtain user id of the peer by
#ifdef HAVE_UNIX_SOCKETS ... #endif.

Is there any possibilities that both WIN32 and HAVE_UNIX_SOCKETS are
set concurrently? If possible, the libpq may try to call undefined
function, then build will be failed.

I'd like someone to try to build with this patch on win32 platform,
and report it.

Thanks,
-- 
KaiGai Kohei kai...@ak.jp.nec.com

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] server authentication over Unix-domain sockets

2010-07-02 Thread Magnus Hagander
On Fri, Jul 2, 2010 at 8:35 AM, KaiGai Kohei kai...@ak.jp.nec.com wrote:
 (2010/07/01 11:30), Peter Eisentraut wrote:
 I have a question.

 The pqGetpwuid() is enclosed by #ifndef WIN32 ... #endif, although
 this patch encloses the section to obtain user id of the peer by
 #ifdef HAVE_UNIX_SOCKETS ... #endif.

 Is there any possibilities that both WIN32 and HAVE_UNIX_SOCKETS are
 set concurrently? If possible, the libpq may try to call undefined
 function, then build will be failed.

Win32 never has HAVE_UNIX_SOCKET.

Cygwin might though, I recall some old discussion about that - can't
remember the outcome though, and I can't find it right now.

 I'd like someone to try to build with this patch on win32 platform,
 and report it.

I think cygwin may be the more important one here.

-- 
 Magnus Hagander
 Me: http://www.hagander.net/
 Work: http://www.redpill-linpro.com/

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] server authentication over Unix-domain sockets

2010-07-02 Thread Peter Eisentraut
On fre, 2010-07-02 at 09:16 +0100, Magnus Hagander wrote:
 On Fri, Jul 2, 2010 at 8:35 AM, KaiGai Kohei kai...@ak.jp.nec.com wrote:
  (2010/07/01 11:30), Peter Eisentraut wrote:
  I have a question.
 
  The pqGetpwuid() is enclosed by #ifndef WIN32 ... #endif, although
  this patch encloses the section to obtain user id of the peer by
  #ifdef HAVE_UNIX_SOCKETS ... #endif.
 
  Is there any possibilities that both WIN32 and HAVE_UNIX_SOCKETS are
  set concurrently? If possible, the libpq may try to call undefined
  function, then build will be failed.
 
 Win32 never has HAVE_UNIX_SOCKET.
 
 Cygwin might though, I recall some old discussion about that - can't
 remember the outcome though, and I can't find it right now.

Cygwin doesn't define WIN32 anyway.



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] server authentication over Unix-domain sockets

2010-07-02 Thread Andrew Dunstan



Peter Eisentraut wrote:

Is there any possibilities that both WIN32 and HAVE_UNIX_SOCKETS are
set concurrently? If possible, the libpq may try to call undefined
function, then build will be failed.
  

Win32 never has HAVE_UNIX_SOCKET.

Cygwin might though, I recall some old discussion about that - can't
remember the outcome though, and I can't find it right now.



Cygwin doesn't define WIN32 anyway.

  


Indeed, and we've been very careful to keep it that way.

cheers

andrew


--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] server authentication over Unix-domain sockets

2010-06-30 Thread Peter Eisentraut
On tis, 2010-06-22 at 09:37 +0900, KaiGai Kohei wrote:
 As you described at the source code comments as follows,
 it is not portable except for Linux due to the getsockopt() API.
 
 +   // TODO: currently Linux-only code, needs to be made
 +   // portable; see backend/libpq/auth.c
 
 I expect it shall be fixed (using the code come from ident_unix()?)
 before committing.

Updated patch attached.

Note that the code that gets the user ID from the other end of a socket
appears to have two different modes of operation.  On some platforms
(Linux, OpenBSD, Solaris), you call a function and get the answer.  On
some other platforms (other BSDs?), you need to send a packet and read
the answer.  I don't have any possibility to test the latter approach,
and it seemed a bit complicated to code blindly.  So I have omitted
support for that, but if someone else wants to do the porting, that is
of course possible.

 I'd like to point out one other point.
 It uses getpwuid() to translate a user identifier into a user name,
 but it returns a pointer of the static variable within glibc.
 So, it is not thread-safe. I recommend to use getpwnam_r() instead.

Good catch.  pqGetpwuid() was actually the right function to use.
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 8f0a9cf..6a811c5 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -503,6 +503,28 @@
  /listitem
 /varlistentry
 
+varlistentry id=libpq-connect-requirepeer xreflabel=requirepeer
+ termliteralrequirepeer/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., literalrequirepeer=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
  termliteralkrbsrvname/literal/term
  listitem
@@ -6136,6 +6158,16 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
 listitem
  para
   indexterm
+   primaryenvarPGREQUIREPEER/envar/primary
+  /indexterm
+  envarPGREQUIREPEER/envar behaves the same as the xref
+  linkend=libpq-connect-requirepeer connection parameter.
+ /para
+/listitem
+
+listitem
+ para
+  indexterm
primaryenvarPGKRBSRVNAME/envar/primary
   /indexterm
   envarPGKRBSRVNAME/envar  behaves the same as the xref
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index ed37bbd..74595e0 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -226,6 +226,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,
@@ -592,6 +595,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;
@@ -1673,6 +1678,85 @@ keep_going:		/* We will come back to here until there is
 char	   *startpacket;
 int			packetlen;
 
+#ifdef HAVE_UNIX_SOCKETS
+if (conn-requirepeer)
+{
+	char		pwdbuf[BUFSIZ];
+	struct passwd pass_buf;
+	struct passwd *pass;
+	uid_t		uid;
+
+#if defined(HAVE_GETPEEREID)
+	gid_t		gid;
+
+	errno = 0;
+	if (getpeereid(sock, uid, gid) != 0)
+	{
+		appendPQExpBuffer(conn-errorMessage,
+		  libpq_gettext(could not get peer credentials: %s\n),
+		  pqStrerror(errno, sebuf, sizeof(sebuf)));
+		goto error_return;
+	}
+#elif defined(SO_PEERCRED)
+	struct ucred peercred;
+	ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
+
+	errno = 0;
+	if (getsockopt(conn-sock, 

Re: [HACKERS] server authentication over Unix-domain sockets

2010-06-21 Thread Peter Eisentraut
On fre, 2010-06-11 at 08:07 -0400, Stephen Frost wrote:
 Having the option wouldn't do much unless users know of it and use it
 and it strikes that will very often not be the case.

That situation is the same as with SSL over TCP/IP with certificate
validation.  I don't think we can make either of these the default
without risking breaking a lot of things.


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] server authentication over Unix-domain sockets

2010-06-21 Thread KaiGai Kohei
I've checked on this patch.

As you described at the source code comments as follows,
it is not portable except for Linux due to the getsockopt() API.

+   // TODO: currently Linux-only code, needs to be made
+   // portable; see backend/libpq/auth.c

I expect it shall be fixed (using the code come from ident_unix()?)
before committing.


I'd like to point out one other point.
It uses getpwuid() to translate a user identifier into a user name,
but it returns a pointer of the static variable within glibc.
So, it is not thread-safe. I recommend to use getpwnam_r() instead.

Except for the issue, it looks to me fine.

* The patch can be applied on the head of the git repository.
* We can build the code without any warnings/errors.
* It works as described in the documentation.

  [kai...@saba ~]$ php -r 'pg_connect(dbname=postgres requirepeer=);'
  PHP Warning:  pg_connect(): Unable to connect to PostgreSQL server: invalid 
connection option requirepeer in Command line code on line 1
= Existing library, so not supported.

  [kai...@saba ~]$ env LD_LIBRARY_PATH=/usr/local/pgsql/lib/ \
   php -r 'pg_connect(dbname=postgres requirepeer=);'
  PHP Warning:  pg_connect(): Unable to connect to PostgreSQL server: 
requirepeer failed (actual: kaigai != required: ) in Command line code on 
line 1
  LOG:  incomplete startup packet
= Patched library, so it prevent unexpected user-id of server process

  [kai...@saba ~]$ env LD_LIBRARY_PATH=/usr/local/pgsql/lib/ \
   php -r 'pg_connect(dbname=postgres requirepeer=kaigai);'
= Patched library, so it does not prevent anything for the expected user-id.

  [kai...@saba ~]$ env LD_LIBRARY_PATH=/usr/local/pgsql/lib/ \
   php -r 'pg_connect(dbname=postgres);'
= No requirepeer, so it does not prevent anything.

  [kai...@saba ~]$ env LD_LIBRARY_PATH=/usr/local/pgsql/lib/ \
   env PGREQUIREPEER=xyz php -r 'pg_connect(dbname=postgres);'
  PHP Warning:  pg_connect(): Unable to connect to PostgreSQL server: 
requirepeer failed (actual: kaigai != required: xyz) in Command line code on 
line 1
  LOG:  incomplete startup packet
= PGREQUIREPEER environment variable, instead of requirepeer option. Same 
result.

  [kai...@saba ~]$ env LD_LIBRARY_PATH=/usr/local/pgsql/lib/ \
   env PGREQUIREPEER=kaigai php -r 
'pg_connect(dbname=postgres);'
= PGREQUIREPEER environment variable, instead of requirepeer option. Same 
result.

Thanks,

(2010/05/30 20:00), Peter Eisentraut wrote:
 It has been discussed several times in the past that there is no way for
 a client to authenticate a server over Unix-domain sockets.  So
 depending on circumstances, a local user could easily insert his own
 server and collect passwords and data.  Suggestions for possible
 remedies included:
 
 You can put the socket file in a sufficiently write-protected directory.
 But that would strongly deviate from the default setup, and anyway the
 client still cannot readily verify that the server is the right one.
 
 You can also run SSL over Unix-domain sockets.  This is currently
 disabled in the code, but it would work just fine.  But it's obviously
 kind of awkward, and the connection overhead was noticeable in tests.
 
 Then it was suggested to use the local ident mechanism in reverse, so
 the client could verify what user the server runs under.  I have
 implemented a prototype of this.  You can put, e.g.,
 
 requirepeer=postgres
 
 into the connection parameters, and the connection will be rejected
 unless the process at the other end of the socket is running as
 postgres.
 
 The patch needs some portability work and possible refactoring because
 of that, but before I embark on that, comments on the concept?
 
 
 
 
 


-- 
KaiGai Kohei kai...@ak.jp.nec.com

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] server authentication over Unix-domain sockets

2010-06-20 Thread KaiGai Kohei
(2010/06/11 21:11), Stephen Frost wrote:
 * Magnus Hagander (mag...@hagander.net) wrote:
 On Fri, Jun 11, 2010 at 14:07, Stephen Frostsfr...@snowman.net  wrote:
 I definitely like the idea but I dislike requiring the user to do
 something to implement it.  Thinking about how packagers might want to
 use it, could we make it possible to build it defaulted to a specific
 value (eg: 'postgres' on Debian) and allow users a way to override
 and/or unset it?

 Well, even if we don't put that in, the packager could export a global
 PGREQUIREPEER environment variable.
 
 Yea, no, that's a crappy solution, sorry. :)  I've been down that
 road with people trying to monkey with /etc/bashrc; oh wait, not
 everyone uses bash, and having every package screw with that stuff is
 equally horrible.  Admittedly, in this specific case, Debian could
 implement what you're talking about in it's wrapper system, maybe, but I
 still don't like it and if people don't use the wrapper (I can imagine
 cases why that might happen, tho I havn't ever had to myself), they
 wouldn't get the benefit..
 
Are you suggesting the packager enforces a certain unix user on the
installation time, although 'postgres' shall be used in most cases?

Let's back to the purpose of the feature.
In my understanding, it provides the client process the way to verity
user identifier of the server process before sending password.
Indeed, if we provide a default value of the requirepeer using
environment variable, the client process can override its own setting.
But is there any problem?

This option allows the client process to specify an expected user
identifier of the server process, then libpq closes the connection
if not matched.
Even if the default shall be given from the system default, the
client can provide an explicit alternative in the connection string.
Is there any fundamental differences to the environment variable?

Thanks,
-- 
KaiGai Kohei kai...@ak.jp.nec.com

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] server authentication over Unix-domain sockets

2010-06-11 Thread Magnus Hagander
On Sun, May 30, 2010 at 13:00, Peter Eisentraut pete...@gmx.net wrote:
 It has been discussed several times in the past that there is no way for
 a client to authenticate a server over Unix-domain sockets.  So
 depending on circumstances, a local user could easily insert his own
 server and collect passwords and data.  Suggestions for possible
 remedies included:

 You can put the socket file in a sufficiently write-protected directory.
 But that would strongly deviate from the default setup, and anyway the
 client still cannot readily verify that the server is the right one.

 You can also run SSL over Unix-domain sockets.  This is currently
 disabled in the code, but it would work just fine.  But it's obviously
 kind of awkward, and the connection overhead was noticeable in tests.

 Then it was suggested to use the local ident mechanism in reverse, so
 the client could verify what user the server runs under.  I have
 implemented a prototype of this.  You can put, e.g.,

 requirepeer=postgres

 into the connection parameters, and the connection will be rejected
 unless the process at the other end of the socket is running as
 postgres.

 The patch needs some portability work and possible refactoring because
 of that, but before I embark on that, comments on the concept?

I like it. ISTM like something that would be very useful - an easy way
to get a fair amount of extra security in the case of local
connections, at almost zero cost. Just an export
PGREQUIREPEER=postgres in .profile goes a long way :-)



-- 
 Magnus Hagander
 Me: http://www.hagander.net/
 Work: http://www.redpill-linpro.com/

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] server authentication over Unix-domain sockets

2010-06-11 Thread Magnus Hagander
On Sun, May 30, 2010 at 13:00, Peter Eisentraut pete...@gmx.net wrote:
 It has been discussed several times in the past that there is no way for
 a client to authenticate a server over Unix-domain sockets.  So
 depending on circumstances, a local user could easily insert his own
 server and collect passwords and data.  Suggestions for possible
 remedies included:

 You can put the socket file in a sufficiently write-protected directory.
 But that would strongly deviate from the default setup, and anyway the
 client still cannot readily verify that the server is the right one.

 You can also run SSL over Unix-domain sockets.  This is currently
 disabled in the code, but it would work just fine.  But it's obviously
 kind of awkward, and the connection overhead was noticeable in tests.

 Then it was suggested to use the local ident mechanism in reverse, so
 the client could verify what user the server runs under.  I have
 implemented a prototype of this.  You can put, e.g.,

 requirepeer=postgres

 into the connection parameters, and the connection will be rejected
 unless the process at the other end of the socket is running as
 postgres.

 The patch needs some portability work and possible refactoring because
 of that, but before I embark on that, comments on the concept?



 --
 Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
 To make changes to your subscription:
 http://www.postgresql.org/mailpref/pgsql-hackers





-- 
 Magnus Hagander
 Me: http://www.hagander.net/
 Work: http://www.redpill-linpro.com/

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] server authentication over Unix-domain sockets

2010-06-11 Thread Stephen Frost
* Peter Eisentraut (pete...@gmx.net) wrote:
 The patch needs some portability work and possible refactoring because
 of that, but before I embark on that, comments on the concept?

I definitely like the idea but I dislike requiring the user to do
something to implement it.  Thinking about how packagers might want to
use it, could we make it possible to build it defaulted to a specific
value (eg: 'postgres' on Debian) and allow users a way to override
and/or unset it?

Having the option wouldn't do much unless users know of it and use it
and it strikes that will very often not be the case.

I'm impartial towards whatever PG wants to do with the default, just so
long as packagers can override it and set it to something specific.
Also, to that end, it's got to be name-based.  Exim in Debian did
something similar and actually tried to force a particular UID..  that
was horrid. :)  On Debian, at least, the user is almost always
'postgres', but the UID will vary depending on exactly when the packages
were installed (before or after other system-user-creating packages).

Thanks,

Stephen


signature.asc
Description: Digital signature


Re: [HACKERS] server authentication over Unix-domain sockets

2010-06-11 Thread Magnus Hagander
On Fri, Jun 11, 2010 at 14:07, Stephen Frost sfr...@snowman.net wrote:
 * Peter Eisentraut (pete...@gmx.net) wrote:
 The patch needs some portability work and possible refactoring because
 of that, but before I embark on that, comments on the concept?

 I definitely like the idea but I dislike requiring the user to do
 something to implement it.  Thinking about how packagers might want to
 use it, could we make it possible to build it defaulted to a specific
 value (eg: 'postgres' on Debian) and allow users a way to override
 and/or unset it?

Well, even if we don't put that in, the packager could export a global
PGREQUIREPEER environment variable.


 Having the option wouldn't do much unless users know of it and use it
 and it strikes that will very often not be the case.

 I'm impartial towards whatever PG wants to do with the default, just so
 long as packagers can override it and set it to something specific.
 Also, to that end, it's got to be name-based.  Exim in Debian did
 something similar and actually tried to force a particular UID..  that
 was horrid. :)  On Debian, at least, the user is almost always
 'postgres', but the UID will vary depending on exactly when the packages
 were installed (before or after other system-user-creating packages).

Oh yes, absolutely name-based.

-- 
 Magnus Hagander
 Me: http://www.hagander.net/
 Work: http://www.redpill-linpro.com/

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] server authentication over Unix-domain sockets

2010-06-11 Thread Stephen Frost
* Magnus Hagander (mag...@hagander.net) wrote:
 On Fri, Jun 11, 2010 at 14:07, Stephen Frost sfr...@snowman.net wrote:
  I definitely like the idea but I dislike requiring the user to do
  something to implement it.  Thinking about how packagers might want to
  use it, could we make it possible to build it defaulted to a specific
  value (eg: 'postgres' on Debian) and allow users a way to override
  and/or unset it?
 
 Well, even if we don't put that in, the packager could export a global
 PGREQUIREPEER environment variable.

Yea, no, that's a crappy solution, sorry. :)  I've been down that
road with people trying to monkey with /etc/bashrc; oh wait, not
everyone uses bash, and having every package screw with that stuff is
equally horrible.  Admittedly, in this specific case, Debian could
implement what you're talking about in it's wrapper system, maybe, but I
still don't like it and if people don't use the wrapper (I can imagine
cases why that might happen, tho I havn't ever had to myself), they
wouldn't get the benefit..

Thanks,

Stephen


signature.asc
Description: Digital signature


[HACKERS] server authentication over Unix-domain sockets

2010-05-30 Thread Peter Eisentraut
It has been discussed several times in the past that there is no way for
a client to authenticate a server over Unix-domain sockets.  So
depending on circumstances, a local user could easily insert his own
server and collect passwords and data.  Suggestions for possible
remedies included:

You can put the socket file in a sufficiently write-protected directory.
But that would strongly deviate from the default setup, and anyway the
client still cannot readily verify that the server is the right one.

You can also run SSL over Unix-domain sockets.  This is currently
disabled in the code, but it would work just fine.  But it's obviously
kind of awkward, and the connection overhead was noticeable in tests.

Then it was suggested to use the local ident mechanism in reverse, so
the client could verify what user the server runs under.  I have
implemented a prototype of this.  You can put, e.g.,

requirepeer=postgres

into the connection parameters, and the connection will be rejected
unless the process at the other end of the socket is running as
postgres.

The patch needs some portability work and possible refactoring because
of that, but before I embark on that, comments on the concept?

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
+ termliteralrequirepeer/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., literalrequirepeer=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
  termliteralkrbsrvname/literal/term
  listitem
@@ -6082,6 +6104,16 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
 listitem
  para
   indexterm
+   primaryenvarPGREQUIREPEER/envar/primary
+  /indexterm
+  envarPGREQUIREPEER/envar behaves the same as the xref
+  linkend=libpq-connect-requirepeer connection parameter.
+ /para
+/listitem
+
+listitem
+ para
+  indexterm
primaryenvarPGKRBSRVNAME/envar/primary
   /indexterm
   envarPGKRBSRVNAME/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);