17    Authentication Database

The authentication database is a set of databases that store all Tru64 UNIX security information when enhanced security is enabled. The following databases comprise the authentication database:

This chapter introduces each database and discusses its logical organization.

The trusted programs (that is, any program that could subvert a security rule) you create specifically for systems with enhanced security enabled need to use the information in these databases. Except for a few specialized cases, system administrators maintain these databases using the Tru64 UNIX administrative interfaces. Therefore your programs usually only read them. This chapter describes the databases only to the extent that they are used by your programs. See the system management chapters of this book for information on managing these databases. The authcap(4) reference pagew contains general information on the file format.

17.1    Accessing the Databases

Tru64 UNIX includes a set of library routines to access each database. The following reference pages describe the form and use of these databases; you should read them in conjunction with this chapter.

Subject Database Reference Page
Device Assignment devassign getesdvent(3)
File Control file getesfient(3)
System Default default getesdfent(3)
Protected Password auth.db/prpasswd (NIS) getespwent(3)
Terminal Control ttys.db getestcent(3)

The library routines defined on these reference pages hide the actual file format of the databases. Trusted programs do not need to know the format - they simply use these library routines.

17.2    Database Components

Each database consists of a set of named entries. Programs primarily use the name of the entry to request a specific entry from a database, although a program can also sequentially search through the entries in a database.

Each entry contains a set of fields. Each field has an identifier, used to access the field and a value. Each database has an allowed set of fields in one of its entries. Individual fields are optional and can be omitted from an entry. There are several types of fields including string, integer, and boolean.

The general format for an entry is as follows:

entry_name:string_field=value:integer_field#value:\
                         :boolean_field_true:boolean_field_false@:chkent:
 

In general, library routines read or write an entry as a whole. A C structure holds all possible fields for a given entry of the database. This structure is always accompanied by a flags structure which holds a mask designating which fields are to be read or written.

Your programs should take appropriate action when a field is undefined. In many cases, the undefined fields should be fetched from the system defaults database, as described in the following section. Structures for each database include system default fields and flags for that database. Thus, it is easy to retrieve the system default values associated with a particular field because the system default values are available from the same structure that stores values for the individual entry.

17.2.1    Database Form

In general, you will not have to deal with the physical format of the authentication databases. All databases have the same logical form and similar access libraries. For example, the terminal control database consists of an entry for each controlled terminal. The following ttys file sample physical format entry for tty01and the associated table illustrate the database file format.

tty01:t_devname=tty01:t_uid#44:t_logtime#772479074:\
	:t_login_timeout#20:t_failures#3:t_lock@:\
	:chkent:

Meaning Field Value Description
Name t_devname tty01 Terminal 1
User of last login t_uid 44 UID of 44
Time of last login t_logtime 772479074 Fri Jun 24 13:31:13 EDT 1994
Login timeout t_login_timeout#20 20 Login timeout in seconds
Attempts since last login t_failures#3 3 Failed login attempts since last successful login
Account status t_lock @ Unlocked (false)
Check entry :chkent:<EOL> chkent End of entry

The following C structure is used for fetching an entry from the ttys database (see the include file <prot.h>):

struct es_term  {
    struct estc_field  *ufld;     /* fields for this entry */
    struct estc_flag   *uflg;     /* flags for this entry */
    struct estc_field  *sfld;     /* system default fields */
    struct estc_flag   *sflg;     /* system default flags */
};

se

The estc_field holds the data for the fields of the entry and estc_flag holds the flags that designate which fields in estc_field are present or are set. The following is the estc_field structure:

struct estc_field  {
    char    *fd_devname;      /* terminal name */
    uid_t   fd_uid;           /* uid of last successful login */
    time_t  fd_slogin;        /* time of last successful login*/
    ushort  fd_nlogins;       /* consecutive failed attempts */
    char    fd_lock;          /* terminal lock status */
    ushort  fd_login_timeout; /* login timeout value */
};

struct estc_flag  {
unsigned short
    fg_devname        :1,     /* name present? */
    fg_uid            :1,     /* uid present? */
    fg_slogin         :1,     /* time present? */
    fg_nlogins        :1,     /* failed attempts present? */
    fg_lock           :1,     /* lock status present? */
    fg_login_timeout  :1      /* login timeout present? */
 
 
};

The getestcent(3) reference page defines the library routines that you can use to access the terminal control database. The access routines return or set the fields for a specific entry ufld and uflg and for the system defaults (sfld and sflg). For each database whose fields have system defaults, the system defaults are returned in addition to the fields for that entry.

17.2.2    Reading and Writing a Database

Each database is owned by a user/group, to which your program must have discretionary access. Your program can be installed in two ways:

