From: Martin Willi Date: Wed, 17 Oct 2012 13:36:45 +0000 (+0200) Subject: Refactored stroke smartcard token parsing, support module and slot in leftcert option X-Git-Tag: 5.0.2dr4~290 X-Git-Url: https://git.strongswan.org/?p=strongswan.git;a=commitdiff_plain;h=2abe404927a3ec04b8d7fd8a7e99d50fa7677e43 Refactored stroke smartcard token parsing, support module and slot in leftcert option --- diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c index 60dbdf6..1bb1fe7 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.c +++ b/src/libcharon/plugins/stroke/stroke_cred.c @@ -82,6 +82,89 @@ struct private_stroke_cred_t { 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@: + * - %smartcard: + * - %smartcard: + */ + 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) { @@ -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) { - certificate_t *cert; + certificate_t *cert = NULL; 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 { @@ -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; - 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; @@ -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; - 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); @@ -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'; - /* parse slot and key id. Three formats are supported: - * - %smartcard@: - * - %smartcard: - * - %smartcard: - */ - 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); @@ -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 */ - 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);