Authorization Infrastructure in Solaris
Authorization Infrastructure in Solaris   By Glenn Faden, August 2001  

Abstract

An authorization infrastructure was added to the Solaris 8 operating environment as part of the role-based access control (RBAC) project, which provides a common mechanism for managing the rights of users and roles. Although RBAC is used extensively in the Solaris Management Console and in Trusted Solaris, it is not widely used in other products.

This article outlines the advantages of a common infrastructure for managing authorizations, and describes how authorization enforcement, hierarchy, delegation, and scope are supported. It provides examples in C and Java programming languages. Finally, it discusses how authorizations can be associated with executables to restrict access to authorized users.

Introduction

In traditional UNIX® systems, the root user is the superuser, and is exempt from all policy enforcement. The problem with this approach is not just that root is so powerful; it is that everyone else is so weak. Root access is required to perform almost all aspects of administration. There is no hierarchy of privileged operations, no separation of powers, nor the ability to delegate any of the powers to others. There is a mismatch between what is necessary and what is sufficient with respect to access control. For example, setting the system date requires root access, which in turn provides full access to the system.

An authorization infrastructure can be used to distribute some of the superuser's powers. This is not the same thing as actually restricting the power of root. Systems that fully implement the principle of least privilege, such as Trusted Solaris, actually replace the traditional kernel policy with one based on fine-grained privileges. Authorizations can be used on systems with either the traditional superuser implementation, or a privilege based implementation.

Authorizations

The terms privilege and authorization are frequently used interchangeably. In this article these terms are used to mean different things, and it will help to understand the context of each term.

A privilege is an attribute of a process that is used to override a standard security policy. In traditional UNIX, all root processes are privileged because they may override any kernel policy. However, in systems that implement the principle of least privilege in the kernel, an arbitrary number of fine grained privileges can be associated with a process, each of which is used to override a specific policy.

An authorization is a right assigned to a user or a role that is used to grant access to an otherwise restricted operation. These are generally checked by privileged programs to restrict some of their inherent functionality.

A variety of authorization systems have been used in the Solaris product. These systems share no common framework, are generally not supported in name services, and are difficult to maintain. A common defect is that there are many configuration files, each containing lists of authorized users rather than direct links to the user. Thus, many files need to be modified as the user population changes, and in addition, authorizations cannot be managed globally.

In the Solaris 8 operating environment, a new authorization system was introduced as part of the role-based access control (RBAC) infrastructure. RBAC authorizations address most of the deficiencies because they are managed consistently and scale well. However, they are not widely used at this time because they are new and not well understood. This article describes some of the advantages of RBAC authorizations and provides examples of their use.

Legacy Authorization Checks

An authenticated user ID is required for authorization checking. Programs that are setuid generally use getuid(2) to determine who they are executing for because they are intended to be executed by normal users. Daemons that need to identify the client typically use an authentication protocol such as AUTH_DES. Login services identify and authenticate the user through a PAM conversation.

Authorization checking in existing Solaris privileged programs fall into three categories:

  1. Programs that check user authorizations
  2. Programs that check for root
  3. Programs that don't check any IDs

Programs that Check User Authorizations

The following table gives some examples of privileged commands and the various mechanisms they use to do authorization checking:

Command Positive Authorization Negative Authorization allocate RBAC authorizations   crontab cron.allow and RBAC authorizations cron.deny at at.allow and RBAC authorizations at.deny pmconfig /etc/default/pwer   sys-suspend /etc/default/sys-suspend   sunscreen GUI list of admin users   lpadmin -u allow -u deny

Servers also use a variety of mechanisms. The following table provides examples of servers that check for authorization using various mechanisms.

Service Positive Authorization Negative Authorization Solaris Management Console RBAC authorizations   Sun Management Center Admin, Operator, and General Access   nisd NIS+ groups   X server .xhost +name xhost -name rlogind hosts.equiv hosts.equiv

Programs that Check for Root

