This section provides short examples of the Trusted Solaris security mechanisms to give you an idea of how they are used. Every example in this section has a corresponding chapter, and the interface declarations can be found in the chapters. All examples compile with the -ltsol library, and in some cases, other libraries are also needed as noted with the example.
Privileges let a process perform security-related tasks normally prohibited by the system security policy. Authorizations let a user perform privileged tasks not allowed to all users. Every authorization maps to a privileged task. Always check a user's authorizations before allowing a privileged task to take place.
The development, testing, and debugging of privileged applications should always be on an isolated development machine to prevent bugs and incomplete code from compromising security policy on the main system.
Privileges distribute security-related powers so a process has enough power to perform a task and no more. Likewise, authorizations distribute security-related powers so each user or role has enough power to perform a task and no more.
The system administrator assigns authorizations to users and roles through an execution profile. The chkauth(3TSOL) routine accepts a valid user name and authorization as parameters and returns true if the authorization is assigned to that user. During development, privileges can be assigned to the executable file and/or inherited from the user's or role's executable profile at run time.
To know if a program performs tasks that require privilege and user authorization checks, ask these questions:
Does the task require privilege?
Information on privileges for system calls is on the Intro(2) man page and the man page for the particular system call.
Information on privileges for library routines is on the man page for the library routine or the man page for the underlying system call if there is an underlying system call. Check the See Also section of the library routine man page for a list of system calls where you can find privilege information if there is no information on the library routine man page.
The priv_desc(4) man page provides a list of Trusted Solaris privileges and a description of the tasks they enable.
Refer to Chapter 3, Privileges for information to help you decide if the privileges should be assigned to the file, inherited, or both.
Use privilege debugging mode as described in Trusted Solaris Administrator's Procedures or "Privilege Debugging" in Appendix A, Programmer's Reference" to find out what privileges an application needs.
Does the task have an authorization? - The Trusted Solaris authorizations and their descriptions are in /etc/security/auth_attr.
This example checks the process permitted set for the file_downgrade_sl privilege, and the user authorization solaris.label.file.downgrade for user ID zelda before performing a task that involves downgrading the sensitivity label on a file. If the privilege is in the permitted set and if zelda has the authorization, the code turns the file_downgrade_sl privilege on in the effective set (makes the privilege effective) and performs the task. When the task completes, file_downgrade_sl is turned off (is no longer effective).
The example compiles with the following libraries:
-lsecdb -lnsl -lcmd -ltsol |
The permitted set contains the privileges the process can potentially use during execution, and the effective set contains the privileges the process is actually using at a given time. Turning effective privileges on and off is called privilege bracketing and is discussed in Chapter 3, Privileges.
#include <tsol/priv.h> #include <tsol/auth.h> main() { char *zelda = "zelda"; priv_set_t priv_set; /* Retrieve the permitted privilege set */ getppriv(PRIV_PERMITTED, &priv_set); if(PRIV_ISASSERT(&priv_set, PRIV_FILE_DOWNGRADE_SL) && chkauthattr(solaris.label.file.downgrade, zelda)) { set_effective_priv(PRIV_ON, 1, PRIV_FILE_DOWNGRADE_SL); /* Downgrade sensitivity label on file*/ set_effective_priv(PRIV_OFF, 1, PRIV_FILE_DOWNGRADE_SL); } else {/* Raise Errors */} }
When a process writes to a file with a higher sensitivity label or changes the CMW label of an object, the system checks that the file sensitivity label dominates the process sensitivity label and the process clearance dominates the file sensitivity label. If your application writes to files at different sensitivity labels, you might want to perform these checks in the code to catch errors or to turn privileges on in the effective set as needed.
This code performs the following tasks:
Retrieves the binary file CMW label, process CMW label, and process clearance.
Retrieves the sensitivity label portion of the file CMW label and process CMW label.
Checks for dominance by comparing the process sensitivity label to the file sensitivity label, and the process clearance to the file sensitivity label.
If the comparisons return 0 (process sensitivity label and clearance do not dominate the file sensitivity label), the operation to change the file CMW label or write up to the file requires privilege. See "Privileges and Authorizations" for information on privileges.
Chapter 4, Labels and Chapter 6, Process Clearance describe the programming interfaces for translating a binary label or clearance to text so they can be handled like a string.
#include <tsol/label.h> main() { int retval, retvalclearance, retvalsens; bclabel_t filecmwlabel, processcmwlabel; bslabel_t filesenslabel, processsenslabel; bclear_t processclearance; char *file = "/export/home/labelfile"; /* Get CMW label of file */ retval = getcmwlabel(file, &filecmwlabel); /* Get Process CMW label */ retval = getcmwplabel(&processcmwlabel); /* Get sensitivity label portion of CMW labels */ getcsl(&filesenslabel, &filecmwlabel); getcsl(&processsenslabel, &processcmwlabel); /* Get process clearance */ retval = getclearance(&processclearance); /* See if process label dominates file label (retvalclearance > 0) */ retvalclearance = bldominates(&processsenslabel, &filesenslabel); /* See if process clearance dominates file label (retvalsens > 0) */ retvalsens = bldominates(&processclearance, &filesenslabel); /* Test results */ if(retvalclearance && retvalsens > 0) { /* Change file CMW label or write-up to file */} else if (retvalclearance == 0) { /* Turn on error message or make appropriate privilege effective */} else if (retvalsens == 0) { /* Turn on error message or make appropriate privilege effective*/} }
Multilevel directories (MLDs) enable an application to run at different sensitivity labels and access data in the single-level directory (SLD) at the sensitivity label at which its process was launched. This example shows how to get the name for the Confidential SLD in the zelda MLD by translating a text string to binary with stobsl(3TSOL) and passing the binary label to getsldname(1). The /export/home/zelda MLD is at ADMIN_LOW and the process is running at Confidential. The process needs no privileges because it has mandatory read access to the MLD and the process sensitivity label dominates the SLD sensitivity label.
#include <tsol/mld.h> char *file = "/export/home/zelda"; char buffer[3*1024]; bslabel_t senslabel; int length, flags, retval, error; main() { /* Get the Confidential SLD name */ retval = stobsl("CONFIDENTIAL", &senslabel, NEW_LABEL, &error); length = sizeof(buffer); retval = getsldname(file, &senslabel, buffer, length); printf("SLD Name = %s\n", buffer); }
The printf statement prints the name of the SLD at ADMIN_LOW. See Chapter 7, Multilevel Directories for the meaning of the SLD name.
SLD Name = .SLD.2 |
You can get file attribute information for an MLD or symbolic link that is an MLD with the mldstat(3TSOL) and mldlstat(3TSOL) system calls. See also the stat(2) man page and Chapter 7, Multilevel Directories.
An application can log its own third-party audit events with the auditwrite(3TSOL) library routine. This example creates a user audit record in one call to auditwrite(). The audit event logged is AUE_su with the text "successful login at console". Normally, auditwrite() logs application-level audit events. This example logs a Trusted Solaris user event to show how the routine is used. Chapter 8, Application Auditing shows third-party audit events.
The process executing this program needs the proc_audit_tcb privilege in its effective set because AUE_su is a Trusted Computing Base (TCB) audit event. The code comments indicate where privilege bracketing as described in Chapter 3, Privileges should take place. The aw_strerror(3TSOL) routine converts auditwrite error messages (aw_errno) to strings. The parameters passed to auditwrite() are as follows:
AW_EVENT specifies the audit event to be written to the audit log. AW_EVENT is a user event string name as defined in audit_event. There can be only one event written to a single audit record.
AW_TEXT is a null-terminated string placed in the audit record to provide additional information on the audit event.
AW_WRITE writes the event and its associated text to the audit trail.
AW_END tells auditwrite() to stop parsing information.
#include <bsm/auditwrite.h> #include <types.h> #include <unistd.h> main() { char *aw_string; int retval, errno; /* Turn proc_audit_tcb on in the effective set */ retval = auditwrite( AW_EVENT, "AUE_su", AW_TEXT, "Successful login at console", AW_WRITE, AW_END); /* Turn the proc_audit_tcb privilege off */ aw_string = aw_strerror(aw_errno); printf("Retval = %d AW_ERROR = %s ERRNO = %d\n", retval, aw_string, errno); }
To run the program and view the audit record, do the following:
Assume an administrative role, open a terminal at ADMIN_HIGH, and execute the following command where lo is the class to which AUE_su belongs and pid is the process ID of the terminal.
#auditconfig -setpmask pid lo
Assume an administrative role, open a second viewing terminal at ADMIN_HIGH, and use praudit(1M) to read the not_terminated (most recent and not yet closed) audit log file by typing the command and options shown:
This syntax works when there is only one *not_terminated* file. If there are others, delete the older ones before executing this command.
phoenix% tail -0f *not_terminated* | praudit |
Compile and run the code from the first terminal window.
These libraries are needed for the example to successfully compile. -lbsm -lnsl -lintl -lsocket -ltsol
The process needs the proc_audit_tcb privilege for this example to work. Use setfpriv(1) to set the privileges as follows. The file_setpriv privilege is required with setfpriv(1)so this command must be executed from the profile shell with this privilege. phoenix% setfpriv -s -a proc_audit_tcb executable
The printf statement prints the following in the first terminal window:
Retval = 0, AW_ERROR = No error, ERRNO = 0
The viewing window shows the following audit record:
header, 129,2,su,,Wed Jun 26 14:50:19 1996, +698 msec text, Successful login at console subject,zelda,zelda,staff,zelda,staff,1050,853,24,7 phoenix slabel,Confidential return,success,0 |
The audit record consists of a sequence of tokens. Each line starts with a token followed by the token value. In the example, the tokens for audit event AUE_su are header, text, subject, slabel, and return; and the token values are the information following the tokens until the next token is encountered. Trusted Solaris Audit Administration describes the tokens in detail.