PERDITIONDB(5)

NAME
perditiondb - perdition modular popmap support

DESCRIPTION
Perdition supports a dynamic library mechanism to access arbitrary databases that resolve a user to a host and port.

DATABASE ACCESS LIBRARIES

If you are using the -s|--default server option then creating an empty database will cause all users to use the default server. Alternatively, setting no popmap by passing an empty string to the -m|--map_name option will cause no map lookups to take place and only the default server to be used.

E.g.: perdition -m ""

In this case, if no default server is set then perdition will still run but users will not be able to connect to a real server.

GDBM

This is the default library used by perdition. The gdbm library reads server and port information from a GDBM database. The database is opened each time perdition looks up a server and port pair. The information for each lookup key is stored in a flat file, popmap with the format:

<key>:[<username><domain_delimiter>]<host>[:<port>]

Where:
    host: hostname or ip address
    port: port name or number

E.g.

horms:foo.bar:110
jain:jane@foo.bar

A domain_delimiter of "@" is used in the example above. For more information on keys and the domain delimiter, see perdition(8).

If the -n|--no_lookup option is in effect, then ip addresses and port names should be used as host and port names will not be resolved.

To build the flat file into a binary format the makegdbm utility, which is provided as part of perdition should be used.

makegdbm popmap.gdbm.db < popmap

A makefile is provided and you can simply run make to rebuild the popmap. This is installed into /etc/perdition/ in the RPM and Debian distributions.

An alternate location for the popmap.gdbm.db can be specified using the -m|--map_library_opt command line option or configuration file option.

E.g.

perdition -m /etc/my_popmap.gdbm.db

This map library is the default. It may also be used explicitly, used by specifying the full path to the library using the -M|--map_library command line option or configuration file option.

E.g.

perdition -M /usr/lib/libperditiondb_gdbm.so.0

Where /usr/lib is the directory in which the perdition libraries were installed.

Berkeley DB

This is analogous to the GDBM library, except that a popmap.bdb.db should be created using makebdb.

This library may be used by specifying the full path to the library using the -M|--map_library command line option or configuration file option.

E.g.

perdition -M /usr/lib/libperditiondb_bdb.so.0

Where /usr/lib is the directory in which the perdition libraries were installed.

YP/NIS

The NIS library reads a YP/NIS map, the key is the userid, the value is the servername.

The default map name is 'user_mail_server', and can be changed by specifying the map name with the -m flag.

To use this library, you need to specify:

perdition -M /usr/lib/libperditiondb_nis.so.0

Where /usr/lib is the directory in which the perdition libraries were installed. You will need to customise your yp server's Makefile to actually get a new map on the server. This map library is intended for sites that already have a significant infrastructure based around YP/NIS.

POSIX REGULAR EXPRESSIONS

This library allows users to be looked matched against a list of regular expressions.

This library can be used by specifying the full path to the library using the -M|--map_library command line option or configuration file option.

E.g.

perdition -M /usr/lib/libperditiondb_posix_regex.so.0

Where /usr/lib is the directory in which the perdition libraries were installed.

The regular expression is kept in a flat file, by default /etc/perdition/popmap.re . A sample map file is shipped with the source and can be found in etc/perdition/popmap.re, this is installed into /etc/perdition/popmap.re in the RPM and Debian distributions. The format for the flat file is:

<regular expression>: [<username><domain_delimiter>]<server>[:<port>]

A single colon may follow a regular_expression Some amount of white space must follow this colon or the regular_expression if the colon is omitted. Blank lines are ignored, as is anything including and after a # (hash) on a line. If a precedes a new line then the lines will be concatenated. If a precedes any other character, including a # (hash) it will be treated as a literal. Anything inside single quotes (') will be treated as a literal. Anything other than a (') inside double quotes (") will be treated as a literal. Whitespace in a regular_expression must be escaped or quoted. Whitespace in a substitution need not be escaped or quoted.

Information on setting the domain_delimiter is found in perdition(8), "@" is used in this example.

E.g.

^[a-k]: localhost
^[^a-k]: localhost:110
^user: user2@localhost
(.*)@(.*): $1_$2@localhost

The first matching regular expression will be used. The regular expressions are extended posix regular expressions. The last example illustrates the ability to expand backreferances. Backreferences may be used by inserting $n in the substitution where n is in the range 1..9. The backreference substitution code in this library is courtesy of Wim Bonis and in turn the PHP3 project.

