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