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.