E.g.

For the regex (.*)@(.*): $1_$2@localhost
user@x.y.z.de
would return
user_x.y.z.de@localhost

Note that there is no implicit ^ or $ around the regular expressions. The popmap entry "flim: localhost" will match "flim", "flimstix", "itsflim" and "totallyflimless". To only match "flim" you need the popmap entry "^flim$: localhost".

The map file is read once on startup and cached. This is to increase performance as the regular expressions must be compiled internally before they can be used. The map file can be re read by sending perdition a SIGHUP. An alternate location for the popmap.re can be specified using the -m|--map_library_opt command line option or configuration file option.

E.g.

perdition -m /etc/perdition/my_popmap.re

MYSQL

This map library can be used by specifying the full path to the library using the -M|--map_library command line option or configuration file option.

E.g.

perdition -M /usr/lib/libperditiondb_mysql.so.0

Where /usr/lib is the directory in which the perdition libraries were installed.

The library will connect to a MySQL database and do a query on a table expected to have the columns:

+------------+--------------+------+-----+---------+-------+
| Field      | Type         | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| user       | varchar(128) |      | PRI |         |       |
| servername | varchar(255) |      |     |         |       |
| port       | varchar(8)   | YES  |     | NULL    |       |
+------------+--------------+------+-----+---------+-------+

The fields may be in a different order and other, non-perdition fields may also be present in this table. The names of the columns can be other than their above defaults by using the library option string described below. All fields must be literal character strings. The allowed length of the strings is not important, however, it is recommended that the length of the user field be kept under 128 to avoid exceeding perdition's internal query length limit, PERDITIONDB_MYSQL_QUERY_LENGTH which is 256 by default. This may be altered by recompiling perdition. The user field must also be a unique index as an exact match will be made of this field from the username supplied by the user.

The servername is of the form.

[<username><domain_delimiter>]<host>[:<port>]

Where:
    host: hostname or ip address
    port: port name or number

If the -n|--no_lookup option is in effect then ip addresses and port numbers should be used as host and port names will not be resolved.

The port is the TCP port to use when connecting to the server. This field can be specified if the back-end server answers on a non-standard port (standard ports being 110 for POP3 and 143 for IMAP). Only specify this field in the database if you intend to use POP3 or IMAP exclusively as it will try to use this port no matter what protocol is being used. If POP3 and IMAP are both being used on non-standard back-end server ports, those ports can be specified with the -p argument when you invoke the perdition executable.

The database is accessed each time perdition needs to find the host and port for a user. The default database values are as follows:

database host: localhost
database port: (MySQL Client Default: usually 3306)
database name: dbPerdition
database table: tblPerdition
database user: perdition
database password: perdition
user column: user
server column: servername
port column: port

A script, perditiondb_mysql_makedb, is provided to initialise such a database. Alternate values can be set using the -m|--map_library_opt command line option or configuration file option with an argument of the following form. (N.B.: this example has been split over multiple lines for ease of reading)

<dbhost>[:<dbport>[:<dbname>[:<dbtable>[:<dbuser>
[:<dbpwd>[:<dbservercol>[:<dbusercol>[:<dbportcol>]]]]]]]]

E.g.

perdition -m "some.host.com:3306:aDb:bTable:cUser:"\
"dPassword:eSrvCol:fUserCol:gPortCol"

Arguments may be omitted from the end of the option string with no consequence other than that the default value for any omitted argument will be used. Arguments may not be omitted if any argument to its right is defined. Someone seeking to set only the server and password to something other than the default might attempt the following:

perdition -m some.host.com:::::OddPassword

This will not work. It will set the server and password to the values shown, but all arguments in between will be set as NULL rather than the default. In the author's opinion it is always best to specify all of the arguments to avoid confusion.

Database servers may be grouped together for higher performance or high availability by using ODBC and accessing them using the ODBC module.

Multiple MySQL Servers

It is possible to specify multiple MySQL servers by specifying them, comma separated (without any space), in the dbhost column. In this case all MySQL servers need to have an identical configuration, because all other options are shared. If the first server is not reachable, perdition will fall back to the second etc.

POSTGRESQL