Root checks in programs are generally redundant since the kernel makes the same check in the system call. Such checks should be scrutinized since the Solaris kernel policy is evolving. A policy of least privilege is being developed that will provide an alternative to the superuser. Therefore, root checks in applications should either be replaced by better error handling or by authorization checks. The following table provides examples of programs that check for root rather than use authorization checks.

Program Problem mount inflexible root check halt inconsistent with sys-suspend sacadm suid but requires real uid=0 for most functions

Programs that Don't Check Any IDs

Most programs rely on the kernel for all security enforcement. However, if they are setuid (or could be), they may be candidates for authorization checks. The following table includes some setuid programs that allow any user to perform sensitive operations. These are clearly candidates for authorization checks.

Program Risk fdformat Allows anyone to reformat a diskette regardless of ownership ffbconfig Allows anyone to change the persistent frame buffer settings regardless of workstation ownership

RBAC Infrastructure

RBAC extends the general concept of authorization by introducing the concept of roles. A role is a special identity that may be assumed by authorized users to perform restricted operations. A principal may be either a user or a role. When a role is assumed, the authorizations associated with the user are replaced by those of the role. If BSM auditing is enabled, the actions of a role are auditable, and each audit records indicates on whose behalf the role is operating. The user who assumed the role is recorded as the audit ID, while the role is recorded as the real user ID. Central to the RBAC design is the notion that root is a role, and that anonymous logins as root are disallowed. However, in order to provide an opportunity for users to become familiar with RBAC, root is not a role by default in Solaris, and must be explicitly declared as a role in the RBAC user attribute database, user_attr(4).

Authorizations in RBAC are fine-grained, like privileges, but they are not directly associated with processes. Instead, they are looked up in the user_attr database based on the identity of the principal. Privilege checks are typically done in the kernel, while authorization checks should be done in applications and services.

An authorization name is a unique string that identifies the organization that created the authorization and the functionality it controls. Following the Java convention, the hierarchical individual components of an authorization are separated by a dot (.), starting with the reverse order Internet domain of the creating organization, and ending with the specific function within a class of authorizations.

An asterisk is used as a wildcard to indicate all authorizations in a class. When an authorization check is made, the authorization is compared against the explicitly assigned authorization and any wildcard entries covering the class (or superclass) of the authorization. For example,

solaris.role.*

covers the authorizations

solaris.role.delegate, solaris.role.assign, solaris.role.write.

By using the wildcard suffix discussed above, a set of hierarchical authorizations can be managed using a single assignment.

Delegation

When the authorization name ends with the keyword grant, the authorization is used to support fine-grained delegation. Principals with appropriate grant authorizations can delegate some of their authorizations to others. To delegate an authorization, the principal needs to have both the authorization and an appropriate grant authorization that covers it. In addition, the principal must be authorized in the same domain as the one in which the assignment is made.


Figure 1: Solaris Management Console Rights Manager Authorizations Tab
(Click image to enlarge.)

Authorizations are the key to providing separation of powers, and delegation. The databases that are used to maintain attributes of users and roles are managed by the Solaris Management Console, shown in Figure 1. Neither users nor roles are permitted to assign authorizations unless they satisfy the delegation policy. The Management Console enforces the appropriate authorization policy for any transaction that takes place. The principal making the request must be authenticated and authorized for the specific update or query in the domain in which the data is maintained.

For practical reasons, it is often required to have a chief security officer who has all authorizations. This is expressed by assigning the two authorizations solaris.* and solaris.grant. The chief security officer can use these authorizations to delegate powers to other principals.


Default Authorizations

Maintaining explicit authorizations for a large community of users can be burdensome. To make it less so, the RBAC infrastructure provides significant flexibility and scalability. For example, instead of assigning authorizations directly to principals (using the auth_attr database), system-wide defaults can be specified in the file /etc/security/policy.conf. This file can enumerate authorizations that are granted implicitly to all principals. Therefore, individual user_attr entries for most users are not generally required.

Rights Profiles

Rights profiles provide another mechanism for aggregating authorizations. The prof_attr(4) database is used to maintain lists of profiles, each of which can contain a list of authorizations or authorization hierarchies. Rights profiles themselves can contain other rights profiles to support rights hierarchies. When a rights profile is assigned to a principal using the user_attr database, all of the authorizations in that profile, and any nested profiles, are assigned to the principal.

