Vitalnix : User Management Suite
  manual v1.90.8.3

Name

libaccdb - The Unified Account Database

libaccdb API

libaccdb provides some essential functions for applications wishing to access a user database. It also contains some common used code, such as password generation routines. Applications that wish to use ACCDB must link against it, usually with gcc's -laccdb parameter.

#include <accdb.h>

struct accdb_module *accdb_load(char *module);
void accdb_unload(struct accdb_module *mp);

accdb_load() opens a back-end module (module.so and/or module.dll), acquires all necessary symbols and returns them in a malloc()ed struct accdb_module, which is then to be freed with accdb_unload(). In most cases, module will be just be an asterisk, which says to use the default ACCDB back-end, defined in etc/libaccdb/accdb, variable DEFAULT_BACKEND.

On failure, accdb_load() returns NULL and sets errno to the ones set by system calls, plus EFAULT if no q_open() function in the ACCDB module could be found. ENOENT is returned if no default module was defined.

struct accdb_module *res = accdb_load("*");

The back-end interface is discussed in its own chapter.

Configuration file parsing

While developing the Vitalnix Suite, I have come to a point where I realized I had common used code duplicated in nearly every file that used ACCDB in some way, so I decided to move that code part to ACCDB since it is a central place.

Configuration files are based on the key=value scheme, and lines beginning with a hash mark (#) are ignored, as are empty lines and unrecognized keys:

# From etc/autouid
# Minimum / maximum values for automatic UID selection

UID_MIN=100
UID_MAX=65000

# Minimum / maximum values for automatic GID selection
GID_MIN=100
GID_MAX=65000

ACCDB provides two (one) function to deal with configuration files:

// From accdb.h
struct rconfig_opt {
  const char *key;
  char type;
  void *ptr;
};

enum accdb_rconfig_flags {
  RCONFIG_ONE = 1 << 0,
};

int accdb_rconfig(char *file, struct rconfig_opt *table);
void accdb_rconfig_pv(const char **pv, char *file, struct rconfig_opt *table, enum accdb_rconfig_flags fl);

To start parsing a file, call the accdb_rconfig() function with the corresponding parameters. If you want to read configuration files from different paths, i.e. to build up on default values, you can use accdb_rconfig_pv() like the next code example. (pv = path vector)

struct rconfig_opt table[] = {
  {"UID_MIN", 'l', &uid_min},
  {"UID_MAX", 'l', &uid_max},
  {NULL, '\0', NULL},
};

const char *pv_a[] = {"/etc", "/usr/local/etc", NULL}, *pv_b[] = {".", "/etc", NULL};

// Will parse /etc/configfile
accdb_rconfig("/etc/configfile", table);

// Will parse /etc/configfile and /usr/local/etc/configfile
accdb_rconfig_pv(pv_a, "configfile", table, 0);

// Will only parse the first successful file
accdb_rconfig_pv(pv_b, "configfile", table, RCONFIG_ONE);

The call to accdb_rconfig() will either return 1 for success, 0 for no success (actually 0 is never returned) and -errno for an error. The next call, with pv_a will parse /etc/configfile, etc. (pv from left to right). No value is returned. The call with pv_b will only read the first successful opened file, i.e. if you have both ./configfile and /etc/configfile, only the former is read if it can be opened.

Password generation

#include <accdb.h>

int accdb_genpw(char *plain, char **crypted, size_t len, enum accdb_genpw_meth meth, enum accdb_genpw_flags flags, void *randp);

accdb_genpw() generates a random password. Depending on flags, it might even produce one to be easily memorized by humans, but still being pronouncible. The method and flags fields are:

enum accdb_genpw_meth {
  PW_DES = 0,
  PW_MD5,
  PW_BLOWFISH,
};

enum accdb_genpw_flags {
  PW_PHONEMIC  = 1 << 0,
  PW_ONE_DIGIT = 1 << 1,
  PW_ONE_CASE  = 1 << 2,
};


November 14 2003