Document revision date: 30 March 2001

## OpenVMS Programming Concepts Manual

Previous | Contents | Index

### 30.4.2 Declaring Privileged Routines as Universal Symbols Using Symbol Vectors on Alpha Systems

On Alpha systems, you declare a user-written system service to be a universal symbol by using the symbol vector mechanism. (See the OpenVMS Linker Utility Manual for more information about creating symbol vectors.) However, because user-written system services must be accessed by using the privileged library vector (PLV), you must specify an alias for the user-written system service. Use the following syntax for the SYMBOL_VECTOR= option to specify an alias that can be universal:

`SYMBOL_VECTOR = ([universal_alias_name/]internal_name = {PROCEDURE || DATA})`

In a privileged shareable image, calls from within the image that use the alias name result in a fixup and subsequent vectoring through the PLV, which results in a mode change. Calls from within the shareable image that use the internal name are made in the caller's mode. (Calls from external images always result in a fixup.)

The linker command procedures and options file shown in Example 30-4 illustrate how to declare universal symbols in an Alpha system privileged shareable image.

Example 30-4 Declaring Universal Symbols for Privileged Shareable Image on an Alpha System

    $ !
    $ ! Link the protected shareable image containing
    $ ! the user-written system services
    $ !
    $ LINK  /SHARE=UWSS -
            /PROTECT -
            /MAP=UWSS -
            /SYSEXE -
            /FULL/CROSS/NOTRACE -
            UWSS, -
            SYS$INPUT:/OPTIONS

    !
    ! Set the GSMATCH options
    !
    GSMATCH=LEQUAL,1,1

    !
    ! Define transfer vectors for protected shareable image
    !
    SYMBOL_VECTOR = ( -
                    FIRST_SERVICE   = PROCEDURE, -
                    SECOND_SERVICE  = PROCEDURE, -
                    THIRD_SERVICE   = PROCEDURE, -
                    FOURTH_SERVICE  = PROCEDURE  -
                    )

    !
    ! Need to add the VEC attribute to the PLV psect
    !
    PSECT=USER_SERVICES,VEC

## Chapter 31
System Security Services

This chapter describes the security system services that provide various mechanisms to enhance the security of operating systems. It contains the following sections:

Section 31.1 provides an overview of the protection scheme.

Section 31.2 describes identifiers and how they are used in security.

Section 31.3 describes the rights database.

Section 31.4 describes the persona and per-thread security features.

Section 31.5 describes how to create, translate, and maintain access control entries (ACEs).

Section 31.6 describes protected subsystems.

Section 31.7 describes security auditing.

Section 31.8 describes how to determine a user's access to an object.

Section 31.9 describes SYS$CHECK_PRIVILEGE system service.

Section 31.10 describes how to implement site-specific security policies.

## 31.1 Overview of the Operating System's Protection Scheme

The basis of the security scheme is an identifier, which is a 32-bit binary value that represents a set of users to the system. An identifier can represent an individual user, a group of users, or some aspect of the environment in which a user is operating. A process is a holder of an identifier when that identifier can represent that process to the system. The protection scheme also includes the user identification code (UIC), the authorization database, and access control lists.

Authorization Database

The authorization database consists of the system authorization file (SYSUAF.DAT), the network proxy database, and the rights list database (RIGHTSLISTS.DAT). Note that the network proxy database is called NETPROXY.DAT on Alpha systems and NET$PROXY.DAT on VAX systems. (The file NETPROXY.DAT on VAX systems is maintained for platform compatibility, translation of DECnet Phase IV node names, and layered product support.) The system rights database is an indexed file consisting of identifier and holder records. These records define the identifiers and the holders of those identifiers on a system. When a user logs in to the system, a process is created and LOGINOUT creates a rights list for the process from the applicable entries in the rights database. The process rights list contains all the identifiers that the process holds. A process can be the holder of a number of identifiers. These identifiers determine the access rights of the list holder. The process rights list becomes part of the process and is propagated to any created subprocesses.

Access Protection

When a process without special privileges attempts to access an object (protected by an ACL) in the system, the operating system uses the rights list when performing a protection check. The system compares the identifiers in the rights list to the protection attributes of the object and grants or denies access to the object based on the comparison. In other words, the entries in the rights list do not specifically grant access; instead, the system uses them to perform a protection check when the process attempts to access an object.

Access Control Lists

The protection scheme provides security with the mechanism of the access control list (ACL). An ACL consists of access control entries (ACEs) that specify the type of access an identifier has to an object like a file, device, or queue. When a process attempts to access an object with an associated ACL, the system grants or denies access based on whether an exact match for the identifier in the ACL exists in the process rights list.

The following sections describe each of the components of the security scheme---identifiers, rights database, process and system rights lists, protection codes, and ACLs---and the system services affecting those components.

## 31.2 Identifiers

