About
-----

This package consists of two simple C functions, getpgnam() and getpguid(),
that are intended to be drop-in replacements for getpwnam() and getpwuid().
Many unix applications use these functions to authenticate users against the
system password file or a shadow of it. By replacing these functions, the
application can be made to authenticate against records in a PostgreSQL
database, effectively giving the application "virtual user" support.

The general idea is to replace all occurrences of getpwnam() with getpgnam(),
and all occurrences of getpwuid() with getpguid() in the application's source
code. The PostgreSQL enabled versions accept and return parameters in the same
format. The application must then be recompiled and linked with the PostgreSQL
libpq library. This is typically done by adding "-lpq" to the appropriate rule
in the application's Makefile. Additional instructions such as
"-I/usr/local/pgsql/include" and "-L/usr/local/pgsql/lib" will probably also
have to be added.

The names of the database, database user, table, and fields are configurable in
the getpg.h file. Edit it before compiling your application to set your
preferences.


Database Fields
---------------

The PostgreSQL table that contains the authentication information must contain
at least the following fields for each virtual user. These _fields_ must exist
in the database because the query specifically looks for them, but the _values_
in the fields may be blank. It depends on your application.

userid
  This field contains the login id for the user. It can't be blank. Well, ok,
sure it _can_ be, but what would be the point? I suppose it might be a way to
implement an anonymous login to a service that wouldn't normally provide it.

password
  This field contains the user's password. It probably shouldn't be blank,
either, but hey, it's your database. Whether or not it should be stored
encrypted depends on what the application is expecting.

uid
gid
  These fields contain the system user and group numbers associated with a
user. This may not make much sense for a virtual user, but depending on your
application, it may be required to indicate permissions for files that the
virtual user owns. It might be wise to create a new user and a new group called
"virtual", then assign their unique uid/gid numbers to each of the uid/gid
fields for all user records. This will allow one system account to own all
files for all virtual users.

name
  This field contains the full name of the user. It is (typically) optional.

home
  This field contains the home directory for the user. Some applications
require this to be a valid system directory.

shell
  This field contains the name of the system shell program to use for the user.
Unless you're making a virtual version of /bin/login or /bin/su, you probably
don't need it.

domain
  The getpgnam() function has an additional feature for domain based virtual
hosts. If the userid passed to it contains an at sign '@', it will be split
into its user and domain components. This field stores the domain part, not
including the at sign.


Optional Fields
---------------

The getpg functions also support a few optional database fields. That is, the
fields themselves may or may not exist in the database. Each optional field
has an associated USE_FIELD define in getpg.h to indicate whether or not it
should be used.

enabled
  This is a boolean field that indicates whether or not a particular record
is considered active. It is a simple way to "turn off" an account without
having to delete the record. 

start
  This is a timestamp that indicates when a record becomes active. If the
value is blank or in the past, the record is active.

stop
  This is a timestamp that indicates when a record expires. If the value is
blank or in the future, the record is active.

last
  This is a timestamp that indicates the last time a user authenticated.

Note that these fields do not necessarily have to be named as shown here; the
field names are configurable in getpg.h. Also, additional fields may be present
in the table.


Domain Based Authentication
---------------------------

If the userid passed to getpgnam() contains an at sign '@', it will be split
into its userid and domain components. The userid will be matched against the
userid field, and the domain will be matched against the domain field. Do not
put strings like "joe@thing.com" in the userid field! Instead, put "joe" in the
userid field, and "thing.com" in the domain field. For example:

A call to getpgnam("joe") would generate an SQL query similar to:
  select * from users where userid = 'joe'

A call to getpgnam("joe@thing.com") would generate an SQL query similar to:
  select * from users where userid = 'joe' and domain = 'thing.com'

The reason for splitting the userid and the domain into two different fields is
because it allows other applications to perform fast (i.e., indexed) queries on
all users that belong to a certain domain. For example, the users table could
be utilized by an Apache authentication module, which might be configured to
"require group thing.com". If the userid and domain were stored in one database
field as "joe@thing.com", the database engine would have to read every record
in the database and perform a regular expression match on it. Compared to a
direct indexed lookup, this would be extremely slow.


Sample Database Configuration
-----------------------------

create table users (
  userid text,
  password text,
  uid int,
  gid int,
  name text,
  home text,
  shell text,
  domain text,
  enabled bool,
  start timestamp,
  stop timestamp,
  last timestamp
);

create index users_userid on users ( userid );
create index users_domain on users ( domain );
