$Cambridge: hermes/src/prayer/docs/DESIGN,v 1.3 2008/05/21 10:38:58 dpc22 Exp $

Overview
========

Prayer consists of two master daemons named "prayer" and "prayer-session",
plus a small auxiliary server named "accountd" which is used for operations
on user accounts such as quota checking and mail redirection which are not
normally provided by the IMAP server.  "prayer" and "prayer-session" both
run on the same gateway system. In fact a "prayer-session" daemon is
normally started automatically by the "prayer" frontend server, though it
is possible to run the two daemons independently, typically when debugging.

"prayer": HTTP server and proxy
===============================

The "prayer" frontend server is a very simple HTTP/1.0 and HTTP/1.1 server
(serving icons and login pages only) and HTTP proxy.

The frontend server normally preforks a number of child processes which
accept incoming HTTP connections: child process are added and retire as
required, according to the load of the system and the prayer configuration.

Each child process will process a defined number of HTTP connections (where
each connection in turn will process a defined number of HTTP requests).
The total number of child processes is capped to prevent denial of service
attacks.  This cap should not be reached during normal operation.

"prayer-session": User logins
=============================

A fresh prayer-session backend is forked off whenever a user logs in.

This process contains all of the permanent state associated with that login
session including one or more connections to a IMAP server and possibly
connections to accountd servers. prayer-session communicates with the user
using HTML over HTTP connections via the "prayer" proxy. Each login has a
sessionid which the front end processes use to find the correct backend.

This arrangement is rather unorthodox from a Web interface design point of
view. However a Webmail interface is an extremely specialised application
which contains much more permanent state than most interactive Web pages.
This design has the advantage of being extremely efficient, at least
compared to a Apache CGI or mod_php interface which maintains no internal
session state and which has to reconnect to a database and the IMAP server
for each HTTP request.

Backend server processes move into a dormant state after a certain period
of inactivity, shutting down IMAP and accountd connections which can be
easily resuscitated when the session wakes up. After a long period of
inactivity, typically several hours the session process shuts down.

Session Security
================

Prayer starts off with a username and password when a user logs in. A
successful login attempt translates this into a session URL which consists
of a username and a crypographically session identifier.

The session identifier is the key to security in Prayer. If someone can
derive the session URL including the the session identifier then they may
be able to break into someone's login session. Prayer provides the
following counter-measures.

1) The session-ID is moved from the session URL to a HTTP Cookie if at all
   possible to stop people from simply reading session identifiers over
   each others shoulders.

2) People are strongly encouraged to use HTTPS rather than HTTP to prevent
   sniffers from pick up valid passwords and active session identifiers.
   The plaintext version of the login screen has a big banner warning.

3) The fix_client_ipaddr configuration option allows the sys admin to only
   accept incoming HTTP(S) connections from the IP address which originated
   the login address. This doesn't protect people on shared Unix systems,
   and it is a little bit harsh for people with private systems on dialup
   links which intermittently disconnect: now disabled by default.

The Prayer URL address space
============================

There are three basic forms of URL that are in use in Prayer:

Login URLS. Example:
  http://webmail1.hermes.cam.ac.uk/
  http://webmail1.hermes.cam.ac.uk/login/dpc22

Icon URLS. Example:
  http://webmail1.hermes.cam.ac.uk/icons/left.gif

Session URLS. Example:
  https://webmail1.hermes.cam.ac.uk/session/dpc22//list/last


Login and icon URL should hopefully be fairly self explanatory. There are a
number of modifiers and options which can be provided to either form of URL
to alter the behaviour of the user interface. These are documented
separately in the URL_OPTIONS file in this directory.

Session URLS will require a little further explanation:

    .../session/dpc22//display/15/452
        ^       ^    ^ ^       ^
        |       |    | |       +- Arguments
        |       |    | +--------- Command
        |       |    +----------- SessionID
        |       +---------------- Username
        +------------------------ Session URL i.e: not icon
                                                        

Session-ID is either an 18 digit (URL friendly) BASE64 encoded value which
is a crypographically secure random number or an empty string which
indicates that the session ID is stored in a HTTP cookie which is based on
the login name, and possibly the port used by the session process (example:
"dpc22:5000=FhsFG6754bncdsfhd". Prayer will attempt to store the session-ID
automatically in a Cookie if the use of cookies is not disabled in the User
Preferences or explicitly by options on the login URL. However the use of
cookies is also negotiated with the browser using a number of round trips
to set a cookie and then test to find out if the cookie value has been
accepted correctly by the browser.

Concurrency
===========

prayer-session processes are single threaded and very stateful: they can
only process a single _complete_ HTTP request at a time. The prayer
frontend servers can however cope with an arbitrary number of incoming
connections and partially complete HTTP requests at the same time. This
should handle browsers that open several concurrent connections to the same
server and also prevent an obvious denial of service attack where an
attacker connects to the the Internet domain socket associated with an
active login session, preventing the genuine user from communicating with
their login session.

In normal use there should only be a single active session URL at a time:
prayer-session manages an interactive interface. The one obvious exception
is during download (and conceivably upload) of large attachments and
mailfolders. It would be rather useful if mail folders and attachments
could be downloaded asynchronously while the user proceeded to other parts
of the user interface. This is possible in the proxy case if the prayer
frontend servers buffer download requests. It would also be possible in the
direct connection case if a separate process was forked off for the
download. One complication: this only becomes asynchronous once the folder
or attachment has been downloaded from the IMAP server. Unfortunately it is
rather hard to make IMAP downloads asynchronous without opening concurrent
IMAP connections to the same mail folder, which is only practical if the
IMAP server and mail folder format used on that IMAP server both support
safe concurrent access to mail folders.

