diff options
author | Stef Walter <stef@thewalter.net> | 2013-06-14 13:02:22 +0200 |
---|---|---|
committer | Stef Walter <stef@thewalter.net> | 2013-06-14 13:32:04 +0200 |
commit | bfe10cd0660fd81d78c8c5ce3eaa7d1f046859e1 (patch) | |
tree | 7c691c0a82eca27ce905bc448e6f51575b46dae8 | |
parent | 045df29606ea9853b4fc8bdba062a5e4a7a5be95 (diff) |
trust: Correctly reflect the CK_TOKEN_INFO writability flags
Correctly set the CKF_TOKEN_WRITE_PROTECTED flag for paths
which we will be able to write to.
-rw-r--r-- | common/compat.h | 3 | ||||
-rw-r--r-- | trust/module.c | 5 | ||||
-rw-r--r-- | trust/tests/test-module.c | 57 | ||||
-rw-r--r-- | trust/tests/test-token.c | 76 | ||||
-rw-r--r-- | trust/token.c | 47 | ||||
-rw-r--r-- | trust/token.h | 2 |
6 files changed, 187 insertions, 3 deletions
diff --git a/common/compat.h b/common/compat.h index 0f9677b..9127f95 100644 --- a/common/compat.h +++ b/common/compat.h @@ -103,6 +103,8 @@ char * strdup_path_mangle (const char *template); #define WIN32_LEAN_AND_MEAN 1 #include <windows.h> +#include <io.h> + /* Oh ... my ... god */ #undef CreateMutex @@ -164,6 +166,7 @@ void p11_mmap_close (p11_mmap *map); #include <pthread.h> #include <dlfcn.h> #include <time.h> +#include <unistd.h> typedef pthread_mutex_t p11_mutex_t; diff --git a/trust/module.c b/trust/module.c index abfabae..ea514b1 100644 --- a/trust/module.c +++ b/trust/module.c @@ -544,7 +544,7 @@ sys_C_GetTokenInfo (CK_SLOT_ID id, info->firmwareVersion.minor = 0; info->hardwareVersion.major = PACKAGE_MAJOR; info->hardwareVersion.minor = PACKAGE_MINOR; - info->flags = CKF_TOKEN_INITIALIZED | CKF_WRITE_PROTECTED; + info->flags = CKF_TOKEN_INITIALIZED; strncpy ((char*)info->manufacturerID, MANUFACTURER_ID, 32); strncpy ((char*)info->model, TOKEN_MODEL, 16); strncpy ((char*)info->serialNumber, TOKEN_SERIAL_NUMBER, 16); @@ -566,6 +566,9 @@ sys_C_GetTokenInfo (CK_SLOT_ID id, length = sizeof (info->label); memset (info->label, ' ', sizeof (info->label)); memcpy (info->label, label, length); + + if (!p11_token_is_writable (token)) + info->flags |= CKF_WRITE_PROTECTED; } p11_unlock (); diff --git a/trust/tests/test-module.c b/trust/tests/test-module.c index bf28124..910b9b4 100644 --- a/trust/tests/test-module.c +++ b/trust/tests/test-module.c @@ -60,10 +60,13 @@ #define NUM_SLOTS 3 static CK_OBJECT_CLASS data = CKO_DATA; +static CK_BBOOL vtrue = CK_TRUE; +static CK_BBOOL vfalse = CK_FALSE; struct { CK_FUNCTION_LIST *module; CK_SLOT_ID slots[NUM_SLOTS]; + char *directory; } test; static void @@ -109,7 +112,44 @@ teardown (void *unused) rv = test.module->C_Finalize (NULL); assert (rv == CKR_OK); + free (test.directory); + + memset (&test, 0, sizeof (test)); +} + +static void +setup_writable (void *unused) +{ + CK_C_INITIALIZE_ARGS args; + char *arguments; + CK_ULONG count; + CK_RV rv; + memset (&test, 0, sizeof (test)); + + /* This is the entry point of the trust module, linked to this test */ + rv = C_GetFunctionList (&test.module); + assert (rv == CKR_OK); + + test.directory = p11_path_expand ("$TEMP/test-module.XXXXXX"); + if (!mkdtemp (test.directory)) + assert_not_reached (); + + memset (&args, 0, sizeof (args)); + if (asprintf (&arguments, "paths='%s'", test.directory) < 0) + assert (false && "not reached"); + args.pReserved = arguments; + args.flags = CKF_OS_LOCKING_OK; + + rv = test.module->C_Initialize (&args); + assert (rv == CKR_OK); + + free (arguments); + + count = 1; + rv = test.module->C_GetSlotList (CK_TRUE, test.slots, &count); + assert (rv == CKR_OK); + assert (count == 1); } static void @@ -587,8 +627,6 @@ static void test_find_builtin (void) { CK_OBJECT_CLASS klass = CKO_NSS_BUILTIN_ROOT_LIST; - CK_BBOOL vtrue = CK_TRUE; - CK_BBOOL vfalse = CK_FALSE; CK_ATTRIBUTE match[] = { { CKA_CLASS, &klass, sizeof (klass) }, @@ -987,6 +1025,18 @@ test_login_logout (void) assert (rv == CKR_USER_NOT_LOGGED_IN); } +static void +test_token_writable (void) +{ + CK_TOKEN_INFO info; + CK_RV rv; + + rv = test.module->C_GetTokenInfo (test.slots[0], &info); + + assert_num_eq (rv, CKR_OK); + assert_num_eq (info.flags & CKF_WRITE_PROTECTED, 0); +} + int main (int argc, char *argv[]) @@ -1020,5 +1070,8 @@ main (int argc, p11_test (test_find_serial_der_mismatch, "/module/find_serial_der_mismatch"); p11_test (test_login_logout, "/module/login_logout"); + p11_fixture (setup_writable, teardown); + p11_test (test_token_writable, "/module/token-writable"); + return p11_test_run (argc, argv); } diff --git a/trust/tests/test-token.c b/trust/tests/test-token.c index 6f5ccdb..d372814 100644 --- a/trust/tests/test-token.c +++ b/trust/tests/test-token.c @@ -42,6 +42,7 @@ #include "attrs.h" #include "debug.h" +#include "path.h" #include "pkcs11x.h" #include "message.h" #include "token.h" @@ -206,6 +207,75 @@ test_token_slot (void *path) assert_num_eq (333, p11_token_get_slot (test.token)); } +static void +test_not_writable (void) +{ + p11_token *token; + + token = p11_token_new (333, "/", "Label"); + assert (!p11_token_is_writable (token)); + p11_token_free (token); + + token = p11_token_new (333, "", "Label"); + assert (!p11_token_is_writable (token)); + p11_token_free (token); + + token = p11_token_new (333, "/non-existant", "Label"); + assert (!p11_token_is_writable (token)); + p11_token_free (token); +} + +static void +test_writable_exists (void) +{ + char *directory; + p11_token *token; + + directory = p11_path_expand ("$TEMP/test-module.XXXXXX"); + if (!mkdtemp (directory)) + assert_not_reached (); + + token = p11_token_new (333, directory, "Label"); + + /* A writable directory since we created it */ + assert (p11_token_is_writable (token)); + + p11_token_free (token); + + if (rmdir (directory) < 0) + assert_not_reached (); + + free (directory); +} + +static void +test_writable_no_exist (void) +{ + char *directory; + p11_token *token; + char *path; + + directory = p11_path_expand ("$TEMP/test-module.XXXXXX"); + if (!mkdtemp (directory)) + assert_not_reached (); + + path = p11_path_build (directory, "subdir", NULL); + assert (path != NULL); + + token = p11_token_new (333, path, "Label"); + free (path); + + /* A writable directory since parent is writable */ + assert (p11_token_is_writable (token)); + + p11_token_free (token); + + if (rmdir (directory) < 0) + assert_not_reached (); + + free (directory); +} + int main (int argc, char *argv[]) @@ -218,5 +288,11 @@ main (int argc, p11_testx (test_token_path, "/wheee", "/token/path"); p11_testx (test_token_label, "/wheee", "/token/label"); p11_testx (test_token_slot, "/unneeded", "/token/slot"); + + p11_fixture (NULL, NULL); + p11_test (test_not_writable, "/token/not-writable"); + p11_test (test_writable_exists, "/token/writable-exists"); + p11_test (test_writable_no_exist, "/token/writable-no-exist"); + return p11_test_run (argc, argv); } diff --git a/trust/token.c b/trust/token.c index f48f66b..c5991df 100644 --- a/trust/token.c +++ b/trust/token.c @@ -65,6 +65,9 @@ struct _p11_token { char *label; CK_SLOT_ID slot; int loaded; + + bool checked_writable; + bool is_writable; }; static int @@ -314,3 +317,47 @@ p11_token_index (p11_token *token) return_val_if_fail (token != NULL, NULL); return token->index; } + +static bool +check_writable_directory (const char *path) +{ + struct stat sb; + char *parent; + bool ret; + + if (access (path, W_OK) == 0) + return stat (path, &sb) == 0 && S_ISDIR (sb.st_mode); + + switch (errno) { + case EACCES: + return false; + case ENOENT: + parent = p11_path_parent (path); + if (parent == NULL) + ret = false; + else + ret = check_writable_directory (parent); + free (parent); + return ret; + default: + p11_message ("couldn't access: %s: %s", path, strerror (errno)); + return false; + } +} + +bool +p11_token_is_writable (p11_token *token) +{ + /* + * This function attempts to determine whether a later write + * to this token will succeed so we can setup the appropriate + * token flags. Yes, it is racy, but that's inherent to the problem. + */ + + if (!token->checked_writable) { + token->is_writable = check_writable_directory (token->path); + token->checked_writable = true; + } + + return token->is_writable; +} diff --git a/trust/token.h b/trust/token.h index d7375e7..49140bb 100644 --- a/trust/token.h +++ b/trust/token.h @@ -57,4 +57,6 @@ const char * p11_token_get_label (p11_token *token); CK_SLOT_ID p11_token_get_slot (p11_token *token); +bool p11_token_is_writable (p11_token *token); + #endif /* P11_TOKEN_H_ */ |