Re: Getting peer credentials on a unix domain socket

2001-05-08 Thread Dima Dorfman

Terry Lambert <[EMAIL PROTECTED]> writes:
> I think adding a new system call is _not_ the way to go; there
> are perfectly good fcntl() commands, which fail to work under
> FreeBSD, but work just fine under Solaris, SunOS, Linux, and
> most other UNIX systems (we are back to "struct fileops" being
> major suckage here).

Are you objecting to specifically making this a system call, or
implementing it in general?  I.e., is a socket option acceptable?
Basically, this thread is about trying to find a mechanism that can be
used to meet these two conditions on unix domain sockets:

1. Server can obtain the credentials of the connect() caller.
2. The above can be done without depending on the connect() caller
   to send any data through the socket.

Condition 1 is easy to meet; SCM_CREDS already exists.  On the other
hand, nobody has found an existing way to meet condition 2.  If you
can change this (i.e., describe a way to do this for the list), great.
Otherwise, I have a patch[1] that implements this as a socket option,
and William Baxter has a patch to implement it as a system call.

Dima Dorfman
[EMAIL PROTECTED]

[1] http://www.unixfreak.org/~dima/home/peercred.diff

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message



Re: Getting peer credentials on a unix domain socket

2001-05-08 Thread Terry Lambert

Alfred Perlstein wrote:
> Someone had some patches for a getpeercreds() syscall, but I wasn't
> happy with it considering we already have the sendmsg() stuff to pass
> credentials along with the fact that the initial creator of a socket
> may be long gone before it's used to connect to something.

The credentials (ucred) persist; that's actually part of the
problems I was having a while ago with 30,000+ open files (if
they didn't, I'd have had 65,000+ open files before I saw any
problems, and the reasons would have been much more obviously
a bit count boundary problem, instead of a bug hunt).

I think adding a new system call is _not_ the way to go; there
are perfectly good fcntl() commands, which fail to work under
FreeBSD, but work just fine under Solaris, SunOS, Linux, and
most other UNIX systems (we are back to "struct fileops" being
major suckage here).

-- Terry

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message



Re: Getting peer credentials on a unix domain socket

2001-05-07 Thread Mike Silbersack


On 7 May 2001, Dag-Erling Smorgrav wrote:

> Alfred Perlstein <[EMAIL PROTECTED]> writes:
> > The silly part of it is that the socket's initial credentials
> > might be different than the holder's credentials.
>
> That's a feature, just like you can open /dev/io as root, then drop
> root privs and do direct I/O to your heart's content even if you're no
> longer root.
>
> DES

That feature is undesireable in some places, however.  As an example,
sockets passed from a daemon running as root to child processes as nobody
still have root privs on the sockets.  As such, you can't use sbsize
limiting or ipfw's uid-based tracking on apache and presumably any other
root spawning, priv dropping daemons.

Patching the net code to drop the privs to match those of the accepting
connection was easy, though I didn't test enough to check if it broke the
/dev/io case or others.

Mike "Silby" Silbersack


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message



Re: Getting peer credentials on a unix domain socket

2001-05-06 Thread Robert Watson

On 7 May 2001, Dag-Erling Smorgrav wrote:

> Alfred Perlstein <[EMAIL PROTECTED]> writes:
> > The silly part of it is that the socket's initial credentials
> > might be different than the holder's credentials.
> 
> That's a feature, just like you can open /dev/io as root, then drop root
> privs and do direct I/O to your heart's content even if you're no longer
> root. 

However, a lot of device drivers do checks on p->p_ucred (or indirectly
via suser(p)) rather than using the cached credential in the struct file.
This is arguably wrong or evil, but since the driver writers really feel
like doing that, I suppose all we can do is shoot them, not stop them.

There are actually a number of places in netinet and netinet6 where some
checks are performed on so->so_cred while others are performed on
p->p_ucred.  This is to restrict the rebinding of sockets by processes,
preventing the following scenario:

(1) privileged process p1 creates socket s1, and binds it to (PF_INET,
IPPROTO_TCP, 80)
(2) privileged process p1 transfers s1 to unprivileged process p2 (or
drops privileges)
(3) unprivileged process p2 rebinds to (PF_INET, IPPROTO_TYPE, 22)

