Index: src/tspi/ps/tspps.c |
diff --git a/src/tspi/ps/tspps.c b/src/tspi/ps/tspps.c |
index 2a270793873c8806bbaee58aee2dfb5f93b6a456..9dfc16d007fe1bbbb3aa93b64ed15f696eec988e 100644 |
--- a/src/tspi/ps/tspps.c |
+++ b/src/tspi/ps/tspps.c |
@@ -19,6 +19,21 @@ |
#include <sys/file.h> |
#include <sys/stat.h> |
#include <assert.h> |
+#include <fcntl.h> |
+#include <limits.h> |
+#include <netdb.h> |
+#if defined (HAVE_BYTEORDER_H) |
+#include <sys/byteorder.h> |
+#elif defined(HAVE_ENDIAN_H) |
+#include <endian.h> |
+#define LE_16 htole16 |
+#define LE_32 htole32 |
+#define LE_64 htole64 |
+#else |
+#define LE_16(x) (x) |
+#define LE_32(x) (x) |
+#define LE_64(x) (x) |
+#endif |
#include "trousers/tss.h" |
#include "trousers/trousers.h" |
@@ -33,6 +48,17 @@ static MUTEX_DECLARE_INIT(user_ps_lock); |
#if (defined (__FreeBSD__) || defined (__OpenBSD__)) |
static MUTEX_DECLARE_INIT(user_ps_path); |
#endif |
+#if defined (SOLARIS) |
+static struct flock fl = { |
+ 0, |
+ 0, |
+ 0, |
+ 0, |
+ 0, |
+ 0, |
+ {0, 0, 0, 0} |
+}; |
+#endif |
/* |
@@ -44,7 +70,7 @@ get_user_ps_path(char **file) |
TSS_RESULT result; |
char *file_name = NULL, *home_dir = NULL; |
struct passwd *pwp; |
-#if (defined (__linux) || defined (linux)) |
+#if (defined (__linux) || defined (linux) || defined(__GLIBC__)) |
struct passwd pw; |
#endif |
struct stat stat_buf; |
@@ -62,9 +88,19 @@ get_user_ps_path(char **file) |
euid = geteuid(); |
+#if defined (SOLARIS) |
+ /* |
+ * Solaris keeps user PS in a local directory instead of |
+ * in the user's home directory, which may be shared |
+ * by multiple systems. |
+ * |
+ * The directory path on Solaris is /var/tpm/userps/[EUID]/ |
+ */ |
+ rc = snprintf(buf, sizeof (buf), "%s/%d", TSS_USER_PS_DIR, euid); |
+#else |
setpwent(); |
while (1) { |
-#if (defined (__linux) || defined (linux)) |
+#if (defined (__linux) || defined (linux) || defined(__GLIBC__)) |
rc = getpwent_r(&pw, buf, PASSWD_BUFSIZE, &pwp); |
if (rc) { |
LogDebugFn("USER PS: Error getting path to home directory: getpwent_r: %s", |
@@ -93,8 +129,9 @@ get_user_ps_path(char **file) |
return TSPERR(TSS_E_OUTOFMEMORY); |
/* Tack on TSS_USER_PS_DIR and see if it exists */ |
- rc = snprintf(buf, PASSWD_BUFSIZE, "%s/%s", home_dir, TSS_USER_PS_DIR); |
- if (rc == PASSWD_BUFSIZE) { |
+ rc = snprintf(buf, sizeof (buf), "%s/%s", home_dir, TSS_USER_PS_DIR); |
+#endif /* SOLARIS */ |
+ if (rc == sizeof (buf)) { |
LogDebugFn("USER PS: Path to file too long! (> %d bytes)", PASSWD_BUFSIZE); |
result = TSPERR(TSS_E_INTERNAL_ERROR); |
goto done; |
@@ -104,7 +141,7 @@ get_user_ps_path(char **file) |
if ((rc = stat(buf, &stat_buf)) == -1) { |
if (errno == ENOENT) { |
errno = 0; |
- /* Create the base directory, $HOME/.trousers */ |
+ /* Create the user's ps directory if it is not there. */ |
if ((rc = mkdir(buf, 0700)) == -1) { |
LogDebugFn("USER PS: Error creating dir: %s: %s", buf, |
strerror(errno)); |
@@ -119,10 +156,15 @@ get_user_ps_path(char **file) |
} |
/* Directory exists or has been created, return the path to the file */ |
- rc = snprintf(buf, PASSWD_BUFSIZE, "%s/%s/%s", home_dir, TSS_USER_PS_DIR, |
+#if defined (SOLARIS) |
+ rc = snprintf(buf, sizeof (buf), "%s/%d/%s", TSS_USER_PS_DIR, euid, |
TSS_USER_PS_FILE); |
- if (rc == PASSWD_BUFSIZE) { |
- LogDebugFn("USER PS: Path to file too long! (> %d bytes)", PASSWD_BUFSIZE); |
+#else |
+ rc = snprintf(buf, sizeof (buf), "%s/%s/%s", home_dir, TSS_USER_PS_DIR, |
+ TSS_USER_PS_FILE); |
+#endif |
+ if (rc == sizeof (buf)) { |
+ LogDebugFn("USER PS: Path to file too long! (> %d bytes)", sizeof (buf)); |
} else |
*file = strdup(buf); |
@@ -143,12 +185,16 @@ get_file(int *fd) |
/* check the global file handle first. If it exists, lock it and return */ |
if (user_ps_fd != -1) { |
+#if defined (SOLARIS) |
+ fl.l_type = F_WRLCK; |
+ if ((rc = fcntl(user_ps_fd, F_SETLKW, &fl))) { |
+#else |
if ((rc = flock(user_ps_fd, LOCK_EX))) { |
+#endif /* SOLARIS */ |
LogDebug("USER PS: failed to lock file: %s", strerror(errno)); |
MUTEX_UNLOCK(user_ps_lock); |
return TSPERR(TSS_E_INTERNAL_ERROR); |
} |
- |
*fd = user_ps_fd; |
return TSS_SUCCESS; |
} |
@@ -167,8 +213,12 @@ get_file(int *fd) |
MUTEX_UNLOCK(user_ps_lock); |
return TSPERR(TSS_E_INTERNAL_ERROR); |
} |
- |
+#if defined (SOLARIS) |
+ fl.l_type = F_WRLCK; |
+ if ((rc = fcntl(user_ps_fd, F_SETLKW, &fl))) { |
+#else |
if ((rc = flock(user_ps_fd, LOCK_EX))) { |
+#endif /* SOLARIS */ |
LogDebug("USER PS: failed to get lock of %s: %s", file_name, strerror(errno)); |
free(file_name); |
close(user_ps_fd); |
@@ -190,7 +240,12 @@ put_file(int fd) |
fsync(fd); |
/* release the file lock */ |
+#if defined (SOLARIS) |
+ fl.l_type = F_UNLCK; |
+ if ((rc = fcntl(fd, F_SETLKW, &fl))) { |
+#else |
if ((rc = flock(fd, LOCK_UN))) { |
+#endif /* SOLARIS */ |
LogDebug("USER PS: failed to unlock file: %s", strerror(errno)); |
rc = -1; |
} |
@@ -365,6 +420,7 @@ psfile_change_num_keys(int fd, BYTE increment) |
LogDebug("read of %zd bytes: %s", sizeof(UINT32), strerror(errno)); |
return TSPERR(TSS_E_INTERNAL_ERROR); |
} |
+ num_keys = LE_32(num_keys); |
if (increment) |
num_keys++; |
@@ -377,6 +433,7 @@ psfile_change_num_keys(int fd, BYTE increment) |
return TSPERR(TSS_E_INTERNAL_ERROR); |
} |
+ num_keys = LE_32(num_keys); |
if ((result = write_data(fd, (void *)&num_keys, sizeof(UINT32)))) { |
LogDebug("%s", __FUNCTION__); |
return result; |
@@ -498,16 +555,20 @@ psfile_write_key(int fd, |
} |
/* [UINT16 pub_data_size0 ] yes */ |
+ pub_key_size = LE_16(pub_key_size); |
if ((result = write_data(fd, &pub_key_size, sizeof(UINT16)))) { |
LogDebug("%s", __FUNCTION__); |
goto done; |
} |
+ pub_key_size = LE_16(pub_key_size); |
/* [UINT16 blob_size0 ] yes */ |
+ key_blob_size = LE_16(key_blob_size); |
if ((result = write_data(fd, &key_blob_size, sizeof(UINT16)))) { |
LogDebug("%s", __FUNCTION__); |
goto done; |
} |
+ key_blob_size = LE_16(key_blob_size); |
/* [UINT32 vendor_data_size0 ] yes */ |
if ((result = write_data(fd, &zero, sizeof(UINT32)))) { |
@@ -516,10 +577,12 @@ psfile_write_key(int fd, |
} |
/* [UINT16 cache_flags0 ] yes */ |
+ cache_flags = LE_16(cache_flags); |
if ((result = write_data(fd, &cache_flags, sizeof(UINT16)))) { |
LogDebug("%s", __FUNCTION__); |
goto done; |
} |
+ cache_flags = LE_16(cache_flags); |
/* [BYTE[] pub_data0 ] no */ |
if ((result = write_data(fd, (void *)key.pubKey.key, pub_key_size))) { |
@@ -685,6 +748,7 @@ psfile_get_all_cache_entries(int fd, UINT32 *size, struct key_disk_cache **c) |
LogDebug("%s", __FUNCTION__); |
goto err_exit; |
} |
+ tmp[i].pub_data_size = LE_16(tmp[i].pub_data_size); |
DBG_ASSERT(tmp[i].pub_data_size <= 2048); |
@@ -693,6 +757,7 @@ psfile_get_all_cache_entries(int fd, UINT32 *size, struct key_disk_cache **c) |
LogDebug("%s", __FUNCTION__); |
goto err_exit; |
} |
+ tmp[i].blob_size = LE_16(tmp[i].blob_size); |
DBG_ASSERT(tmp[i].blob_size <= 4096); |
@@ -701,12 +766,14 @@ psfile_get_all_cache_entries(int fd, UINT32 *size, struct key_disk_cache **c) |
LogDebug("%s", __FUNCTION__); |
goto err_exit; |
} |
+ tmp[i].vendor_data_size = LE_32(tmp[i].vendor_data_size); |
/* cache flags */ |
if ((result = read_data(fd, &tmp[i].flags, sizeof(UINT16)))) { |
LogDebug("%s", __FUNCTION__); |
goto err_exit; |
} |
+ tmp[i].flags = LE_16(tmp[i].flags); |
/* fast forward over the pub key */ |
offset = lseek(fd, tmp[i].pub_data_size, SEEK_CUR); |
@@ -1031,6 +1098,8 @@ psfile_get_num_keys(int fd) |
num_keys = 0; |
} |
+ /* The system PS file is written in little-endian */ |
+ num_keys = LE_32(num_keys); |
return num_keys; |
} |
@@ -1109,7 +1178,7 @@ psfile_get_cache_entry_by_uuid(int fd, TSS_UUID *uuid, struct key_disk_cache *c) |
LogDebug("%s", __FUNCTION__); |
return result; |
} |
- |
+ c->pub_data_size = LE_16(c->pub_data_size); |
DBG_ASSERT(c->pub_data_size <= 2048 && c->pub_data_size > 0); |
/* blob size */ |
@@ -1117,7 +1186,7 @@ psfile_get_cache_entry_by_uuid(int fd, TSS_UUID *uuid, struct key_disk_cache *c) |
LogDebug("%s", __FUNCTION__); |
return result; |
} |
- |
+ c->blob_size = LE_16(c->blob_size); |
DBG_ASSERT(c->blob_size <= 4096 && c->blob_size > 0); |
/* vendor data size */ |
@@ -1125,12 +1194,14 @@ psfile_get_cache_entry_by_uuid(int fd, TSS_UUID *uuid, struct key_disk_cache *c) |
LogDebug("%s", __FUNCTION__); |
return result; |
} |
+ c->vendor_data_size = LE_32(c->vendor_data_size); |
/* cache flags */ |
if ((result = read_data(fd, &c->flags, sizeof(UINT16)))) { |
LogDebug("%s", __FUNCTION__); |
return result; |
} |
+ c->flags = LE_16(c->flags); |
/* fast forward over the pub key */ |
offset = lseek(fd, c->pub_data_size, SEEK_CUR); |
@@ -1198,6 +1269,7 @@ psfile_get_cache_entry_by_pub(int fd, UINT32 pub_size, BYTE *pub, struct key_dis |
return result; |
} |
+ c->pub_data_size = LE_16(c->pub_data_size); |
DBG_ASSERT(c->pub_data_size <= 2048 && c->pub_data_size > 0); |
/* blob size */ |
@@ -1206,6 +1278,7 @@ psfile_get_cache_entry_by_pub(int fd, UINT32 pub_size, BYTE *pub, struct key_dis |
return result; |
} |
+ c->blob_size = LE_16(c->blob_size); |
DBG_ASSERT(c->blob_size <= 4096 && c->blob_size > 0); |
/* vendor data size */ |
@@ -1213,12 +1286,14 @@ psfile_get_cache_entry_by_pub(int fd, UINT32 pub_size, BYTE *pub, struct key_dis |
LogDebug("%s", __FUNCTION__); |
return result; |
} |
+ c->vendor_data_size = LE_32(c->vendor_data_size); |
/* cache flags */ |
if ((result = read_data(fd, &c->flags, sizeof(UINT16)))) { |
LogDebug("%s", __FUNCTION__); |
return result; |
} |
+ c->flags = LE_16(c->flags); |
if (c->pub_data_size == pub_size) { |
/* read in the pub key */ |