HP OpenVMS Systems Documentation

Content starts here

OpenVMS Programming Concepts Manual


Previous Contents Index

  1. The sample program sets the VEC attribute of the program section containing the PLV.
  2. Values are assigned to each field of the PLV.

31.3.3 Declaring Privileged Routines as Universal Symbols Using Transfer Vectors on VAX Systems

On VAX systems, you use the transfer vector mechanism to declare universal symbols (described in the OpenVMS Linker Utility Manual). However, for privileged shareable images, the transfer vector must also contain a CHMx instruction because the target routine operates in a more privileged mode. You identify the privileged routine by its identification code, supplied as the only operand to the CHMx instruction. Note that the code number used must match the code used to identify the routine in the dispatch routine. The following example illustrates a typical transfer vector for a privileged routine:


.TRANSFER  my_serv
.MASK      my_serv
CHMK  <code_number>
RET

Because the OpenVMS system services codes are all positive numbers and because the call to a privileged routine is initially handled by the system service dispatcher, you should assign negative code numbers to identify your privileged routines so they do not conflict with system services identification codes.

31.4 Creating a User-Written System Service (Alpha Only)

On Alpha systems, in addition to the routines that perform privileged functions, you must also include a PLV in your source file. However, on Alpha systems, you list the privileged routines by name in the PLV. You do not need to create a dispatch routine that transfers control to the routine; the routine is identified by a special code.

31.4.1 Creating a PLV on Alpha Systems

On Alpha systems, the PLV contains a list of the actual addresses of the privileged routines. The image activator creates the dispatch routines. Figure 31-3 illustrates the linkage for a privileged routine on Alpha systems.

Figure 31-3 Linkage for a Privileged Routine After Image Activation


Table 31-2 describes the components of the privileged library vector on Alpha systems.

Table 31-2 Components of the Alpha Privileged Library Vector
Component Symbol Description
Vector type code PLV$L_TYPE Identifies the type of vector. You must specify the symbolic constant, PLV$C_TYP_CMOD, to identify a privileged library vector.
System version number PLV$L_VERSION Specifies the system version number (unused).
Kernel-mode routine count PLV$L_KERNEL_ROUTINE_COUNT Specifies the number of user-supplied kernel-mode routines listed in the kernel-mode routine list. The address of this list is specified in PLV$PS_KERNEL_ROUTINE_LIST.
Executive-mode routine count PLV$L_EXEC_ROUTINE_COUNT Specifies the number of user-supplied executive-mode routines listed in the executive-mode routine list. The address of this list is specified in PLV$PS_EXEC_ROUTINE_LIST.
Kernel-mode routine list PLV$PS_KERNEL_ROUTINE_LIST Specifies the address of a list of user-supplied kernel-mode routines.
Executive-mode routine list PLV$PS_EXEC_ROUTINE_LIST Specifies the address of a list of user-supplied executive-mode routines.
User-supplied rundown routine PLV$PS_KERNEL_RUNDOWN_HANDLER May contain the address of a user-supplied rundown routine that performs image-specific cleanup and resource deallocation. When the image linked against the user-written system service is run down by the system, this run-time routine is invoked. Unlike exit handlers, the routine is always called when a process or image exits. (Image rundown code calls this routine with a JSB instruction; it returns with an RSB instruction called in kernel mode at IPL 0.)
Thread-safe system service PLV$M_THREAD_SAFE Flags the system service dispatcher that the service requires no explicit synchronization. It is assumed by the dispatcher that the service provides its own internal data synchronization and that multiple kernel threads can safely execute the service in parallel.
RMS dispatcher PLV$PS_RMS_DISPATCHER Specifies the address of an alternative RMS dispatching routine.
Kernel Routine Flags Vector PLV$PS_KERNEL_ROUTINE_FLAGS Contains either the address of an array of quadwords that contains the defined flags associated with each kernel system service, or a zero. If a flag is set, the kernel mode service may return the status SS$_WAIT_CALLERS_MODE.
Executive Routine Flags Vector PLV$PS_EXEC_ROUTINE_FLAGS Contains a zero value, because there are no defined flags for executive mode.