The basic component of the protection scheme is an identifier. An identifier represents various types of agents using the system. The types of agents represented include individual users, groups of users, and environments in which a process is operating. Identifiers and their attributes apply to both processes and objects. An identifier name consists of 1 to 31 alphanumeric characters with no embedded blanks and must contain at least one nonnumeric character. It can include the uppercase letters A through Z, dollar signs ($), and underscores (_), as well as the numbers 0 through 9. Any lowercase letters are automatically converted to uppercase.

### 31.2.1 Identifier Format

Each of the three types of identifier has an internal format in the rights database: user identification code (UIC) format, identification (ID) format, and facility-specific format. The high-order bits <31:28> of the identifier value specify the format of the identifier.

### 31.2.2 General Identifiers

You can define general identifiers to meet the specific needs of your site. You grant these identifiers to users by establishing holder records in the rights database. General identifiers can identify a single user, a single UIC group, a group of users, or a number of groups.

Bit <31>, which is set to 1, specifies ID format used by general identifiers as shown in Figure 31-1. Bits <30:28> are reserved by Compaq. The remaining bits specify the identifier value.

Figure 31-1 ID Format

You define identifiers and their holders in the rights database with the Authorize utility or with the appropriate system services. Each user can hold multiple identifiers. This allows you to create a different kind of group designation from the one used with the user's UIC.

The alternative grouping described here permits each user to be a member of multiple overlapping groups. Access control lists (ACLs) define the access to protected objects based on the identifiers the user holds rather than on the user's UIC. See Section 31.5.3.1 for information on creating ACLs.

You can also define identifiers to represent particular terminals, times of day, or other site-specific environmental attributes. These identifiers are not given holder records in the rights database but may be granted to users by customer-written privileged software. This feature of the security system allows each site flexibility and, because the identifiers can be specific to the site, enhanced security. For a programming example demonstrating this technique, see Section 31.3.2.4. For more information, also see the OpenVMS Guide to System Security.

### 31.2.3 System-Defined Identifiers

System-defined identifiers, or environmental identifiers, are general identifiers that are automatically defined when the rights database is initialized. The following system-defined identifiers correspond directly with the login classes and relate to the environment in which the process operates:

BATCH | All attempts at access made by batch jobs
NETWORK | All attempts at access made across the network
INTERACTIVE | All attempts at access made by interactive processes
LOCAL | All attempts at access made by users logged in at local terminals
DIALUP | All attempts at access made by users logged in at dialup terminals
REMOTE | All attempts at access made by users logged in on a network

Depending on the environment in which the process is operating, the system includes one or more of these identifiers when creating the process rights list.

### 31.2.4 UIC Identifiers

Each UIC identifier is unique and represents a system user. By default, when an account is created, its UIC is associated with the account's user name generating an identifier value. When the high-order bit <31> of the identifier value is zero, the value identifies a UIC format identifier as shown in Figure 31-2.

Figure 31-2 UIC Identifier Format

Bits <27:16> and <15:0> designate a group field and member field. Group numbers range from 1 through 16,382; member numbers range from 0 through 65,534.

### 31.2.5 Facility Identifiers

Facility-specific rights identifiers allow a range of unique binary identifier values to be reserved for a particular software product or application. Compare the format of facility-specific identifiers with the format of general identifiers and UIC identifiers, as shown in Section 31.2.1. The system normally determines the binary values of general identifiers when the system manager creates them; the system manager determines the binary values of UIC identifiers.

Figure 31-3 shows the facility-specific identifiers.

Figure 31-3 Facility-Specific Identifiers

The binary value of a facility-specific identifier is determined at the time the application is designed. The facility number of the identifier must match the facility number the application has chosen for its condition and message codes. The remaining 16-bit facility-specific value may be assigned at will by the application designer. By reserving specific binary identifier values, the application designer may code fixed identifier values into an application's calls to $CHECK_PRIVILEGE, $GRANT_ID, and so forth. It avoids the added complexity of first having to translate an identifier name to binary with $ASCTOID.

An application can choose to register the identifiers in the rights database or not, depending on its needs. If the identifiers are registered, they are visible to the system manager who may grant them to users. In any case, they will be displayed properly if they appear on access control lists. If they are not registered, they will remain invisible to the system manager. Unregistered identifiers that appear on access control lists are displayed as a hexadecimal value.

To register its identifiers, the installation procedure of the application must run a program that enters the identifiers into the rights database using the $ADD_IDENT service. You cannot specify facility-specific identifier values to AUTHORIZE with the ADD/IDENTIFIER command.

Typically, facility-specific identifiers serve to extend the OpenVMS privilege mechanism for an application. For example, consider a database manager that includes a function to allow appropriately privileged users to modify a schema. Access to this function could be controlled through a facility-specific identifier named, for example, DBM$MOD_SCHEMA. The system manager grants the identifier to authorized persons using the AUTHORIZE command GRANT/ID. The database services that modify schemas use the $CHECK_PRIVILEGE service to check that the caller holds the identifier.

