Check out the new USENIX Web site.


NetAuth Application Programming Interface

There are several ways to set the owner of a network service: (1) the service can be configured to run as a pseudo user (e.g., apache) with enough privileges to satisfy any request. (2) the service may need user authentication to ensure that it is a valid user (e.g., for mail relay), but all users are treated identically. This service too can be owned by a pseudo user. (3) the service provided depends on the user, who therefore must be authenticated--it is usually appropriate that the service process be owned by its user (i.e., UBNS).

A UBNS service (a process run under the user's ID) performs the following steps: (a) it accepts a connection, (b) performs user authentication to identify the user requesting the service, (c) creates a new process, and (d) changes the ownership of the process to the authenticated user. Once the ownership of the process is changed to the user, it cannot be used by anyone else.

We next examine how this general paradigm is performed in Unix and then in netAuth.

Figure 3: UNIX: Sequence of system calls executed by a client and a server. The server forks a process to service a request; the forked process is owned by the authenticated user.

Image flowChartUNIX

Figure 4: netAuth: Sequence of system calls executed by a client and a server. The server forks a process to service a request; the forked process is owned by the authenticated user.
Image flowChart

Figure 3 shows the call sequence for implementing a user authenticated service using UNIX socket APIs. The client creates a socket (socket), connects to the server (connect), and then does a series of sends and receives (send/recv), and when its done closes the socket.

The server creates a socket (socket), associates it with a network address on the server (bind), allocates a pending queue of connection requests (listen), waits for a new connection request to arrive (accept). To perform UBNS, it spawns a process (fork), and after determining the user via network messages (not shown) it then changes the owner of the process (setuid). At this point the newly created service process is operating as the user. It communicates back and forth with the client and then closes the connection. Since there is typically no way to reuse the process after it closes the socket, it exits.

Figure 4 shows the equivalent sequencing for netAuth. On the client side, the only programming change needed to adapt to netAuth is to replace connect with connect_by_user (of course, the application-level authentication must be removed).

On the server side, netAuth basically splits the accept for a new connection into two phases:

The accept is split into two APIs because there are now two actions (1) determining that there is an unaccepted connection for a new user (so that a new process can be created) and (2) completing the accept by a (child) process owned by the new user. (2) ensures that the accepted socket can be read or written (since the process is owned by the user). Hence, the split accept ensures that the accept_by_user only succeeds if the owner of the process is the authenticated user on the connection.

The change of ownership of the process is performed by set_net_user. The set_net_user changes the owner of the process to the authenticated user and consumes the netAuthenticate privilege for that process. Thus, set_net_user serves as a highly restricted version of setuid, and is far safer to use.

Manigandan Radhakrishnan 2008-05-13