Solaris Trusted Extensions Developer's Guide
Previous Next

get_peer_label() Label-Aware Function

The get_peer_label() function in the lp/lib/lp/tx.c file implements the logic of multilevel printing in Trusted Extensions. The following sections describe this function and step you through its implementation.

In Trusted Extensions software, much of the logic for handling labels in the printing service is in the get_peer_label() function. This function obtains the credential of the remote process in a ucred_t data structure and extracts the label from the credential.

The following shows the get_peer_label() code.

int
get_peer_label(int fd, char **slabel)
{
    if (is_system_labeled()) {
        ucred_t *uc = NULL;
        m_label_t *sl;
        char *pslabel = NULL; /* peer's slabel */

        if ((fd < 0) || (slabel == NULL)) {
            errno = EINVAL;
            return (-1);
        }
    
        if (getpeerucred(fd, &uc) == -1)
            return (-1);
    
        sl = ucred_getlabel(uc);
        if (label_to_str(sl, &pslabel, M_INTERNAL, DEF_NAMES) != 0)
            syslog(LOG_WARNING, "label_to_str(): %m");
        ucred_free(uc);
    
        if (pslabel != NULL) {
            syslog(LOG_DEBUG, "get_peer_label(%d, %s): becomes %s",
                fd, (*slabel ? *slabel : "NULL"), pslabel);
            if (*slabel != NULL)
                free(*slabel);
            *slabel = strdup(pslabel);
        }
    }
    
    return (0);
}

Determining Whether the Printing Service Is Running in a Labeled Environment

The printing service is designed to work in labeled and unlabeled environments. Therefore, the printing application must determine when the label of a remote host should be requested and whether the label should be applied. The printing process first checks its own environment. Is the process running in a label-aware environment?

Note that the application does not first determine whether the remote request is labeled. Instead, the printing application determines if its own environment is labeled. If the application is not running on a labeled host, the MAC policy prevents the printing application from receiving labeled requests.

The printing service uses the is_system_labeled() function to determine whether the process is running in a labeled environment. For information about this function, see the is_system_labeled(3C) man page.

This code excerpt shows how to determine whether the application is running in a labeled environment:

if (is_system_labeled()) {
    ucred_t *uc = NULL;
    m_label_t *sl;
    char *pslabel = NULL; /* peer's slabel */

    if ((fd < 0) || (slabel == NULL)) {
        errno = EINVAL;
        return (-1);
    }

If the printing adapter process is running on a system configured with Trusted Extensions, the is_system_labeled() function obtains the ucred_t credential abstraction from the remote process. The ucred_t data structure for the remote process and the peer's label are then set to NULL. The functions that return values for the credential and the peer's label fill the data structures. These data structures are discussed in the following sections.

See get_peer_label() Label-Aware Function to view the source of the entire get_peer_label() routine.

Understanding the Remote Host Credential

The Solaris OS network API provides an abstraction of a process's credentials. This credentials data is available through a network connection. The credentials are represented by the ucred_t data structure that was introduced in the Solaris 10 release. This structure can include the label of a process.

The ucred API provides functions for obtaining the ucred_t data structure from a remote process. This API also provides functions for extracting the label from the ucred_t data structure.

Obtaining the Credential and Remote Host Label

Obtaining the label of a remote process is a two-step procedure. First, you must obtain the credential. Then, you must obtain the label from this credential.

The credential is in the ucred_t data structure of the remote process. The label is in the m_label_t data structure in the credential. After obtaining the credential of the remote process, you extract the label information from that credential.

The getpeerucred() function obtains the ucred_t credential data structure from the remote process. The ucred_getlabel() function extracts the label from the ucred_t data structure. In the get_peer_label() function, the two-step procedure is coded as follows:

if (getpeerucred(fd, &uc) == -1)
    return (-1);

sl = ucred_getlabel(uc);

See get_peer_label() Label-Aware Function to view the source of the entire get_peer_label() routine.

For information about the two functions, see the getpeerucred(3C) and ucred_getlabel(3C) man pages.

In addition to obtaining a remote host's label, you can obtain a remote host's type. To obtain the remote host type, use the tsol_getrhtype() routine. See Obtaining the Remote Host Type.

Using the label_to_str() Function

After obtaining the credential and remote host label, an application can call label_to_str() to convert the label data structure into a string. The string form of the label data structure can be used by the application.

Note that in the Trusted Extensions printing service, the label is returned as a string. The get_peer_label() function returns the string that is obtained by calling label_to_str() on the m_label_t data structure. This string value is returned in the slabel parameter of the get_peer_label() function, char** slabel.

The following code excerpt shows how the label_to_str() function is used:

sl = ucred_getlabel(uc);
if (label_to_str(sl, &pslabel, M_INTERNAL, DEF_NAMES) != 0)
    syslog(LOG_WARNING, "label_to_str(): %m");
ucred_free(uc);

if (pslabel != NULL) {
    syslog(LOG_DEBUG, "get_peer_label(%d, %s): becomes %s",
        fd, (*slabel ? *slabel : "NULL"), pslabel);
    if (*slabel != NULL)
        free(*slabel);
    *slabel = strdup(pslabel);
}

See get_peer_label() Label-Aware Function to view the source of the entire get_peer_label() routine.

Handling Memory Management

As shown in get_peer_label() Label-Aware Function, labels are often dynamically allocated. The functions str_to_label(), label_to_str(), getdevicerange(), and other functions allocate memory that must be freed by the caller. The following man pages for these functions describe the memory allocation requirements:

Using the Returned Label String

The get_peer_label() function extracts the label from a remote host and returns that label as a string. The printing application, as is typical of label-aware applications, uses the label for the following purposes:

  • To make sure that information associated with a label is clearly marked with the correct label. The banner and trailer pages, as well as the header and footer, are marked with the label of the document being printed.

  • To validate that the label of a resource permits a given operation to be performed by another labeled resource. That is, the label of the requesting process permits this printer to accept a request from that requesting process. This permission is based on the range of labels that this printer is assigned.

Previous Next