Refactored stroke smartcard token parsing, support module and slot in leftcert option
authorMartin Willi <martin@revosec.ch>
Wed, 17 Oct 2012 13:36:45 +0000 (15:36 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 24 Oct 2012 11:07:53 +0000 (13:07 +0200)
src/libcharon/plugins/stroke/stroke_cred.c

index 60dbdf6..1bb1fe7 100644 (file)
@@ -82,6 +82,89 @@ struct private_stroke_cred_t {
        bool cachecrl;
 };
 
        bool cachecrl;
 };
 
+/**
+ * Kind of smartcard specifier token
+ */
+typedef enum {
+       SC_FORMAT_SLOT_MODULE_KEYID,
+       SC_FORMAT_SLOT_KEYID,
+       SC_FORMAT_KEYID,
+       SC_FORMAT_INVALID,
+} smartcard_format_t;
+
+/**
+ * Parse a smartcard specifier token
+ */
+static smartcard_format_t parse_smartcard(char *smartcard, u_int *slot,
+                                                                       char module[BUF_LEN], char keyid[BUF_LEN])
+{
+       /* The token has one of the following three formats:
+        * - %smartcard<slot>@<module>:<keyid>
+        * - %smartcard<slot>:<keyid>
+        * - %smartcard:<keyid>
+        */
+       char buf[BUF_LEN], *pos;
+
+       if (sscanf(smartcard, "%%smartcard%u@%127s", slot, buf) == 2)
+       {
+               pos = strchr(buf, ':');
+               if (!pos)
+               {
+                       return SC_FORMAT_INVALID;
+               }
+               *pos++ = '\0';
+               snprintf(module, BUF_LEN, "%s", buf);
+               snprintf(keyid, BUF_LEN, "%s", pos);
+               return SC_FORMAT_SLOT_MODULE_KEYID;
+       }
+       if (sscanf(smartcard, "%%smartcard%u:%63s", slot, keyid) == 2)
+       {
+               return SC_FORMAT_SLOT_KEYID;
+       }
+       if (sscanf(smartcard, "%%smartcard:%63s", keyid) == 1)
+       {
+               return SC_FORMAT_KEYID;
+       }
+       return SC_FORMAT_INVALID;
+}
+
+/**
+ * Load a credential from a smartcard
+ */
+static certificate_t *load_from_smartcard(smartcard_format_t format,
+                                                                                 u_int slot, char *module, char *keyid,
+                                                                                 credential_type_t type, int subtype)
+{
+       chunk_t chunk;
+       void *cred;
+
+       chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL);
+       switch (format)
+       {
+               case SC_FORMAT_SLOT_MODULE_KEYID:
+                       cred = lib->creds->create(lib->creds, type, subtype,
+                                                       BUILD_PKCS11_SLOT, slot,
+                                                       BUILD_PKCS11_MODULE, module,
+                                                       BUILD_PKCS11_KEYID, chunk, BUILD_END);
+                       break;
+               case SC_FORMAT_SLOT_KEYID:
+                       cred = lib->creds->create(lib->creds, type, subtype,
+                                                       BUILD_PKCS11_SLOT, slot,
+                                                       BUILD_PKCS11_KEYID, chunk, BUILD_END);
+                       break;
+               case SC_FORMAT_KEYID:
+                       cred = lib->creds->create(lib->creds, type, subtype,
+                                                       BUILD_PKCS11_KEYID, chunk, BUILD_END);
+                       break;
+               default:
+                       cred = NULL;
+                       break;
+       }
+       free(chunk.ptr);
+
+       return cred;
+}
+
 METHOD(stroke_cred_t, load_ca, certificate_t*,
        private_stroke_cred_t *this, char *filename)
 {
 METHOD(stroke_cred_t, load_ca, certificate_t*,
        private_stroke_cred_t *this, char *filename)
 {
@@ -131,17 +214,21 @@ METHOD(stroke_cred_t, load_ca, certificate_t*,
 METHOD(stroke_cred_t, load_peer, certificate_t*,
        private_stroke_cred_t *this, char *filename)
 {
 METHOD(stroke_cred_t, load_peer, certificate_t*,
        private_stroke_cred_t *this, char *filename)
 {
-       certificate_t *cert;
+       certificate_t *cert = NULL;
        char path[PATH_MAX];
        char path[PATH_MAX];
-       chunk_t keyid;
 
 
-       if (strneq(filename, "%smartcard:", strlen("%smartcard:")))
+       if (strneq(filename, "%smartcard", strlen("%smartcard")))
        {
        {
-               keyid = chunk_create(filename, strlen(filename));
-               keyid = chunk_from_hex(chunk_skip(keyid, strlen("%smartcard:")), NULL);
-               cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
-                                                                 BUILD_PKCS11_KEYID, keyid, BUILD_END);
-               free(keyid.ptr);
+               smartcard_format_t format;
+               char module[BUF_LEN], keyid[BUF_LEN];
+               u_int slot;
+
+               format = parse_smartcard(filename, &slot, module, keyid);
+               if (format != SC_FORMAT_INVALID)
+               {
+                       cert = (certificate_t*)load_from_smartcard(format,
+                                                       slot, module, keyid, CRED_CERTIFICATE, CERT_X509);
+               }
        }
        else
        {
        }
        else
        {
@@ -597,7 +684,7 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
                                         FILE *prompt)
 {
        chunk_t sc = chunk_empty, secret = chunk_empty;
                                         FILE *prompt)
 {
        chunk_t sc = chunk_empty, secret = chunk_empty;
-       char smartcard[64], keyid[64], module[64], *pos;
+       char smartcard[BUF_LEN], keyid[BUF_LEN], module[BUF_LEN];
        private_key_t *key = NULL;
        u_int slot;
        chunk_t chunk;
        private_key_t *key = NULL;
        u_int slot;
        chunk_t chunk;
@@ -606,11 +693,7 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
        mem_cred_t *mem = NULL;
        callback_cred_t *cb = NULL;
        pin_cb_data_t pin_data;
        mem_cred_t *mem = NULL;
        callback_cred_t *cb = NULL;
        pin_cb_data_t pin_data;
-       enum {
-               SC_FORMAT_SLOT_MODULE_KEYID,
-               SC_FORMAT_SLOT_KEYID,
-               SC_FORMAT_KEYID,
-       } format;
+       smartcard_format_t format;
 
        err_t ugh = extract_value(&sc, &line);
 
 
        err_t ugh = extract_value(&sc, &line);
 
@@ -627,33 +710,8 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
        snprintf(smartcard, sizeof(smartcard), "%.*s", (int)sc.len, sc.ptr);
        smartcard[sizeof(smartcard) - 1] = '\0';
 
        snprintf(smartcard, sizeof(smartcard), "%.*s", (int)sc.len, sc.ptr);
        smartcard[sizeof(smartcard) - 1] = '\0';
 
-       /* parse slot and key id. Three formats are supported:
-        * - %smartcard<slot>@<module>:<keyid>
-        * - %smartcard<slot>:<keyid>
-        * - %smartcard:<keyid>
-        */
-       if (sscanf(smartcard, "%%smartcard%u@%s", &slot, module) == 2)
-       {
-               pos = strchr(module, ':');
-               if (!pos)
-               {
-                       DBG1(DBG_CFG, "line %d: the given %%smartcard specifier is "
-                                "invalid", line_nr);
-                       return FALSE;
-               }
-               *pos = '\0';
-               strncpy(keyid, pos + 1, sizeof(keyid));
-               format = SC_FORMAT_SLOT_MODULE_KEYID;
-       }
-       else if (sscanf(smartcard, "%%smartcard%u:%s", &slot, keyid) == 2)
-       {
-               format = SC_FORMAT_SLOT_KEYID;
-       }
-       else if (sscanf(smartcard, "%%smartcard:%s", keyid) == 1)
-       {
-               format = SC_FORMAT_KEYID;
-       }
-       else
+       format = parse_smartcard(smartcard, &slot, module, keyid);
+       if (format == SC_FORMAT_INVALID)
        {
                DBG1(DBG_CFG, "line %d: the given %%smartcard specifier is not"
                                " supported or invalid", line_nr);
        {
                DBG1(DBG_CFG, "line %d: the given %%smartcard specifier is not"
                                " supported or invalid", line_nr);
@@ -700,27 +758,8 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
        }
 
        /* unlock: smartcard needs the pin and potentially calls public set */
        }
 
        /* unlock: smartcard needs the pin and potentially calls public set */
-       switch (format)
-       {
-               case SC_FORMAT_SLOT_MODULE_KEYID:
-                       key = lib->creds->create(lib->creds,
-                                                       CRED_PRIVATE_KEY, KEY_ANY,
-                                                       BUILD_PKCS11_SLOT, slot,
-                                                       BUILD_PKCS11_MODULE, module,
-                                                       BUILD_PKCS11_KEYID, chunk, BUILD_END);
-                       break;
-               case SC_FORMAT_SLOT_KEYID:
-                       key = lib->creds->create(lib->creds,
-                                                       CRED_PRIVATE_KEY, KEY_ANY,
-                                                       BUILD_PKCS11_SLOT, slot,
-                                                       BUILD_PKCS11_KEYID, chunk, BUILD_END);
-                       break;
-               case SC_FORMAT_KEYID:
-                       key = lib->creds->create(lib->creds,
-                                                       CRED_PRIVATE_KEY, KEY_ANY,
-                                                       BUILD_PKCS11_KEYID, chunk, BUILD_END);
-                       break;
-       }
+       key = (private_key_t*)load_from_smartcard(format, slot, module, keyid,
+                                                                                         CRED_PRIVATE_KEY, KEY_ANY);
        if (mem)
        {
                lib->credmgr->remove_local_set(lib->credmgr, &mem->set);
        if (mem)
        {
                lib->credmgr->remove_local_set(lib->credmgr, &mem->set);