|
Included on this page:
The Pubcookie login server has two primary functions: to authenticate
users and to issue authentication tokens (granting cookies) consumed by
Pubcookie-enabled target application servers. Authentication occurs
either by verifying user-provided credentials via a backend authentication
service (Kerberos, LDAP, etc.) or by checking a token that was created
on a previous visit to the login server. Example code to interface to an
authentication system is provided.
The Pubcookie login server consists of two primary components: a CGI
program and a keyserver.
The Pubcookie login server uses the CGI program to handle all HTTP
requests. This CGI program, hereafter referred to as "the login cgi"
or index.cgi, is compiled from C and is the central Pubcookie
component. The login cgi displays the web page where users are asked
to enter authentication credentials as well as other web pages that
display error messages.
The Pubcookie login server uses the keyserver to generate, distribute,
and manage DES keys for application servers.
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. As deployed at the
University of Washington, the Pubcookie login server is powered by the
Apache web server software. Other web server software which supports CGI
and SSL should also work, but this supposition has not been tested.
The login cgi is designed to support different authentication feature
sets by abstracting them into login "flavors". However, only one login
flavor is currently provided: the "basic" login flavor. The basic login
flavor supports username/password single-sign-on authentication and a
simple pluggable interface to backend authentication services called
"verifiers." Pubcookie currently ships with several verifiers for the
basic login flavor:
- "kerberos_v5": check username/password against a Kerberos 5 KDC.
- "ldap": check username/password against an LDAP server.
- "shadow": check username/password against /etc/shadow.
- "alwaystrue": allow any username/password combination to authenticate.
You can choose which verifiers to build at compile time and then decide at run-time
which verifier is used by the basic login flavor by setting the "basic_verifier"
configuration variable (see run-time configuration). Some
verifiers allow or require further configuration; see the section referring to each
verifier for details.
Choosing the location of your login page
Depending on your deployment environment, you may choose to install the
login server in a number of configurations. Two general models are
presented here, along with the necessary Apache configuration directives
for each.
Specifying the login server URL as a directory
For a clean looking URL for your login server, you can install the login cgi
as the default file in a directory. For example, the University of Washington
uses the server's root directory, resulting in https://weblogin.washington.edu/
as the login server URL. This address is easy for users to identify in a browser's
address field.
The default binary filename for the login cgi, index.cgi, is a common
name for a cgi program that will be executed when a directory's URL is requested.
The DirectoryIndex
directive tells Apache how to handle requests to directories. See the mod_dir documentation
for more information on its use. When a request is
made for a directory, Apache will choose the first file it finds in the
DirectoryIndex list. This can be your login cgi.
For example, you might use the follow DirectoryIndex directive:
DirectoryIndex index.html index.cgi
If this is the configuration you choose, make sure there isn't an
index.html file in the same directory as the index.cgi binary.
Explicit specification of login cgi
The login cgi does not depend on its own filename. Therefore, it can be
deployed as index.cgi, login.cgi, or any other filename handled as a
cgi script. It can also be put in any subdirectory you wish. Thus,
it really depends on what you want users to see and how you want to
configure things in Apache.
To avoid conflict or confusion with the server's main page, you might
deploy a login server at https://www.example.edu/cgi-bin/login.cgi
or maybe https://www.example.edu/login where /login is
mapped to the login cgi (index.cgi or whatever you rename it to).
Note: in order to configure applications servers, other system administrators
will need to know the URL of your login server.
Apache configuration directive you might have to tweak
Apache needs to know how to identify and handle cgi scripts. Some
distributions of Apache will have the cgi handler disabled, you will
want to make sure the following line is in your httpd.conf and not
commented out.
AddHandler cgi-script .cgi
Compiling the source code has been made easier with autoconf. (Thanks Jon Miner,
University of Wisconsin!)
To build a barebones login server, run:
$ ./configure --enable-login --disable-apache
$ make
This will build the login cgi and its "alwaystrue" verifier, as well
as the keyserver and keyclient binaries. It also prepares for
installation using the default installation directory prefix, henceforth
called {PUBCOOKIE_DIR}, of /usr/local/pubcookie.
To build other verifiers (e.g. "kerberos_v5", "ldap", or "shadow")
along with the other base components, look at the configure options and
re-run the configure script accordingly:
$ ./configure --help
To install the login server components into the installation directory,
run:
$ make install
Now you can view the results by listing the contents of
{PUBCOOKIE_DIR}.
$ ls /usr/local/pubcookie
keyclient keys keyserver login login_templates login_templates.default
The login cgi and keyserver share a simple configuration file:
the Pubcookie config file. Most run-time configuration
can be set up via this file, which is located at
{PUBCOOKIE_DIR}/config. The format is one attribute-value
pair per line.
A sample config file appropriate for
a login server is provided as a starting point. You might consider
copying it to {PUBCOOKIE_DIR}/config and edit it there, e.g.:
$ cp doc/config.login.sample /usr/local/pubcookie/config
Refer to the config
documentation to setup your configuration file. Some of the more notable
variables are:
- debug
- An integer. A non-zero value enables debug logging. The higher
the number, the more debugging output that is generated.
- login_host
- The hostname of login server (e.g. weblogin.example.edu)
- login_uri
- The complete URI of the login cgi (e.g. https://weblogin.example.edu)
- enterprise_domain
- The domain under which all hosts will live. Must be at least a
second level domain (e.g. example.edu).
- basic_verifier
- The verifier to use for the "basic" login flavor.
- keymgt_uri
- The location of the "keyserver" CGI. See the Key
Management section.
The following configuration variables are crucial, as they determine
the keypair used to sign and verify "login" cookies and more importantly
to authenticate your keyserver's identity. In most cases, they should
refer to the same files that your web server uses for SSL.
- ssl_key_file
- The location of the SSL key.
- ssl_cert_file
- The location of the SSL certificate.
The following configuration variables define which Certificate
Authority (CA) is trusted by your keyserver.
If your institution uses a single CA without any intermediate
certificates, set ssl_ca_file to the full path to the CA's
root certificate. If your institution uses multiple CAs or intermediate
certificates, you'll need a directory (ssl_ca_path) containing
those certificates named via their OpenSSL hashes. At least one of
ssl_ca_file and ssl_ca_path must be specified.
- ssl_ca_file
- The location of a single CA.
- ssl_ca_path
- A directory containing files named after their OpenSSL hash.
Again, see config.html for a full list of
configuration variables and their descriptions.
{PUBCOOKIE_DIR}/keys is the location of the keystore used by
the login cgi. The login cgi makes use of several different keys.
Reuse SSL keypairs for the "login" cookie and keyserver
The login cgi uses a keypair to sign and verify the "login" cookie
that maintains a user's single sign-on session with the login server.
These files are kept exclusively on the login server and are also
used by the keyserver. We recommend that you reuse your existing private
key and SSL server certificate, rather than generating a new keypair.
The login cgi will automatically do so if you set ssl_cert_file
and ssl_key_file correctly. If this works for your keyserver, it
is probably the optimal solution.
Generate granting keypair for authentication assertions
Next, a "granting" keypair is needed to secure authentication
assertions sent from login server to application servers, as represented
by a "granting" cookie. The key is kept exclusively on the login
server; the certificate must be distributed to every application server.
We've historically recommend that you generate a new keypair for this
purpose, although you could reuse you SSL keypair here too.
$ openssl req -new -x509 -nodes \
-out /usr/local/pubcookie/keys/pubcookie_granting.cert \
-newkey rsa:1024 -keyout /usr/local/pubcookie/keys/pubcookie_granting.key
If you want to place these files in a different location (than
{PUBCOOKIE_DIR}/keys/pubcookie_granting.{key,cert}), you'll
need to set the granting_cert_file and
granting_key_file variables in your config file.
The keyserver binary you build earlier is a program that generates
and maintains DES keys for participating servers to use to encrypt cookie
contents. Unfortunately, due to subtleties in the key usage constraints,
keyserver is unable to run as a cgi script underneath a login server. Instead,
we recommend that keyserver be run from inetd.
Add a line like the following to the login server's
/etc/inetd.conf:
2222 stream tcp nowait root /usr/local/pubcookie/keyserver keyserver
where /usr/local/pubcookie/keyserver is where the keyserver binary
is installed. Make sure that your pubcookie/config file is
correctly configured.
If you are using xinetd, you should create a file named keyserver in
/etc/xinetd.d with the following contents:
# description: pubcookie keyserver
service 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 this line to inetd.conf (or file to xinetd), restart inetd
(or xinetd).
Generate a DES key for the login server with keyclient
Now run keyclient to generate a DES key for the login server:
% /usr/local/pubcookie/keyclient
This will cause the keyserver program to generate a new DES key for
the login server to use to provide confidentiality for the login
cookies.
Generating DES keys for the application servers with keyclient
When the time comes, generating DES keys for application servers is
very similar. You configure the keyclient on the application server
ahead of time, making sure the keyclient's certicate (probably the
server's SSL certificate) is signed by the same CA trusted by your
keyserer's CA configuration. Refer to the application server documentation
for specifics.
Once your run-time config file is set up and you've succeeded in using
keyclient to generate a DES key for your login server, you can deploy the
login cgi by copying it into your production directory from which Apache
will serve requests. (See Apache Configuration
above for some discussion of this topic.) For example:
% cp index.cgi /var/www/html
You don't need to set up an application server to test the login cgi;
simply open your login URL in a browser and it should ask you to log in
using whichever verifier you've configured. This direct approach to
your login cgi is known as a "pinit" or "Pubcookie init" since it
establishes a single sign-on session without authenticating you to
any applications.
The login cgi serves up pages based on a set of HTML templates.
By default, these templates reside in {PUBCOOKIE_DIR}/login_templates,
but the location can be set by changing template_root in your config
file. Generic templates are installed by default in
{PUBCOOKIE_DIR}/login_templates.default. They should be
copied to {PUBCOOKIE_DIR}/login_templates and they will
serve as a starting point for further localization.
Note: For reference and comparison purposes, copies of CMU and
Washington's login templates (of some vintage) are provided in this
source distribution. See src/login_templates.cmu and
src/login_templates.uw, respectively. Note: the syntax
for variable substitution within the templates changed during the
development of version 3.0.0. The UWash and CMU templates may be in
the older format.
The name of each template file can be set via the
{PUBCOOKIE_DIR}/config file. The name for each config
variable is tmpl_{default_file_name}, and they are located relative to the
template_root. (For example, the attribute that controls the
name of the login page is tmpl_login.)
Template Files (incomplete)
We are in the process of reworking the template files to make them
more user-friendly. The list below will be updated as work progresses.
- login
- The Login HTML page.
Paramters
- Login Server URL
- The reason for the redirect (pulled from the login_*
snippets)
- Hidden fields maintaining state
- GetCred Hidden fields
- login_bad_auth
- The error displayed when the authentication failed.
- login_cache_creds_wrong
- The error displayed when the single-signon credential is not the type
that the application is requesting. (Rarely seen.)
- login_nolcookie
- The error displayed when the user doesn't have or has an invalid login
cookie
- login_reauth
- The error displayed when the application has requested that the user
reauthenticate.
- status
- The status page displaying the time remaining on the login.
Parameters
- Refresh header
- User name
- Time remaining.
The {PUBCOOKIE_DIR}/ok_browsers file contains a list of acceptable
browsers. The idea behind ok_browsers is 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
really use the 'ok_browsers' functionality to block browsers that we know
don't work. Our ok_browsers file has a single line: "Mozilla". This
pattern matches most of the browsers we support and/or encounter; mainly
MS Internet Explorer, Netscape, and Mozilla. Proceed according to your own
policy.
The login cgi automatically handles logout requests from applications.
This functionality is built in; no configuration is necessary on the login
server. Through additional configuration you can create a separate logout
URL on your login server and also tailor some of the logout text for your
favoriate applications.
Note: Pubcookie 3.0 does not support "global" logout: logout of all
applications, all cookies, all at once. Rather, it supports per-application
logout, plus the ability to logout of the login server, all separately.
Therefore, users must still be educated and warned to exit their browser
in order to get logged out of everything at once.
Configuring a Logout URI
If you want to provide a URL where users can go directly to clear their
single sign-on session (pubcookie 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 web server's root directory
(e.g. https://weblogin.example.edu) and you want to create a logout URI of "/logout/"
just below that (e.g. https://weblogin.example.edu/logout/). First, you would want
to create the subdirectory and symbolic link to your login cgi:
$ cd /var/www/html
$ ls
index.cgi images/
$ mkdir logout
$ cd logout
$ ln -s ../index.cgi index.cgi
Now any request to /logout/ on the server will map to your login cgi.
(editor: Is there a better way to do this in httpd.conf instead?) All that's left
is adding the appropriate logout_prog variable to your Pubcookie config file:
logout_prog: /logout/index.cgi
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
app_logout_string-appserver.example.edu-testapp: <font size="+1">Testapp logout worked just fine.</font>
app_logout_string-webmail.example.edu-webmail: <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 text.
Upgrading from pre-3.0 pubcookie
- Maintaining DES key compatibility from hashed IP addresses
If you have an exisiting pubcookie installation using a shared DES key
with hashed IP addresses, you can upgrade your login server without
generating new keys on every application server.
On the login server, in the .../pubcookie/keys/ directory, make a copy of
the master DES key (before hashing it to any IP address) for each application
server, named with the full hostname of the server.
For example, create .../pubcookie/keys/oldappserver.example.edu
containing the original DES keyfile.
The login server will use this key to encrypt data going to that application
server, and the application server can continue to use it's key (XOR'd with
it's IP address) to decrypt the data.
During the application server's next scheduled downtime, you can
create a new unique DES key for that application, as in the Key Management & Setup section above.
Redundant login servers
Redundant application hosts
Sites frequently want several hosts configured identically to provide
redundancy (either for performance or stability). In this section,
we're assuming that you have a set of machines with an identical SSL
certificate and key on them.
For instance, an institution might have 15 webmail servers named
webmail1.example.edu through webmail15.example.edu
with 15 unique IP addresses. All of them are equipped with a
webmail.example.edu certificate and are behind a Cisco Load
Director which controls the IP address for
webmail.example.edu.
Use keyclient on webmail1.example.edu to generate
a webmail.example.edu DES key. Use keyclient -d on
all other webmail machines (webmail2.example.edu, etc.) to
download an identical application key to the remaining servers.
Login server security
Don't run anything else on it: anyone who can add content
to the login server can steal all cookies.
Application server security
Handling secrets
Other stuff
pbc_create creates a pubcookie cookie, convenient for
creating cookies ad hoc. Arguments come in via stdin and the cookie
is put out on stdout. Args are space delimited, and in order: user
appsrvid appid type creds serial crypt_file cert_key_file. Anything
too big is just truncated, no support for defaults or anything like
that. See src for details.
pbc_verify decrypts/verifies/displays pubcookie cookies,
convenient for 'unbundling' a cookie and seeing what's inside. The
arguments come in on the command line, the cookie comes in on stdid,
and the contents are dumped to stdout. The required argument is
cookie_type and the optional arguments are encryption_key and
cert_file.
As an example you can use these two programs to do things like:
# echo "willey appsrvid appid 1 2 23 \
/usr/local/pubcookie/c_key /usr/local/pubcookie/test.key" | \
./pbc_create | \
./pbc_verify 1 /usr/local/pubcookie/c_key /usr/local/pubcookie/test.cert
and get something like
user: willey
version: a5
type: 1
creds: 2
serial: 23
appsrvid: appsrvid
appid: appid
create_ts: 1006986719
last_ts: 1006986719
|