This is a port of the MySQL library to PostgreSQL, The library can be used by specifying the full path to the library using the -M|--map_library command line option or configuration file option.

E.g.

perdition -M /usr/lib/libperditiondb_postgresql.so.0

Where /usr/lib is the directory in which the perdition libraries were installed. A script, perditiondb_postgresql_makedb is provided to initialise the database. For more information please see the MySQL documentation above.

ODBC

This is a port of the MySQL library to ODBC. It may be used to access databases that do not have a perditiondb module. It may also be used to group database servers into clusters.

The library can be used by specifying the full path to the library using the -M|--map_library command line option or configuration file option.

E.g.

perdition -M /usr/lib/libperditiondb_odbc.so.0

Where /usr/lib is the directory in which the perdition libraries were installed. A script, perditiondb_odbc_makedb is provided to seed the. For more information please see the MySQL documentation above. The database options passed using -m are the same as for MySQL except that the database name (dbname) is the Data Source Name (DSN).

<dbhost>[:<dbport>[:<DSN>[:<dbtable>[:<dbuser>
[:<dbpwd>[:<dbsrvcol>[:<dbusercol>[:<dbportcol>]]]]]]]]

E.g.

perdition -m "some.host.com:3306:aDb:bTable:cUser:"\
"dPassword:eSrvCol:fUserCol:gPortCol"

As per the notes in the MySQL documentation above, please avoid omitting values.

LDAP

This library allows access to LDAP based popmaps. This library can be used by specifying the full path to the library using the -M|--map_library command line option or configuration file option.

E.g.

perdition -M /usr/lib/libperditiondb_ldap.so.0

Where /usr/lib is the directory in which the perdition libraries were installed.

Options are parsed to this module using the -m|--map_library_opt command line option or configuration file option. It has the form:

[ldap_version:][ldap_url]

The ldap_version is the version of the ldap procotol used. It should be a numeric value. At the time of writing, OpenLdap supports 2 or 3, and defaults to 2. This may vary between different ldap implementations. If you inspect the local ldap.h file, the values of LDAP_VERSION_MIN, LDAP_VERSION_MAX and LDAP_VERSION should reflect the minimum, maximum and default ldap protocol versions respectively.

The ldap_url is the query made to the ldap server. The default URL is as follows. Note that this has been split onto multiple lines for ease of reading.

ldap://localhost/ou=mailbox,dc=nodomain?
username,mailhost,port?one?(uid=%s)

Perdition will replace any instance of %s with the key being used for the lookup. Optionally, there may be an integer between the % and the s, in which case the key will be white-space padded to this width, with the key right justified.

The attribute names (username, mailhost and port) may be changed. But the first attribute will be used as the username, the second attribute as the host and the third atribute as the port. Any subsequent attributes will be ignored. Trailing attributes may also be omitted. So if there are only two attributes the port will not be read from the database.

A script, perditiondb_ldap_makedb is provided to initialise LDAP.

x-bindpw bindname

Perdition can be configured to use use an alternate bind name, and the non-standard "x-bindpw". In fact perdition can use any extensions that are supported by openldap. (N.B.: these examples have been split over multiple lines for ease or reading)

ldap://ldap.mydomain.com/o=domain.com?
uid,mailhost,port?sub?(uid=%s)?!bindname=uid=perdition%2co=domain.com

ldap://ldap.mydomain.com/o=domain.com?uid,mailhost,port?
sub?(uid=%s)?!BINDNAME=uid=perdition%2co=domain.com,X-BINDPW=secret

The first example does the usual LDAP lookup, but tries to bind to the server with "uid=perdition,o=domain.com" rather than the usual anonymous binding. Note: The commas inside the bind string itself must be URL encoded, thus the %2c.

The second example is the same as the first, but in addition to specifying a bind string it also uses the non-standard "x-bindpw" extension to specify a password, in this case "secret".

The "!" character is used to ensure Perdition supports the "bindname" extension. If it didn't, the LDAP connection would be aborted. Right now it isn't really needed, but it may become useful as other extensions appear. For full details of this, take a look at RFC2255.

Multiple LDAP Servers

It is possible to specify multiple LDAP servers by specifying them, space delimited, in the LDAP UDL. If this is the case an attempt will be made to open a connection to each host in order, the first host to which a connection is successfully made will be used.

