Using Apache httpd's suexec with IBM HTTP Server

These instructions refer to Apache 1.3's suexec for use with any level of IBM HTTP Server. suexec is essentially the same between Apache 1.3.x and Apache 2.0.x, and Apache 1.3.x is simpler to build.

suexec is a wrapper program which allows CGI or SSI programs to be started by the web server but run with a different identity. As an example, the web server could run under user wwwuser but a CGI script could run under user dbadmin. Because web server operations may be triggered by clients connecting over a public network, switching identities from the web server user id can only be performed under specific guidelines which are compiled into the suexec program.

Description of example suexec deployment

Our example web server supports two virtual hosts which require CGI script execution:

The two web sites are administered by different teams and we want the CGI scripts for those virtual hosts to run under user ids specific to the appropriate web site team.

web server user id and group dbaccess.example.com user id and group catalog.example.com user id and group
wwwrun/www dbaccess (53)/dbaccess (71) catalog (59)/catalog (79)

Note that we have displayed the numeric values for the users and groups. This is needed later when we actually build suexec.

Here are some other characteristics of the deployment:

location of suexec log file (one per web server) /www/logs/suexec.log
location of CGI scripts for dbaccess.example.com /www/cgi-bin/dbaccess.example.com
location of CGI scripts for catalog.example.com /www/cgi-bin/catalog.example.com

Customizing suexec for the deployment

First, download a recent Apache httpd 1.3 tarball, such as apache_1.3.42.tar.gz, from http://www.apache.org/dist/httpd/ .

Next, unpack the source code:

$ gunzip apache_1.3.42.tar.gz
$ tar -xf apache_1.3.42.tar

Next, make a small change to the suexec source code so that it will work with any release of Apache or IBM HTTP Server:

$ cd apache_1.3.42

Edit src/support/suexec.c and replace

    if ((pw = getpwnam(target_uname)) == NULL) {
        log_err("crit: invalid target user name: (%s)\n",
        target_uname);
        exit(105);
    }
with
if (strspn(target_uname, "1234567890") != strlen(target_uname)) {
    if ((pw = getpwnam(target_uname)) == NULL) {
        log_err("crit: invalid target user name: (%s)\n",
    target_uname);
        exit(105);
    }
}
    else {
        if ((pw = getpwuid(atoi(target_uname))) == NULL) {
            log_err("invalid target user id: (%s)\n", target_uname);
            exit(121);
        }
    }

It is unfortunate to have to modify the source. But Apache 2.0 and IBM HTTP Server 2.0 will not work with this suexec without the modification. And building Apache 2.0 in order to get suexec brings with it more potential problems.

Next, if you might be using suexec with SSL and would like the usual environment variables available, you will need to make another change. The suexec code contains a list of environment variables that are safe to pass through, and the 1.3 version of suexec does not include the SSL variables in its list.

Look for this part:

