diff options
author | Stef Walter <stefw@collabora.co.uk> | 2011-06-24 15:31:02 +0200 |
---|---|---|
committer | Stef Walter <stefw@collabora.co.uk> | 2011-07-06 12:49:26 +0200 |
commit | fd7dee836d0b14efc48bf59955c8a12a72561043 (patch) | |
tree | b4dd8ffef5688edd3ca4321037d6acd2999cf929 | |
parent | 2cc2ab90a6b96ea75dfe4d6413e41539075e8f8a (diff) |
Add P11KitPin structure, which encapsulates a returned pin.
* Lets us use variable size buffers.
* Helps minimize copying.
-rw-r--r-- | p11-kit/pin.c | 171 | ||||
-rw-r--r-- | p11-kit/pin.h | 44 | ||||
-rw-r--r-- | tests/files/test-pinfile | 1 | ||||
-rw-r--r-- | tests/pin-test.c | 161 |
4 files changed, 302 insertions, 75 deletions
diff --git a/p11-kit/pin.c b/p11-kit/pin.c index 14cb171..879b6b7 100644 --- a/p11-kit/pin.c +++ b/p11-kit/pin.c @@ -42,11 +42,14 @@ #include "pin.h" #include "private.h" #include "ptr-array.h" +#include "util.h" #include <assert.h> #include <errno.h> +#include <fcntl.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> /** * SECTION:p11-pin @@ -138,7 +141,7 @@ typedef struct _PinfileCallback { /* Readonly after construct */ p11_kit_pin_callback func; void *user_data; - p11_kit_pin_callback_destroy destroy; + p11_kit_pin_destroy_func destroy; } PinfileCallback; /* @@ -173,7 +176,7 @@ unref_pinfile_callback (void *pointer) int p11_kit_pin_register_callback (const char *pinfile, p11_kit_pin_callback callback, - void *callback_data, p11_kit_pin_callback_destroy callback_destroy) + void *callback_data, p11_kit_pin_destroy_func callback_destroy) { PinfileCallback *cb; ptr_array_t *callbacks; @@ -283,16 +286,15 @@ p11_kit_pin_unregister_callback (const char *pinfile, p11_kit_pin_callback callb _p11_unlock (); } -int +P11KitPin* p11_kit_pin_retrieve (const char *pinfile, P11KitUri *pin_uri, - const char *pin_description, P11KitPinFlags flags, - char *pin, size_t pin_length) + const char *pin_description, P11KitPinFlags flags) { PinfileCallback **snapshot = NULL; unsigned int snapshot_count = 0; ptr_array_t *callbacks; + P11KitPin *pin; unsigned int i; - int ret; _p11_lock (); @@ -315,12 +317,11 @@ p11_kit_pin_retrieve (const char *pinfile, P11KitUri *pin_uri, _p11_unlock (); if (snapshot == NULL) - return 0; + return NULL; - ret = 0; - for (i = snapshot_count; ret == 0 && i > 0; i--) { - ret = (snapshot[i - 1]->func) (pinfile, pin_uri, pin_description, flags, - snapshot[i - 1]->user_data, pin, pin_length); + for (pin = NULL, i = snapshot_count; pin == NULL && i > 0; i--) { + pin = (snapshot[i - 1]->func) (pinfile, pin_uri, pin_description, flags, + snapshot[i - 1]->user_data); } _p11_lock (); @@ -329,5 +330,151 @@ p11_kit_pin_retrieve (const char *pinfile, P11KitUri *pin_uri, free (snapshot); _p11_unlock (); - return ret; + return pin; +} + +P11KitPin* +p11_kit_pin_file_callback (const char *pinfile, + P11KitUri *pin_uri, + const char *pin_description, + P11KitPinFlags pin_flags, + void *callback_data) +{ + unsigned char *buffer; + size_t used, allocated; + int error = 0; + int fd; + int res; + + /* We don't support retries */ + if (pin_flags & P11_KIT_PIN_FLAGS_RETRY) + return NULL; + + fd = open (pinfile, O_RDONLY); + if (fd == -1) + return NULL; + + buffer = NULL; + used = 0; + allocated = 0; + + for (;;) { + if (used + 256 > allocated) { + buffer = xrealloc (buffer, used + 1024); + if (buffer == NULL) { + error = ENOMEM; + break; + } + allocated = used + 1024; + } + + res = read (fd, buffer + used, allocated - used); + if (res < 0) { + if (errno == EAGAIN) + continue; + error = errno; + free (buffer); + buffer = NULL; + error = errno; + break; + } else if (res == 0) { + break; + } else { + used += res; + } + } + + if (buffer == NULL) { + errno = error; + return NULL; + } + + return p11_kit_pin_new_for_buffer (buffer, used, free); +} + +struct _P11KitPin { + int ref_count; + unsigned char *buffer; + size_t length; + p11_kit_pin_destroy_func destroy; +}; + +P11KitPin* +p11_kit_pin_new (const unsigned char *value, size_t length) +{ + unsigned char *copy; + P11KitPin *pin; + + copy = malloc (length); + if (copy == NULL) + return NULL; + + memcpy (copy, value, length); + pin = p11_kit_pin_new_for_buffer (copy, length, free); + if (pin == NULL) + free (copy); + return pin; +} + +P11KitPin* +p11_kit_pin_new_for_string (const char *value) +{ + return p11_kit_pin_new ((const unsigned char *)value, strlen (value)); +} + +P11KitPin* +p11_kit_pin_new_for_buffer (unsigned char *buffer, size_t length, + p11_kit_pin_destroy_func destroy) +{ + P11KitPin *pin; + + pin = calloc (1, sizeof (P11KitPin)); + if (pin == NULL) + return NULL; + + pin->ref_count = 1; + pin->buffer = buffer; + pin->length = length; + pin->destroy = destroy; + + return pin; +} + +const unsigned char* +p11_kit_pin_get_value (P11KitPin *pin, size_t *length) +{ + if (length) + *length = pin->length; + return pin->buffer; +} + +P11KitPin* +p11_kit_pin_ref (P11KitPin *pin) +{ + _p11_lock (); + + pin->ref_count++; + + _p11_unlock (); + + return pin; +} + +void +p11_kit_pin_unref (P11KitPin *pin) +{ + int last = 0; + + _p11_lock (); + + last = (pin->ref_count == 1); + pin->ref_count--; + + _p11_unlock (); + + if (last) { + if (pin->destroy) + (pin->destroy) (pin->buffer); + free (pin); + } } diff --git a/p11-kit/pin.h b/p11-kit/pin.h index bb5daae..532aa54 100644 --- a/p11-kit/pin.h +++ b/p11-kit/pin.h @@ -41,6 +41,8 @@ extern "C" { #endif +typedef struct _P11KitPin P11KitPin; + typedef enum { P11_KIT_PIN_FLAGS_USER_LOGIN = 1, P11_KIT_PIN_FLAGS_SO_LOGIN = 2, @@ -52,31 +54,49 @@ typedef enum { #define P11_KIT_PIN_FALLBACK "" -typedef int (*p11_kit_pin_callback) (const char *pinfile, +typedef void (*p11_kit_pin_destroy_func) (void *callback_data); + +P11KitPin* p11_kit_pin_new (const unsigned char *value, + size_t length); + +P11KitPin* p11_kit_pin_new_for_string (const char *value); + +P11KitPin* p11_kit_pin_new_for_buffer (unsigned char *buffer, + size_t length, + p11_kit_pin_destroy_func destroy); + +P11KitPin* p11_kit_pin_ref (P11KitPin *pin); + +void p11_kit_pin_unref (P11KitPin *pin); + +const unsigned char * p11_kit_pin_get_value (P11KitPin *pin, + size_t *length); + +typedef P11KitPin* (*p11_kit_pin_callback) (const char *pinfile, P11KitUri *pin_uri, const char *pin_description, P11KitPinFlags pin_flags, - void *callback_data, - char *pin, - size_t pin_length); - -typedef void (*p11_kit_pin_callback_destroy) (void *callback_data); + void *callback_data); -int p11_kit_pin_register_callback (const char *pinfile, +int p11_kit_pin_register_callback (const char *pinfile, p11_kit_pin_callback callback, void *callback_data, - p11_kit_pin_callback_destroy callback_destroy); + p11_kit_pin_destroy_func callback_destroy); -void p11_kit_pin_unregister_callback (const char *pinfile, +void p11_kit_pin_unregister_callback (const char *pinfile, p11_kit_pin_callback callback, void *callback_data); -int p11_kit_pin_retrieve (const char *pinfile, +P11KitPin* p11_kit_pin_retrieve (const char *pinfile, + P11KitUri *pin_uri, + const char *pin_description, + P11KitPinFlags pin_flags); + +P11KitPin* p11_kit_pin_file_callback (const char *pinfile, P11KitUri *pin_uri, const char *pin_description, P11KitPinFlags pin_flags, - char *pin, - size_t pin_max); + void *callback_data); #ifdef __cplusplus } /* extern "C" */ diff --git a/tests/files/test-pinfile b/tests/files/test-pinfile new file mode 100644 index 0000000..f646f3d --- /dev/null +++ b/tests/files/test-pinfile @@ -0,0 +1 @@ +yogabbagabba
\ No newline at end of file diff --git a/tests/pin-test.c b/tests/pin-test.c index 344fe6b..086f892 100644 --- a/tests/pin-test.c +++ b/tests/pin-test.c @@ -36,31 +36,28 @@ #include "CuTest.h" #include <assert.h> +#include <errno.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include "p11-kit/pin.h" -static int +static P11KitPin * callback_one (const char *pinfile, P11KitUri *pin_uri, const char *pin_description, - P11KitPinFlags pin_flags, void *callback_data, char *pin, - size_t pin_max) + P11KitPinFlags pin_flags, void *callback_data) { int *data = callback_data; assert (*data == 33); - strncpy (pin, "one", pin_max); - return 1; + return p11_kit_pin_new_for_buffer ((unsigned char*)strdup ("one"), 3, free); } -static int +static P11KitPin* callback_other (const char *pinfile, P11KitUri *pin_uri, const char *pin_description, - P11KitPinFlags pin_flags, void *callback_data, char *pin, - size_t pin_max) + P11KitPinFlags pin_flags, void *callback_data) { char *data = callback_data; - strncpy (pin, data, pin_max); - return 1; + return p11_kit_pin_new_for_string (data); } static void @@ -88,50 +85,54 @@ static void test_pin_read (CuTest *tc) { P11KitUri *uri; - char buffer[256]; + P11KitPin *pin; int data = 33; - int ret; + size_t length; + const unsigned char *ptr; p11_kit_pin_register_callback ("/the/pinfile", callback_one, &data, destroy_data); uri = p11_kit_uri_new (); - ret = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", - P11_KIT_PIN_FLAGS_USER_LOGIN, - buffer, sizeof (buffer)); + pin = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", + P11_KIT_PIN_FLAGS_USER_LOGIN); p11_kit_uri_free (uri); - CuAssertIntEquals (tc, 1, ret); - CuAssertStrEquals (tc, "one", buffer); + CuAssertPtrNotNull (tc, pin); + ptr = p11_kit_pin_get_value (pin, &length); + CuAssertIntEquals (tc, 3, length); + CuAssertTrue (tc, memcmp (ptr, "one", 3) == 0); p11_kit_pin_unregister_callback ("/the/pinfile", callback_one, &data); + + p11_kit_pin_ref (pin); + p11_kit_pin_unref (pin); } static void test_pin_read_no_match (CuTest *tc) { P11KitUri *uri; - char buffer[256]; - int ret; + P11KitPin *pin; uri = p11_kit_uri_new (); - ret = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", - P11_KIT_PIN_FLAGS_USER_LOGIN, - buffer, sizeof (buffer)); + pin = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", + P11_KIT_PIN_FLAGS_USER_LOGIN); p11_kit_uri_free (uri); - CuAssertIntEquals (tc, 0, ret); + CuAssertPtrEquals (tc, NULL, pin); } static void test_pin_register_duplicate (CuTest *tc) { P11KitUri *uri; + P11KitPin *pin; char *value = "secret"; - char buffer[256]; int data = 33; - int ret; + size_t length; + const unsigned char *ptr; uri = p11_kit_uri_new (); @@ -141,31 +142,34 @@ test_pin_register_duplicate (CuTest *tc) p11_kit_pin_register_callback ("/the/pinfile", callback_other, value, NULL); - ret = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", - P11_KIT_PIN_FLAGS_USER_LOGIN, - buffer, sizeof (buffer)); + pin = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", + P11_KIT_PIN_FLAGS_USER_LOGIN); - CuAssertIntEquals (tc, 1, ret); - CuAssertStrEquals (tc, "secret", buffer); + CuAssertPtrNotNull (tc, pin); + ptr = p11_kit_pin_get_value (pin, &length); + CuAssertIntEquals (tc, 6, length); + CuAssertTrue (tc, memcmp (ptr, "secret", length) == 0); + p11_kit_pin_unref (pin); p11_kit_pin_unregister_callback ("/the/pinfile", callback_other, value); - ret = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", - P11_KIT_PIN_FLAGS_USER_LOGIN, - buffer, sizeof (buffer)); + pin = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", + P11_KIT_PIN_FLAGS_USER_LOGIN); - CuAssertIntEquals (tc, 1, ret); - CuAssertStrEquals (tc, "one", buffer); + CuAssertPtrNotNull (tc, pin); + ptr = p11_kit_pin_get_value (pin, &length); + CuAssertIntEquals (tc, 3, length); + CuAssertTrue (tc, memcmp (ptr, "one", length) == 0); + p11_kit_pin_unref (pin); p11_kit_pin_unregister_callback ("/the/pinfile", callback_one, &data); - ret = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", - P11_KIT_PIN_FLAGS_USER_LOGIN, - buffer, sizeof (buffer)); + pin = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", + P11_KIT_PIN_FLAGS_USER_LOGIN); - CuAssertIntEquals (tc, 0, ret); + CuAssertPtrEquals (tc, NULL, pin); p11_kit_uri_free (uri); } @@ -175,31 +179,36 @@ test_pin_register_fallback (CuTest *tc) { char *value = "secret"; P11KitUri *uri; - char buffer[256]; + P11KitPin *pin; int data = 33; - int ret; + size_t length; + const unsigned char *ptr; uri = p11_kit_uri_new (); p11_kit_pin_register_callback (P11_KIT_PIN_FALLBACK, callback_one, &data, destroy_data); - ret = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", - P11_KIT_PIN_FLAGS_USER_LOGIN, - buffer, sizeof (buffer)); + pin = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", + P11_KIT_PIN_FLAGS_USER_LOGIN); - CuAssertIntEquals (tc, 1, ret); - CuAssertStrEquals (tc, "one", buffer); + CuAssertPtrNotNull (tc, pin); + ptr = p11_kit_pin_get_value (pin, &length); + CuAssertIntEquals (tc, 3, length); + CuAssertTrue (tc, memcmp (ptr, "one", length) == 0); + p11_kit_pin_unref (pin); p11_kit_pin_register_callback ("/the/pinfile", callback_other, value, NULL); - ret = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", - P11_KIT_PIN_FLAGS_USER_LOGIN, - buffer, sizeof (buffer)); + pin = p11_kit_pin_retrieve ("/the/pinfile", uri, "The token", + P11_KIT_PIN_FLAGS_USER_LOGIN); - CuAssertIntEquals (tc, 1, ret); - CuAssertStrEquals (tc, "secret", buffer); + CuAssertPtrNotNull (tc, pin); + ptr = p11_kit_pin_get_value (pin, &length); + CuAssertIntEquals (tc, 6, length); + CuAssertTrue (tc, memcmp (ptr, "secret", length) == 0); + p11_kit_pin_unref (pin); p11_kit_pin_unregister_callback ("/the/pinfile", callback_other, value); @@ -210,6 +219,54 @@ test_pin_register_fallback (CuTest *tc) p11_kit_uri_free (uri); } +static void +test_pin_file (CuTest *tc) +{ + P11KitUri *uri; + P11KitPin *pin; + size_t length; + const unsigned char *ptr; + + uri = p11_kit_uri_new (); + + p11_kit_pin_register_callback (P11_KIT_PIN_FALLBACK, p11_kit_pin_file_callback, + NULL, NULL); + + pin = p11_kit_pin_retrieve (SRCDIR "/files/test-pinfile", uri, "The token", + P11_KIT_PIN_FLAGS_USER_LOGIN); + + CuAssertPtrNotNull (tc, pin); + ptr = p11_kit_pin_get_value (pin, &length); + CuAssertIntEquals (tc, 12, length); + CuAssertTrue (tc, memcmp (ptr, "yogabbagabba", length) == 0); + p11_kit_pin_unref (pin); + + pin = p11_kit_pin_retrieve (SRCDIR "/files/nonexistant", uri, "The token", + P11_KIT_PIN_FLAGS_USER_LOGIN); + + CuAssertPtrEquals (tc, NULL, pin); + + p11_kit_pin_unregister_callback (P11_KIT_PIN_FALLBACK, p11_kit_pin_file_callback, + NULL); + + p11_kit_uri_free (uri); +} + +static void +test_pin_ref_unref (CuTest *tc) +{ + P11KitPin *pin; + P11KitPin *check; + + pin = p11_kit_pin_new_for_string ("crack of lies"); + + check = p11_kit_pin_ref (pin); + CuAssertPtrEquals (tc, pin, check); + + p11_kit_pin_unref (pin); + p11_kit_pin_unref (check); +} + int main (void) { @@ -222,6 +279,8 @@ main (void) SUITE_ADD_TEST (suite, test_pin_read_no_match); SUITE_ADD_TEST (suite, test_pin_register_duplicate); SUITE_ADD_TEST (suite, test_pin_register_fallback); + SUITE_ADD_TEST (suite, test_pin_file); + SUITE_ADD_TEST (suite, test_pin_ref_unref); CuSuiteRun (suite); CuSuiteSummary (suite, output); |