Example 31-3 illustrates how to create a PLV on Alpha systems.

Example 31-3 Creating a PLV on Alpha Systems



! What follows is the definition of the PLV. The PLV lives
! in its own PSECT, which must have the VEC attribute. The
! VEC attribute is forced in the linker. The PLV looks like
! this:
!
!   +-------------------------------------+
!   |         Vector Type Code            | PLV$L_TYPE
!   |         (PLV$C_TYP_CMOD)            |
!   +-------------------------------------+
!   |       System Version Number         | PLV$L_VERSION
!   |             (unused)                |
!   +-------------------------------------+
!   |     Count of Kernel Mode Services   | PLV$L_KERNEL_ROUTINE_COUNT
!   |                                     |
!   +-------------------------------------+
!   |     Count of Exec Mode Services     | PLV$L_EXEC_ROUTINE_COUNT
!   |                                     |
!   +-------------------------------------+
!   |  Address of a List of Entry Points  | PLV$PS_KERNEL_ROUTINE_LIST
!   |       for Kernel Mode Services      |
!   +-------------------------------------+
!   |  Address of a List of Entry Points  | PLV$PS_EXEC_ROUTINE_LIST
!   |         for Exec Mode Services      |
!   +-------------------------------------+
!   |        Address of Kernel Mode       | PLV$PS_KERNEL_RUNDOWN_HANDLER
!   |             Rundown Routine         |
!   +-------------------------------------+
!   |                                     | PLV$M_THREAD_SAFE
!   |                                     |
!   +-------------------------------------+
!   |      Address of Alternative RMS     | PLV$PS_RMS_DISPATCHER
!   |          Dispatching Routine        |
!   +-------------------------------------+
!   |      Kernel Routine Flags Vector    | PLV$PS_KERNEL_ROUTINE_FLAGS
!   |                                     |
!   +-------------------------------------+
!   |      Exec Routine Flags Vector      | PLV$PS_EXEC_ROUTINE_FLAGS
!   |                                     |
!   +-------------------------------------+
!
PSECT OWN = USER_SERVICES (NOWRITE, NOEXECUTE);

OWN PLV_STRUCT : $BBLOCK[PLV$C_LENGTH] INITIAL (LONG (PLV$C_TYP_CMOD,! Type
                                                    ! of vector
0,                                                  ! System version number
(KERNEL_TABLE_END - KERNEL_TABLE_START) / %UPVAL,   ! Number of kernel mode
                                                    ! services
(EXEC_TABLE_END - EXEC_TABLE_START) / %UPVAL,       ! Number of exec mode
                                                    ! services
KERNEL_TABLE_START,   ! Address of list of kernel mode service routine
EXEC_TABLE_START,     ! Address of list of exec mode service routine
RUNDOWN_HANDLER,      ! Address of list of kernel mode rundown routine
0,                    ! Reserved longword
0,                    ! Address of alternate RMS dispatcher
0,                    ! reserved
0));                  ! reserved

PSECT OWN = $OWN$;

31.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 31-4 illustrate how to declare universal symbols in an Alpha system privileged shareable image.

Example 31-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 32
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 32.1 provides an overview of the protection scheme.

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

Section 32.3 describes the rights database.

persona describes the persona and per-thread security features.

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

Section 32.6 describes protected subsystems.

Section 32.7 describes security auditing.

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

Section 32.9 describes SYS$CHECK_PRIVILEGE system service.

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

32.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.

32.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.

32.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.

32.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 32-1. Bits <30:28> are reserved by Compaq. The remaining bits specify the identifier value.

Figure 32-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 32.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 32.3.2.4. For more information, also see the OpenVMS Guide to System Security.

32.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.

32.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 32-2.

Figure 32-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.

32.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 32.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 32-3 shows the facility-specific identifiers.

Figure 32-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.

32.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);
    }
}


Previous Next Contents Index