The Rights Properties tool in the Management Console is used to manage the attributes of individual rights profiles. Authorizations that are assigned to a right may only be changed by a principal who has both a covering wildcard authorization and a covering grant authorization. Authorization assignments that cannot be changed by the current principal are dimmed in the GUI.

Distributed Authorizations

Another important feature is that the authorization databases can be maintained in any of the standard Solaris name services: files, NIS, NIS+, and LDAP. Therefore, authorizations can be maintained on a central server and apply consistently to all machines in a domain. On the other hand, the use of the name service switch allows an administrator to extend or restrict a principal's distributed set of authorizations on a per-machine basis. Both the passwd(4) and prof_attr entries can affect how authorizations are interpreted on a specific machine. For example, by placing files ahead of nisplus in the prof_attr entry, the definition of rights profiles (which contain authorization lists) can be overridden on individual machines.

Authorization API

RBAC authorization checks are provided for both C/C++ and Java programs. The C/C++ API is implemented in the library libsecdb.so. The Java APIs are implemented using the Java Native Interface (JNI), which uses the same functions in libsecdb.so, so the implementation is compatible.

C/C++ Example

The primary authorization function is chkauthattr(3).

chkauthattr

int chkauthattr(const char *authname, const char* username);

The chkauthattr() function verifies whether or not a principal has a given authorization. It first reads the AUTHS_GRANTED key in the /etc/security/policy.conf file and returns 1 if it finds a match for the given authorization. If chkauthattr() does not find a match, it reads the PROFS_GRANTED key in policy.conf and returns 1 if the given authorization is in any profiles specified with the PROFS_GRANTED keyword. If a match is not found from the default authorizations and default profiles, chkauthattr() reads the user_attr database. If it does not find a match in user_attr, it reads the prof_attr database, using the list of profiles assigned to the principal, and checks if any of the profiles assigned to the principal has the given authorization.The chkauthattr() function returns 0 if it does not find a match in any of the three sources.

A principal is considered to have been assigned an authorization if either of the following is true:

  • The authorization name matches exactly any authorization assigned in the user_attr or prof_attr databases (authorization names are case-sensitive).
  • The authorization name suffix is not the keyword grant and the authorization name matches any authorization up to the asterisk (*) character assigned in the user_attr or prof_attr databases.

The following code fragment demonstrates a typical authorizations check.


#define CRONADMIN_AUTH "solaris.jobs.admin" 

    user = getuid();
    pwd = getpwuid_r(user, &pwds, buf_pwd, 
        sizeof(buf_pwd));
    if (pwd == NULL) { 
            atabort("Invalid user.n");
    }
    if (!chkauthattr(CRONADMIN_AUTH, pwd->pw_name))
            return NOT_AUTHORIZED;

Solaris Management Console SDK Example

In the Solaris Management Console SDK, the public interface is defined in the class com.sun.management.viper.services.Authorization. The Authorization service is used to determine whether an action towards some critical system resource is to be allowed or denied, based on the security policy currently in effect. Each action authorization is represented with a VPermission object that extends the Java 2 Permission class. VPermission is defined by a properly scoped action name string, for example: solaris.admin.usermgr.write defines the write authorization in the Solaris User Manager tool.

The following is an example of how the Management Console SDK is used to check an RBAC authorization as a VPermission object.

import com.sun.management.viper.services.Authorization

// This example illustrates how to check authorizations
// for a service that supports write authorizations

public static final String AUTH_MYSERVICE_WRITE =
"solaris.admin.myservice.write";
   
PermissionCollection permissionCollection = null;
ToolInfrastructure infrastructure = <gotten from SMC>;

// Get authorizations.
try {
    Authorization auth =
       (Authorization)infrastructure.getServiceByName(
       ServiceList.AUTHORIZATION);
    permissionCollection = auth.readUserPermissions(
       infrastructure.getIdentity());
} catch (Exception ex) {
     // Report exception
}
...
/*
 * Determine if user is authorized for "write" access.
 *
 * @return  true if user has write authorization,
 * otherwise false
 */
