httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Michael Clark <>
Subject [RFC] Apache Privilege Separation for WebDAV (against 2.3.0-dev)
Date Wed, 05 Dec 2007 15:11:46 GMT
Hi Folks,

I have been maintaining a patch against 1.3.x for privilege separation
support (for WebDAV with UNIX quotas and permissions) that has been used
in a production environment for quite some time (for remote access to
files that are served on an internal network by samba/netatalk).

I have finally got around to porting it to Apache 2.3.0 trunk. Below is
a link to *experimental* patches for those who are interested. Also it
is now working on both Linux and FreeBSD (other unices should be
relatively easy, see notes below on portability issues and potential
possibility for a Windows implementation).

I was thinking of sending the patches to the list for some wider review.
Shall I go ahead and post them here?

Do let us know if any of you are interested in helping me out with this.
It has some interesting applications (like the potential for
implementing an iDisk type service with working quotas support).

Feedback of any sort much appreciated.


Apache Privilege Separation for WebDAV


The Privilege Separation module addresses the problem of a WebDAV
virtual server only being able to write files as a single user id
(usually something like 'nobody' or 'www').

The Privilege Separation module addresses this problem in a secure
way by adding privilege separation to the Apache web server
(conceptually similar to ssh privilege separation).

A privilege separated Apache can be used to allow WebDAV write access
to users home directories while both preserving and honouring unix
permissions and allowing the use of unix quotas and PAM authentication.


In Privilege Separation mode Apache continues to run as an unprivileged
user although an additional secure process runs as 'root'.

The apache worker processes communicate with the 'root' privileged
separated process via unix sockets to carry out system authentication
and privileged file system operations. Namely:

* Responding to PAM authentication requests
   pam_unix authentication is not normally possible in apache due to
   the unprivileged process not being able to access the shadow file.
   Due to the privilege separated design this is now possible.
   Authentication responses include a cryptographic token which encodes
   the users credentials and is verified in successive privileged
   filesystem requests made to the privsep process.

* Performing privileged filesystem operations on behalf of the
   unprivileged apache worker processes with the privileges of the
   authenticated user. The cryptographic token is verified and then the
   effective userid is set and the filesystem operation is performed.

Certain auditable points in the apache core code (core.c, request.c),
mod_autoindex and mod_dav code have been changed to use the privilege
separated file io calls which communicate via unix sockets to the
privileged daemon. File descriptors are passed back over unix sockets
for open calls.


APR file IO calls are modified to use the privsep versions which take
an additional context argument (request_rec* r):


The privsep versions of the function fetch a token from r->notes.
If the privsep token exists then the request is dispatched to the
privilege separated daemon, otherwise the file io method is
executed directly in the regular way.

One special case exists for the stat and lstat calls made from
ap_directory_walk. This is called before map_to_storage has been
done and any authentication hooks. This special case needs the stat
and lstat calls to be executed as root to know if the path actually
exists. The security leak potential is minimised by making stat
the only call that is able to be made as uid 0 and ap_directory_walk
is the only routine that calls ap_privsep_special_stat.

NOTE: This experimental version of privsep has modified private copies
of the associated apr file io routines. It is envisioned that these
additional privsep interfaces could be added to apr with an additional
void *priv_context argument and a hook callback linkage with a default
behaviour of passing through to the regular functions. e.g.

Regular stat interface:

   apr_status_t apr_stat(apr_finfo_t *finfo, const char *fname,
                         apr_int32_t wanted, apr_pool_t *pool);

Privsep interface:

   apr_status_t apr_privsep_stat(void *priv_context,
                              apr_finfo_t *finfo, const char *fname,
                              apr_int32_t wanted, apr_pool_t *pool);


mod_privsep has been tested on Linux and FreeBSD.

apr interfaces have been used where possible but mod_privsep relies on
unix sockets (socketpair,sendmsg,recvmsg) and the ability to send file
descriptors over unix sockets. It also currently depends on PAM.

It should be relatively easily ported to other unix-like OS.

NOTE: the opendir implementation relies on platform specific details.
Specifically, that directories can be opened as file descriptors and
also that the file descriptor is the first structure member of the
private DIR* structure.

It is potentially possible to implement this feature for Windows as
a preliminary investigation shows that it is possible to pass file
handles between processes. More investigation is needed.


  # apply patch

  # run buildconf to pick up change

  LIBS=-lpam ./configure \
    --enable-dav \
    --enable-privsep \

The experimental patch-set requires the modules to be compiled in
and will not link if the patch is applied and the options are not
enabled. A future patch will address the issue of proper modularity.


Example configuration:

  <Directory "/opt/apache2.2/uploads/">

    # Enable WebDAV and privilege separation for this directory
    Dav On
    PrivilegeSeparation On

    # System authentication through privilege separated PAM
    AuthType Basic
    AuthName DAV-upload
    AuthBasicProvider privsep

    Options Indexes
    AllowOverride None
    Require valid-user

    # Workaround for WebDAV PROPFIND bug on dirs with index files
    DirectoryIndex /no_directory_index



* Single privileged separated process seriliazes stat/lstat/open
   * Potential solution: change to a pool of privsep processes

* Overhead of PAM authentication for each request
   * Potential solution: cache authentication

* Overhead of setgroups in each privileged operation
   * Route requests to a pooled process that is already switched
     to the required user

View raw message