For example: (N.B.: this example has been split over multiple lines for ease or reading)

ldap://host1 host2 host3/ou=mailbox,dc=nodomain?
username,mailhost,port?one?(uid=%s)

perdition.schema

A schema has been defined for perdition and is supplied as part of perdition. To use this you should install it on the LDAP server in the LDAP daemon's schema directory and include it in slapd.conf, after other includes and before any database definitions.

LIBRARY FUNCTIONS
The database is accessed using the dlopen(3) mechanism on a library. The library should define the symbol dbserver_get with the following semantics.

int (*dbserver_get)(char *, char *, char **, size_t *)

Find the server (value) given the user (key)

pre:
    key_str: Key as a null terminated string

    options_str: Options string. The usage of this is implementation dependent.

    str_return: Value is returned here

    len_return: Length of value is returned here

post:
    The str_key is looked up and the corresponding value is returned in str_return and len_return.

return:
    0 on success

    -1 on db access error This includes file, connection and other data access errors. It does not cover memory allocation problems.

    -2 if key cannot be found in map

    -3 on other error

Note:
    The string returned in str_return should be in the following form. Setting the domain_delimiter is discussed in the perdition(8), "@" is used in this example.

    [<username><domain_delimiter>]<servername>[:<port>]

    E.g.:

    localhost:110
    user@localhost:110
    user@localhost
    localhost

As the library is opened using the dlopen(3) mechanism the library may also export functions _init and _fini that will be executed when the library is opened and closed respectively. In addition if the symbols following symbols are defined then these are run when the library is opened and closed respectively. If defined these symbols should have the following semantics.

int *(*dbserver_init)(char *)

Initialise db as necessary

pre:
    options_str: Options string. The usage of this is implementation dependent.

post:
    db is initialised

return:
    0 on success

    -1 on db access error This includes file, connection and other data access errors. It does not cover memory allocation problems.

    -2 if key cannot be found in map

    -3 on other error

int *(*dbserver_fini)(void)

Shut down db as necessary

pre:
    none

post:
    db is shut down

return:
    0 on success

    -1 on db access error This includes file, connection and other data access errors. It does not cover memory allocation problems.

    -2 if key cannot be found in map

    -3 on other error

In addition, if a SIGHUP is sent to a process then a signal handler will call dbserver_fini if it is defined and then dbserver_init if it is defined. Note: dbserver_init will be called if defined, even if dbserver_fini is not defined.

In the case of the posix regular expressions library this will cause popmap.re to be re-parsed, hence effecting any changes that have been made to that file. For the GDBM library it will reopen the database and for the other libraries it will reinitialise its connection to the database, LDAP or NIS server.

The shared library has access to the following global symbols exported by perdition.

struct utsname *system_uname
    The uname information for the system as per uname(2)

struct sockaddr_in *peername
    The sockaddr_in for address and port of the client end of the connection.

struct sockaddr_in *sockname
    The sockaddr_in for the local address and port that the client connected to. Note: Under Solaris 7 and above, this is actually the sockaddr_in bound to, not the address and port the connection was accepted on.

SEE ALSO
perdition(8), makegdbm(1), makebdb(1), make(1), perditiondb_mysql_makedb(8), perditiondb_postgresql_makedb(8) perditiondb_ldap_makedb(8), perditiondb_odbc_makedb(8)

AUTHORS
Lead
Horms <horms@vergenet.net>

Perditiondb Library Authors
Frederic Delchambre <dedel@freegates.be> (MySQL)
Chris Stratford: <chriss@uk.uu.net> (LDAP and BDB)
Nathan Neulinger <nneul@umr.edu> (NIS)

Contributing Authors
Daniel Roesen <droesen@entire-systems.com>
Clinton Work <work@scripty.com>
Youri <ya@linkline.be>
Jeremy Nelson <jnelson@optusnet.com.au>
Wim Bonis <bonis@solution-service.de>
Arvid Requate <arvid@Team.OWL-Online.DE>
Mikolaj J. Habryn <dichro@rcpt.to>
Ronny Cook <ronny@asiaonline.net>
Geoff Mitchell <g.mitchell@videonetworks.com>
Willi Langenberger <wlang@wu-wien.ac.at>
Matt Prigge <mprigge@pobox.com>
Wolfgang Breyha <wolfgang.breyha@uta.at>