Re: Getting peer credentials on a unix domain socket
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
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
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
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
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
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
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
* 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
"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
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
* 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
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