Getting the checks for that right is hard, as the definition of correct is
a bit ambiguous, and it's not clear all the code in there is "right" at
this point.  It's one of the things on the list of authorization
components to review.  Generally speaking, I'd much rather the cached
credential was used, but understand why it's not in this scenario.

Robert N M Watson FreeBSD Core Team, TrustedBSD Project
[EMAIL PROTECTED]  NAI Labs, Safeport Network Services



To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message



Re: Getting peer credentials on a unix domain socket

2001-05-06 Thread Dag-Erling Smorgrav

Alfred Perlstein <[EMAIL PROTECTED]> writes:
> The silly part of it is that the socket's initial credentials
> might be different than the holder's credentials.

That's a feature, just like you can open /dev/io as root, then drop
root privs and do direct I/O to your heart's content even if you're no
longer root.

DES
-- 
Dag-Erling Smorgrav - [EMAIL PROTECTED]

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message



Re: Getting peer credentials on a unix domain socket

2001-05-04 Thread William E. Baxter

On Fri, May 04, 2001 at 08:34:57PM -0700, Alfred Perlstein wrote:
 
> The silly part of it is that the socket's initial credentials
> might be different than the holder's credentials.

A user calls connect() with one set of credentials, subsequently changes
credentials, and writes to the socket.  Alternatively, the same user first
changes credentials, then calls connect() and writes to the socket.

So what?

> What makes a lot more sense is packaging the messages with the
> credentials using the existing interface rather than trusting
> possibly stale credential information.

My conditions are:

1. Server can obtain credentials of connect() caller (effective uid and gid suffice).
2. Server can obtain credentials without depending on client to send data.

Condition (2) prevents local users from launching an anonymous DoS attack by
calling connect() and sending no data.  How does your approach satisfy
condition (2)?

W.


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message



Re: Getting peer credentials on a unix domain socket

2001-05-04 Thread Dima Dorfman

Alfred Perlstein <[EMAIL PROTECTED]> writes:
> * Dima Dorfman <[EMAIL PROTECTED]> [010504 20:22] wrote:
> > 
> > Just to expand on that a little more (for others on the list),
> > consider crontab(1).  It's setuid root right now.  Obviously that's
> > not good.  One way of getting rid of that setuid bit is to have
> > cron(8) (or another daemon) listen on a world-writable unix domain
> > socket, and have crontab(1) just be a user interface which sends the
> > information via that socket.  With some mechanism to get the
> > credentials of the user that connected, this would be possible.
> 
> The silly part of it is that the socket's initial credentials
> might be different than the holder's credentials.

Perhaps it is silly to a human, but I don't see how it makes much of a
difference.  I'm assuming you're talking about either fork()/exec() or
descriptor passing.  I don't mean to sound rude, but if a user is
silly enough to forget to close that descriptor before exec'ing an
untrusted program, or he passes it to a program that has no business
using it, there are bigger problems.

OTOH, the user may legitmately want to do that.  If the server is
concerned about that, it can always use both techniques (this and
SCM_CREDS) together.  Without using this, however, the server may be
vulnerable to a DoS attack.  In cron's case, this attack may be in the
form of opening lots of connections and not writing anything.  It
can't refuse duplicate connections from the same user because it
doesn't know who's connected until they send something.

BTW, I hope I made it clear that this is for *stream sockets*.  It's
horribly useless on datagram sockets.  Just making sure in case that's
what you were thinking about.

Thanks,

Dima Dorfman
[EMAIL PROTECTED]

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message



Re: Getting peer credentials on a unix domain socket

2001-05-04 Thread Alfred Perlstein

* Dima Dorfman <[EMAIL PROTECTED]> [010504 20:22] wrote:
> 
> Just to expand on that a little more (for others on the list),
> consider crontab(1).  It's setuid root right now.  Obviously that's
> not good.  One way of getting rid of that setuid bit is to have
> cron(8) (or another daemon) listen on a world-writable unix domain
> socket, and have crontab(1) just be a user interface which sends the
> information via that socket.  With some mechanism to get the
> credentials of the user that connected, this would be possible.

