rwind icon indicating copy to clipboard operation
rwind copied to clipboard

Let server listen on + client connect to unix domain socket

Open TauPan opened this issue 11 years ago • 9 comments

A possible solution to the "security issue" mentioned in the README:

Since unix domain sockets are protected via unix file permissions, there's no further security measures needed.

The server should create and listen on a socket file, that belongs to the user running the window manager and should be created with restrictive file permissions (i.e. set umask accordingly).

The client should connect to that socket.

To make the code portable to machines with non-local filesystems, there should be a list of paths that is tried for socket creation/connect:

  • some subdirectory of $HOME, might fail for some remote filesystems
  • /tmp/$USER/, must be created first and checked for permissions

Also socket creation might be vulnerable to a race condition, which must be prevented in the server code.

Rough draft, I might try my hand at this when/if I find the time. First step is to figure out how to use unix-domain-sockets in racket.

Drawback of this approach is of course that client connections won't work across the network any more, but a proper authentication scheme would be needed for this, which imho is overkill for a window manager client.

I dimly remember sawfish uses unix-domain sockets, too, but it's been a long time since I used it.

TauPan avatar Apr 05 '13 14:04 TauPan

Interesting, thanks for the idea!

I guess it may be a simple matter of using sync' on anopen-input-file' port, along with make-temporary-file' andfile-or-directory-permissions'. With proper filenames, like 'rwind-socket-1', it should be possible to have multiple connections on different sockets.

For race conditions, we can restrict to one connection for now, I don't think that's currently a big deal (though in some cases multiple connections can clearly be useful).

For network connection, clients should probably use an ssh tunnel, so I think that's not a real problem, and that's even probably the "right" way to do it. Connections are currently only local anyway, and I don't believe it's necessary to change that.

Laurent

On Fri, Apr 5, 2013 at 4:38 PM, TauPan [email protected] wrote:

A possible solution to the "security issue" mentioned in the README:

Since unix domain sockets are protected via unix file permissions, there's no further security measures needed.

The server should create and listen on a socket file, that belongs to the user running the window manager and should be created with restrictive file permissions (i.e. set umask accordingly).

The client should connect to that socket.

To make the code portable to machines with non-local filesystems, there should be a list of paths that is tried for socket creation/connect:

  • some subdirectory of $HOME, might fail for some remote filesystems
  • /tmp/$USER/, must be created first and checked for permissions

Also socket creation might be vulnerable to a race condition, which must be prevented in the server code.

Rough draft, I might try my hand at this when/if I find the time. First step is to figure out how to use unix-domain-sockets in racket.

Drawback of this approach is of course that client connections won't work across the network any more, but a proper authentication scheme would be needed for this, which imho is overkill for a window manager client.

I dimly remember sawfish uses unix-domain sockets, too, but it's been a long time since I used it.

— Reply to this email directly or view it on GitHubhttps://github.com/Metaxal/RWind/issues/4 .

Metaxal avatar Apr 05 '13 15:04 Metaxal

Thanks for your pointers, as I'm more familiar with the posix-api than the particular way racket wraps it!

I've been using scsh for posix programming a couple of years ago and found it very convenient, but I have to read up on the relevant parts of the racket api first.

With "race condition" I referred to the situation that a malicious local user could create and control a socket file with the correct filename before we do and thus hijack the window manager. This just has to be done according to best practice.

TauPan avatar Apr 08 '13 11:04 TauPan

On Mon, Apr 8, 2013 at 1:49 PM, TauPan [email protected] wrote:

Thanks for your pointers, as I'm more familiar with the posix-api than the particular way racket wraps it!

I've been using scsh for posix programming a couple of years ago and found it very convenient, but I have to read up on the relevant parts of the racket api first.

Actually, it seems that the racket FFI will be needed here (I'm not really familiar with unix domain sockets, though now a bit more than 3 days ago). The client side should be quite similar to: https://github.com/plt/racket/blob/master/collects/unstable/socket.rkt (note for the future: this collection is unstable, so the link to the file may change in the near future). The server side needs to be implemented though.

With "race condition" I referred to the situation that a malicious local user could create and control a socket file with the correct filename before we do and thus hijack the window manager. This just has to be done according to best practice.

Oh, right, of course. One possibility: If the client and the server verify that the socket file access right are user rw only, right after connection, do you think there could still be a race condition? Probably putting it in the user dir before trying other temporary paths could not harm though.

Laurent

Metaxal avatar Apr 08 '13 14:04 Metaxal

Ok, I'll look into that collection you mentioned, should be helpful. (Sorry, I can't seem to reply quoted with this browser here.)