The library routines automatically enforce one database writer at a time. However, the database is locked only for the duration of the time the database is being rewritten. There is no way to lock an entry against access across a retrieval and write operation. You should complete your writes as quickly as possible.

17.2.2.1    Buffer Management

You must understand how the system allocates and returns buffers for database entries to properly code programs that retrieve, replace, and add database entries. All database routines are patterned after the getpwent() routines in that they return pointers to static storage that is reused on each call. You must save the buffer contents if you are going to retrieve another entry and need to refer again to the previous entry, or if you need to rewrite an existing entry or add a new entry. You cannot read a database entry, change one or more field and flag values, and submit the same buffer to the routine that modifies the database.

The logical form for some database entry fields is self-contained. Other fields contain pointers to variable length data.

The devassign database logical form contains some fields that are pointers to variable length data. The getesdvent(3) reference page describes the copyesdvent() routine that allocates a structure to hold a device assignment database entry and copies the contents of a buffer returned from getesdvent() or getesdvnam() into it.

You can save an entry for a self-contained database by simple structure assignment, as follows:

struct es_passwd *pr;       /* returned value */
struct es_passwd *pwcopy;   /* buffer for saved values */
 
/* Retrieve john's protected password database entry */
 
pr = getesnam("john");
 
/* store values of john's entry to a local buffer */
 
pwcopy = copyespwent(pr);
if (!pwcopy) abort();
 
/* Change the password minimum change time to two weeks */
 
pwcopy->uflg->fg_min = 1;
pwcopy->ufld->fd_min = 14 * 24 * 60 * 60;
 
/* Rewrite john's protected password database entry */
 
if (!putespwnam("john", pwcopy))
    errmsg("Could not write protected password entry\n");
free(pwcopy);

17.2.2.2    Reading an Entry by Name or ID

