Solaris Trusted Extensions Developer's Guide
Previous Next

Accessing Lower-Level Untrusted Servers

Sometimes a client needs to be able to access a server on an unlabeled system. An unlabeled system is a system that does not run the Trusted Extensions software. In such a case, you cannot use multilevel ports because they are restricted to privileged servers that run in the global zone or in labeled zones.

For example, suppose your browser is running in the INTERNAL zone. You want to access a web server that runs on a single-level network that has been assigned the PUBLIC sensitivity label by means of the tnrhdb database. Such access is not permitted by default. However, you could write a privileged proxy server to forward the HTTP request to the PUBLIC web server. The proxy should use a special Trusted Extensions socket option called SO_MAC_EXEMPT. This socket option permits a request to be sent to an untrusted lower-level service, and permits the reply from that service to be returned to the requester.


Note - The use of the SO_MAC_EXEMPT option represents an unprotected downgrade channel and should be used very carefully. The SO_MAC_EXEMPT option cannot be set unless the calling process has the PRIV_NET_MAC_AWARE privilege in its effective set. Such a process must enforce its own data filtering policy to prevent leaking higher-level data to the lower-level service. For example, the proxy should sanitize URLs to restrict words from being used as values.


The following code excerpt demonstrates the use of SO_MAC_EXEMPT in a modified version of the wget command's connect_to_ip() routine in connect.c. The call to setsockopt() has been added to show how to set the SO_MAC_EXEMPT option.

int
connect_to_ip (const ip_address *ip, int port, const char *print)
{
  struct sockaddr_storage ss;
  struct sockaddr *sa = (struct sockaddr *)&ss;
  int sock;
  int on = 1;

  /* If PRINT is non-NULL, print the "Connecting to..." line, with
     PRINT being the host name we're connecting to.  */
  if (print)
    {
      const char *txt_addr = pretty_print_address (ip);
      if (print && 0 != strcmp (print, txt_addr))
    logprintf (LOG_VERBOSE, _("Connecting to %s|%s|:%d... "),
           escnonprint (print), txt_addr, port);
      else
    logprintf (LOG_VERBOSE, _("Connecting to %s:%d... "), txt_addr, port);
    }

  /* Store the sockaddr info to SA.  */
  sockaddr_set_data (sa, ip, port);

  /* Create the socket of the family appropriate for the address.  */
  sock = socket (sa->sa_family, SOCK_STREAM, 0);
  if (sock < 0)
    goto err;

  if (setsockopt (sock, SOL_SOCKET, SO_MAC_EXEMPT, &on, sizeof (on)) == -1) {
    perror("setsockopt SO_MAC_EXEMPT");
  }

#if defined(ENABLE_IPV6) && defined(IPV6_V6ONLY)
  if (opt.ipv6_only) {
    /* In case of error, we will go on anyway... */
    int err = setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on));
  }
#endif
Previous Next