summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stefw@collabora.co.uk>2011-06-24 15:31:02 +0200
committerStef Walter <stefw@collabora.co.uk>2011-07-06 12:49:26 +0200
commitfd7dee836d0b14efc48bf59955c8a12a72561043 (patch)
treeb4dd8ffef5688edd3ca4321037d6acd2999cf929
parent2cc2ab90a6b96ea75dfe4d6413e41539075e8f8a (diff)
downloadp11-kit-fd7dee836d0b14efc48bf59955c8a12a72561043.tar.gz
Add P11KitPin structure, which encapsulates a returned pin.
* Lets us use variable size buffers. * Helps minimize copying.
-rw-r--r--p11-kit/pin.c171
-rw-r--r--p11-kit/pin.h44
-rw-r--r--tests/files/test-pinfile1
-rw-r--r--tests/pin-test.c161
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);