You can read database entries by specifying their name or, in some databases, some other identifying value. For example, you can fetch entries from the enhanced (protected) password database by the entry name (the user's name) or the user ID. The following code reads the entry associated with the name tty44 from the terminal control database:

 ...
struct es_term   *entry;
 ...
if ((entry = getestcnam("tty44")) == NULL)
            errmsg ("Entry not found");

Note that getestcnam() allocates the data structure for the returned entry. Hence, entry is only a pointer to a es_term structure that is reused the next time any of the prtc() or estc() routines is called.

17.2.2.3    Reading Entries Sequentially

You can also read database entries sequentially as illustrated in the following code:

 ...
struct es_term   *entry;
 ...
setprtcent();                            /* rewind the database*/
while ((entry = getestcent()) != NULL){  /* read next entry   */
      ...                                /* process the entry */
}
endprtcent ();                           /* close */

Note that getestcent() also allocates the data structure for the entry. You can restart the search from the beginning using setprtcent().

17.2.2.4    Using System Defaults

A system default is a field that is used when the corresponding field in an entry is not defined. The system default database contains defaults for the other databases. The following databases contain information for which there are system defaults:

Note that only certain fields in these databases are allowed to have defaults.

When your program reads a logical entry, the library routine returns both the fields for that entry (ufld and uflg) and for the system default (sfld and sflg). If the entry does not contain the field you need, use the system default. In some cases if the system default is also undefined, your program should generate audit data to report the error and execute a failure path. In other cases, you can safely define a default value.

For example, if you need to determine the timeout value for the terminal tty14, your code might look like this:

struct es_term  *entry;        /* the entry for the terminal */
ushort          time_out;      /* final timeout value */
 ...
 
/*--- fetch the entry by name ---*/
 
if ((entry = getestcnam ("tty14")) == NULL)
      errmsg ("Entry not found");
 
/*--- if defined for the terminal, use it ---*/
 
if (entry->uflg->fg_login_timeout)
      time_out = entry->ufld->fd_login_timeout;
 
/*--- else if system default is defined, use it ---*/
 
else if (entry->sflg->fg_login_timeout)
      time_out = entry->sfld->fd_login_timeout;
 
/*--- otherwise, assume a value of 0 ---*/
 
else time_out = 0;

17.2.2.5    Writing an Entry

Your program should seldom have to modify a database, and even more rarely a system default. However, if this is necessary, place the new fields in ufld and set the corresponding flags in uflg, and then call the appropriate library routine. For example, to set a new timeout value for the terminal tty14 to 20 your code might look like this:

struct es_term  *entry, *ecopy;
 ...
/*--- fetch the entry by name ---*/
 
if ((entry = getestcnam("tty14")) == NULL)
      errmsg ("Entry not found");
 
/*--- change the desired field(s) ---*/
 
ecopy = copyestcent(entry); if (! ecopy) abort():
ecopy->ufld->fd_login_timeout = 20;  /* set timeout value */
ecopy->uflg->fg_login_timeout =  1;  /* set flag to show the
                                          field has been set */
/*--- update the database ---*/
 
if (!putestcnam("tty14", ecopy))
      errmsg ("Could not update database");
free(ecopy);

Note

You must call the appropriate copyes*() routine to save the data for later use.

The copyes*() routines return pointers to a malloc() storage area that the caller must clear.

You can only set system defaults using the putesdfnam() interface for the system default database. You cannot, for example, set the sfld and sflg fields in a es_term entry and then call putestcnam() to set system defaults.

17.3    Device Assignment Database (devassign)

The device assignment database contains device attributes for devices on the system. Currently there are two kinds of devices included in the devassign database:

The name of a device entry is used in the device-related commands. This name is independent of the names of the device files that represent the device.

System administrators maintain the device assignment database; your programs should not modify its contents.

The logical entries for this database have dynamic sizes (are not self-contained). For this reason, you must use the copyesdvent() routine to make a working copy of a structure that contains one of its entries. See the getesdvent(3) reference page for details.

The text file /etc/auth/system/devassign holds the entire device assignment database.

17.4    File Control Database (file)

The file control database helps to assure that your security-sensitive files have the correct protection attributes (owner, mode bits, and so forth). It contains the absolute pathname and the correct attributes for each file (or directory). These attributes include any combination of the following:

Your programs should not read from or write to the file control database other than to use its entries for newly created files through the create_file_securely() interface. However, you should add all new security-sensitive files and directories to the database. Include all of the attributes that do not change. This ensures that these attributes are regularly checked and corrected.

You can use the create_file_securely() routine to create files with the attributes specified in the file control database. This routine can only be used to create a new file. You should create new versions of files in a different file (the Tru64 UNIX convention is to append a :t to a pathname for the file's new contents) and then rename (using the rename() system call) the new file to the existing file.

The file control database is a text file: /etc/auth/system/files. See the files(4) reference page for a definition of the format of this file. The system administrator can use the edauth -df command to add or remove entries from this database. See the edauth(8) reference page for more information.

17.5    System Default Database (default)

The system default database, /etc/auth/system/default, is a text file that contains fields that are to be used when the corresponding fields are left undefined in other databases. Specifically, this database contains default information for the enhanced (protected) password, device assignment, and terminal control databases. (Note that all fields in each of the authentication databases may be left undefined, but all fields do not have system default values.)

The system default database also contains fields for miscellaneous system parameters. Your programs should not need this miscellaneous information.

System administrators maintain this database and your programs should never have to modify it. The access routines for other databases also return the system default values. See Section 17.7, for an example of how to access and use the information in the system default database.

The entire system default database has only one entry, the default entry.

17.6    Enhanced (Protected) Password Database (prpasswd or auth)

The enhanced password database (/tcb/files/auth.db and /var/tcb/files/auth.db) are dbm files that hold a set of user authentication profiles. User authentication profiles can also be distributed between Tru64 UNIX systems using the NIS prpasswd map. Each authentication profile entry is named with a user name (a name that a user supplies during login). The authentication profile has many fields that govern the user's login session. Chapter 18 describes these fields in detail.

An authentication profile is associated with the account whose presence is indicated by a line in the traditional /etc/passwd file or NIS passwd map. The encrypted password has been moved from the /etc/passwd file to the authentication profile.

The system assigns the traditional meanings for the other fields in the /etc/passwd database. Each entry in /etc/passwd corresponds to exactly one authentication profile in the protected password database with the same user ID and name (both must be present for an account to be considered valid). The /etc/passwd entry contains a dummy encrypted password field - the authentication profile holds the real one.

The traditional UNIX interfaces for querying /etc/passwd file is getpwent(). The interfaces' functions are unchanged and always fetch their information from the /etc/passwd file or NIS map. Note however, that the encrypted password that is returned is a dummy value (the routine is not modified to retrieve the encrypted password from the authentication profile).

Your programs should not modify the enhanced (protected) password database. However, many trusted programs need to read the information from the user authentication profiles.

17.7    Terminal Control Database (ttys)

The terminal control database, /etc/auth/system/ttys.db, is a dbm file that contains fields used primarily during login that apply to the login terminal, as opposed to the user who is logging in. This database consists of an entry for each terminal upon which users may log in including X terminals.

Each entry in the database has a name of the terminal that matches a name in the file used to specify login ports (/etc/inittab). The entries in the device assignment database correspond to each entry in the terminal control database. Most trusted programs (for example, login) do not provide their services if there is no corresponding entry in the device assignment database.

Each terminal control database entry contains the following fields:

System administrators maintain the entries in this database, although the Tru64 UNIX login programs modify many fields. Your programs do not usually modify this database. Although it is unlikely, trusted programs may need to read this database.

The file /etc/auth/system/ttys.db holds the entire terminal control database.