public boolean hasWriteAuthorization() {

    // Allow only if explicitly authorized.

    VPermission perm = new 
      VPermission(AUTH_MYSERVICE_WRITE);
    if ((permissionCollection != null)
      &&permissionCollection.implies(perm))
        return true;

    // Otherwise, deny
        return false;

} // hasWriteAuthorization

Authorization Checking in WBEM

Web-Based Enterprise Management (WBEM) provides a protocol for remote administration. Part of the protocol makes it possible for providers to supply their own authorization infrastructures, and RBAC is used in the Solaris implementation of WBEM.

Many of the tools provided in the Solaris Management Console are implemented using WBEM providers, built on the Solaris WBEM SDK. The Solaris WBEM providers are delivered in the package SUNWwbcou, and are archived in solarisprovider.jar. RBAC authorization checking is done in the method checkRights() in the ProviderUtility class. However, developers should be aware that this interface is likely to change in an upcoming release.

Managing Execution Attributes

Another RBAC feature is the ability to limit privileged execution to authorized principals. Instead of specifying setuid permissions in the file system, RBAC provides a new database, exec_attr(4), in which the security attributes of commands can be enumerated and associated with rights profiles. Figure 2 summarizes the datbase relationships.


Figure 2: Relationships among RBAC Databases
(Click image to enlarge.)

In Solaris 8 the attributes that are supported are real and effective user and group IDs. (The exec_attr database is extensible and can manage other process attributes that may be supported in the future.) Using the effective ID attributes is preferred, not just because it is equivalent to the setuid functionality in the file permission bits, but because it maintains the principal ID used for RBAC authorization. However, there are cases in which shell scripts and other programs require a real user ID of root, so this flexibility is provided.

In order to take advantage of this database, a profile-based launcher is required. The three standard Solaris shells have been enhanced to support profiles, but this feature is only enabled when the shells are invoked with the prefix pf; for example, pfsh(1), pfcsh(1), and pfksh(1). The Management Console legacy application service also supports profile-based execution so a toolbox of restricted applications can be accessed through the Management Console.


Creating New Authorizations

When an application is modified to perform an authorization check, a new authorization may need to be created. A private header file, auth_list.h contains manifest constants for authorizations that are currently used in the Solaris operating environment. It should be updated to facilitate the maintenance of the code. The new authorization should be added to the auth_attr database, and assigned to a rights profile in the prof_attr database. If the authorization is the first member of a new hierarchy, a header entry, with a "dot" suffix should also be provided.

Since RBAC authorizations are intended to be used by any package and any consolidation, it is important to understand how to install new entries in these databases without affecting existing entries. The RBAC databases provide a means to upgrade the databases without destroying content that may have been stored by other development projects or by end-users. Two class action scripts support adding new entries, as well as updating individual fields in existing entries.

The SUNWcsu package installs class action scripts for merging RBAC data in developer installation packages. The package CLASS for these scripts is rbac, so the scripts in /usr/sadm/install/scripts are i.rbac and r.rbac.

Organizing the Data

When adding only authorizations or commands to profiles, use the pre-defined profiles if possible, merging the attributes into them. An alternative is to define your own profile, but merge that profile into one of the existing pre-defined profiles. Avoid creating a lot of small, application specific profiles; rather a profile should represent an entire class of functions and commands, like Network Management.

The SUNWwbcor package includes three profiles, one for the Primary Administrator role, one for the System Administrator role, and one for the Operator role. These profiles do not have authorizations, but include other profiles which, in turn, include authorizations. When adding a new profile to one of these, specify a dependency on the SUNWwbcor package (which delivers them).

Updating the Core Package Build Source

The CLASSES=none rbac variable should be added to the package pkginfo file for the core package since the files are updated in /etc. Add the edit entries in the package prototype file for each attr file being merged. The format of this line is:

e rbac etc/security/XXXX_attr 0444 root bin

