diff -r e524216b0586 -r e2e604cdbd6a components/trousers/patches/tcsd_svrside.c.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/trousers/patches/tcsd_svrside.c.patch Wed Apr 18 10:38:45 2012 -0700 @@ -0,0 +1,336 @@ +--- src/tcsd/svrside.c 2010-06-09 13:19:00.000000000 -0700 ++++ src/tcsd/svrside.c 2012-04-11 14:37:28.993408000 -0700 +@@ -27,6 +27,15 @@ + #include + #include + #include ++#ifdef SOLARIS ++#include ++#include ++#endif ++#ifndef HAVE_DAEMON ++#include ++#include ++#endif ++ + #include "trousers/tss.h" + #include "trousers_types.h" + #include "tcs_tsp.h" +@@ -44,6 +53,10 @@ + static volatile int hup = 0, term = 0; + extern char *optarg; + ++#ifdef SOLARIS ++static int get_event_log_from_kernel(void); ++#endif ++ + static void + tcsd_shutdown(void) + { +@@ -170,6 +183,10 @@ + (void)req_mgr_final(); + return result; + } ++#ifdef SOLARIS ++ /* Not fatal if this fails */ ++ (void) get_event_log_from_kernel(); ++#endif + + result = owner_evict_init(); + if (result != TSS_SUCCESS) { +@@ -208,13 +225,169 @@ + } + + ++#ifdef SOLARIS ++ ++extern int get_device_fd(void); ++ ++#define TPM_IOCTL_GETEVTABLE 1 ++struct tpm_evtable_ioblk { ++ uint32_t buflen; ++ caddr_t buf; ++}; ++ ++static int ++store_eventlog(char *filename, struct tpm_evtable_ioblk *evlog) ++{ ++ int fd; ++ int bytes = 0; ++ ++ fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0600); ++ if (fd == -1) { ++ LogError("Error opening logfile %s: %s", filename, ++ strerror(errno)); ++ return (-1); ++ } ++ while (bytes < evlog->buflen) { ++ int n; ++ n = write(fd, evlog->buf, evlog->buflen - bytes); ++ if (n == -1 && errno != EAGAIN) { ++ LogError("Error writing logfile %s: %s", ++ filename, strerror(errno)); ++ close(fd); ++ return (-1); ++ } ++ if (n != -1) ++ bytes += n; ++ } ++ close(fd); ++ ++ return (0); ++} ++ ++static int ++get_event_log_from_kernel(void) ++{ ++ int fd = get_device_fd(); ++ struct tpm_evtable_ioblk ioblk; ++ ++ if (fd == -1) ++ return (-1); ++ ++ (void) memset(&ioblk, 0, sizeof (ioblk)); ++ if (ioctl(fd, TPM_IOCTL_GETEVTABLE, &ioblk)) { ++ LogDebug("Cannot get event log from kernel: %s", ++ strerror(errno)); ++ return (-1); ++ } ++ if (ioblk.buflen == 0) ++ return (0); ++ ++ ioblk.buf = calloc(1, ioblk.buflen); ++ if (ioblk.buf == NULL) { ++ return (-1); ++ } ++ if (ioctl(fd, TPM_IOCTL_GETEVTABLE, &ioblk)) { ++ free(ioblk.buf); ++ LogDebug("Cannot get event log from kernel: %s", ++ strerror(errno)); ++ return (-1); ++ } ++ ++ return (store_eventlog(tcsd_options.firmware_log_file, &ioblk)); ++} ++ ++/* ++ * For Solaris, make the tcsd privilege aware and drop ++ * risky privileges if they are not needed. ++ */ ++static int ++drop_privs(void) ++{ ++ priv_set_t *myprivs; ++ int rv; ++ ++ /* ++ * Drop unneeded privs such as fork/exec. ++ * ++ * Get "basic" privs and remove the ones we don't want. ++ */ ++ if ((myprivs = priv_str_to_set("basic", ",", NULL)) == NULL) { ++ LogError("priv_str_to_set failed: %s", strerror(errno)); ++ return (1); ++ } else { ++ (void) priv_delset(myprivs, PRIV_PROC_EXEC); ++ (void) priv_delset(myprivs, PRIV_PROC_FORK); ++ (void) priv_delset(myprivs, PRIV_FILE_LINK_ANY); ++ (void) priv_delset(myprivs, PRIV_PROC_INFO); ++ (void) priv_delset(myprivs, PRIV_PROC_SESSION); ++ (void) priv_delset(myprivs, PRIV_PROC_SETID); ++ ++ /* for auditing */ ++ (void) priv_addset(myprivs, PRIV_PROC_AUDIT); ++ ++ if ((rv = setppriv(PRIV_SET, PRIV_PERMITTED, myprivs))) ++ return (rv); ++ if ((rv = setppriv(PRIV_SET, PRIV_LIMIT, myprivs))) ++ return (rv); ++ if ((rv = setppriv(PRIV_SET, PRIV_INHERITABLE, myprivs))) ++ return (rv); ++ ++ (void) priv_freeset(myprivs); ++ } ++ return (0); ++} ++#endif /* SOLARIS */ ++ ++#ifndef HAVE_DAEMON ++static int ++daemon(int nochdir, int noclose) { ++ int rv, fd; ++ ++ if (!noclose) { ++ closelog(); ++ closefrom(0); ++ } ++ ++ switch (fork()) { ++ case -1: /* failure: parent process */ ++ return (-1); ++ case 0: /* success: child process */ ++ break; ++ default: /* success: parent process */ ++ exit (0); ++ } ++ ++ /* Create a new SID for the child process */ ++ if (setsid() == -1) ++ return (-1); ++ /* Prevent cwd from being left open and unremovable */ ++ if (!nochdir) ++ (void) chdir("/"); ++ (void) umask(0); ++ /* Redirect stdin, stdout, and stderr to /dev/null */ ++ if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) { ++ (void) dup2(fd, STDIN_FILENO); ++ (void) dup2(fd, STDOUT_FILENO); ++ (void) dup2(fd, STDERR_FILENO); ++ if (fd > 2) ++ (void)close (fd); ++ } ++ return (0); ++} ++#endif /* !HAVE_DAEMON */ ++ + int + main(int argc, char **argv) + { +- struct sockaddr_in serv_addr, client_addr; ++ typedef union { ++ struct sockaddr_in in; ++ struct sockaddr_un un; ++ } sockaddr_un_in_t; ++ sockaddr_un_in_t serv_addr, client_addr; ++ int rv; + TSS_RESULT result; + int sd, newsd, c, option_index = 0; +- unsigned client_len; ++ unsigned client_len, serv_len; + char *hostname = NULL; + struct passwd *pwd; + struct hostent *client_hostent = NULL; +@@ -245,26 +418,49 @@ + if ((result = tcsd_startup())) + return (int)result; + +- sd = socket(AF_INET, SOCK_STREAM, 0); +- if (sd < 0) { +- LogError("Failed socket: %s", strerror(errno)); +- return -1; +- } ++ if (tcsd_options.port == 0) { /* UNIX Domain socket */ ++ /* Use UNIX Domain socket instead of TCP/IP socket */ ++ sd = socket(AF_UNIX, SOCK_STREAM, 0); ++ if (sd < 0) { ++ LogError("Failed socket: %s", strerror(errno)); ++ return -1; ++ } ++ ++ memset(&serv_addr, 0, sizeof (serv_addr)); ++ serv_addr.un.sun_family = AF_UNIX; ++ strncpy(serv_addr.un.sun_path, TCSD_DEFAULT_SOCKET, ++ sizeof (serv_addr.un.sun_path)); ++ ++ } else { /* TCP socket */ ++ sd = socket(AF_INET, SOCK_STREAM, 0); ++ if (sd < 0) { ++ LogError("Failed socket: %s", strerror(errno)); ++ return -1; ++ } + +- memset(&serv_addr, 0, sizeof (serv_addr)); +- serv_addr.sin_family = AF_INET; +- serv_addr.sin_port = htons(tcsd_options.port); +- +- /* If no remote_ops are defined, restrict connections to localhost +- * only at the socket. */ +- if (tcsd_options.remote_ops[0] == 0) +- serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); +- else +- serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); +- +- c = 1; +- setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &c, sizeof(c)); +- if (bind(sd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) { ++ memset(&serv_addr, 0, sizeof (serv_addr)); ++ serv_addr.in.sin_family = AF_INET; ++ serv_addr.in.sin_port = htons(tcsd_options.port); ++ ++ /* If no remote_ops are defined, restrict connections to localhost ++ * only at the socket. */ ++ if (tcsd_options.remote_ops[0] == 0) ++ serv_addr.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); ++ else ++ serv_addr.in.sin_addr.s_addr = htonl(INADDR_ANY); ++ ++ c = 1; ++ setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &c, sizeof(c)); ++ } ++ ++ if (tcsd_options.port == 0) { /* UNIX Domain socket */ ++ serv_len = (unsigned)sizeof(serv_addr.un); ++ client_len = (unsigned)sizeof(client_addr.un); ++ } else { /* TCP socket */ ++ serv_len = (unsigned)sizeof(serv_addr.in); ++ client_len = (unsigned)sizeof(client_addr.in); ++ } ++ if (bind(sd, (struct sockaddr *) &serv_addr, serv_len) < 0) { + LogError("Failed bind: %s", strerror(errno)); + return -1; + } +@@ -285,7 +481,6 @@ + LogError("Failed listen: %s", strerror(errno)); + return -1; + } +- client_len = (unsigned)sizeof(client_addr); + + if (getenv("TCSD_FOREGROUND") == NULL) { + if (daemon(0, 0) == -1) { +@@ -295,6 +490,12 @@ + } + } + ++#ifdef SOLARIS ++ /* For Solaris, drop privileges for security. */ ++ if ((rv = drop_privs())) ++ return (rv); ++#endif /* SOLARIS */ ++ + LogInfo("%s: TCSD up and running.", PACKAGE_STRING); + do { + newsd = accept(sd, (struct sockaddr *) &client_addr, &client_len); +@@ -314,20 +515,22 @@ + } + LogDebug("accepted socket %i", newsd); + +- if ((client_hostent = gethostbyaddr((char *) &client_addr.sin_addr, +- sizeof(client_addr.sin_addr), ++ if (tcsd_options.port != 0) { /* TCP socket */ ++ if ((client_hostent = gethostbyaddr((char *) &client_addr.in.sin_addr, ++ sizeof(client_addr.in.sin_addr), + AF_INET)) == NULL) { +- char buf[16]; +- uint32_t addr = htonl(client_addr.sin_addr.s_addr); ++ char buf[16]; ++ uint32_t addr = htonl(client_addr.in.sin_addr.s_addr); + +- snprintf(buf, 16, "%d.%d.%d.%d", (addr & 0xff000000) >> 24, +- (addr & 0x00ff0000) >> 16, (addr & 0x0000ff00) >> 8, +- addr & 0x000000ff); ++ snprintf(buf, 16, "%d.%d.%d.%d", (addr & 0xff000000) >> 24, ++ (addr & 0x00ff0000) >> 16, (addr & 0x0000ff00) >> 8, ++ addr & 0x000000ff); + +- LogWarn("Host name for connecting IP %s could not be resolved", buf); +- hostname = strdup(buf); +- } else { +- hostname = strdup(client_hostent->h_name); ++ LogWarn("Host name for connecting IP %s could not be resolved", buf); ++ hostname = strdup(buf); ++ } else { ++ hostname = strdup(client_hostent->h_name); ++ } + } + + tcsd_thread_create(newsd, hostname);