agent plugin optionally accepts a BUILD_PUBLIC_KEY to select a specific private key from the agent

This commit is contained in:
Martin Willi
2008-09-04 08:35:11 +00:00
parent 60055b7e1c
commit 6af6f88a79
@@ -168,10 +168,47 @@ static int open_connection(char *path)
return s; 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 * 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; int len, count;
char buf[2048]; char buf[2048];
@@ -203,7 +240,7 @@ static bool read_key(private_agent_private_key_t *this)
read_string(&tmp); read_string(&tmp);
tmp = read_string(&tmp); tmp = read_string(&tmp);
if (type.len && strneq("ssh-rsa", type.ptr, type.len) && 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 = chunk_clone(key);
this->key_size = tmp.len; this->key_size = tmp.len;
@@ -374,6 +411,7 @@ static bool build_ids(private_agent_private_key_t *this)
hasher_t *hasher; hasher_t *hasher;
key = this->key; key = this->key;
read_string(&key);
e = read_string(&key); e = read_string(&key);
n = 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"); DBG1("SHA1 hash algorithm not supported, unable to use RSA");
return FALSE; 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); hasher->allocate_hash(hasher, publicKey, &hash);
this->keyid = identification_create_from_encoding(ID_PUBKEY_SHA1, hash); this->keyid = identification_create_from_encoding(ID_PUBKEY_SHA1, hash);
chunk_free(&hash); chunk_free(&hash);
@@ -435,7 +475,8 @@ static void destroy(private_agent_private_key_t *this)
/** /**
* Internal constructor * 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); 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); free(this);
return NULL; return NULL;
} }
this->key = chunk_empty;
this->keyid = NULL; this->keyid = NULL;
this->keyid_info = NULL; this->keyid_info = NULL;
this->ref = 1; this->ref = 1;
if (!read_key(this) || !build_ids(this)) if (!read_key(this, pubkey) || !build_ids(this))
{ {
destroy(this); destroy(this);
return NULL; return NULL;
@@ -474,8 +516,10 @@ typedef struct private_builder_t private_builder_t;
struct private_builder_t { struct private_builder_t {
/** implements the builder interface */ /** implements the builder interface */
builder_t public; builder_t public;
/** loaded/generated private key */ /** agent unix socket */
agent_private_key_t *key; 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) 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); free(this);
return key; return key;
} }
@@ -496,25 +544,26 @@ static void add(private_builder_t *this, builder_part_t part, ...)
{ {
va_list args; va_list args;
if (this->key)
{
DBG1("ignoring surplus build part %N", builder_part_names, part);
return;
}
switch (part) switch (part)
{ {
case BUILD_AGENT_SOCKET: case BUILD_AGENT_SOCKET:
{ {
va_start(args, part); va_start(args, part);
this->key = agent_private_key_create(va_arg(args, char*)); this->socket = va_arg(args, char*);
va_end(args); 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: default:
DBG1("ignoring unsupported build part %N", builder_part_names, part);
break; 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 = 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.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
this->public.build = (void*(*)(builder_t *this))build; this->public.build = (void*(*)(builder_t *this))build;