charon-cmd: Add --agent option to authenticate using ssh-agent(1)

The socket path is read from the SSH_AUTH_SOCK environment variable.
So using this with sudo might require the -E command line (or an appropriate
sudoers config) to preserve the environment.
This commit is contained in:
Tobias Brunner 2013-04-01 14:51:09 +02:00
parent 4dc50bf9de
commit ee7b73832c
4 changed files with 72 additions and 0 deletions

View File

@ -387,6 +387,7 @@ METHOD(cmd_connection_t, handle, bool,
this->identity = arg; this->identity = arg;
break; break;
case CMD_OPT_RSA: case CMD_OPT_RSA:
case CMD_OPT_AGENT:
this->key_seen = TRUE; this->key_seen = TRUE;
break; break;
case CMD_OPT_LOCAL_TS: case CMD_OPT_LOCAL_TS:

View File

@ -47,6 +47,16 @@ struct private_cmd_creds_t {
* Already prompted for password? * Already prompted for password?
*/ */
bool prompted; bool prompted;
/**
* Provide keys via ssh-agent
*/
bool agent;
/**
* Local identity
*/
char *identity;
}; };
/** /**
@ -119,6 +129,54 @@ static void load_key(private_cmd_creds_t *this, key_type_t type, char *path)
this->creds->add_key(this->creds, privkey); this->creds->add_key(this->creds, privkey);
} }
/**
* Load a private and public key via ssh-agent
*/
static void load_agent(private_cmd_creds_t *this)
{
private_key_t *privkey;
public_key_t *pubkey;
identification_t *id;
certificate_t *cert;
char *agent;
agent = getenv("SSH_AUTH_SOCK");
if (!agent)
{
DBG1(DBG_CFG, "ssh-agent socket not found");
exit(1);
}
privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
KEY_RSA, BUILD_AGENT_SOCKET, agent, BUILD_END);
if (!privkey)
{
DBG1(DBG_CFG, "failed to load private key from ssh-agent");
exit(1);
}
pubkey = privkey->get_public_key(privkey);
if (!pubkey)
{
DBG1(DBG_CFG, "failed to load public key from ssh-agent");
privkey->destroy(privkey);
exit(1);
}
id = identification_create_from_string(this->identity);
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
CERT_TRUSTED_PUBKEY, BUILD_PUBLIC_KEY, pubkey,
BUILD_SUBJECT, id, BUILD_END);
pubkey->destroy(pubkey);
id->destroy(id);
if (!cert)
{
DBG1(DBG_CFG, "failed to create certificate for ssh-agent public key");
privkey->destroy(privkey);
exit(1);
}
this->creds->add_cert(this->creds, TRUE, cert);
this->creds->add_key(this->creds, privkey);
}
METHOD(cmd_creds_t, handle, bool, METHOD(cmd_creds_t, handle, bool,
private_cmd_creds_t *this, cmd_option_type_t opt, char *arg) private_cmd_creds_t *this, cmd_option_type_t opt, char *arg)
{ {
@ -130,9 +188,19 @@ METHOD(cmd_creds_t, handle, bool,
case CMD_OPT_RSA: case CMD_OPT_RSA:
load_key(this, KEY_RSA, arg); load_key(this, KEY_RSA, arg);
break; break;
case CMD_OPT_IDENTITY:
this->identity = arg;
break;
case CMD_OPT_AGENT:
this->agent = TRUE;
break;
default: default:
return FALSE; return FALSE;
} }
if (this->agent && this->identity)
{
load_agent(this);
}
return TRUE; return TRUE;
} }

View File

@ -35,6 +35,8 @@ cmd_option_t cmd_options[CMD_OPT_COUNT] = {
"trusted certificate, for authentication or trust chain validation" }, "trusted certificate, for authentication or trust chain validation" },
{ CMD_OPT_RSA, "rsa", required_argument, "path", { CMD_OPT_RSA, "rsa", required_argument, "path",
"RSA private key to use for authentication" }, "RSA private key to use for authentication" },
{ CMD_OPT_AGENT, "agent", no_argument, "",
"use SSH agent for authentication"},
{ CMD_OPT_LOCAL_TS, "local-ts", required_argument, "subnet", { CMD_OPT_LOCAL_TS, "local-ts", required_argument, "subnet",
"additional traffic selector to propose for our side" }, "additional traffic selector to propose for our side" },
{ CMD_OPT_REMOTE_TS, "remote-ts", required_argument, "subnet", { CMD_OPT_REMOTE_TS, "remote-ts", required_argument, "subnet",

View File

@ -35,6 +35,7 @@ enum cmd_option_type_t {
CMD_OPT_REMOTE_IDENTITY, CMD_OPT_REMOTE_IDENTITY,
CMD_OPT_CERT, CMD_OPT_CERT,
CMD_OPT_RSA, CMD_OPT_RSA,
CMD_OPT_AGENT,
CMD_OPT_LOCAL_TS, CMD_OPT_LOCAL_TS,
CMD_OPT_REMOTE_TS, CMD_OPT_REMOTE_TS,
CMD_OPT_PROFILE, CMD_OPT_PROFILE,