Included on this page:
This guide helps site administrators run a Pubcookie
login server. Everything from setup and configuration to integration
and customization is covered below.
Application server administrators should refer to the
Pubcookie Apache module guide
or ISAPI filter guide for instructions on
deploying a Pubcookie application server which authenticates using your
local login server.
The Pubcookie login server really consists of two separate components
with separate purposes:
- login server cgi
The Pubcookie login server uses a CGI program to handle browser
requests. This CGI program, hereafter referred to as the login cgi
or index.cgi, is compiled from C and is a site's central Pubcookie
component. End-users rely on it to authenticate; application servers rely on
it for authentication assertions. The login cgi is typically powered by
Apache HTTP Server software.
The Pubcookie login server uses the keyserver component to generate
and distribute symmetric encryption keys for participating servers,
including your Pubcookie login server and all application servers.
The keyserver runs as a service under inetd or xinetd.
The login cgi supports an abstraction called a login flavor. A login
flavor encapsulates a specific set of functionality and features that influence
how and when end-user authentication takes place.
The distribution comes with one login flavor called the basic login
flavor. This login flavor has a rich feature set, including
single sign-on (SSO) user authentication, a pluggable backend authentication
service interface, kiosk mode, and much more.
This guide might, in fact, be described as a guide to the basic login
flavor, it is so tailored to its installation and use.
What the login cgi calls a login flavor, the application
server components call an authentication type. The naming is
rooted in Apache's AuthType directive and it's somewhat
regrettable since they aren't quite the same thing.
For now it's probably enough to say that, unless you build another
login flavor, most application servers will be configured with a single
choice of Pubcookie authentication types, one corresponding directly with
the basic login flavor.
How primary authentication takes place (that is, how usernames
and passwords are actually authenticated) depends on how
the basic login flavor verifies credentials with your backend
The basic login flavor performs username-and-password credential
verification through a simple pluggable interface to backend
authentication services. These plug-ins are called verifiers
and the distribution comes with several:
- verifies credentials using a Kerberos 5 KDC
- verifies credentials using an LDAP server
- verifies credentials using /etc/shadow
- verifies all credentials as successful. good for testing.
Compile-time decisions and run-time configuration determines
which verifier is used by basic login flavor.
These login cgi abstractions help applications to remain independent
of the method, or methods, used by the login server to authenticate user
For example, a site might migrate from LDAP-based to Kerberos
authentication. It's attractive to hide the transition from applications.
Here applications would continue to use their institutional "netid"
authentication type, corresponding with their site's basic login flavor,
while the login server administrators transition, transparently, from
one verifier to another.
Other sites may want to be able to choose from different backend
authentication services. For example, the University of Washington uses
the basic login flavor along side and a more secure flavor that uses
SecurID in addition to username and password for primary authentication.
Applications choose which flavor they want by configuring the
appropriate authentication type.
The configure script included in the distribution helps you build
and install the login cgi and keyserver according to your platform and
To build and install a barebones login server for evaluation and testing,
run the following commands:
$ ./configure --enable-login --disable-apache
$ make install
This builds the login cgi with support for the basic flavor and the
"alwaystrue" verifier. It also builds the keyserver and keyclient binaries.
Files are installed, and directories created, according to the default
installation directory prefix, henceforth called PREFIX, which
defaults to /usr/local/pubcookie. Use the --prefix
configure option to define an alternative location.
Review the results by listing the installation PREFIX directory
-rw-r--r-- root root 935 config # config file
-rw-r--r-- root root 935 config.login.sample # sample config
-rwxr-xr-x root root 92229 keyclient* # keyclient
drwxr-xr-x root root 4096 keys/ # keystore
-rwxr-xr-x root root 92929 keyserver* # keyserver
drwxr-xr-x root root 4096 login/ # login cgi dir
drwxr-xr-x root root 4096 login_templates/ # templates
drwxr-xr-x root root 4096 login_templates.default/ # originals
-rw-r--r-- root root 2048 starter.key # starter key
$ ls login
drwxr-xr-x root root 4096 images/ # images
-rwxr-xr-x root root 99299 index.cgi* # login cgi
Note: initial file permissions assigned by the installation
process may not be acceptable for production use. Please
refer to Appendix B: Permissions & Security
section for a discussion of this subject.
Continue through the setup and configration instructions using
the alwaystrue verifier. After you've gained some familiarity
with a working system, you can rebuild the login cgi to use a
different verifier that goes against your local authentication
service. Review the configure help for the build options.
$ ./configure --help
Refer also to the Kerberos, LDAP, and FastCGI configuration
SSL key pairs have several functions in the operation of
a Pubcookie login server. One key pair may suffice for all of
them, but two key pairs often works better in practice.
SSL key pair:
The SSL private key and certificate used to SSL-enable Apache can
be reused for the first keypair. This key pair is particularly suited
for use with the keyclient and keyserver because the SSL public key
certificate most likely has been signed and issued by a trusted
Certificate Authority. The login cgi also uses this key pair, but only
for signing and verifying "login" cookies.
Note: the login cgi and keyserver cannot read encrypted RSA private
keys because they can't prompt for the passphrase. To reuse an
encrypted SSL key, you'll first have to remove the passphrase. Refer to Appendix C: OpenSSL Commands for help.
The ssl_key_file and ssl_cert_file config file
variables will point to these keys.
Granting key pair:
A second key pair is used to sign and verify "granting" cookies,
the authentication assertions generated and signed by the login cgi
and verified by application servers. Here the certificate issuer
isn't important, but the SSL public key certificate must be
distributed to other servers. Therefore, a separate "granting" key
pair is often used. Refer to Appendix C: OpenSSL
Commands if you need help generating this key pair.
The granting_cert_file and granting_key_file
config file variables will point to these keys.
Note: the key pairs described in this section (used for SSL and
message signing primarily) are in addition to the symmetric encryption
keys Pubcookie uses for data encryption.
The login cgi and keyserver share a run-time configuration file
located at PREFIX/config. The file format is one
attribute-value-pair per line, except where a trailing backslash
\ character continues a value to the next line.
A sample config file appropriate for a login server is provided (see
PREFIX/config or PREFIX/config.login.sample if you're
upgrading) as a starting point. It will look something like this:
# 1 is a good starting point
# the credential verifier used by the basic flavor
# SSL session keypair
# granting keypair
# login server config
# keyserver config
keyserver_client_list: login.example.edu trusted.example.edu
# site-specific policies
Begin editing your config file, using the config
file variable reference as needed for examples and descriptions.
See how several variables in the example above are derived from the
login server name, login.example.edu. This will be true for your
config file too.
The example login server appears to be reusing its SSL key pair
located in server.key and server.crt.
The example login server has a separate "granting" key pair. Refer to
Appendix C: OpenSSL Commands if you need help
generating this key pair.
The example keyserver appears to be using a file bundle of trusted
Certificate Authorities (i.e., ca-bundle.crt). This file
must contain all the trusted CA root certificates the site is using to
verify keyclient certificates.
Keyserver is designed to run as a service under inetd or xinetd.
If you use inetd, add a line like the following to
2222 stream tcp nowait root /usr/local/pubcookie/keyserver keyserver
If you use xinetd, create /etc/xinetd.d/keyserver with the
# description: pubcookie keyserver
type = UNLISTED
protocol = tcp
port = 2222
disable = no
socket_type = stream
wait = no
user = root
group = tty
server = /usr/local/pubcookie/keyserver
After adding the line to inetd.conf, or the file to xinetd, restart
your inetd or xinetd service.
Note: keyserver requires ssl_key_file and
ssl_cert_file, and either ssl_ca_file or
ssl_ca_path depending on how you handle trusted root CA
certificates. Keyserver also uses granting_cert_file for
distributing your "granting" certificate. And if you want control over
which hosts can request keys, you can do so by defining a
keyserver_client_list for authorizing new hosts.
This section describes how symmetric encryption keys are
managed by the keyserver, which issues keys to participating servers,
including all login servers and application servers, upon
request by the keyclient.
A master copy of each 2048-byte DES key is stored on
the login server in its keystore, PREFIX/keys, in a filename
based on the server's SSL certificate's Common Name. For example, a site
with a login server and three application servers might have a keystore
$ ls /usr/local/pubcookie/keys
-rw-r--r-- root root 2048 weblogin.example.edu
-rw-r--r-- root root 2048 appserver.example.edu
-rw-r--r-- root root 2048 mail.example.edu
-rw-r--r-- root root 2048 my.example.edu
-rw-r--r-- root root 887 pubcookie_granting.key
-rw-r--r-- root root 1224 pubcookie_granting.cert
New key generation:
New keys are generated and issued by the keyserver upon request. Running
keyclient on a host initiates the request. If they keyclient host is
authorized, and the keyclient and keyserver trust each other, the
request is fulfilled.
Keyclient host authorization:
The keyserver performs authorization on keyclient requests when
keyserver_client_list is set. Otherwise, it will issue keys
to any keyclient with a verifiable SSL certificate.
When keyclient authorization is enabled, authorization is based on the
presence a host in the keystore. If keyserver finds a host in the
keystore, then that host can request a key. This seems like a catch-22:
to create a new host key in the keystore, the key must already exist
in the keystore. But it's not, becuase site administrators can use
the keyclient's "permit" option to authorize new servers to request keys.
$ keyclient -P new.example.edu
Host new.example.edu is permitted
This can be done manually or by some kind of automated web-based
registration service. The keyserver_client_list defines which
hosts are authorized to use the permit option, allowing you to authorize
new hosts without necessarily having to log in to the login server to do
SSL/TLS mutual authentication
Pubcookie uses elements of public-key infrastructure (PKI) for mutual
server authentication and data privacy in the SSL/TLS connection between
keyclient and keyserver. This is where the trusted Certificat Authority
certificates come in.
The keyclient must verify your keyserver SSL certificate. And the
keyserver must verify each keyclient's SSL certificate. To do so, they
both use ssl_ca_file or ssl_ca_path to find trusted CA
root certificates (to which you can add your own institutional CA if you
have one) to verify the peer certificates.
To generate a symmetric encryption key for your login server, copy
the starter key found in the distribution into your keystore. Use your
login_host name for the filename. For example:
$ cd /usr/local/pubcookie
$ cp starter.key keys/login.example.edu
The starter key allows keyserver to initialize when the keystore
would otherwise be empty. Now you should be able to run keyclient to
request a new DES key for the login server based on your current
config file settings:
Set crypt key for login.example.edu
Note: if keyclient is unable to set a new key, look in syslog for
keyserver error messages.
The login cgi doesn't depend on its own filename or location, so your
primary concern in deploying it should be to create a simple URL that's
easy for users to recognize and trust with their password.
The most common approach is to copy it from
PREFIX/login/index.cgi to the server's root directory, resulting
in a URL such as https://weblogin.example.edu/.
Refer to Appendix A: Apache Configuration
if you're unfamiliar with the directives that control how Apache detects
and handles cgi scripts, particularly as a directory index.
The login cgi can be opened directly in a browser. This is sometimes
called a pinit (for Pubcookie init, like kinit) since
authentication is requested without being tied to an application. It's a
good way to test your current config file and verifier. Go ahead and
try it now. The login page you see comes from
If authentication succeeds, congratulations, you now can deploy an
application server using the Pubcookie Apache module or Pubcookie ISAPI Filter to test the
components together. Then you can go on to build and configure another
verifier that goes against your authentication service and customize the
login cgi templates for your site.
If authentication fails, don't panic, look in your syslog for error
messages from the login cgi and refer to the Logging &
Debugging section for further advice.
The login cgi uses syslog to log all messages. Logging can be
configured using the logging_level
variable. A value of 1 gets you basic audit activity
such as logins and redirects which is most likely sufficient for
normal operation. When additional debugging information is needed
increase the value to 3.
The keyserver also uses syslog and tends to log all critical
error messages. Keyclient uses standard output for its messages.
The login cgi creates login, logout, error, and redirect pages using
HTML templates it reads from the PREFIX/login_templates
directory. An alternative location can be defined using the template_root config file
Edit these templates to suit the naming and web design needs of your
login server. A set of generic templates is copied into place during
installation. A backup set is also copied to
Refer to the login cgi template
reference for descriptions of each template.
Note: For comparison purposes, templates (of some vintage) from
Carnegie Mellon University and the Univerisity of Washington are
provided in the distribution. See src/login_templates.cmu and
src/login_templates.uw. Be warned, however, that the syntax
for variable substitution within the templates has changed over time,
and therefore the CMU and UWash templates may be slightly
The optional PREFIX/ok_browsers file contains a list of
browsers accepted by the login cgi. This file provides a way to block
browsers that either have a known security flaw (i.e., don't forget
cookies when they should) or don't work with Pubcookie. The ok_browsers
file is optional.
Note: At the University of Washington, we've so far been too chicken
to use the 'ok_browsers' functionality to block browsers that we
suspect don't work. Our ok_browsers file has a single line:
Mozilla. This pattern matches most of the browsers we support
or encounter; which is mainly Internet Explorer, Netscape, Mozilla, and
The login cgi handles logout requests initiated by, and redirected
from, applications configured with Pubcookie's per-application logout
functionality. Handling these logout requests is built in; no
configuration is necessary to the login cgi itself.
However, through additional configuration you can create a
separate, direct logout URL for your login server (e.g.
https://weblogin.example.edu/logout). You can also tailor the
logout response messages for your favorite applications. Those
are the two subjects of this section.
Note: Pubcookie does not support "global" logout, that is, logout of all
sessions, all cookies, all at once. Rather, it supports per-application-session
logout with optional ability also to logout of the login server. Therefore,
users still must be educated not to leave their browsers open
and unattended without proper precautions such as locking their computer
and using password-protected screensavers. Exiting the browser remains
the best way for users to get logged out of everything at once.
Configuring a Direct Logout URI:
If you want to provide a URL where users can go directly to clear their
single sign-on session (by way of clearning their "login" cookie), it can
be created with the logout_prog config variable and a Unix symbolic
link. Here's an example.
Suppose the login cgi has been installed in the DocumentRoot
directory (e.g. in /var/www/html) with a URL of https://weblogin.example.edu.
To create a logout URI of /logout/ just below that,
i.e., https://weblogin.example.edu/logout/, you'd do
Change to the appropriate directory, create the subdirectory, and make
the symbolic link to your login cgi:
$ cd /var/www/html
$ mkdir logout
$ cd logout
$ ln -s ../index.cgi index.cgi
Adjust the directory according to the location of your login cgi. Now
any request to /logout/ on the server will map to your login
Now add the appropriate logout_prog variable to your config file:
Customizing Logout Responses For Special Apps:
The login cgi builds logout response pages from several templates. One template,
logout_app, which is the most specific to each application, can be overridden
on a per-application basis, as configured and identified by the originating server
name and application id. It requires one app_logout_string config file variable
for each application, where the server name and id are tacked on using dashes. For example:
# custom logout msgs
<font size="+1">Testapp logout worked just fine.</font>
<font size="+1">Webmail Logout Successful!</font>
Note: Since the login cgi reads the config file and its HTML
templates on each request, there's no need to recompile the login cgi
in order to modify response messages.
Use the kiosk variable to apply a site policy for reduced
single sign-on duration for identified kiosks. The login cgi supports
matching by user-agent string, remote IP address, or IP address ranges.
kiosk: 20m Safari/85.6 \
15m Safari \
10m ExampleKiosk 188.8.131.52 140.142.21.* \
This sets a curiously elaborate, but nonetheless illustrative,
kiosk policy: a 20-minute SSO duration for Safari 85.6, a 15-minute
SSO for all other versions of Safari, a 10-minute SSO to remote browsers
with "ExampleKiosk" in the user-agent string as well as to the remote IP
address 184.108.40.206 and the 140.142.21 subdomain, and a one-hour
SSO duration for IP addresses in the range 220.127.116.11-200.
Matching by user-agent string is particularly useful for
applying reduced SSO to managed kiosks that have a locally
customized user-agent string such as:
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; ExampleKiosk; Windows NT 5.0)
How to customize user-agent strings is beyond the scope of this guide,
but resources and tools, such as the Internet
Explorer Administration Kit, do exist to help with this task.
This section highlights some of the possible site policies you can
define in your config file. These options may be overlooked, but they
can enhance the user experience and shape the security policy of your
to define your default single sign-on duration. Primary authentication
occurs when user-provided credentials are verified directly. Subsequent
authentication is based on checking the "login" cookie. This setting
defines how long this cookie is valid.
to define how long users have to log in. Taking too long will result in a
new login form (with the form_expired template message included).
The default expiration is 60 seconds.
to define the editability of the userid field during a single browsing
session. You may want to allow some flexibility or force users to close
the browser before switching between users.
- Use the retain_username_on_failed_authn
to define whether the userid is retained after a failed login attempt. Users will
appreciate this if they mistyped their password, not their userid.
to define whether users can enter a userid that looks like an email address.
Sites that aren't verifying full Kerberos principals (e.g. firstname.lastname@example.org) or
userids that look like email addresses can use this feature to provide
some flexibility in this regard, i.e., to trim off the extra realm info
the user added and verify just the proper userid.
Refer to the config file variable
reference to review these variables and the values they take.
To build the login cgi with support for the Kerberos 5 verifier,
run the configure script with the Kerberos option enabled:
./configure --enable-login --disable-apache --enable-krb5
If needed, the configure script has other options for adjusting the
location of the Kerberos header files and libraries.
To configure the login cgi to use the Kerberos verifier, edit your
config file and set basic_verifier to
kerberos_v5. Additionally, two other config
file variables control the Kerberos 5 verifier:
kerberos5_service_name and kerberos5_keytab. For
# kerberos verifier config
Enable the append_realm
variable if you want the Kerberos authentication realm to be appended to
the user name after authentication but before issuing cookies (i.e., target
servers will receive user@REALM.)
Use the default_realm
variable to define a default Kerberos authentication realm to pass to the
verifier when none is submitted via the login form.
To authenticate responses from your Kerberos server, the login server and
Kerberos server must share a service key. You can use an existing service key
or generate a new one with the help of your Kerberos administrator. Keep in
mind that the keytab file that contains your service key must be readable by
the login cgi. Since the login cgi will most likely run as a non-root user,
it's recommended that you use a service key other than the "host" service key
typically stored in /etc/krb5.keytab.
Similar to user keys, service keys have a principal of the form
<service_name>/<hostname>@<realm>. The hostname is
the fully qualified hostname for your login server, and the realm is the
Kerberos realm. But the service name is what counts most to the Kerberos 5
verifier. Your service name can be set with the
Contact your local Kerberos domain administrator if you need help creating a
service key, generating a keytab file, or otherwise configuring Kerberos
(e.g. /etc/krb5.conf) on your login server.
To build the login cgi with support for the LDAP verifier,
run the configure script with the LDAP option enabled:
./configure --enable-login --disable-apache --enable-ldap
If needed, the configure script has other options for adjusting the
location of the LDAP header files and libraries.
To configure the login cgi to use the LDAP verifier, edit your
config file and set basic_verifier to ldap and
set ldap_uri to your
The login cgi and keyserver can be deployed in a redundant
configuration, provided that they share the same cluster
name and settings. Use the
variable to configure keyserver to push new keys to its peers.
The login cgi can run as a FastCGI process. This allows one or
more instances of the login cgi to persist and handle many requests
rather than just one.
FastCGI support is enabled with the --with-fcgi=<path to
fcgi> option. Example Apache configuration follows below; modify
LoadModule fastcgi_module libexec/mod_fastcgi.so
-appConnTimeout 0 \
-idle-Timeout 30 \
-init-start-delay 2 \
-killInterval 300 \
-listen-Queue-Depth 50 \
-maxProcesses 10 \
-maxClassProcesses 2 \
-minProcesses 1 \
Servers running version 3.0.0 of the login server can build
and install things without overwriting the current config
file or templates. Compare your configuration with the new
config.login.sample and look in login_templates.default
for new templates to install.
To support application servers, other system administrators
will need to know the location of your login server, keyserver, and
how trust is handled on your keyserver. That is, which CAs the
keyserver trusts to verify keyclient certificates; and which CA
can be used by the keyclient to verify your keyserver certificate.
The default filename for the login cgi, index.cgi, is a common
name for a cgi program that is executed when a directory's URL is requested.
directive defines how Apache handles such requests, typically
choosing the first file it finds in its DirectoryIndex list. With
appropriate configuration, this can be your login cgi.
For example, you might use the follow DirectoryIndex directive:
DirectoryIndex index.cgi index.html
Apache also needs to know how to identify cgi scripts by the .cgi
filename extension. Some distributions of Apache have the cgi handler
disabled. Make sure the following line is in your httpd.conf and not
AddHandler cgi-script .cgi
Finally, Apache must allow execution of cgi scripts in the directory
where the login cgi is located. If it's outside of a
directory, you can control this with the
Options Indexes FollowSymLinks ExecCGI
Due to the important nature of the Pubcookie login server, the only
other services that should be run on the same system are those which
receive an equally high level of scrutiny for security.
Some of the login cgi's supporting files are sensitive, particularly
the two private keys, ssl_key_file and granting_key_file.
In a production environment, non-root users shouldn't be able to read
However, in a typical Apache configuration the login cgi runs within
a restricted user context defined by the User
server directives. They are usually set to some non-privileged user and
group (e.g. nobody.nobody).
One approach to permissions is simply to make the sensitive files
owned and readable by the non-privileged Apache user (nobody.nobody
and octal 600, 700 for the keys directory).
drwx------ nobody nobody 4096 keys/
-rw------- nobody nobody 4096 keys/pubcookie_granting.key
-rw------- nobody nobody 4096 keys/pubcookie_session.key
Another approach is to run Apache as a non-privileged user but use a
group that no users are allowed to be in (e.g. nobody.www where
no users are in the www group). Then sensitive files can be
restricted to just root and to the empty group (root.www and
octal 640, 750 for the keys directory). Since the login
cgi runs in the context of the group, it can read the files it needs
drwxr-x--- root www 4096 keys/
-rw-r----- root www 4096 keys/pubcookie_granting.key
-rw-r----- root www 4096 keys/pubcookie_session.key
Note: since the keyserver is run by inetd or xinetd, it is most likely
run as root and therefore can read and write supporting files as needed.
To generate a new RSA private key and self-signed public key certificate,
(for example, for the "granting" key pair), change to the PREFIX/keys
directory and use the following OpenSSL command as an example:
$ cd /usr/local/pubcookie/keys
$ openssl req -new -x509 -out pubcookie_granting.cert \
-newkey rsa:1024 -nodes -keyout pubcookie_granting.key
To remove the pass phrase on an SSL private key:
$ openssl rsa -in server.key -out unencrypted.key
The man pages for x509, rsa, and req
have many other useful OpenSSL command examples.