]> granicus.if.org Git - p11-kit/commitdiff
Add P11KitPin structure, which encapsulates a returned pin.
authorStef Walter <stefw@collabora.co.uk>
Fri, 24 Jun 2011 13:31:02 +0000 (15:31 +0200)
committerStef Walter <stefw@collabora.co.uk>
Wed, 6 Jul 2011 10:49:26 +0000 (12:49 +0200)
 * Lets us use variable size buffers.
 * Helps minimize copying.

p11-kit/pin.c
p11-kit/pin.h
tests/files/test-pinfile [new file with mode: 0644]
tests/pin-test.c

index 14cb171d13b473028430cc4b3f11bf04c249ad15..879b6b72d0a1c35f1d7b8cf0d5134df111b5b892 100644 (file)
 #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);
+       }
 }
index bb5daae2772c326d52756e72c7256d4ed7890509..532aa54b7452c8f7ac2f9b24ad2cbb3a3ac888f4 100644 (file)
@@ -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 (file)
index 0000000..f646f3d
--- /dev/null
@@ -0,0 +1 @@
+yogabbagabba
\ No newline at end of file
index 344fe6b18e36966e9552ab5bcb62cf72d002eb04..086f892adf3f7438bae5efe6e9681c593667454a 100644 (file)
 #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);