Refactored stroke smartcard token parsing, support module and slot in leftcert option

This commit is contained in:
Martin Willi
2012-10-24 13:07:53 +02:00
parent 36e47a409b
commit 2abe404927
+101 -62
View 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*, METHOD(stroke_cred_t, load_ca, certificate_t*,
private_stroke_cred_t *this, char *filename) 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*, METHOD(stroke_cred_t, load_peer, certificate_t*,
private_stroke_cred_t *this, char *filename) 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)); smartcard_format_t format;
keyid = chunk_from_hex(chunk_skip(keyid, strlen("%smartcard:")), NULL); char module[BUF_LEN], keyid[BUF_LEN];
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, u_int slot;
BUILD_PKCS11_KEYID, keyid, BUILD_END);
free(keyid.ptr); 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) FILE *prompt)
{ {
chunk_t sc = chunk_empty, secret = chunk_empty; 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; private_key_t *key = NULL;
u_int slot; u_int slot;
chunk_t chunk; 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; mem_cred_t *mem = NULL;
callback_cred_t *cb = NULL; callback_cred_t *cb = NULL;
pin_cb_data_t pin_data; pin_cb_data_t pin_data;
enum { smartcard_format_t format;
SC_FORMAT_SLOT_MODULE_KEYID,
SC_FORMAT_SLOT_KEYID,
SC_FORMAT_KEYID,
} 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); snprintf(smartcard, sizeof(smartcard), "%.*s", (int)sc.len, sc.ptr);
smartcard[sizeof(smartcard) - 1] = '\0'; smartcard[sizeof(smartcard) - 1] = '\0';
/* parse slot and key id. Three formats are supported: format = parse_smartcard(smartcard, &slot, module, keyid);
* - %smartcard<slot>@<module>:<keyid> if (format == SC_FORMAT_INVALID)
* - %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
{ {
DBG1(DBG_CFG, "line %d: the given %%smartcard specifier is not" DBG1(DBG_CFG, "line %d: the given %%smartcard specifier is not"
" supported or invalid", line_nr); " 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) key = (private_key_t*)load_from_smartcard(format, slot, module, keyid,
{ CRED_PRIVATE_KEY, KEY_ANY);
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;
}
if (mem) if (mem)
{ {
lib->credmgr->remove_local_set(lib->credmgr, &mem->set); lib->credmgr->remove_local_set(lib->credmgr, &mem->set);