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


18    Identification and Authentication

This chapter discusses the following topics:


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


18.1    New libsecurity Library Routines

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.


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


18.1.1    Changed Application Programming Interfaces

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.

Table 18-1: Changed Programming Interfaces

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.

Table 18-2: Changed Data Structures

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


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


18.1.2    What to Do With Existing Programs

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.


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


18.1.3    What to Do For New Programs

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.


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


18.2    The Audit ID

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.


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


18.3    Identity Support Libraries

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.


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


18.4    Using Daemons

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.


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


18.5    Using the Protected Password Database

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

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.


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


18.6    Example: Password Expiration Program

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.

Example 18-1: Password Expiration Program

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 auth group. Programs that need to read the protected password database files must set the group ID to auth (see the setgid(2) reference page). To write this information you must set the UID to 0 or a user ID and have a group ID of auth.


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


18.7    Password Handling

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.