aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan
diff options
context:
space:
mode:
authorMartin Willi <martin@strongswan.org>2008-09-04 08:35:11 +0000
committerMartin Willi <martin@strongswan.org>2008-09-04 08:35:11 +0000
commit6af6f88a7985034cdd83ae26914ac99993cd3f29 (patch)
treeda44424c6f6c0131ea74b1ed73a82606b6157988 /src/libstrongswan
parent60055b7e1c75bd75610408c09bd92b1557ab8fdc (diff)
downloadstrongswan-6af6f88a7985034cdd83ae26914ac99993cd3f29.tar.bz2
strongswan-6af6f88a7985034cdd83ae26914ac99993cd3f29.tar.xz
agent plugin optionally accepts a BUILD_PUBLIC_KEY to select a specific private key from the agent
Diffstat (limited to 'src/libstrongswan')
-rw-r--r--src/libstrongswan/plugins/agent/agent_private_key.c86
1 files changed, 68 insertions, 18 deletions
diff --git a/src/libstrongswan/plugins/agent/agent_private_key.c b/src/libstrongswan/plugins/agent/agent_private_key.c
index 83f22b6f7..a3b8eebf3 100644
--- a/src/libstrongswan/plugins/agent/agent_private_key.c
+++ b/src/libstrongswan/plugins/agent/agent_private_key.c
@@ -168,10 +168,47 @@ static int open_connection(char *path)
return s;
}
+/**
+ * check if the ssh agent key blob matches to our public key
+ */
+static bool matches_pubkey(chunk_t key, public_key_t *pubkey)
+{
+ chunk_t pubkeydata, hash, n, e;
+ hasher_t *hasher;
+ identification_t *id;
+ bool match;
+
+ if (!pubkey)
+ {
+ return TRUE;
+ }
+ read_string(&key);
+ e = read_string(&key);
+ n = read_string(&key);
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (hasher == NULL)
+ {
+ return FALSE;
+ }
+ pubkeydata = asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_wrap(ASN1_INTEGER, "c", n),
+ asn1_wrap(ASN1_INTEGER, "c", e));
+ hasher->allocate_hash(hasher, pubkeydata, &hash);
+ free(pubkeydata.ptr);
+ id = pubkey->get_id(pubkey, ID_PUBKEY_SHA1);
+ if (!id)
+ {
+ return FALSE;
+ }
+ match = chunk_equals(id->get_encoding(id), hash);
+ free(hash.ptr);
+ return match;
+}
+
/**
* Get the first usable key from the agent
*/
-static bool read_key(private_agent_private_key_t *this)
+static bool read_key(private_agent_private_key_t *this, public_key_t *pubkey)
{
int len, count;
char buf[2048];
@@ -203,7 +240,7 @@ static bool read_key(private_agent_private_key_t *this)
read_string(&tmp);
tmp = read_string(&tmp);
if (type.len && strneq("ssh-rsa", type.ptr, type.len) &&
- tmp.len >= 512/8)
+ tmp.len >= 512/8 && matches_pubkey(key, pubkey))
{
this->key = chunk_clone(key);
this->key_size = tmp.len;
@@ -374,6 +411,7 @@ static bool build_ids(private_agent_private_key_t *this)
hasher_t *hasher;
key = this->key;
+ read_string(&key);
e = read_string(&key);
n = read_string(&key);
@@ -383,7 +421,9 @@ static bool build_ids(private_agent_private_key_t *this)
DBG1("SHA1 hash algorithm not supported, unable to use RSA");
return FALSE;
}
- publicKey = asn1_wrap(ASN1_SEQUENCE, "cc", n, e);
+ publicKey = asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_wrap(ASN1_INTEGER, "c", n),
+ asn1_wrap(ASN1_INTEGER, "c", e));
hasher->allocate_hash(hasher, publicKey, &hash);
this->keyid = identification_create_from_encoding(ID_PUBKEY_SHA1, hash);
chunk_free(&hash);
@@ -435,7 +475,8 @@ static void destroy(private_agent_private_key_t *this)
/**
* Internal constructor
*/
-static agent_private_key_t *agent_private_key_create(char *path)
+static agent_private_key_t *agent_private_key_create(char *path,
+ public_key_t *pubkey)
{
private_agent_private_key_t *this = malloc_thing(private_agent_private_key_t);
@@ -456,10 +497,11 @@ static agent_private_key_t *agent_private_key_create(char *path)
free(this);
return NULL;
}
+ this->key = chunk_empty;
this->keyid = NULL;
this->keyid_info = NULL;
this->ref = 1;
- if (!read_key(this) || !build_ids(this))
+ if (!read_key(this, pubkey) || !build_ids(this))
{
destroy(this);
return NULL;
@@ -474,8 +516,10 @@ typedef struct private_builder_t private_builder_t;
struct private_builder_t {
/** implements the builder interface */
builder_t public;
- /** loaded/generated private key */
- agent_private_key_t *key;
+ /** agent unix socket */
+ char *socket;
+ /** matching public key */
+ public_key_t *pubkey;
};
/**
@@ -483,8 +527,12 @@ struct private_builder_t {
*/
static agent_private_key_t *build(private_builder_t *this)
{
- agent_private_key_t *key = this->key;
+ agent_private_key_t *key = NULL;
+ if (this->socket)
+ {
+ key = agent_private_key_create(this->socket, this->pubkey);
+ }
free(this);
return key;
}
@@ -496,25 +544,26 @@ static void add(private_builder_t *this, builder_part_t part, ...)
{
va_list args;
- if (this->key)
- {
- DBG1("ignoring surplus build part %N", builder_part_names, part);
- return;
- }
-
switch (part)
{
case BUILD_AGENT_SOCKET:
{
va_start(args, part);
- this->key = agent_private_key_create(va_arg(args, char*));
+ this->socket = va_arg(args, char*);
va_end(args);
- break;
+ return;
+ }
+ case BUILD_PUBLIC_KEY:
+ {
+ va_start(args, part);
+ this->pubkey = va_arg(args, public_key_t*);
+ va_end(args);
+ return;
}
default:
- DBG1("ignoring unsupported build part %N", builder_part_names, part);
break;
}
+ builder_cancel(&this->public);
}
/**
@@ -531,7 +580,8 @@ builder_t *agent_private_key_builder(key_type_t type)
this = malloc_thing(private_builder_t);
- this->key = NULL;
+ this->pubkey = NULL;
+ this->socket = NULL;
this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
this->public.build = (void*(*)(builder_t *this))build;