The silly part of it is that the socket's initial credentials
might be different than the holder's credentials.

What makes a lot more sense is packaging the messages with the
credentials using the existing interface rather than trusting
possibly stale credential information.

-- 
-Alfred Perlstein - [[EMAIL PROTECTED]]
Represent yourself, show up at BABUG http://www.babug.org/

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message



Re: Getting peer credentials on a unix domain socket

2001-05-04 Thread Dima Dorfman

"William E. Baxter" <[EMAIL PROTECTED]> writes:
> On Fri, May 04, 2001 at 05:07:38PM -0700, Alfred Perlstein wrote:
> > * Dima Dorfman <[EMAIL PROTECTED]> [010504 16:06] wrote:
> > > Is there a reliable method of obtaining the credentials (uid/gid) of a
> > > peer (SOCK_STREAM sockets only, obviously) on a unix domain socket?
> > > All the Stevens books I have suggest that there isn't, but I'm
> > > wondering if something has been developed since those books were
> > > published.  Note that a BSD/OS-like LOCAL_CREDS socket opt is not
> > > sufficient because using the latter the process must wait until the
> > > peer sends something before they can learn its credentials.  If this
> > > process intends to drop the connection if it's not from an authorized
> > > source, this may lead to a DoS attack.  Timers don't help, either;
> > > think of TCP SYN flood-like attacks.
> > 
> > Someone had some patches for a getpeercreds() syscall, but I wasn't
> > happy with it considering we already have the sendmsg() stuff to pass
> > credentials along with the fact that the initial creator of a socket
> > may be long gone before it's used to connect to something.
> 
> 
> I wrote that patch.  Links to my patches appear at
> 
> http://www.superscript.com/patches/intro.html

Cool!  Actually, I wrote a patch[1] to implement something simlar
before sending my original e-mail.  I looked at your patches, and it
seems the main difference is that mine uses the getsockopt interface
instead of a system call, and mine uses struct xucred which, I
believe, is the correct way of passing user credentials to the
userland (this structure didn't exist in FreeBSD 4.0, which is what it
looks like your patch is against).  Other than that they do pretty
much the same thing :-).

> Explanatory material and links to the same appear at
> 
> http://www.superscript.com/ucspi-ipc/getpeereid.html
> 
> My patch is designed to satisfy these conditions:
> 
> 1. Server can obtain credentials of connect() caller (effective uid and gid suffice).
> 2. Server can obtain credentials without depending on client to send data.
> 
> Having met these conditions, it is nearly trivial to create privileged servers
> that run behind a unix socket, in an environment under their own control.  In
> many instances one can replace setuid programs with such servers.

Just to expand on that a little more (for others on the list),
consider crontab(1).  It's setuid root right now.  Obviously that's
not good.  One way of getting rid of that setuid bit is to have
cron(8) (or another daemon) listen on a world-writable unix domain
socket, and have crontab(1) just be a user interface which sends the
information via that socket.  With some mechanism to get the
credentials of the user that connected, this would be possible.

Regards,

Dima Dorfman
[EMAIL PROTECTED]

[1] http://www.unixfreak.org/~dima/home/peercred.diff

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message



Re: Getting peer credentials on a unix domain socket

2001-05-04 Thread William E. Baxter

On Fri, May 04, 2001 at 05:07:38PM -0700, Alfred Perlstein wrote:
> * Dima Dorfman <[EMAIL PROTECTED]> [010504 16:06] wrote:
> > Is there a reliable method of obtaining the credentials (uid/gid) of a
> > peer (SOCK_STREAM sockets only, obviously) on a unix domain socket?
> > All the Stevens books I have suggest that there isn't, but I'm
> > wondering if something has been developed since those books were
> > published.  Note that a BSD/OS-like LOCAL_CREDS socket opt is not
> > sufficient because using the latter the process must wait until the
> > peer sends something before they can learn its credentials.  If this
> > process intends to drop the connection if it's not from an authorized
> > source, this may lead to a DoS attack.  Timers don't help, either;
> > think of TCP SYN flood-like attacks.
> 
> Someone had some patches for a getpeercreds() syscall, but I wasn't
> happy with it considering we already have the sendmsg() stuff to pass
> credentials along with the fact that the initial creator of a socket
> may be long gone before it's used to connect to something.


