Processes and security

Normally, there is is a single per-user domterm server process. When you run the domterm command it will look for a domterm server process; if there is no running server, the domterm command will “daemonize” itself and become the server. Otherwise, the domterm process will be a client, and forward the requested action to the server.

Communication between a domterm client and a server uses Unix domain sockets. By default, this socket will be bound to the file $XDG_RUNTIME_DIR/domterm/default.socket. We make use of Unix file permission to ensure that the client and the server run on behalf of the same user. (This could be generalized to allow groups to co-operate, by setting permissions appropriately, but this has not been explored.)

When you run a new session, that creates a new user process, under control of the domterm server.

The above client-server architecture is same as used by tmux.

The front-end is a separate program that handles the user interface. It is a web browser or an application that embeds a web browser, like Electron. The domterm server is also a web server that supports both http and the WebSockets protocols. The domterm server forwards output from a user process to the associated browser and vice versa: The server uses a pty for the input/output of the user process, and forwards that input/output to the browser using a websocket connection. Normally, the server creates a new browser instance, with a specified URL. When the corresponding page is loaded, the browser runs JavaScript that requests a WebSocket connection with the server.

The obvious concern is that a different malicious browser might try to establish a connection with the server, which would allow executing arbitrary commands on behalf of the user. To thwart that, the server generates a 60-bit random key, and requires this server key to be present in any connection attempts. This means the browser JavaScript process must know the server key when it creates a websocket connection. The server must pass the key to the browser in a secure way. A simple way is to pass the key along with the URL used to start the browser, but that would typically require the key to be part of the browser’s command-line, which is not secure. (It can can viewed with tools like ps.)

FIXME - OBSOSLTE: Instead, the server creates a new file .domterm/default.html in the user’s home directory, and uses that as the URL:

$ ${BROWSER} "file://${HOME}/.domain/default.html"

This file (only readable by the user) includes the following:

DomTerm.server_key = '${SERVER_KEY}';

The ${SERVER_KEY} is substituted when the file is created, and used when the browser needs to make a websocket connection to the server. Again, we depend on Unix file permissions so only a process running as the correct user can read default.html, extract the server key, and make a valid connection back to the server.

Obviously, it could be very useful to handle networked connections, with a browser on one machine managing a user process on another. While one can always run ssh, this does not support detaching from and re-attaching to a session smoothly. For now, you have to use ssh in combination with tmux or screen; we hope to have a smoother interface after studying the issue. It would presumably use forwarding using ssh, or https, or a combination.

Some related links