In another example, a privileged program run by users when they log in uses $GRANT_ID to grant the user certain facility-specific identifiers, depending on conditions determined by the program; for example, time of day or access port name. These identifiers can be placed on the ACLs of files to control file access, or they might be checked by other software with $CHECK_PRIVILEGE.

### 31.2.6 Identifier Attributes

An identifier has attributes associated with it in the rights database. The process rights list includes the attributes of any identifiers that the process holds.

The use of rights identifiers can be extended with the following identifier attribute keywords:

DYNAMIC | Allows unprivileged holders of an identifier to add or remove the identifier from the process rights list using the DCL SET RIGHTS command. Conversely, an unprivileged user who does not have the attribute cannot modify the identifier.
HOLDER_HIDDEN | Prevents someone from using the SYS$FIND_HOLDER system service to get a list of users who hold an identifier, unless that person holds the identifier.
NAME_HIDDEN | Allows only the holders of an identifier to have it translated, either from binary to ASCII or from ASCII to binary.
NO_ACCESS | Specifies that the identifier does not affect the access rights of the user holding the identifier.
RESOURCE | Allows the holder of an identifier to charge resources, such as disk blocks, to an identifier.
SUBSYSTEM | Allows holders of the identifier to create and maintain protected subsystems.

Using the Resource Attribute

The following example demonstrates the advantages of defining an identifier and holders for a project.

The Physics department of a school has a common library with an associated disk quota on the system. In order to use the Resource attribute, you must enable disk quotas and establish a quota file entry using the SYSMAN utility. You want to allow the faculty members to charge disk quota that they use in conjunction with the library to the identifier PHYSICS associated with the common library and to prevent the students from charging resources to that identifier.

- Define an identifier PHYSICS with the Resource attribute in the rights database using the SYS$ADD_IDENT service.
- Enable disk quotas using SYSMAN as shown in the example.

      $ MCR SYSMAN
      SYSMAN> DISKQUOTA CREATE/DEVICE=DKB0:
      SYSMAN> DISKQUOTA MODIFY/DEVICE=DKB0: PHYSICS /PERMQUOTA=150000 -
      _SYSMAN> /OVERDRAFT=5000
      SYSMAN> EXIT

- Create the common library and assign the identifier PHYSICS using the run-time library routine LIB$CREATE_DIR.
- Grant the identifier PHYSICS to holders FRED, a faculty member, and GEORGE, a student, using the SYS$ADD_HOLDER service.

If you specify the Resource attribute for identifier FRED, he can charge disk resources to the PHYSICS identifier; if you do not specify the Resource attribute for identifier GEORGE, he will not inherit the Resource attribute associated with the identifier PHYSICS and cannot charge disk resources to the PHYSICS identifier. The following input file, USERLIST.DAT, contains valid UIC identifiers of students and faculty members:

    FRED NORESOURCE
    GEORGE RESOURCE
    NANCY NORESOURCE
    HAROLD RESOURCE
    SUSAN RESOURCE
    CHERYL NORESOURCE
    MARVIN NORESOURCE

