[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


17    Authentication Database

The authentication database is a set of databases that store all Digital UNIX security information. The following databases comprise the authentication database:

This chapter introduces each database and discusses its logical organization.

The trusted programs you create often need to use the information in these databases. Except for a few specialized cases, system administrators maintain these databases using the Digital 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 - other documentation describes their administrative management.


[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


17.1    Accessing the Databases

Digital 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 Reference Page
Device Assignment getesdvent(3)
File Control getesfient(3)
System Default getesdfent(3)
Protected Password getespwent(3)
Terminal Control 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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


17.2    Database Components

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

Each entry contains an ordered set of fields. Each field has a name, used to access the field and a value. Each database has a set of fields that are allowed to be present in one of its entries. Individual fields are optional and can be omitted from an entry.

In general, library routines read or write the entry as a whole. Each such library defines a C structure to hold all possible fields for a given entry of the database. This structure is always accompanied by a mask that designates which fields are to be read or written.

Fields can hold many kinds of values (integer, string, and so forth). However, you only have to deal with the types in the C structure defined for reading and writing entries in each database. The actual format of the files of the database is neither visible nor needed.

Digital UNIX programs understand what to do when a field is undefined. Similarly, your programs should take some appropriate action. A particular case is when some undefined fields are 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 referenced from the same structure that stores values for the individual entry.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


17.2.1    Database Form

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 entry and 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:

Description Identifier Entry Value
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 seconds  
Attempts since last login t_failures#3 3 trys  
Account status t_lock @ Unlocked
Check entry   chkent End of entry

The following C structure is used for fetching an entry (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 */
};

The estc_field holds the data 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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


17.2.2    Reading and Writing a Database

Each database is protected by a protected subsystem pseudogroup, to which your program must have discretionary access. Your program can be installed in two ways:

The creation of database files is controlled by entries in the file control database. All database file attributes are stored there. The procedure for creating database entries is to create a new file that stores the database contents and then rename that file to replace the old one once the database has been rewritten. 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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


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. A common programming mistake is to read a database entry, change one or more field and flag values, and submit the same buffer to the routine that modifies the database.

Database entries come in two types; those that are self-contained and those that contain pointers to variable-length fields. The getesdvent(3) reference page describes the copyesdvent() routine that allocates a structure to hold a device assignment database entry and copy 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);


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


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 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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


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().


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


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 all system defaults. The following databases contain information for which there are system defaults:

Note that only certain fields in these databases have defaults.

When your program reads an 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. System defaults are defined in normal operation, so if a system default field is also undefined, your program should refuse the request and issue an audit report to report the error, although in some cases you can use some default value when neither is defined.

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;


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


17.3    Device Assignment Database

The device assignment database contains device attributes for devices on the system. There are two kinds of devices:

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 entries in 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 file /etc/auth/system/devassign holds the entire device assignment database.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


17.4    File Control Database

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 install all new security-sensitive files and directories in the database. Include all of the attributes that do not change. This ensures that these attributes are regularly checked and corrected.

The file control database is a text file: /etc/auth/system/files. Use any text editor to add to or alter existing entries. See the files(4) reference page for a definition of the format of this file. 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 Digital 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.

You can use the edauth -df command to add or remove entries from this database. See the edauth(8) reference page for more information.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


17.5    System Default Database

The system default database, /etc/auth/system/default, 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 protected password, device assignment, command authorization, 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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


17.6    Protected Password Database

The protected password database (/tcb/files/auth.db and /var/tcb/files/auth.db) holds a set of user authentication profiles. Each authentication profile 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. 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. 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 this database. However, many trusted programs need to read the information from the authentication profile.

Each authentication profile is held in a file whose name is the profile (user) name. The /tcb/files/auth directory contains a subdirectory for each each letter of the alphabet, and each of those subdirectories holds the files for accounts whose name begins with that letter. Each entry is rewritten individually. Only a single entry need be locked for the duration of a database update.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Chapter] [Index] [Help]


17.7    Terminal Control Database

The terminal control database, /etc/auth/system/ttys.db, 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.

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 Digital 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.