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 .domterm/default.socket in the user’s home directory. 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.)

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