Thread: SSL over Unix-domain sockets

SSL over Unix-domain sockets

From
Peter Eisentraut
Date:
I found an old patch on my disk to enable SSL over Unix-domain sockets.

Remember, about a year ago it was discussed that there might also be 
man-in-the-middle or fake-server attacks using Unix-domain sockets, 
because usually anyone can start a server in /tmp.  After an extensive 
discussion (mainly about moving the socket out of /tmp by default; 
please don't start that again), it was determined that using SSL server 
verification would be the proper solution and it fact works without 
problems.  Except that the start-up overhead was increased significantly 
(because of the initial key exchange and session key setup etc.).

Back then we didn't really have a good solution, but I figured since 8.4 
rearranges the SSL connection parameters anyway, we could stick that in 
there.

I imagine for example, we could invent an additional sslmode of the sort 
prefer-but-not-if-local-socket, which could be the default.

The other question is whether sslverify=cn makes sense, but that may be 
up to the user to find out.

Comments?


Re: SSL over Unix-domain sockets

From
Magnus Hagander
Date:
Peter Eisentraut wrote:
> I found an old patch on my disk to enable SSL over Unix-domain sockets.
> 
> Remember, about a year ago it was discussed that there might also be
> man-in-the-middle or fake-server attacks using Unix-domain sockets,
> because usually anyone can start a server in /tmp.  After an extensive
> discussion (mainly about moving the socket out of /tmp by default;
> please don't start that again), it was determined that using SSL server
> verification would be the proper solution and it fact works without
> problems.  Except that the start-up overhead was increased significantly
> (because of the initial key exchange and session key setup etc.).
> 
> Back then we didn't really have a good solution, but I figured since 8.4
> rearranges the SSL connection parameters anyway, we could stick that in
> there.
> 
> I imagine for example, we could invent an additional sslmode of the sort
> prefer-but-not-if-local-socket, which could be the default.

That parameter is already pretty complex, not sure it's a great idea to
make it even more so :(

Perhaps it's enough to add a "localssl" row to pg_hba.conf?


> The other question is whether sslverify=cn makes sense, but that may be
> up to the user to find out.

Without finding a way to have that make sense, you don't actually fix
the potential MITM problem (at least not in many common scenarios), so I
think that needs to be considered before we put anything in.

//Magnus


Re: SSL over Unix-domain sockets

From
Peter Eisentraut
Date:
Magnus Hagander wrote:
>> I imagine for example, we could invent an additional sslmode of the sort
>> prefer-but-not-if-local-socket, which could be the default.
> 
> That parameter is already pretty complex, not sure it's a great idea to
> make it even more so :(

I think there is a firm difference between complex and having a large 
number of things to choose from.  By your definition, a float type would 
be a complex.  Uh ... hahah.

> Perhaps it's enough to add a "localssl" row to pg_hba.conf?

That defeats the point, I think.  You don't want the server to determine 
whether the client should verify the server.

>> The other question is whether sslverify=cn makes sense, but that may be
>> up to the user to find out.
> 
> Without finding a way to have that make sense, you don't actually fix
> the potential MITM problem (at least not in many common scenarios), so I
> think that needs to be considered before we put anything in.

Yeah, the problem is that there is only one server certificate.  Is it 
possible/does it make sense to add an additional cn to the certificate?

Another thought I had is to somehow employ hostaddr, as in 
"hostaddr=/tmp host=real.hostname.lan".

Another^2 thought is to just examine the certificate for the local host 
name, which the client can find out itself.



Re: SSL over Unix-domain sockets

From
Magnus Hagander
Date:
Peter Eisentraut wrote:
> Magnus Hagander wrote:
>>> I imagine for example, we could invent an additional sslmode of the sort
>>> prefer-but-not-if-local-socket, which could be the default.
>>
>> That parameter is already pretty complex, not sure it's a great idea to
>> make it even more so :(
> 
> I think there is a firm difference between complex and having a large
> number of things to choose from.  By your definition, a float type would
> be a complex.  Uh ... hahah.
> 
>> Perhaps it's enough to add a "localssl" row to pg_hba.conf?
> 
> That defeats the point, I think.  You don't want the server to determine
> whether the client should verify the server.

Good point. OTOH, client behavior can be controlled now fine by setting
it to "require" or "prefer" - I think that's enough.

However, we might want a simple ssl_local=true/false parameter on the
server that turns it on/off completely. That way you can use that
parameter to control the performance side of things (basically to turn
off SSL on unix sockets so you don't pay the overhead) and you keep
using pg_hba to control the policy (because you still need a localssl
line in pg_hba.conf of course). The client gets to say "i require ssl"
in case it cares. And this is the same client that already knows if it's
connecting over tcp or unix sockets...


>>> The other question is whether sslverify=cn makes sense, but that may be
>>> up to the user to find out.
>>
>> Without finding a way to have that make sense, you don't actually fix
>> the potential MITM problem (at least not in many common scenarios), so I
>> think that needs to be considered before we put anything in.
> 
> Yeah, the problem is that there is only one server certificate.  Is it
> possible/does it make sense to add an additional cn to the certificate?

Yes on both. Except the current version of libpq doesn't support this
:-( I was planning to add it (and still do), but the way to do it
appears to be fairly complex and completely undocumented. I did some
searching to find examples of it, but never followed through.


> Another thought I had is to somehow employ hostaddr, as in
> "hostaddr=/tmp host=real.hostname.lan".

That seems rather abusive.


> Another^2 thought is to just examine the certificate for the local host
> name, which the client can find out itself.

That could work. In which case we should probably consider doing the
same thing for "localhost" or "127.0.0.1" connections.

//Magnus



Re: SSL over Unix-domain sockets

From
Bruce Momjian
Date:
Peter Eisentraut wrote:
> I found an old patch on my disk to enable SSL over Unix-domain sockets.
> 
> Remember, about a year ago it was discussed that there might also be 
> man-in-the-middle or fake-server attacks using Unix-domain sockets, 
> because usually anyone can start a server in /tmp.  After an extensive 
> discussion (mainly about moving the socket out of /tmp by default; 
> please don't start that again), it was determined that using SSL server 
> verification would be the proper solution and it fact works without 
> problems.  Except that the start-up overhead was increased significantly 
> (because of the initial key exchange and session key setup etc.).
> 
> Back then we didn't really have a good solution, but I figured since 8.4 
> rearranges the SSL connection parameters anyway, we could stick that in 
> there.
> 
> I imagine for example, we could invent an additional sslmode of the sort 
> prefer-but-not-if-local-socket, which could be the default.
> 
> The other question is whether sslverify=cn makes sense, but that may be 
> up to the user to find out.

I thought the logical solution to this was to place the socket in a
secure directory and not bother with SSL at all.

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + If your life is a hard drive, Christ can be your backup. +


Re: SSL over Unix-domain sockets

From
Peter Eisentraut
Date:
Bruce Momjian wrote:
> I thought the logical solution to this was to place the socket in a
> secure directory and not bother with SSL at all.

How would a client algorithmically determine whether the server socket 
was in a "secure" directory?


Re: SSL over Unix-domain sockets

From
Bruce Momjian
Date:
Peter Eisentraut wrote:
> Bruce Momjian wrote:
> > I thought the logical solution to this was to place the socket in a
> > secure directory and not bother with SSL at all.
> 
> How would a client algorithmically determine whether the server socket 
> was in a "secure" directory?

You have to configure your client to know that, but don't you need to
configure your client for SSL too?

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + If your life is a hard drive, Christ can be your backup. +


Re: SSL over Unix-domain sockets

From
Peter Eisentraut
Date:
Bruce Momjian wrote:
> Peter Eisentraut wrote:
>> Bruce Momjian wrote:
>>> I thought the logical solution to this was to place the socket in a
>>> secure directory and not bother with SSL at all.
>> How would a client algorithmically determine whether the server socket 
>> was in a "secure" directory?
> 
> You have to configure your client to know that, but don't you need to
> configure your client for SSL too?

Yes, but how exactly would a client know?  How is a "secure directory" 
defined, in terms of C library calls, say?


Re: SSL over Unix-domain sockets

From
Peter Eisentraut
Date:
Magnus Hagander wrote:
>>> Perhaps it's enough to add a "localssl" row to pg_hba.conf?
>> That defeats the point, I think.  You don't want the server to determine
>> whether the client should verify the server.
> 
> Good point. OTOH, client behavior can be controlled now fine by setting
> it to "require" or "prefer" - I think that's enough.
> 
> However, we might want a simple ssl_local=true/false parameter on the
> server that turns it on/off completely.

But the choice is that of the client:

1) I want a connection with server authentication. or

2) I want a fast connection, I don't care about server authentication.

No configuration knob in the server can ever solve this.

Of course the client has all the sslmode parameters to make its wishes 
known, but the point here is that the *default* should possibly be a 
different one in the case of Unix-domain sockets.


>> Yeah, the problem is that there is only one server certificate.  Is it
>> possible/does it make sense to add an additional cn to the certificate?
> 
> Yes on both. Except the current version of libpq doesn't support this
> :-( I was planning to add it (and still do), but the way to do it
> appears to be fairly complex and completely undocumented. I did some
> searching to find examples of it, but never followed through.

After further thought, this is probably not the right solution anyway. 
The security of all this depends on the fact that each common name only 
exists once within the scope of a CA.  The socket name or directory, 
however, is more or less them same for everyone.

>> Another thought I had is to somehow employ hostaddr, as in
>> "hostaddr=/tmp host=real.hostname.lan".
> 
> That seems rather abusive.

True, but Kerberos more or less works this way.  hostaddr is where to 
connect, host is what to use for authentication.

>> Another^2 thought is to just examine the certificate for the local host
>> name, which the client can find out itself.
> 
> That could work. In which case we should probably consider doing the
> same thing for "localhost" or "127.0.0.1" connections.

Hmm, as per my statement above, this would be the right thing to do. 
But I think https works differently.  Tricky ...


Re: SSL over Unix-domain sockets

From
Magnus Hagander
Date:
Peter Eisentraut wrote:
> Magnus Hagander wrote:
>>>> Perhaps it's enough to add a "localssl" row to pg_hba.conf?
>>> That defeats the point, I think.  You don't want the server to determine
>>> whether the client should verify the server.
>>
>> Good point. OTOH, client behavior can be controlled now fine by setting
>> it to "require" or "prefer" - I think that's enough.
>>
>> However, we might want a simple ssl_local=true/false parameter on the
>> server that turns it on/off completely.
> 
> But the choice is that of the client:
> 
> 1) I want a connection with server authentication. or
> 
> 2) I want a fast connection, I don't care about server authentication.
> 
> No configuration knob in the server can ever solve this.
> 
> Of course the client has all the sslmode parameters to make its wishes
> known, but the point here is that the *default* should possibly be a
> different one in the case of Unix-domain sockets.

Agreed, except I really don't see why the default should be different.


>>> Another thought I had is to somehow employ hostaddr, as in
>>> "hostaddr=/tmp host=real.hostname.lan".
>>
>> That seems rather abusive.
> 
> True, but Kerberos more or less works this way.  hostaddr is where to
> connect, host is what to use for authentication.

Yeah, and it has always annoyed me :)

I think it'd be better to just gtet the hostname of the system, and use
that.


>>> Another^2 thought is to just examine the certificate for the local host
>>> name, which the client can find out itself.
>>
>> That could work. In which case we should probably consider doing the
>> same thing for "localhost" or "127.0.0.1" connections.
> 
> Hmm, as per my statement above, this would be the right thing to do. But
> I think https works differently.  Tricky ...

Yeah, https requires the cert to be named "localhost". It's a smaller
issue on a Unix system since the http/https ports require root to bind
to them, and if somebody is root no amount of SSL is going to help you
anyway...

//Magnus


Re: SSL over Unix-domain sockets

From
Greg Stark
Date:
Regarding using the hostname of the system... There's no such thing.  
Interfaces have names, hosts can have multiple interfaces so the can  
have multiple names...

I haven't follwes the discussion so I'm not sure if you have an  
existing connection. If so you can get the local interface address  
from the connection and look up the name for that address. But that  
only works if you already have a socket.

-- 
Greg


On 27 Mar 2009, at 07:49, Magnus Hagander <magnus@hagander.net> wrote:

> Peter Eisentraut wrote:
>> Magnus Hagander wrote:
>>>>> Perhaps it's enough to add a "localssl" row to pg_hba.conf?
>>>> That defeats the point, I think.  You don't want the server to  
>>>> determine
>>>> whether the client should verify the server.
>>>
>>> Good point. OTOH, client behavior can be controlled now fine by  
>>> setting
>>> it to "require" or "prefer" - I think that's enough.
>>>
>>> However, we might want a simple ssl_local=true/false parameter on  
>>> the
>>> server that turns it on/off completely.
>>
>> But the choice is that of the client:
>>
>> 1) I want a connection with server authentication. or
>>
>> 2) I want a fast connection, I don't care about server  
>> authentication.
>>
>> No configuration knob in the server can ever solve this.
>>
>> Of course the client has all the sslmode parameters to make its  
>> wishes
>> known, but the point here is that the *default* should possibly be a
>> different one in the case of Unix-domain sockets.
>
> Agreed, except I really don't see why the default should be different.
>
>
>>>> Another thought I had is to somehow employ hostaddr, as in
>>>> "hostaddr=/tmp host=real.hostname.lan".
>>>
>>> That seems rather abusive.
>>
>> True, but Kerberos more or less works this way.  hostaddr is where to
>> connect, host is what to use for authentication.
>
> Yeah, and it has always annoyed me :)
>
> I think it'd be better to just gtet the hostname of the system, and  
> use
> that.
>
>
>>>> Another^2 thought is to just examine the certificate for the  
>>>> local host
>>>> name, which the client can find out itself.
>>>
>>> That could work. In which case we should probably consider doing the
>>> same thing for "localhost" or "127.0.0.1" connections.
>>
>> Hmm, as per my statement above, this would be the right thing to  
>> do. But
>> I think https works differently.  Tricky ...
>
> Yeah, https requires the cert to be named "localhost". It's a smaller
> issue on a Unix system since the http/https ports require root to bind
> to them, and if somebody is root no amount of SSL is going to help you
> anyway...
>
> //Magnus
>
> -- 
> Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-hackers


Re: SSL over Unix-domain sockets

From
Peter Eisentraut
Date:
On Friday 27 March 2009 14:46:32 Greg Stark wrote:
> Regarding using the hostname of the system... There's no such thing.
> Interfaces have names, hosts can have multiple interfaces so the can
> have multiple names...

But there is `hostname` and `hostname --fqdn`, both of which are well-defined 
independent of a connection.



Re: SSL over Unix-domain sockets

From
Robert Haas
Date:
On Fri, Mar 27, 2009 at 9:47 AM, Peter Eisentraut <peter_e@gmx.net> wrote:
> On Friday 27 March 2009 14:46:32 Greg Stark wrote:
>> Regarding using the hostname of the system... There's no such thing.
>> Interfaces have names, hosts can have multiple interfaces so the can
>> have multiple names...
>
> But there is `hostname` and `hostname --fqdn`, both of which are well-defined
> independent of a connection.

But they aren't guaranteed to return anything useful, and IME often don't.

...Robert


Re: SSL over Unix-domain sockets

From
Tom Lane
Date:
Robert Haas <robertmhaas@gmail.com> writes:
> On Fri, Mar 27, 2009 at 9:47 AM, Peter Eisentraut <peter_e@gmx.net> wrote:
>> But there is `hostname` and `hostname --fqdn`, both of which are well-defined
>> independent of a connection.

> But they aren't guaranteed to return anything useful, and IME often don't.

I think "well defined" is stretching it anyway.  I see different
behaviors (partially or fully qualified hostname) on my different Unix
machines.  --fqdn appears particularly useless, as Fedora 10 reports
this:

$ hostname --fqdn
localhost.localdomain

and my other machines don't recognize the switch at all.
        regards, tom lane


Re: SSL over Unix-domain sockets

From
Bruce Momjian
Date:
Peter Eisentraut wrote:
> Bruce Momjian wrote:
> > Peter Eisentraut wrote:
> >> Bruce Momjian wrote:
> >>> I thought the logical solution to this was to place the socket in a
> >>> secure directory and not bother with SSL at all.
> >> How would a client algorithmically determine whether the server socket 
> >> was in a "secure" directory?
> > 
> > You have to configure your client to know that, but don't you need to
> > configure your client for SSL too?
> 
> Yes, but how exactly would a client know?  How is a "secure directory" 
> defined, in terms of C library calls, say?

I assume directory permissions controlling access to the socket file
would be enough.  You are going to have to set up SSL certificates
anyway for this so isn't that just as hard as telling the client where
the socket file is located?

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + If your life is a hard drive, Christ can be your backup. +


Re: SSL over Unix-domain sockets

From
Peter Eisentraut
Date:
On Saturday 28 March 2009 00:42:28 Bruce Momjian wrote:
> I assume directory permissions controlling access to the socket file
> would be enough.  You are going to have to set up SSL certificates
> anyway for this so isn't that just as hard as telling the client where
> the socket file is located?

The permissions on the socket file or the containing directory doesn't tell 
much by itself, because you also need to consider who owns it.  What that 
basically comes down to is that the client would need to specify something 
like, "I only want a connection to a server owned by 'postgres'."  But the 
client currently has no way of saying that, so we'd need to invent something 
new.


Re: SSL over Unix-domain sockets

From
Martijn van Oosterhout
Date:
On Tue, Mar 31, 2009 at 11:33:26PM +0300, Peter Eisentraut wrote:
> On Saturday 28 March 2009 00:42:28 Bruce Momjian wrote:
> > I assume directory permissions controlling access to the socket file
> > would be enough.  You are going to have to set up SSL certificates
> > anyway for this so isn't that just as hard as telling the client where
> > the socket file is located?
>
> The permissions on the socket file or the containing directory doesn't tell
> much by itself, because you also need to consider who owns it.  What that
> basically comes down to is that the client would need to specify something
> like, "I only want a connection to a server owned by 'postgres'."  But the
> client currently has no way of saying that, so we'd need to invent something
> new.

If you're going to get complicated, go the whole way do SO_PEERCRED on
the socket, then you get the UID of the server...

Have a nice day,
--
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> Please line up in a tree and maintain the heap invariant while
> boarding. Thank you for flying nlogn airlines.

Re: SSL over Unix-domain sockets

From
Peter Eisentraut
Date:
On Wednesday 01 April 2009 20:37:56 Martijn van Oosterhout wrote:
> On Tue, Mar 31, 2009 at 11:33:26PM +0300, Peter Eisentraut wrote:
> > On Saturday 28 March 2009 00:42:28 Bruce Momjian wrote:
> > > I assume directory permissions controlling access to the socket file
> > > would be enough.  You are going to have to set up SSL certificates
> > > anyway for this so isn't that just as hard as telling the client where
> > > the socket file is located?
> >
> > The permissions on the socket file or the containing directory doesn't
> > tell much by itself, because you also need to consider who owns it.  What
> > that basically comes down to is that the client would need to specify
> > something like, "I only want a connection to a server owned by
> > 'postgres'."  But the client currently has no way of saying that, so we'd
> > need to invent something new.
>
> If you're going to get complicated, go the whole way do SO_PEERCRED on
> the socket, then you get the UID of the server...

I have added this to the Todo list.