This section discusses the interfaces for working with privileges. To use the privilege programming interfaces, you need the following header file.
#include <priv.h>
Example 3, Using Least Privilege Bracketing in Code demonstrates how privilege interfaces are used in a privileged application.
The major data types that are used by the privilege interfaces are:
Privilege type – An individual privilegeis represented by thepriv_t type definition. You initializea variable of typepriv_t with a privilege ID string, asfollows:
priv_t priv_id = PRIV_FILE_DAC_WRITE;
Privilege set type – Privilege sets are representedby thepriv_set_t data structure. Use one of the privilegemanipulation functions shown inFigure 1, Table 1, Interfaces for Using Privileges to initialize variables of typepriv_set_t.
Privilege operation type – The type of operation tobe performed on a file or process privilege set is represented by thepriv_op_t type definition. Not all operations are valid for every type ofprivilege set. Read the privilege set descriptions inProgramming with Privileges for details.
Privilege operations can have the followingvalues:
PRIV_ON – Turn the privilegesthat have been asserted in thepriv_set_t structure onin the specified file or process privilege set.
PRIV_OFF – Turn the privileges assertedin thepriv_set_t structure off in the specified file orprocess privilege set.
PRIV_SET – Set the privileges in thespecified file or process privilege set to the privileges asserted in thepriv_set_t structure. If the structure is initialized to empty,PRIV_SET sets the privilege set tonone.
The following table lists the interfaces for using privileges. Descriptions of some major privilege interfaces are provided after the table.
|
The main function for setting privileges issetppriv(), which has the following syntax:
int setppriv(priv_op_top, priv_ptype_twhich, priv_set_t*set);
op represents the privilege operation thatis to be performed. Theop parameter has one ofthree possible values:
PRIV_ON – Adds the privileges thatare specified by theset variable to the set typethat is specified bywhich
PRIV_OFF – Removes the privilegesthat are specified by theset variable from theset type that is specified bywhich
PRIV_SET – Uses the privileges thatare specified by theset variable to replace privilegesin the set type that is specified bywhich
which specifies the type of privilege setto be changed, as follows:
PRIV_PERMITTED
PRIV_EFFECTIVE
PRIV_INHERITABLE
PRIV_LIMIT
set specifies the privileges to be used inthe change operation.
In addition, a convenience function is provided:priv_set().
These functions are convenient for mapping privilege names with their numeric values.priv_str_to_set() is a typical function in this family.priv_str_to_set() has the following syntax:
priv_set_t *priv_str_to_set(const char *buf, const char *set, \const char **endptr);
priv_str_to_set() takes a string of privilege namesthat are specified inbuf.priv_str_to_set() returnsa set of privilege values that can be combined with one of the four privilegesets.**endptr can be used to debug parsing errors.
Note that the following keywords can be included inbuf:
"all" indicates all definedprivileges."all,!priv_name,..." enables you to specify all privileges except the indicatedprivileges.
"none" indicates no privileges.
"basic" indicates the set ofprivileges that are required to perform operations that are traditionallygranted to all users on login to a standard UNIX operating system.
This section compares how privileges are bracketed using the superusermodel and the least privilege model.
The following program demonstrates how privileged operations are bracketed in the superuser model.
/* Program start */uid = getuid();seteuid(uid);/* Privilege bracketing */seteuid(0);/* Code requiring superuser capability */.../* End of code requiring superuser capability */seteuid(uid);.../* Give up superuser ability permanently */setreuid(uid,uid);
This example demonstrates how privileged operations are bracketed in the least privilege model. The example uses the following assumptions:
The program issetuid 0.
The permitted and effective sets are initially set to allprivileges as a result ofsetuid 0.
The inheritable set is initially set to the basic privileges.
The limit set is initially set to all privileges.
An explanation of the example follows the code listing.
Example 3 Using Least Privilege Bracketing in Code1 #include <priv.h>2 /* Always use the basic set. The Basic set might grow in future3 * releases and potentially restrict actions that are currently4 * unrestricted */5 priv_set_t *temp = priv_str_to_set("basic", ",", NULL);6 /* PRIV_FILE_DAC_READ is needed in this example */7 (void) priv_addset(temp, PRIV_FILE_DAC_READ);8 /* PRIV_PROC_EXEC is no longer needed after program starts */9 (void) priv_delset(temp, PRIV_PROC_EXEC);10 /* Compute the set of privileges that are never needed */11 priv_inverse(temp);12 /* Remove the set of unneeded privs from Permitted (and by13 * implication from Effective) */14 (void) setppriv(PRIV_OFF, PRIV_PERMITTED, temp);15 /* Remove unneeded priv set from Limit to be safe */16 (void) setppriv(PRIV_OFF, PRIV_LIMIT, temp);17 /* Done with temp */18 priv_freeset(temp);19 /* Now get rid of the euid that brought us extra privs */20 (void) seteuid(getuid());21 /* Toggle PRIV_FILE_DAC_READ off while it is unneeded */22 priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_FILE_DAC_READ, NULL);23 /* Toggle PRIV_FILE_DAC_READ on when special privilege is needed*/24 priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_FILE_DAC_READ, NULL);25 fd = open("/some/restricted/file", O_RDONLY);26 /* Toggle PRIV_FILE_DAC_READ off after it has been used */27 priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_FILE_DAC_READ, NULL);28 /* Remove PRIV_FILE_DAC_READ when it is no longer needed */29 priv_set(PRIV_OFF, PRIV_ALLSETS, PRIV_FILE_DAC_READ, NULL);
The program defines a variable that is namedtemp.Thetemp variable determines the set of privilegesthat are not needed by this program. Initially in line 5,temp isdefined to contain the set of basic privileges. In line 7, thefile_dac_read privilege is added totemp. Theproc_exec privilege is necessary toexec(1) new processes, which is not permitted in this program.Therefore,proc_exec is removed fromtemp inline 9 so that theexec(1) command cannot run new processes.
At this point,temp contains only those privilegesthat are needed by the program, that is, the basic set plusfile_dac_read minusproc_exec. In line 11, thepriv_inverse() function computes the inverse oftemp andresets the value oftemp to the inverse. The inverseis the result of subtracting the specified set,temp inthis case, from the set of all possible privileges. As a result of line 11,temp now contains those privileges that are never needed bythe program. In line 14, the unneeded privileges that are defined bytemp are subtracted from the permitted set. This removal effectivelyremoves the privileges from the effective set as well. In line 16, the unneededprivileges are removed from the limit set. In line 18, thetemp variableis freed, sincetemp is no longer needed.
This program is aware of privileges. Accordingly, the program does notusesetuid and can reset the effective UID to the user'sreal UID in line 20.
Thefile_dac_read privilege is turned off in line22 through removal from the effective set. In a real program, other activitieswould take place beforefile_dac_read is needed. In thissample program,file_dac_read is needed for to read a filein line 25. Accordingly,file_dac_read is turned on inline 24. Immediately after the file is read,file_dac_read isagain removed from the effective set. When all files have been read,file_dac_read is removed for good by turning offfile_dac_read inall privilege sets.
The following table shows the transition of the privilege sets as theprogram progresses. The line numbers are indicated.
|