char *safe_env_lst[] =
{
    /* variable name starts with */
    "HTTP_",

    /* variable name is */
    "AUTH_TYPE=",
    "CONTENT_LENGTH=",

and edit it to look like:

char *safe_env_lst[] =
{
    /* variable name starts with */
    "HTTP_",
    "HTTPS_",
    "SSL_",

    /* variable name is */
    "HTTPS=",
    "AUTH_TYPE=",
    "CONTENT_LENGTH=",

Next, configure the Apache server and specify the suexec configuration, then build it. Here is how the different parameters to configure were determined:

--enable-suexec This is required to build suexec.
--suexec-caller The value must be the user id of the web server.
--suexec-logfile The value specifies the log created by suexec to report errors and other information.
--suexec-docroot The value specifies a location where all CGI scripts must reside. The value chosen is common for our two virtual hosts.
--suexec-uidmin The value specifies the minimim uid for our set of users (53 for the dbaccess user id and 59 for the catalog user id).
--suexec-gidmin The value specifies the minimum gid for our set of groups (71 for the dbaccess group and 79 for the catalog group).
$ ./configure --enable-suexec               \
--suexec-caller=wwwrun                      \
--suexec-logfile=/www/logs/suexec.log       \
--suexec-docroot=/www/cgi-bin               \
--suexec-uidmin=53                          \
--suexec-gidmin=71

$ make

There is no need to run make install.

After make completes, the suexec binary is in src/support/suexec. The location to copy the file is specific to the IBM HTTP Server version and platform and will be covered by a later section.

Integrating suexec with IBM HTTP Server 2.0 or above

Copying suexec to the proper location

The suexec program must be placed in a specific directory in order for IBM HTTP Server to find it. The name of the directory can be displayed using the apachectl -V command. Example:

$ /opt/IHS-2.0.47.1/bin/apachectl -V
Server version: IBM_HTTP_Server/2.0.47.1 Apache/2.0.47
Server built:   May 20 2004 17:07:49
Build level:    WWWIHS2047/web_IHS0420.04
Server's Module Magic Number: 20020903:4
Architecture:   32-bit
Server compiled with....
 -D APACHE_MPM_DIR="server/mpm/worker"
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D HTTPD_ROOT="/usr/IBMIHS"
 -D SUEXEC_BIN="/usr/IBMIHS/bin/suexec"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="conf/mime.types"
 -D SERVER_CONFIG_FILE="conf/httpd.conf"

After copying suexec to the location displayed by apachectl -V, the file must be made setuid-root.

Here are example commands:

# cp -p src/support/suexec /usr/IBMIHS/bin/
# chown root /usr/IBMIHS/bin/suexec
# chgrp system /usr/IBMIHS/bin/suexec
# chmod +s /usr/IBMIHS/bin/suexec
# ls -l /usr/IBMIHS/bin/suexec
-rwsr-sr-x   1 root     system     56213 Jan 08 09:54 /usr/IBMIHS/bin/suexec

Updating httpd.conf

Presumably you already have virtual hosts defined for dbaccess.example.com and catalog.example.com. Add these ScriptAlias and SuexecUserGroup directives:

<VirtualHost dbaccess.example.com>
existing directives
ScriptAlias /cgi-bin /www/cgi-bin/dbaccess.example.com/
SuexecUserGroup dbaccess dbaccess
</VirtualHost>

<VirtualHost catalog.example.com>
existing directives
ScriptAlias /cgi-bin /www/cgi-bin/catalog.example.com/
SuexecUserGroup catalog catalog
</VirtualHost>

Integrating suexec with IBM HTTP Server 1.3

Copying suexec to the proper location

The suexec program must be placed in a specific directory in order for IBM HTTP Server to find it. The name of the directory can be displayed using the httpd -V. Example:

$ /usr/HTTPServer/bin/httpd -V
Server version: IBM_HTTP_SERVER/1.3.19.5  Apache/1.3.20 (Unix)
Server built:   Feb 10 2003 15:49:36
Server's Module Magic Number: 19990320:11
Server compiled with....
 -D HAVE_MMAP
 -D USE_MMAP_SCOREBOARD
 -D USE_MMAP_FILES
 -D HAVE_FCNTL_SERIALIZED_ACCEPT
 -D HAVE_SYSVSEM_SERIALIZED_ACCEPT
 -D HAVE_PTHREAD_SERIALIZED_ACCEPT
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D HTTPD_ROOT="/usr/HTTPServer"
 -D SUEXEC_BIN="/usr/HTTPServer/bin/suexec"
 -D DEFAULT_PIDLOG="logs/httpd.pid"
 -D DEFAULT_SCOREBOARD="logs/httpd.scoreboard"
 -D DEFAULT_LOCKFILE="logs/httpd.lock"
 -D DEFAULT_XFERLOG="logs/access_log"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D TYPES_CONFIG_FILE="conf/mime.types"
 -D SERVER_CONFIG_FILE="conf/httpd.conf"
 -D ACCESS_CONFIG_FILE="conf/access.conf"
 -D RESOURCE_CONFIG_FILE="conf/srm.conf"

After copying suexec to the location displayed by httpd -V, the file must be made setuid-root.

Here are example commands. The system group and the location may be different on your system:

# cp -p src/support/suexec /usr/HTTPServer/bin/
# chown root /usr/HTTPServer/bin/suexec
# chgrp system /usr/HTTPServer/bin/suexec
# chmod +s /usr/HTTPServer/bin/suexec
# ls -l /usr/HTTPServer/bin/suexec
-rwsr-sr-x   1 root     system     56213 Jan 08 09:54 /usr/HTTPServer/bin/suexec

Updating httpd.conf

Presumably you already have virtual hosts defined for dbaccess.example.com and catalog.example.com. Add these ScriptAlias, User, and Group directives:

<VirtualHost dbaccess.example.com>
existing directives
ScriptAlias /cgi-bin /www/cgi-bin/dbaccess.example.com/
User dbaccess
Group dbaccess
</VirtualHost>

<VirtualHost catalog.example.com>
existing directives
ScriptAlias /cgi-bin /www/cgi-bin/catalog.example.com/
User catalog
Group catalog
</VirtualHost>

Debugging the suexec configuration

The suexec log file (/www/logs/suexec.log in our example) contains information for debugging. You will likely have to re-configure Apache to change the suexec configuration during debugging. Prior to invoking configure again, run make distclean from the Apache source directory.

Note that if a problem with a suexec configuration option is found and suexec has to be rebuilt, a new suexec binary may be reinstalled without stopping/starting IBM HTTP Server.

For more information...

The Apache documentation for suexec is at http://www-306.ibm.com/software/webservers/httpservers/doc/v1328/htdocs/en_US/manual/suexec.html .

A good tutorial is at http://apache-server.com/tutorials/LPsuexec.html .