The following program reads USERLIST.DAT and associates the UIC identifiers with the identifier PHYSICS:

    #include <stdio.h>
    #include <descrip.h>
    #include <ssdef.h>
    #include <lib$routines.h>
    #include <kgbdef.h>
    #include <nam.h>
    #include <string.h>
    #include <stdlib.h>

    #define IDENT_LEN 31
    #define NO_ATTR 0

    #define RESOURCE 1
    #define NORESOURCE 0

    unsigned int sys$asctoid(),
                sys$add_ident(),
                sys$add_holder(),
                sys$idtoasc(),
                convert_id( struct dsc$descriptor_s, unsigned int );

    void add_holder( unsigned int, unsigned int, unsigned int);

    struct {
        unsigned int uic;
        unsigned int terminator;
    }holder;

    static char ascii_ident[IDENT_LEN],
                abuffer[IDENT_LEN],
                dirbuf[NAM$C_MAXRSS],
                targbuf[IDENT_LEN];

    $DESCRIPTOR(target,targbuf);

    unsigned int status;

    main() {

        FILE *ptr;
        char attr[11];
        unsigned int  owner_uic, attrib, resid, bin_id;
        $DESCRIPTOR(dirspec,dirbuf);
        $DESCRIPTOR(aident, abuffer);

        printf("\nEnter directory spec: ");
        gets(dirbuf);
        dirspec.dsc$w_length = strlen(dirbuf);

        printf("\nEnter its owner identifier: ");
        gets(targbuf);
        target.dsc$w_length = strlen(targbuf);

    /* Add target identifier WITH resource attribute to the rights database */

        attrib = KGB$M_RESOURCE;
        status = sys$add_ident( &target, 0, attrib, &resid);
        if((status & 1) != SS$_NORMAL)
            lib$signal( status );
        else
            printf("\nAdding identifier %s to rights database...\n",
                   target.dsc$a_pointer);

    /* Create the common directory with the target id as owner */

        owner_uic = resid;
         status = lib$create_dir( &dirspec, &owner_uic, 0, 0);
        if((status & 1) != SS$_NORMAL)
            lib$signal( status );
        else
            printf("Creating the directory %s...\n",dirspec.dsc$a_pointer);

    /* Open an input file of UIC identifiers and attribute types */
        if((ptr = fopen("USERLIST.DAT","r")) == NULL) {
            perror("OPEN");
            exit(EXIT_FAILURE);
        }

    /* Read the input file of UIC identifiers */
        while((fscanf(ptr,"%s %s\n",abuffer,attr)) != EOF) {
            aident.dsc$w_length = strlen(abuffer);
            attrib = (strcmp(attr,"RESOURCE")) == 0 ? KGB$M_RESOURCE : NO_ATTR;
            bin_id = convert_id( aident, attrib);
            add_holder( bin_id, resid, attrib );
        }

    /* Close the input file */
        fclose(ptr);
     }

    unsigned int convert_id( struct dsc$descriptor_s uic_id,
                        unsigned int attr ) {

        unsigned int bin_id;

        status = sys$asctoid(&uic_id, &bin_id, &attr);
        if((status & 1) != SS$_NORMAL)
            lib$signal( status );
        else {
            printf("Converting identifier %s to binary format...\n",
                   uic_id.dsc$a_pointer);
            return bin_id;
        }
    }

    void add_holder( unsigned int bin_id, unsigned int resid,
                     unsigned int attrib ) {

        int i;
        $DESCRIPTOR(nambuf,    ascii_ident);

        holder.uic = bin_id;
        holder.terminator = 0;

        status = sys$add_holder( resid, &holder, attrib);
        if((status & 1) != SS$_NORMAL)
            lib$signal( status );
        else {
            status = sys$idtoasc(bin_id, 0, &nambuf, 0, 0, 0);
            if((status & 1) != SS$_NORMAL)
                lib$signal( status );
    /* Remove padding */
            nambuf.dsc$w_length = strlen(ascii_ident);
            for(i=0;i < nambuf.dsc$w_length + 1; i++)
                if (ascii_ident[i] == 0x20)
                    ascii_ident[i] = '\0';
            printf("\nAdding holder %s to target identifier %s...\n", \
                            nambuf.dsc$a_pointer,target.dsc$a_pointer);
        }
    }

## 31.3 Rights Database

The rights database is an indexed file containing two types of records that define all identifiers: identifier records and holder records.

One identifier record appears in the rights database for each identifier. The identifier record associates the identifier name with its 32-bit binary value and specifies the attributes of the identifier. Figure 31-4 depicts the format of the identifier record.

Figure 31-4 Format of the Identifier Record

One holder record exists in the rights database for each holder of each identifier. The holder record associates the holder with the identifier, specifies the attributes of the holder, and identifies the UIC identifier of the holder. Figure 31-5 depicts the format of the holder record.

Figure 31-5 Format of the Holder Record

The rights database is an indexed file with three keys. The primary key is the identifier value, the secondary key is the holder ID, and the tertiary key is the identifier name. Through the use of the secondary key of the holder ID, all the identifiers held by a process can be retrieved quickly when the system creates the process's rights list.

### 31.3.1 Initializing a Rights Database

You initialize the rights database in one of the following ways:

- When a system is installed
- With the Authorize utility
- With the SYS$CREATE_RDB system service

When you call SYS$CREATE_RDB, you can use the sysid argument to pass the system identification value associated with the rights database. If you omit sysid, the system uses the current system time in 64-bit format. If the rights database already exists, SYS$CREATE_RDB fails with the error code RMS$_FEX. To create a new rights database when one already exists, you must explicitly delete or rename the old one.

You can specify the location and name of the rights database by defining the logical name RIGHTSLIST as a system logical name in executive mode; its equivalence string must contain the device, directory, and file name of the rights database.

The file RIGHTSLIST.DAT has the protection of (S:RWED,O:RWED,G:R,W).

In order to use SYS$CREATE_RDB, write access to the database is necessary. If the database is in SYS$SYSTEM, which is the default, you need the SYSPRV privilege to grant write access to the directory.

When SYS$CREATE_RDB initializes a rights database, system-defined identifiers, which describe the environment in which a process can operate, are automatically created.

To add any other identifiers to the rights database, you must define them with the Authorize utility or with the appropriate system service.

Previous | Next | Contents | Index

| privacy and legal statement |
5841PRO_079.HTML