This chapter documents the Security Integration Architecture (SIA) interfaces.
The Security Integration Architecture (SIA) allows the layering of local and distributed security authentication mechanisms onto the Digital UNIX operating system. The SIA configuration framework isolates security sensitive commands from the specific security mechanisms. These commands have been modified to call a set of mechanism-dependent routines. By providing a library with a unique set of routines, developers can change the behavior of security sensitive commands, without changing the commands themselves. The SIA defines the security mechanism-dependent interfaces (siad_*() routines) required for SIA configurability. Figure 20-1 illustrates the relationship of the components that make up the SIA.
The security sensitive commands are listed in Table 20-1.
Command | Description |
chfn | Changes finger information |
chsh | Changes login shell information |
dnascd | Spwans DECnet |
ftpd | Serves the Internet File Transfer Protocol |
login | Authenticates users |
passwd | Creates or changes user passwords |
rshd | Serves remote execution |
su | Substitutes a user ID |
Table 20-2 and Table 20-3 list the SIA porting routines.
SIA Routine | Description |
sia_init() | Initializes the SIA configuration |
sia_chk_invoker() | Checks the calling application for privileges |
sia_collect_trm() | Collects parameters |
sia_chg_finger() | Changes finger information |
sia_chg_password() | Changes the user's password |
sia_chg_shell() | Changes the login shell |
sia_ses_init() | Initializes SIA session processing |
sia_ses_authent() | Authenticates an entity |
sia_ses_reauthent() | Revalidates a user's password |
sia_ses_suauthent() | Processes the su command |
sia_ses_estab() | Establishes the context for a session |
sia_ses_launch() | Logs session startup and any tty conditioning |
sia_ses_release() | Releases resources associated with session |
sia_make_entity_pwd() | Provides the password structure for SIAENTITY |
sia_audit() | Generates the audit records |
sia_chdir() | Changes the current directory safely (NFS-safe) |
sia_timed_action() | Calls with a time limit and signal protection |
sia_become_user() | su routine |
sia_validate_user() | Validate a user's password |
sia_get_groups() | Gets groups |
SIA Routine | Description |
siad_init() | Initializes processing once per reboot |
siad_chk_invoker() | Verifys the calling program privileges |
siad_ses_init() | Initializes the session |
siad_ses_authent() | Authenticates the session |
siad_ses_estab() | Checks resources and licensing |
siad_ses_launch() | Logs the session startup |
siad_ses_suauthent() | Processes the su command |
siad_ses_reauthent() | Revalidates a user's password |
siad_ses_release() | Releases session resources |
siad_chg_finger() | Processes the chfn command |
siad_chg_password() | Invokes a function to change passwords |
siad_chg_shell() | Processes the chsh command |
siad_getpwent() | Processes getpwent and getpwent_r |
siad_getpwuid() | Processes getpwuid() and getpwuid_r() |
siad_getpwnam() | Processes getpwnam() and getpwnam_r() |
siad_setpwent() | Initializes a series of getpwent calls |
siad_endpwent() | Releases resources after a series of getpwent calls |
siad_getgrent() | Processes getgrent() and getgrent_r() |
siad_getgrgid() | Processes getgrgid() and getgrgid_r() |
siad_getgrnam() | Processes getgrnam() and getgrnam_r() |
siad_setgrent() | Initializes a series of getgrent() calls |
siad_endgrent() | Closes series of getgrent() calls |
siad_chk_user() | Determines if a mechanism can change the requested information |
siad_get_groups() | Fills in the array of a user's supplementary groups |
The SIA establishes a layer between the security sensitive commands and the security mechanisms that deliver the security mechanism-dependent functions. Each of the security-dependent SIA routines can be configured to use up to four security mechanisms, called in varying orders.
The selection and order of the calls is established by a switch table file, /etc/sia/matrix.conf (see Chapter 13), similar to the way /etc/svc.conf is used to control libc get* functions. However, the calling mechanism is distinctly different.
The SIA calling mechanism looks up the addresses of routines in the shared libraries and calls them to access the specific security mechanism routine. SIA provides alternative control and configuration for the getpw* and getgr* functions in Digital UNIX.
SIA layering establishes internationalized message catalog support and thread-safe porting interfaces for new security mechanisms and new security sensitive commands that need transparency. The thread safety is provided by a set of locks pertaining to types of SIA interfaces. However, because SIA is a layer between utilities and security mechanisms, it is the responsibility of the layered security mechanisms to provide reentrancy in their implementations.
The primary focus for SIA is to provide transparent interfaces for security sensitive commands like login, su, and passwd that are sufficiently flexible and extensible to suit future security requirements. Any layered product on Digital UNIX that is either creating a new security mechanism or planning to use a specific security mechanism, requires SIA integration.
The SIA components consist of only user-level modules. The components resolve the configuration issues with respect to command and utility utilization of multiple security mechanisms. The SIA components do not resolve any kernel issues pertaining to the configuration and utilization of multiple security mechanisms.
The layering introduced by SIA in Digital UNIX consists of the following two groups of interface routines:
Security mechanisms deliver a shared library containing the siad_*() routines and provide a unique security mechanism name to satisfy the configuration. The one word security mechanism name and the library name are used as keys in the matrix.conf file to specify which mechanisms to call and in what order.
The security-sensitive commands have been modified to use the mechanism-independent sia_*() routines. The routines are used by the commands and utilities to access security functions yet remain isolated from the specific security technologies. The sia_*() routines call the associated mechanism-dependent siad_*() routine, depending on the selected configuration specified in the matrix.conf file. See Chapter 13 for a more detailed discussion of the file.
The mechanism-dependent siad_*() interface routines are defined by SIA as callouts to security mechanism-dependent functions provided by the security mechanisms. The matrix.conf file is used to determine which security mechanisms are called and in what order they are called for each SIA function.
The process of calling a particular module within a specified security mechanism and passing the required state is done by the mechanism-dependent layer. The calling process uses shared library functions to access and lookup specific module addresses within specified shared libraries provided by the security mechanisms.
The naming of the security mechanism-dependent modules, siad_*() routines, is fixed to alleviate name conflicts and to simplify the calling sequence. Digital UNIX uses the dlopen() and dlsym() shared library interfaces to open the specified security-mechanism shared library and lookup the siad_*() function addresses. If you need to preempt the siad_*() routines, your names must be of the form __siad_* in your library and the library must be linked ahead of linc. See Appendix E for more information on the naming and preempting requirements.
The SIA provides a callout to each security mechanism on each reboot of the system. This callout is performed by the /usr/sbin/siainit program, which calls each of the configured security mechanisms at their siad_init() entry point. This allows the security mechanisms to perform a reboot initialization. A SIADFAIL response from the siad_init() call causes the system to not reboot and a SIA INITIALIZATION FAILURE message to be sent to the console. Consequently, only problems that would cause a security risk or would not allow root to log in should warrant a SIADFAIL response from the siad_init() call.
SIA security mechanisms are configured as separate shared libraries with entry points that are SIA defined names. Each mechanism is required to have a unique mechanism identifier. The actual entry points in the shared library provided by the security mechanism are the same for each mechanism, siad_*() form entry points.
The default security configuration is the BASE security mechanism contained in libc. The default BASE security mechanism uses the /etc/passwd file, or a hashed database version, as the user database and the /etc/group file as the group's database. The default BASE mechanism also uses the network information service (NIS) if it is configured. In single-user mode or during installation the BASE security mechanism is in effect.
The SIA interfaces and structures are defined in the /usr/include/sia.h and /usr/include/siad.h files. The sia*.h files are part of the program development subsets.
The SIAENTITY structure contains session processing parameters and is used to transfer session state between the session processing stages. Example 20-1 is the SIAENTITY structure:
typedef struct siaentity { char *name; /* collected name */ char *password; /* entered or collected password */ char *acctname; /* verified account name */ char **argv; /* calling command argument list */ int argc; /* number of arguments */ uid_t suid; /* starting ruid */ char *hostname; /* requesting host NULL=>local */ char *tty; /* pathname of local tty */ int can_collect_input; /* 1 => yes, 0 => no input */ int error; /* error message value */ int authcount; /* Number of consecutive */ /* failed authent attempts */ int authtype; /* Type of last authent */ struct passwd *pwd; /* pointer to passwd struct */ char *gssapi; /* for gss_api prototyping */ char *sia_pp; /* for passport prototyping */ int *mech[SIASWMAX]; /* pointers to mech-specific data */ /* allocated by mechanisms indexed */ /* by the mechind argument */ } SIAENTITY;
The SIA provides parameter collection callback capability so that any graphical user interface (GUI) can provide a callback. The sia_collect_trm() routine is used for terminal parameter collection. Commands calling the sia_*() routines pass as an argument to the appropriate collection routine pointer, thus allowing the security mechanism to prompt the user for specific input. If the collection routine argument is NULL, the security mechanism assumes that no collection is allowed and that the other arguments must be used to satisfy the request. The previous case is used for noninteractive commands. For reliability, use a collection routine whenever possible.
The can_collect_input argument is included in the session processing and disables the collection facility for input while allowing the output of warnings or error messages. Collection routines support simple form and menu data collection. Some field verification is supported to check parameter lengths and content (alphanumeric, numeric only, letters only, and invisible). The collection routine supplied by the command or utility is responsible for providing the appropriate display characteristics.
The parameter collection capability provided by SIA uses the following interface definition in sia.h:
int sia_collect_trm(timeout, rendition, title, num_prompts, prompts);
int timeout /* number of seconds to wait */ /* 0 => wait forever */ int rendition SIAMENUONE 1 /* select one of the choices given */ SIAMENUANY 2 /* select any of the choices given */ SIAFORM 3 /* fill out the form */ SIAONELINER 4 /* One question with one answer */ SIAINFO 5 /* Information only */ SIAWARNING 6 /* ERROR or WARNING message */
unsigned char *title /* pointer to a title string. */ /* NULL => no title */
int num_prompts /* Number of prompts in collection */
prompt_t *prompts /* pointer to prompts */
typedef struct prompt_t { unsigned char *prompt; unsigned char *result; int max_result_length; /* in chars */ int min_result_length; /* in chars */ int control_flags; } prompt_t;
control_flags SIARESINVIS 0x2 result is invisible SIARESANY 0x10 result can contain any ASCII chars SIAPRINTABLE 0x20 result can contain only printable chars SIAALPHA 0x40 result can contain only letters SIANUMBER 0x80 result can contain only numbers SIAALPHANUM 0x100 result can contain only letters and numbers
See the sia_collect_trm(3) reference page for more information on parameter collection.
Some commands require making multiple calls to sia_*() routines and maintaining state across those calls. The state is always associated with a particular user (also called an entity). SIA uses the term entity to mean a user, program, or system which can be authenticated. The entity identifier is the user ID (UID). All security mechanisms which are ported to Digital UNIX must be administered such that a particular UID maps equivalently across each mechanism. This constraint allows for the interaction and coexistence of multiple security mechanisms. If a security mechanism has an alternative identifier for a user, it must provide a mapping to a unique UID for other mechanisms to properly interoperate and provide synchronized security information.
A pointer to the SIAENTITY structure (see Section 20.6) is used as an argument containing intermediate state identifying the entity requesting a security session function. The SIAENTITY structure also allows for the sharing of state between security mechanisms while processing a session.
The libc library provides for the allocating and freeing of primitives for SIAENTITY structures. The allocation of the SIAENTITY structures occurs as part of the session initialization routine, sia_ses_init(). The deallocation of the SIAENTITY structure occurs in the call to the session release sia_ses_release() routine. If errors occur during session processing (such as in the sia_ses_*authent() routines) and you give up instead of retrying, sia_ses_release() must be called to clean or free up the SIAENTITY structure related to the session. If errors occur during a sia_ses_estab() or sia_ses_launch() routine causing failure status to be returned, the routines call sia_ses_release().
SIA supports the passing of a success or failure response back to the calling command or utility. The SIAENTITY structure has a reserved error code field (error), which is available for finer error definition.
The siad_ses_*() routines return bitmapped values that indicate the following status:
SIA supports a general logging capability that allows appending data to the /var/adm/sialog file. The SIA logging facility supports the following three log-item types:
The sia_log() logging routine is available to security mechanisms and accepts formatting strings compatible to printf() format. Each log entry is time stamped. Example 20-2 is a typical /var/adm/sialog file.
SIA:EVENT Wed Feb 3 05:21:31 1995 Successful SIA initialization SIA:EVENT Wed Feb 3 05:22:08 1995 Successful session authentication for terry on :0 SIA:EVENT Wed Feb 3 05:22:08 1995 Successful establishment of session SIA:ERROR Wed Feb 3 05:22:47 1995 Failure to authenticate session for root on :0 SIA:ERROR Wed Feb 3 05:22:52 1995 Failure to authenticate session for root on :0 SIA:EVENT Wed Feb 3 05:22:59 1995 Successful session authentication for root on :0 SIA:EVENT Wed Feb 3 05:22:59 1995 Successful establishment of session SIA:EVENT Wed Feb 3 05:23:00 1995 Successful launching of session SIA:EVENT Wed Feb 3 05:24:40 1995 Successful authentication for su from root to terry SIA:EVENT Wed Feb 3 05:25:46 1995 Successful password change for terry
The sia_log() routine is for debugging only. The _ses_* routines use audgen() for audit logging.
Depending on the class or type of SIA processing being requested, the selection and order of security mechanisms may vary. A typical set of security mechanisms might include a local mechanism (one that is only concerned with the local system security) and a distributed security mechanism (one that is concerned with aspects of security that span several systems). SIA layering allows these two security mechanisms to either coexist or be better integrated.
An example of security mechanism integration is the log in or session processing. SIA layering passes state (SIAENTITY) between the various security mechanisms during the session processing. This state contains collected names and passwords and the current state of session processing. The local security mechanism can be designed to trust the authentication process of a previously run security mechanism, thus allowing authentication vouching. In this case, if a user is successfully authenticated by the distributed mechanism, the local mechanism can accept or trust that authentication and continue with session processing.
SIA also allows the local mechanism to not accept vouching. In this case, the local mechanism would be forced to do its own authentication process regardless of previous authentication outcomes. This typically results in the user being asked for several sets of user names and passwords. Although SIA allows any ordering of security mechanisms, it makes sense that those mechanisms that accept vouching be ordered after those that do not.
Notes
The default security mechanism, BASE, accepts authentication vouching.
The SIA layer deals with the isolation of security mechanisms from the commands' specific user interface preferences. To accomplish this isolation, the calling command provides a pointer to a parameter collection routine as an argument to the sia_*() routines. The collection routine must support simple form and menu type of processing. The definitions or the requirements of the collection routine are defined in sia.h. This separation of user interface from the security mechanisms allows for the flexibility to change the user interface to suit any workstation or dumb terminal model.
The session processing interfaces are associated with the process of a utility or command that needs to become or act as some other entity. Figure 20-2 illustrates the SIA routines and their relationship in a typical login session.
The session processing interfaces to the security mechanism-dependent routines (siad_*()) all use the same returns to determine the state of the session and whether it should continue. The returns are as follows:
Not all security mechanisms have processing required in each phase of the session processing. In general, the default response is SIADFAIL to force the other configured security mechanisms to produce the required SIADSUCCESS response. The only exceptions to this is the first and last stage of session processing. If a security mechanism has nothing to do in either session initialization or session release, it should return a SIADSUCCESS response. For all other phases of session processing, a SIADFAIL response is the default.
The session processing interfaces are typically called in the following order:
The session routines must all have the same number and order of mechanisms to keep the mechanism index (mechind) consistent.
Example 20-3 is a code fragment that shows session processing for the login command.
. . . /* SIA LOGIN PROCESS BEGINS */
/* Logging of failures to sia_log is done within the libsia */ /* Logging to syslog is responsibility of calling routine */
if((sia_ses_init(&entity, oargc, oargv, hostname, loginname, \ ttyn, 1, NULL)) == SIASUCCESS) {
/***** SIA SESSION AUTHENTICATION *****/
if(!fflag) { for(cnt=5; cnt; cnt--) { if((authret=sia_ses_authent(sia_collect,NULL,entity)) \ == SIASUCCESS) break; else if(authret & SIASTOP) break; fputs(MSGSTR(INCORRECT, "Login incorrect\n"), stderr); } if(cnt <= 0 || (authret & SIASTOP)) { sia_ses_release(&entity); exit(1); } }
/***** SIA SESSION ESTABLISHMENT *****/
if(sia_ses_estab(sia_collect,entity) == SIASUCCESS) { /****** set up environment *******/ /* destroy environ. unless user requested preservation */ if (!pflag) { pp = getenv("TERM"); if (pp) strncpy(term, pp, sizeof term); clearenv(); } (void)setenv("HOME", entity->pwd->pw_dir, 1); if(entity->pwd->pw_shell && *entity->pwd->pw_shell) strncpy(shell, entity->pwd->pw_shell, sizeof shell); (void)setenv("SHELL", shell, 1); if (term[0] == ' ') (void)strncpy(term, stypeof(tty), sizeof(term)); (void)setenv("TERM", term, 0); (void)setenv("USER", entity->pwd->pw_name, 1); (void)setenv("LOGNAME", entity->pwd->pw_name, 1); (void)setenv("PATH", _PATH_DEFPATH, 0); /***** SIA LAUNCHING SESSION *****/ if(sia_ses_launch(sia_collect,entity) == SIASUCCESS) { /* 004 - start */ if ((entity -> pwd != NULL) && (entity -> pwd -> pw_dir != NULL) && (entity -> pwd -> pw_dir [0] != 0)) sprintf (hush_path, "%s/%s", entity -> pwd -> pw_dir, _PATH_HUSHLOGIN); else strcpy (hush_path, _PATH_HUSHLOGIN); quietlog = access(hush_path, F_OK) == 0; /* 004 - end */ if(!quietlog) quietlog = !*entity->pwd->pw_passwd && \ !usershell(entity->pwd->pw_shell); if (!quietlog) { struct stat st; motd(); (void)sprintf(tbuf, "%s/%s", _PATH_MAILDIR, \ entity->pwd->pw_name); if (stat(tbuf, &st) == 0 && st.st_size != 0) (void)printf(MSGSTR(MAIL, "You have %smail.\n"), (st.st_mtime > st.st_atime) ? MSGSTR(NEW, \ "new ") : ); } sia_ses_release(&entity); /******* Setup default signals **********/ (void)signal(SIGALRM, SIG_DFL); (void)signal(SIGQUIT, SIG_DFL); (void)signal(SIGINT, SIG_DFL); (void)signal(SIGTSTP, SIG_IGN); tbuf[0] = '-'; (void)strcpy(tbuf + 1, (p = rindex(shell, '/')) ? p + 1 : shell); /****** Nothing left to fail *******/ if(setreuid(geteuid(),geteuid()) < 0) { perror("setreuid()"); exit(3); } execlp(shell, tbuf, 0); (void)fprintf(stderr, MSGSTR(NO_SHELL, \ "login: no shell: %s.\n"), strerror(errno)); exit(0); } /***** SIA session launch failure *****/ } /***** SIA session establishment failure *****/ } logerror(entity); exit(1); } logerror(entity) SIAENTITY *entity; { if(entity != NULL) { sia_ses_release(&entity); } syslog(LOG_ERR, MSGSTR(FAILURE3," LOGIN FAILURE ")); } . . .
Session initialization is performed by the sia_ses_init() routine. The sia_ses_init() routine calls each configured security mechanism's siad_ses_init() entry point to do any processing associated with the start of a session processing sequence. The session initialization stage is responsible for setting up the SIAENTITY structure, which is used to maintain state though the different stages of session processing.
The authentication stage of session processing is responsible for proving the identity for the session. This stage of the processing must determine the entity associated with the session. If the entity can not be determined, the authentication fails. If the authentication is successful, an entity is derived.
The top level SIA session authentication routine, sia_ses_authent(), calls the security mechanism-dependent siad_ses_authent() routines according to the configured sequence stored in the matrix.conf file. As the multiple authentication routines are called, the SIAENTITY structure is used to hold precollected parameters like the name, password, and eventually the associated /etc/passwd entry of the entity.
By using precollected arguments, the security mechanisms avoid re-collecting arguments. An example is when root attempts to log in to a system configured to first call the DCE siad_ses_authent() routine followed by the local ENHANCED (enhanced security) siad_ses_authent() routine.
It is likely that the DCE authentication process will not be capable of authenticating root. However, it is capable of asking the user for a name and password, which are then passed on to the ENHANCED siad_ses_authent() routine using the SIAENTITY structure. This allows the ENHANCED mechanism to verify the root name and password, thus authenticating root. As soon as the session authentication stage is complete, the password field is cleared.
Each security mechanism-dependent authentication routine must have the ability to determine and set the entity on a successful authentication. If a security mechanism has its own private interpretation of the entity, it must provide a translation to the common SIA entity, user name and UID. Without this restriction there is no way to synchronize security mechanisms with respect to a common entity.
At the successful completion of the session authentication stage, the SIAENTITY structure must contain the user name and UID of the authenticated entity. If the session authentication fails, the calling command or program can call sia_ses_authent() again to retry the authentication process. Certain mechanisms may allow other mechanisms to vouch for this stage of session processing. This usually occurs when local mechanisms default their authentication process to other distributed mechanisms.
The session establishment stage is invoked with sia_ses_estab() following a successful session authentication stage. The sia_ses_estab() routine is configured to call multiple security mechanism's siad_ses_estab() routines in the order defined in the matrix.conf file. The session establishment stage of session processing is responsible for checking mechanism resources and licensing to determine whether this session can be successfully launched. The determination of the passwd struct entry and any other required security context must occur in this stage. At the successful completion of the session establishment stage, the system is prepared to grant the session launching.
The session launch stage is responsible for the logging and the accounting of the session startup. The local mechanism is additionally responsible for setting the wtmp and utmp entries, and for setting the effective UID to the UID associated with the entity. The processing by the setgid() and initgroup() routines as well as lastlog updating are also done by the local mechanism. Only catastrophic errors should be able to stop the session from continuing.
The last stage of the session processing sequence (either successful or failed) is the call to the sia_ses_release() routine. This routine frees all session processing resources, such as the SIAENTITY structure. Each configured mechanism is called to release any resources which are no longer required for the session.
The following sections describe specific session processing for the login, rshd, and rlogind commands. See Section 20.12 for a generic description of session processing.
The most common case of session processing is the login process becoming the entity associated with a user. The entity is the unique SIA identifier for any person or process that can be authenticated and authorized. The code in Example 20-3 is from the login command.
Session processing for /usr/sbin/rshd differs from login. The rshd process requires calling ruserok() to check the .rhosts and host.equiv files for authorization. If ruserok() fails, the rshd fails.
The rlogind, program executes the login command with the -f flag if its call to ruserok() is successful, and without -f if the call to ruserok() is unsuccessful. If login is executed without the -f flag, sia_ses_authent() is called, which prompts for a user name and password, if required.
The routines described in this section handle the changing of the traditional /etc/passwd entry information. This class of routines could be extended to handle other types of common secure information. Only the traditional passwd, chfn, and chsh types of command processing are specified. Each of these routines follows the same operational model. When a user requests a change, the routines in this class check each mechanism that was configured by calling siad_chk_user() to determine whether the user is registered with the mechanism. Once it is determined that the user is registered with more than one security mechanism, the user is given a menu selection by the collection routine, to choose which mechanism is targeted for the change. If only one mechanism is configured to handle the request then that mechanism is called directly.
To change a password, the sia_chg_password() routine calls the configured mechanisms by using the siad_chg_password() routine. To determine which mechanisms support a particular user, the siad_chk_user() call is made to all mechanisms configured for the siad_chg_passwd() routine. When multiple mechanisms claim registry of a user, the user is given a selection to choose from. If the user is only registered with one mechanism, then that mechanism is called.
The sia_chg_finger() routine calls the configured mechanisms by the siad_chg_finger() routine to change finger information. To determine which mechanisms support a particular user, the siad_chk_user() call is made to all mechanisms configured for the siad_chg_finger() routine. When multiple mechanisms claim registry of the user, the user is given a selection menu to choose one from. If the user is only registered with one mechanism, then that mechanism is called.
The sia_chg_shell() routine calls the configured mechanisms by the siad_chg_shell() routine to change a user's login shell. To determine which mechanisms support a particular user, the siad_chk_user() call is made to all mechanisms configured for the siad_chg_shell() routine. When multiple mechanisms claim registry of the user, the user is given a selection menu from which to choose a mechanism. If the user is only registered with one mechanism, then that mechanism is called.
The SIA interfaces described in the following sections handle the access to the traditional UNIX /etc/passwd and /etc/group information. You can create routines to handle the access of other common secure information. Mechanism-dependent security information access should not be handled by the SIA interfaces unless nearly all mechanisms support the type of information being accessed.
The sia_context and mech_contexts structures, defined in sia.h, are used to maintain state across mechanisms. The structures are as follows:
struct mech_contexts { void *value; void (*destructor)(); };
struct sia_context { FILE *fp; union { struct group *group; struct passwd *pass; } value; int pkgind; unsigned buflen; char *buffer; struct mech_contexts mech_contexts[SIASWMAX]; };
Because the getgr*() and the getpw*() routines have SIA interfaces, security mechanisms need only provide one routine for both reentrant and non-reentrant, threadsafe applications. This is accomplished by the sia_getpasswd() and sia_getgroup() routines which encapsulate the arguments in a common form for the security mechanism's siad_*() routines.
Access to traditional /etc/passwd entries is accomplished by the getpw*() routines in libc and libc_r. The sia_getpasswd() routine in the SIA layer preserves the calling semantics of the current getpw*() routines and converts them into one common routine used for both single and multithreaded processes. By doing this conversion, security mechanisms need only support one set of getpw*() routines. The processing of the getpwent() routine is accomplished by calling each configured security mechanism in the predefined order until all entries have been exhausted.
Access to traditional /etc/group entries is accomplished by the getgr*() routines in libc and libc_r. The sia_getgroup() routine in the SIA layer preserves the calling semantics of the current getgr*() routines and converts them into one common routine used for both single and multithreaded processes. The conversion to a single routine eases the security mechanism port by reducing the number of routines required. The processing of the getgrent() routine works by calling each configured security mechanism in the predefined order until all group entries have been exhausted.
The SIA session interfaces and the interfaces that change secure information use a predefined parameter collection capability. The calling application passes the address to a parameter collection routine through the SIA to the siad_*() routines. The collection routine allows different security mechanisms to prompt the user for different parameters without having to be aware of the user interface details.
This capability isolates the SIA security mechanisms from the user interface and the ability to do simple forms and menus. This collection capability is sufficiently limited to allow ease of implementation by different user-interface packages or windowing systems. However, the collection routines must support simple (up to eight item) menu or form styles of processing. On dumb terminals, forms processing becomes a set of one line questions. Without this capability, the application needs to be modified to support new security questions.
The SIA defines the security mechanism components that are required to port to the Digital UNIX system. These components are as follows:
The shared library must contain all of the siad_*() routines described in this chapter. The default dummy routine for any siad_*() routine always returns the SIADFAIL failure response. If a security mechanism is supplying dummy routines, these routines should not be configured into the matrix.conf file.
The /etc/sia/matrix.conf file contains one line for each siad_*() routine. This line contains the mechanism identifiers (called mech_types) and the actual path to the security mechanism library. The sia_*() routines use this set of keys to call mechanisms in a right to left ordering. Example 13-1 illustrates the default matrix.conf settings for Digital UNIX.
If the DCE security mechanism is to be called first followed by the BASE (BSD) security mechanism, the configuration line for siad_init() might look like the following:
siad_init=(DCE,/usr/shlib/libdcesia.so)(BSD,libc.so)
Layered security products must deliver pretested matrix.conf files on their kits. The relinking of a SIA matrix.conf file is followed by a reboot. System administrators must never be required to edit a live matrix.conf file.
See Chapter 13 for a more detailed discussion of the matrix.conf file.
Security mechanisms are required to provide all of the siad_*() entry points (See Table 20-3). The default stub routine should simply return SIADFAIL. With the exception of the session routines, no stubs should ever be called in the /etc/sia/matrix.conf file. The session routines must all have the same number and order of mechanism to keep the mechanism index (mechind) consistent. However, if an error in configuration occurs, the stub routines deliver the appropriate SIADFAIL response.
The order of security mechanisms in the /etc/sia/matrix.conf file is the same for each class of interfaces. Therefore, if a security mechanism supports session processing it is called in the same order for all the session related interfaces.
The layered security mechanism should provide a set of private entry points prefixed by mechanism_name__ for each of the siad_*() entries used for internal calls within the mechanism to siad_*() routines. An example of this is in the BASE mechanism in libc. To assure that the BASE mechanism is calling its own siad_getpwuid() routine, a separate entry point is created and called from the siad_getpwuid() entry as follows:
int siad_getpwuid(uid_t uid, struct passwd *result, \ char *buffer, int buflen) { return(bsd_siad_getpwuid(uid,result,buffer,buflen)); }
static int bsd_siad_getpwuid(uid_t uid, struct passwd *result, \ char *buffer, int buflen) { /* The BSD security mechanism siad_getpwuid() routine */ }
If the convention of supplying internal names is used for all of the siad_*() entry points, a layered security mechanism can then produce a separate library containing all the security mechanism-dependent code. This leaves the configured shared library with only stubs that call the other library.
Security mechanisms generally fall into two categories: local and distributed. The local security mechanism is responsible for establishing all of the local context required to establish a session on the local system. There are two local security mechanism in Digital UNIX: the BASE mechanism and the ENHANCED mechanism.
Distributed mechanisms, like DCE, are more concerned with establishing distributed session context like Kerberos tickets. However, the distributed security mechanism may provide some local context that can be used by the local security mechanism. The distributed security mechanism may also provide a sufficiently strong authentication to allow a local mechanism to trust it for authentication. This notion of one mechanism trusting another is called vouching and allows the user to be authenticated only once to establish a login session. Local mechanisms should always be configured last in the calling sequences.
All of the SIA capabilities listed in this section can be configured to use multiple security mechanisms.
If you want to have your own single-user security mode, you need to rebuild and replace the commands and utilities affected, such as any staticly linked binaries found in /sbin. This can be accomplished by providing a siad_*() routine library to precede libc in the link order for the affected commands.
The new routines need to override the \_\_siad_*() routines, as opposed to the siad_*() routines. The siad_*() naming convention is the weak symbol, while the \_\_siad_*() convention is the strong symbol entry point that is actually used. See Appendix E for more information about routine naming conventions.