Ideally, the files should be merged in the order: auth_attr, prof_attr, exec_attr. It may be necessary to add the SUNWsbcor package to the depend file if attributes are merged into the three profiles it delivers.

Updating the usr Package Build Source

For any new authorizations and profiles, a corresponding help file should be installed. These files are used by the Management Console tools for context help. Authorization help files go into /usr/lib/help/auths/locale/C and profile help files go into /usr/lib/help/profiles/locale/C. The name of the help file should be the same as that specified in the help attribute in the auth_attr or prof_attr entry; only the file name should be specified (the tool knows the path name).

Verifying the RBAC Databases

To facilitate loading and testing changes to these databases, a new utility, smattrpop(1M) has been created. Unlike the package class actions scripts that are used for installation, this program can merge changes into existing databases in any of the supported name services. It can also validate that relationships between the databases, such as authorizations and rights profiles, are consistent. For example, it verifies that each assigned authorization is in auth_attr, and each assigned profile is in prof_attr.

Conclusions

Using a common infrastructure for authorization management has compelling advantages. Not only does it make it easier for customers to manage their environments in a safer fashion, but it provides an extensible mechanism for adding new security attributes to the Solaris operating environment.

For users, the ability to distribute and delegate the administrative responsibilities based on functional needs reduces the risk of accident or abuse. For Solaris developers, it provides a framework that meets current needs and future directions. The fact that Solaris and Trusted Solaris can share the same files is proof of this extensibility. Policy-specific attributes for executable objects, such as privileges, labels, and clearance can be specified, as well as new executable object types, such as CDE actions.

A consistent approach to administrative authorization is clearly the goal. Ultimately, the success of the RBAC infrastructure will depend on how widely and consistently it is used by developers.

References

  1. "RBAC in the Solaris Operating Environment"
  2. "Solaris Management Console 2.0 SDK Programmer`s Guide," including information on authorization infrastructure
  3. "Sun WBEM SDK Developer`s Guide"
  4. "System Administration Guide, Volume 2"
  5. "Trusted Solaris 8 Operating Environment, A Technical Overview"
  6. "Solaris 10 System Administrator Collection"

About the Author

Glenn Faden has worked as an architect and technical contributor in the Trusted Solaris group at Sun Microsystems for over 12 years. His emphasis has been on user interfaces and window systems. He designed the multilevel versions of OpenWindows and the Common Desktop Environment, and the trusted administration tools used in Trusted Solaris. Recently he has been focused on role-based access control (RBAC) and remote administration.

August 2001

Rate and Review Tell us what you think of the content of this page. Excellent   Good   Fair   Poor   Comments:
If you would like a reply to your comment, please submit your email address:
Note: We may not respond to all submitted comments.
Close    To Top
  • Prev Article-OS:
  • Next Article-OS:
  • Now: Tutorial for Web and Software Design > OS > Solaris > OS Content
    Photoshop Tutorial
     

    Special Effect

      3D Effect
      Photoshop Articles
    Programming Tutorial
     

    C/C++ Tutorial

      Visual Basic
      C# Tutorial
    Database Tutorial
     

    MySQL Tutorial

      MS SQL Tutorial
      Oracle Tutorial
    Geek Tutorial
     

    Blogging Tutorial

      RSS Tutorial
      Podcasting Tutorial
    Graphic Design Tutorial
      Coreldraw Tutorial
      Illustrator Tutorial
      3D Tutorials
    Webmaster Articles
     

    Domain Service

      Web Hosting
      Site Promotion
    Java Tutorial/ Articles
     

    Java Servlets

      JavaEE Tutorial
     

    JavaBeans Tutorial

    XML Tutorial/ Articles
     

    XML Style

      AJAX Tutorial
      XML Mobile
    Flash Tutorial/ Articles
     

    Flash Video

      Action Script
      Flash Articles
    OS Tutorial/ Articles
      Linux Tutorial
      Symbian Tutorial
      MacOS Tutorial
    Personal Tech
      Hardware Tutorial
      Software Tutorial
      Online Auction