JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Developer's Guide to Oracle Solaris 11 Security     Oracle Solaris 11.1 Information Library
search filter icon
search icon

Document Information

Preface

1.  Oracle Solaris Security for Developers (Overview)

2.  Developing Privileged Applications

Privileged Applications

About Privileges

How Administrators Assign Privileges

How Privileges Are Implemented

Permitted Privilege Set

Inheritable Privilege Set

Limit Privilege Set

Effective Privilege Set

Compatibility Between the Superuser and Privilege Models

Privilege Categories

Programming with Privileges

Privilege Data Types

Privilege Interfaces

setppriv(): for Setting Privileges

priv_str_to_set() for Mapping Privileges

Privilege Coding Example

Privilege Bracketing in the Superuser Model

Privilege Bracketing in the Least Privilege Model

Guidelines for Developing Privileged Applications

About Authorizations

3.  Writing PAM Applications and Services

4.  Writing Applications That Use GSS-API

5.  GSS-API Client Example

6.  GSS-API Server Example

7.  Writing Applications That Use SASL

8.  Introduction to the Oracle Solaris Cryptographic Framework

9.  Writing User-Level Cryptographic Applications

10.  Introduction to the Oracle Solaris Key Management Framework

A.  Secure Coding Guidelines for Developers

B.  Sample C-Based GSS-API Programs

C.  GSS-API Reference

D.  Specifying an OID

E.  Source Code for SASL Example

F.  SASL Reference Tables

Glossary

Index

Programming with Privileges

This section discusses the interfaces for working with privileges. To use the privilege programming interfaces, you need the following header file.

#include <priv.h>

An example demonstrating how privilege interfaces are used in a privileged application is also provided.

Privilege Data Types

The major data types that are used by the privilege interfaces are:

Privilege Interfaces

The following table lists the interfaces for using privileges. Descriptions of some major privilege interfaces are provided after the table.

Table 2-1 Interfaces for Using Privileges

Purpose
Functions
Additional Comments
Getting and setting privilege sets
setppriv() and getppriv() are system calls. priv_ineffect() and priv_set() are wrappers for convenience.
Identifying and translating privileges
These functions map the specified privilege or privilege set to a name or a number.
Manipulating privilege sets
These functions are concerned with privilege memory allocation, testing, and various set operations.
Getting and setting process flags
The PRIV_AWARE process flag indicates whether the process understands privileges or runs under the superuser model. PRIV_DEBUG is used for privilege debugging.
Low-level credential manipulation
These routines are used for debugging, low-level system calls, and kernel calls.

setppriv(): for Setting Privileges

The main function for setting privileges is setppriv(), which has the following syntax:

int setppriv(priv_op_t op, priv_ptype_t which, \
const priv_set_t *set);

op represents the privilege operation that is to be performed. The op parameter has one of three possible values:

which specifies the type of privilege set to be changed, as follows:

set specifies the privileges to be used in the change operation.

In addition, a convenience function is provided: priv_set().

priv_str_to_set() for Mapping Privileges

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 names that are specified in buf. priv_str_to_set() returns a set of privilege values that can be combined with one of the four privilege sets. **endptr can be used to debug parsing errors.

Note that the following keywords can be included in buf:

Privilege Coding Example

This section compares how privileges are bracketed using the superuser model and the least privilege model.

Privilege Bracketing in the Superuser Model

The following example demonstrates how privileged operations are bracketed in the superuser model.

Example 2-1 Superuser Privilege Bracketing Example

/* 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);

Privilege Bracketing in the Least Privilege Model

This example demonstrates how privileged operations are bracketed in the least privilege model. The example uses the following assumptions:

An explanation of the example follows the code listing.


Note - The source code for this example is also available through the Oracle download center. See http://www.oracle.com/technetwork/indexes/downloads/sdlc-decommission-333274.html.


Example 2-2 Least Privilege Bracketing Example

1  #include <priv.h>
2  /* Always use the basic set. The Basic set might grow in future
3   * releases and potentially retrict actions that are currently
4   * 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 by
13   * 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/retricted/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 named temp. The temp variable determines the set of privileges that are not needed by this program. Initially in line 5, temp is defined to contain the set of basic privileges. In line 7, the file_dac_read privilege is added to temp. The proc_exec privilege is necessary to exec(1) new processes, which is not permitted in this program. Therefore, proc_exec is removed from temp in line 9 so that the exec(1) command cannot execute new processes.

At this point, temp contains only those privileges that are needed by the program, that is, the basic set plus file_dac_read minus proc_exec. In line 11, the priv_inverse() function computes the inverse of temp and resets the value of temp to the inverse. The inverse is the result of subtracting the specified set, temp in this case, from the set of all possible privileges. As a result of line 11, temp now contains those privileges that are never needed by the program. In line 14, the unneeded privileges that are defined by temp are subtracted from the permitted set. This removal effectively removes the privileges from the effective set as well. In line 16, the unneeded privileges are removed from the limit set. In line 18, the temp variable is freed, since temp is no longer needed.

This program is aware of privileges. Accordingly, the program does not use setuid and can reset the effective UID to the user's real UID in line 20.

The file_dac_read privilege is turned off in line 22 through removal from the effective set. In a real program, other activities would take place before file_dac_read is needed. In this sample program, file_dac_read is needed for to read a file in line 25. Accordingly, file_dac_read is turned on in line 24. Immediately after the file is read, file_dac_read is again removed from the effective set. When all files have been read, file_dac_read is removed for good by turning off file_dac_read in all privilege sets.

The following table shows the transition of the privilege sets as the program progresses. The line numbers are indicated.

Table 2-2 Privilege Set Transition

Step
temp Set
Permitted Privilege Set
Effective Privilege Set
Limit Privilege Set
Initially
all
all
all
Line 5 – temp is set to basic privileges
basic
all
all
all
Line 7 – file_dac_read is added to temp.
basic + file_dac_read
all
all
all
Line 9 – proc_exec is removed from temp.
basic + file_dac_readproc_exec
all
all
all
Line 11 – temp is reset to the inverse.
all – (basic + file_dac_readproc_exec)
all
all
all
Line 14 – The unneeded privileges are turned off in the permitted set.
all – (basic + file_dac_readproc_exec)
basic + file_dac_readproc_exec
basic + file_dac_readproc_exec
all
Line 16 – The unneeded privileges are turned off in the limit set.
all – (basic + file_dac_readproc_exec)
basic + file_dac_readproc_exec
basic + file_dac_readproc_exec
basic + file_dac_readproc_exec
Line 18 – The temp file is freed.
basic + file_dac_readproc_exec
basic + file_dac_readproc_exec
basic + file_dac_readproc_exec
Line 22 – Turn off file_dac_read until needed.
basic – proc_exec
basic – proc_exec
basic + file_dac_readproc_exec
Line 24 – Turn on file_dac_read when needed.
basic + file_dac_readproc_exec
basic + file_dac_readproc_exec
basic + file_dac_readproc_exec
Line 27 – Turn off file_dac_read after read() operation.
basic – proc_exec
basic – proc_exec
basic + file_dac_readproc_exec
Line 29 – Removefile_dac_read from all sets when no longer needed.
basic – proc_exec
basic – proc_exec
basic – proc_exec