I wrote that patch.  Links to my patches appear at

http://www.superscript.com/patches/intro.html

Explanatory material and links to the same appear at

http://www.superscript.com/ucspi-ipc/getpeereid.html

My patch is designed to satisfy these conditions:

1. Server can obtain credentials of connect() caller (effective uid and gid suffice).
2. Server can obtain credentials without depending on client to send data.

Having met these conditions, it is nearly trivial to create privileged servers
that run behind a unix socket, in an environment under their own control.  In
many instances one can replace setuid programs with such servers.

How does one meet these two conditions with vanilla FreeBSD, NetBSD, or OpenBSD?
So far as I know, the answer is "One cannot."

Unfortunately, sendmsg() mechanisms fail to satisfy condition (2).  As Dima
pointed out, this means a local user can launch DoS attacks anonymously.  The
server operates at the mercy of the client.

And as Alfred points out, perhaps unintentionally, the information should be
passed at connect(), because the client process may exit before accept()
returns.  Many simple servers require credentials and nothing more.  In such
cases, there is no reason for the client to wait until accept() returns.

My ucspi-ipc package provides a framework for turning filters into servers based
on getpeereid():

http://www.superscript.com/ucspi-ipc/intro.html

A collection of simple servers, some of which perform operations normally
delegated to setuid programs, is available at:

http://www.superscript.com/ipctools/intro.html

Linux already has sufficient basis for implementing getpeereid(), with
getsockopt() and SO_PEERCRED, and my ucspi-ipc package uses them to satisfy the
two conditions stated above.  I created patches for NetBSD, FreeBSD, and
OpenBSD, hoping to contribute better facilities to these projects.  None of the
implementors displayed any enthusiasm.  Nor did they demonstrate how to satisfy
the two conditions stated above with existing system features.  Too bad.

If you think that getpeereid(), or sufficient basis for it, should appear in
future versions of *BSD, please tell the implementors.  My implementation
remains theirs for the asking.

W.


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message



Re: Getting peer credentials on a unix domain socket

2001-05-04 Thread Alfred Perlstein

* Dima Dorfman <[EMAIL PROTECTED]> [010504 16:06] wrote:
> Is there a reliable method of obtaining the credentials (uid/gid) of a
> peer (SOCK_STREAM sockets only, obviously) on a unix domain socket?
> All the Stevens books I have suggest that there isn't, but I'm
> wondering if something has been developed since those books were
> published.  Note that a BSD/OS-like LOCAL_CREDS socket opt is not
> sufficient because using the latter the process must wait until the
> peer sends something before they can learn its credentials.  If this
> process intends to drop the connection if it's not from an authorized
> source, this may lead to a DoS attack.  Timers don't help, either;
> think of TCP SYN flood-like attacks.

Someone had some patches for a getpeercreds() syscall, but I wasn't
happy with it considering we already have the sendmsg() stuff to pass
credentials along with the fact that the initial creator of a socket
may be long gone before it's used to connect to something.

-- 
-Alfred Perlstein - [[EMAIL PROTECTED]]
Represent yourself, show up at BABUG http://www.babug.org/

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message



Getting peer credentials on a unix domain socket

2001-05-04 Thread Dima Dorfman

Is there a reliable method of obtaining the credentials (uid/gid) of a
peer (SOCK_STREAM sockets only, obviously) on a unix domain socket?
All the Stevens books I have suggest that there isn't, but I'm
wondering if something has been developed since those books were
published.  Note that a BSD/OS-like LOCAL_CREDS socket opt is not
sufficient because using the latter the process must wait until the
peer sends something before they can learn its credentials.  If this
process intends to drop the connection if it's not from an authorized
source, this may lead to a DoS attack.  Timers don't help, either;
think of TCP SYN flood-like attacks.

Thanks,

Dima Dorfman
[EMAIL PROTECTED]

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message