This chapter discusses the following topics:
In order to allow adding new fields to the current for getting and setting authentication information without violating binary compatibility, a new series of interfaces has been added to enhanced security. Take for example the user profile:
struct pr_passwd {
struct pr_field ufld;
struct pr_flag uflg;
struct pr_field sfld;
struct pr_flag sflg;
};
Any new field in
pr_field
changes the offsets to
uflg,
sfld,
and
sflg
(even if you add to the end). Because the offsets are known
and compiled into calling applications, this breaks binary
compatibility.
Additions to (at least)
pr_passwd
are expected as new features are added.
Several of the security routines are being replaced in the Digital UNIX Version 4.0 release. Table 18-1 lists the affected interfaces and the replacements.
| Obsolete Interface | Replacement Interface |
getprpwnam()
|
getespwnam()
|
putprpwnam()
|
putespwnam()
|
getprpwent()
|
getespwent()
|
getprpwuid()
|
getespwuid()
|
getprtcent()
|
getestcent()
|
getprtcnam()
|
getestcnam()
|
putprtcnam()
|
putestcnam()
|
getdvagnam()
|
getesdvnam()
|
getdvagent()
|
getesdvent()
|
copydvagent()
|
copyesdvent()
|
putdvagnam()
|
putesdvnam()
|
getprdfent()
|
getesdfent()
|
getprdfnam()
|
getesdfnam()
|
putprdfnam()
|
putesdfnam()
|
getprfient()
|
getesfient()
|
getprfinam()
|
getesfinam()
|
putprfinam()
|
putesfinam()
|
read_pw_fields()
|
[escap_parse_fields(espw_parse, ...)]
|
store_pw_fields()
|
[escap_print_fields(espw_parse, ...)]
|
read_tc_fields()
|
[escap_parse_fields(estc_parse, ...)]
|
store_tc_fields()
|
[escap_print_fields(estc_parse, ...)]
|
time_lock()
|
time_lock_es()
|
get_seed()
|
get_seed_es()
|
auth_for_terminal()
|
auth_for_terminal_es()
|
locked_out()
|
locked_out_es()
|
The following new APIs are added in the Digital UNIX Version 4.0 release:
copyespwent() copyestcent() copyesfient() copyesdfent() escap_parse_fields() escap_print_fields() escap_cmp_fields() escap_copy_fields() escap_size_data() get_num_crypts() get_crypt_name()
Table 18-2 lists the data structures changed in the Digital UNIX Version 4.0 release.
| Obsolete Structures | Replacement Structures |
pr_field
|
espw_field
|
pr_flag
|
espw_flag
|
pr_passwd
|
es_passwd
|
t_field
|
estc_field
|
t_flag
|
estc_flag
|
pr_term
|
es_term
|
dev_field
|
esdev_field
|
dev_flag
|
esdev_flag
|
dev_asg
|
esdev_asg
|
f_field
|
esfi_field
|
f_flag
|
esfi_flag
|
pr_file
|
es_file
|
system_default_fields
|
es_default_fields
|
system_default_flags
|
es_default_flags
|
pr_default
|
es_default
|
The obsolete routines with the
old names and calling sequences are currently supported.
These obsolete routines were rewritten to be layered on top of
the new interfaces, so that the routines
(putprpwnam
for example)
do not lose new fields, but will instead refetch the affected record,
and propagate changes to the new-format interface, thereby
preserving new fields.
Statically-compiled programs using the obsolete interfaces will lose or destroy the new fields if they are allowed to write data.
The new
libsecurity
library with the new extended routines needs to be compiled
ahead of the application. New programs should use the new
getes*()
and
putes*()
routines.
Digital UNIX preserves all traditional UNIX process user and group identities. Additionally, it provides the per-process audit ID (AUID), which is unique to Digital UNIX. The AUID is similar in principle to the real user ID, except that it remains unchanged even in cases where the real user ID changes. The audit ID is associated with all audit records and establishes the user identity even in those cases where the real and effective user IDs have been changed from their values at login.
The audit ID can be set only once in a line of process descendants,
regardless of any process privileges. The audit ID
is set at login to the authenticated user (the same as the real and effective
user IDs) and is inherited from parent to child when
a process forks using the
fork()
system call.
Programs that are created from startup scripts or that are created as a
result of respawn entries in the
inittab
file are created with an unset
audit ID. Such programs are normally authentication programs
(getty/login sequences, window managers, trusted path
managers) that set the AUID based on the user that authenticates through
that interface.
Programs started through startup scripts typically receive requests for service on behalf of users and spawn a process to service that request. Such programs typically set the audit ID in the child service process based on the requesting process's effective identity.
The
getluid()
and
setluid()
system calls read and set the
audit ID. See their reference pages for details.
The Digital UNIX operating system provides
several library routines for managing
user and group identities.
For example, the
set_auth_parameters()
routine,
usually called at the beginning of a program's
main()
routine,
stores the initial user and group IDs that
can later be queried or tested by the other routines.
Several of the routines for querying the authentication database
require the program to have previously called
set_auth_parameters()
before changing any of the user or group IDs,
or the
command arguments (argc and argv).
See the
identity(3)
reference page for more information.
Whenever a daemon performs an operation at the request of a user program (the client), it acts in one of two ways:
In the latter case, the daemon needs to establish a set of security attributes. The preferred technique is to fork a process, set the identities and privileges, and then either perform the actions directly or execute a program to perform them.
Although the protected password database is intended mainly for Digital UNIX
programs, your programs may need to use the fields
described in the following list.
(These fields are also described in the
getespwent(3)
and
prpasswd(4)
reference pages, the
prot.h
include file, and the administrative
part of this document.)
u_name) and ID (u_id)
These correspond to the user name and ID in
/etc/passwd.
u_pwd)
This is the real encrypted password. The system supports a longer password length than the traditional UNIX limit of 8 characters. The system encrypts the password in 8 character segments. Each cycle of encryption provides an 11-character value plus the initial 2-character salt string. Thus, the length of the encrypted password is the number of segments times 11 plus 2 ((11 * n) + 2).
For example, a plain text password of 1 to 8 characters encodes to 13 characters. A plain text password of 9 to 16 characters encodes to 24 characters and a plain text password of 17 to 24 characters encodes to 35 characters.
See the
crypt(3)
reference page for more information.
u_retired)
Indicates whether the authentication profile is valid. If not valid, login sessions are not allowed. Once retired, an account should never again be reused.
u_priority)
The process priority assigned to programs of the user login session using
setpriority().
u_auditmask) and control flags (u_audcntl)
This mask and its control flags, in conjunction with the system audit
mask, designate the events audited during the login session.
The
login
program assigns a mask to the user's login shell.
Audit masks and the control flags are inherited across
exec()
and
fork()
calls.
See
Chapter 19
and the
auditmask(8)
reference page for more information.
The following parameters describe the login password and its generation:
u_maxlen)
u_exp)
u_minchg)
u_life)
u_succhg)
u_unsucchg)
u_pwchanger)
u_genpwd)
u_nullpw)
This is sometimes called the ``null password option'' and controls attempts to set a null password. Most administrators do not allow this option.
u_tod)
This field is formated like the
UUCP
systems
file.
(The
systems
file describes when a remote system can be
contacted for file transfer.)
It determines the valid times for a user to login.
u_suclog)
Expressed as a canonical UNIX time (in seconds since 1970).
u_suctty)
The terminal name is a cross-reference to the device assignment and terminal control databases.
u_numunsuclog)
This value is used to compute whether the terminal is locked due to too many unsuccessful attempts.
u_maxtries)
This value is the user-specific limit for the number of unsuccessful attempts allowed until the account locks.
u_lock)
Whether or not the administrator has locked the account. A locked profile cannot be used for login or other services. Only an explicit request from the system administrator should unlock an authentication profile, and only programs that handle such requests should reset the locked field.
A common programming error is to assume that the lock indicates all lock conditions. This indicator only shows the status of the administrative lock. An account may also be locked due to a password lifetime expiration or exceeding the number of unsuccessful attempts allowed for the account.
Your program can assume that the user name and ID in the protected password
database is maintained by the system to have a corresponding entry in the
/etc/passwd
file.
The program named
myexpire
in
Example 18-1
prints the user's password
expiration time
as defined in the protected password database.
This program is part
of the authentication protected subsystem and runs in the set
group ID (SGID) mode, setting the GID to
auth.
include <sys/types.h> include <stdio.h> include <sys/security.h> include <prot.h>
main (argc, argv) int argc; char *argv[]; { struct es_passwd *acct; time_t expire_time; time_t expire_date;
/*--- Standard initialization ---*/
set_auth_parameters(argc, argv); initprivs();
/*--- fetch account information using audit ID ---*/
if ((acct = getespwuid(getluid())) == NULL) errmsg("Internal error");
/*-- test if personal or system default applies and print --*/
if (acct->uflg->fg_expire) expire_time = acct->ufld->fd_expire; else if (acct->sflg->fg_expire) expire_time = acct->sfld->fd_expire; else { audit_db_error(acct); /* audit (externally defined) */ errmsg("No user-specific or system default \ expiration time."); }
if (!acct->ufld->fg_schange) { audit_db_error(acct); /* audit (externally defined) */ errmsg("Account does not have successful change time"); }
expire_date = acct->ufld->fd_schange + expire_time;
if (acct->uflg->fg_psw_chg_reqd && \ acct->ufld->fd_psw_chg_reqd) \ expire_date = time((time_t *) NULL);
audit_action(acct->ufld->fd_name, expire_date); exit(0); }
Note
The protected password database files are accessible only to processes in the
authgroup. Programs that need to read the protected password database files must set the group ID toauth(see thesetgid(2) reference page). To write this information you must set the UID to 0 or a user ID and have a group ID ofauth.
Digital UNIX has been designed so that trusted programs can authenticate their users without specifically asking for passwords. Digital UNIX explicitly uses the audit ID for this purpose. Additional password handling is usually not necessary and difficult to handle securely. Appendix D provides an example of a program for password checking.