A little research (web + manual pages) seems to indicate that it's sufficient to create the socket file via bind(2) in a directory where only the user has write-access. So putting it somewhere inside $HOME is a good suggestion for most cases. (Is there XDG_VARDIR or something?).

Since some network filesystems (AFS, which I happen to use in one installation) don't support sockets, I'd like an RWIND_SOCKET variable in the environment as a workaround for those (rare) cases. (Similar to RXVT_SOCKET, see the rxvt manpage.)

Sounds sane and simple enough.

TauPan avatar Apr 09 '13 15:04 TauPan

Are you the one that just uploaded the racket-unix-sockets package on PLaneT? http://planet.racket-lang.org/display.ss?package=racket-unix-sockets.plt&owner=shawnpresser

Anyway, it's just what we need.

For the environment variable, would it be not as good if this goes instead in a config file? (i.e., the rwind user's config file)

Metaxal avatar Apr 17 '13 13:04 Metaxal

Are you the one that just uploaded the racket-unix-sockets package on > PLaneT? http://planet.racket-lang.org/display.ss?package=racket-unix-sockets.plt&owner=shawnpresser

nope

Anyway, it's just what we need.

Cool, I was afraid that my first try at something like this would involve hacking at racket itself ;)

For the environment variable, would it be not as good if this goes instead in a config file? (i.e., the rwind user's config file)

Sure, if you prefer it that way.

I have some free time this weekend but this is competing with a couple other projects, so still don't hold your breath waiting for contributions.

TauPan avatar Apr 20 '13 09:04 TauPan

If it can be of any help, here's a gist to test the package in client/mono-server style : https://gist.github.com/Metaxal/5426707

The main problem here is that the server uses the accept function which will not allow for breaks (see the comments in server.rkt).

I'm not sure then what to do next for that issue.

Laurent

On Sat, Apr 20, 2013 at 11:41 AM, TauPan [email protected] wrote:

Are you the one that just uploaded the racket-unix-sockets package on > PLaneT?

http://planet.racket-lang.org/display.ss?package=racket-unix-sockets.plt&owner=shawnpresser

nope

Anyway, it's just what we need.

Cool, I was afraid that my first try at something like this would involve hacking at racket itself ;)

For the environment variable, would it be not as good if this goes instead in a config file? (i.e., the rwind user's config file)

Sure, if you prefer it that way.

I have some free time this weekend but this is competing with a couple other projects, so still don't hold your breath waiting for contributions.

— Reply to this email directly or view it on GitHubhttps://github.com/Metaxal/RWind/issues/4#issuecomment-16701409 .

Metaxal avatar Apr 20 '13 17:04 Metaxal

See also the discussion here: https://groups.google.com/forum/#!msg/racket-users/LIXBfMlFPCY/3f2IpJi5TZsJ

In particular the use of scheme_fd_to_semaphore. (and its documentation in raw format here: https://github.com/plt/racket/blob/master/collects/scribblings/inside/ports.scrbl#L791 )

Just one thing remains: the double check in atomic mode that there is a client to accept.

Laurent

On Sat, Apr 20, 2013 at 7:18 PM, Laurent [email protected] wrote:

If it can be of any help, here's a gist to test the package in client/mono-server style : https://gist.github.com/Metaxal/5426707

The main problem here is that the server uses the accept function which will not allow for breaks (see the comments in server.rkt).

I'm not sure then what to do next for that issue.

Laurent

On Sat, Apr 20, 2013 at 11:41 AM, TauPan [email protected] wrote:

Are you the one that just uploaded the racket-unix-sockets package on > PLaneT?

http://planet.racket-lang.org/display.ss?package=racket-unix-sockets.plt&owner=shawnpresser

nope

Anyway, it's just what we need.

Cool, I was afraid that my first try at something like this would involve hacking at racket itself ;)

For the environment variable, would it be not as good if this goes instead in a config file? (i.e., the rwind user's config file)

Sure, if you prefer it that way.

I have some free time this weekend but this is competing with a couple other projects, so still don't hold your breath waiting for contributions.

— Reply to this email directly or view it on GitHubhttps://github.com/Metaxal/RWind/issues/4#issuecomment-16701409 .

Metaxal avatar Apr 23 '13 13:04 Metaxal

Ah... I was about to suggest that the filedescriptor was used in a non-blocking way (i.e. not via accept()), with the equivalent of select(3). It seems that scheme_fd_to_semaphore provides an appropriate scheme-y abstraction for that. (Again, I'm way more familiar with the underlying posix semantics than the customary way to encapsulate these things in scheme-implementations, if we can call still call racket an implementation of scheme.)

TauPan avatar Apr 24 '13 08:04 TauPan