mirror of
https://github.com/clearml/dropbear
synced 2025-04-06 21:54:24 +00:00
- Client auth using an agent's key works. Still need to implement client
agent forwarding. --HG-- branch : agent-client extra : convert_revision : 276cf5e82276b6c879d246ba64739ec6868f5150
This commit is contained in:
parent
c742137dc8
commit
8a19a049b2
1
auth.h
1
auth.h
@ -74,6 +74,7 @@ void cli_auth_password();
|
|||||||
int cli_auth_pubkey();
|
int cli_auth_pubkey();
|
||||||
void cli_auth_interactive();
|
void cli_auth_interactive();
|
||||||
char* getpass_or_cancel(char* prompt);
|
char* getpass_or_cancel(char* prompt);
|
||||||
|
void cli_auth_pubkey_cleanup();
|
||||||
|
|
||||||
|
|
||||||
#define MAX_USERNAME_LEN 25 /* arbitrary for the moment */
|
#define MAX_USERNAME_LEN 25 /* arbitrary for the moment */
|
||||||
|
@ -102,17 +102,26 @@ static int new_agent_chan(struct Channel * channel) {
|
|||||||
data Any data, depending on packet type. Encoding as in the ssh packet
|
data Any data, depending on packet type. Encoding as in the ssh packet
|
||||||
protocol.
|
protocol.
|
||||||
*/
|
*/
|
||||||
static buffer * agent_request(int fd, unsigned char type) {
|
static buffer * agent_request(unsigned char type, buffer *data) {
|
||||||
|
|
||||||
buffer * payload = NULL;
|
buffer * payload = NULL;
|
||||||
buffer * inbuf = NULL;
|
buffer * inbuf = NULL;
|
||||||
size_t readlen = 0;
|
size_t readlen = 0;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
const int fd = cli_opts.agent_fd;
|
||||||
|
unsigned int data_len = 0;
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
data_len = data->len;
|
||||||
|
}
|
||||||
|
|
||||||
payload = buf_new(4 + 1);
|
payload = buf_new(4 + 1 + data_len);
|
||||||
|
|
||||||
buf_putint(payload, 1);
|
buf_putint(payload, 1 + data_len);
|
||||||
buf_putbyte(payload, type);
|
buf_putbyte(payload, type);
|
||||||
|
if (data) {
|
||||||
|
buf_putbytes(payload, data->data, data->len);
|
||||||
|
}
|
||||||
buf_setpos(payload, 0);
|
buf_setpos(payload, 0);
|
||||||
|
|
||||||
ret = atomicio(write, fd, buf_getptr(payload, payload->len), payload->len);
|
ret = atomicio(write, fd, buf_getptr(payload, payload->len), payload->len);
|
||||||
@ -160,7 +169,7 @@ out:
|
|||||||
return inbuf;
|
return inbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void agent_get_key_list(int fd, m_list * ret_list)
|
static void agent_get_key_list(m_list * ret_list)
|
||||||
{
|
{
|
||||||
buffer * inbuf = NULL;
|
buffer * inbuf = NULL;
|
||||||
unsigned int num = 0;
|
unsigned int num = 0;
|
||||||
@ -168,9 +177,9 @@ static void agent_get_key_list(int fd, m_list * ret_list)
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
inbuf = agent_request(fd, SSH2_AGENTC_REQUEST_IDENTITIES);
|
inbuf = agent_request(SSH2_AGENTC_REQUEST_IDENTITIES, NULL);
|
||||||
if (!inbuf) {
|
if (!inbuf) {
|
||||||
TRACE(("agent_request returned no identities"))
|
TRACE(("agent_request failed returning identities"))
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +200,6 @@ static void agent_get_key_list(int fd, m_list * ret_list)
|
|||||||
sign_key * pubkey = NULL;
|
sign_key * pubkey = NULL;
|
||||||
int key_type = DROPBEAR_SIGNKEY_ANY;
|
int key_type = DROPBEAR_SIGNKEY_ANY;
|
||||||
buffer * key_buf;
|
buffer * key_buf;
|
||||||
struct SignKeyList *nextkey = NULL;
|
|
||||||
|
|
||||||
/* each public key is encoded as a string */
|
/* each public key is encoded as a string */
|
||||||
key_buf = buf_getstringbuf(inbuf);
|
key_buf = buf_getstringbuf(inbuf);
|
||||||
@ -222,19 +230,66 @@ out:
|
|||||||
be updated. */
|
be updated. */
|
||||||
void load_agent_keys(m_list *ret_list)
|
void load_agent_keys(m_list *ret_list)
|
||||||
{
|
{
|
||||||
int fd;
|
/* agent_fd will be closed after successful auth */
|
||||||
fd = connect_agent();
|
cli_opts.agent_fd = connect_agent();
|
||||||
if (fd < 0) {
|
if (cli_opts.agent_fd < 0) {
|
||||||
dropbear_log(LOG_INFO, "Failed to connect to agent");
|
dropbear_log(LOG_INFO, "Failed to connect to agent");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
agent_get_key_list(fd, ret_list);
|
agent_get_key_list(ret_list);
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void agent_buf_sign(buffer *sigblob, sign_key *key,
|
void agent_buf_sign(buffer *sigblob, sign_key *key,
|
||||||
const unsigned char *data, unsigned int len) {
|
const unsigned char *data, unsigned int len) {
|
||||||
|
buffer *request_data = buf_new(MAX_PUBKEY_SIZE + len + 12);
|
||||||
|
buffer *response;
|
||||||
|
unsigned int keylen, siglen;
|
||||||
|
int packet_type;
|
||||||
|
|
||||||
|
/* Request format
|
||||||
|
byte SSH2_AGENTC_SIGN_REQUEST
|
||||||
|
string key_blob
|
||||||
|
string data
|
||||||
|
uint32 flags
|
||||||
|
*/
|
||||||
|
/* We write the key, then figure how long it was and write that */
|
||||||
|
//buf_putint(request_data, 0);
|
||||||
|
buf_put_pub_key(request_data, key, key->type);
|
||||||
|
keylen = request_data->len - 4;
|
||||||
|
//buf_setpos(request_data, 0);
|
||||||
|
//buf_putint(request_data, keylen);
|
||||||
|
|
||||||
|
//buf_setpos(request_data, request_data->len);
|
||||||
|
buf_putstring(request_data, data, len);
|
||||||
|
buf_putint(request_data, 0);
|
||||||
|
|
||||||
|
response = agent_request(SSH2_AGENTC_SIGN_REQUEST, request_data);
|
||||||
|
buf_free(request_data);
|
||||||
|
|
||||||
|
if (!response) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
packet_type = buf_getbyte(response);
|
||||||
|
if (packet_type != SSH2_AGENT_SIGN_RESPONSE) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Response format
|
||||||
|
byte SSH2_AGENT_SIGN_RESPONSE
|
||||||
|
string signature_blob
|
||||||
|
*/
|
||||||
|
siglen = buf_getint(response);
|
||||||
|
buf_putbytes(sigblob, buf_getptr(response, siglen), siglen);
|
||||||
|
buf_free(response);
|
||||||
|
|
||||||
|
return;
|
||||||
|
fail:
|
||||||
|
/* XXX don't fail badly here. instead propagate a failure code back up to
|
||||||
|
the cli auth pubkey code, and just remove this key from the list of
|
||||||
|
ones to try. */
|
||||||
|
dropbear_exit("Agent failed signing key");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -234,6 +234,10 @@ void recv_msg_userauth_success() {
|
|||||||
ses.authstate.authdone = 1;
|
ses.authstate.authdone = 1;
|
||||||
cli_ses.state = USERAUTH_SUCCESS_RCVD;
|
cli_ses.state = USERAUTH_SUCCESS_RCVD;
|
||||||
cli_ses.lastauthtype = AUTH_TYPE_NONE;
|
cli_ses.lastauthtype = AUTH_TYPE_NONE;
|
||||||
|
|
||||||
|
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||||
|
cli_auth_pubkey_cleanup();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli_auth_try() {
|
void cli_auth_try() {
|
||||||
|
@ -174,7 +174,7 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
|
|||||||
sigbuf = buf_new(4 + SHA1_HASH_SIZE + ses.writepayload->len);
|
sigbuf = buf_new(4 + SHA1_HASH_SIZE + ses.writepayload->len);
|
||||||
buf_putstring(sigbuf, ses.session_id, SHA1_HASH_SIZE);
|
buf_putstring(sigbuf, ses.session_id, SHA1_HASH_SIZE);
|
||||||
buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len);
|
buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len);
|
||||||
buf_put_sign(ses.writepayload, key, type, sigbuf->data, sigbuf->len);
|
cli_buf_put_sign(ses.writepayload, key, type, sigbuf->data, sigbuf->len);
|
||||||
buf_free(sigbuf); /* Nothing confidential in the buffer */
|
buf_free(sigbuf); /* Nothing confidential in the buffer */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,8 +202,22 @@ int cli_auth_pubkey() {
|
|||||||
TRACE(("leave cli_auth_pubkey-success"))
|
TRACE(("leave cli_auth_pubkey-success"))
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
|
/* no more keys left */
|
||||||
TRACE(("leave cli_auth_pubkey-failure"))
|
TRACE(("leave cli_auth_pubkey-failure"))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cli_auth_pubkey_cleanup() {
|
||||||
|
|
||||||
|
#ifdef ENABLE_CLI_AGENTFWD
|
||||||
|
m_close(cli_opts.agent_fd);
|
||||||
|
cli_opts.agent_fd = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (cli_opts.privkeys->first) {
|
||||||
|
sign_key * key = list_remove(cli_opts.privkeys->first);
|
||||||
|
sign_key_free(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif /* Pubkey auth */
|
#endif /* Pubkey auth */
|
||||||
|
@ -124,6 +124,8 @@ typedef struct cli_runopts {
|
|||||||
int agent_fwd;
|
int agent_fwd;
|
||||||
int agent_keys_loaded; /* whether pubkeys has been populated with a
|
int agent_keys_loaded; /* whether pubkeys has been populated with a
|
||||||
list of keys held by the agent */
|
list of keys held by the agent */
|
||||||
|
int agent_fd; /* The agent fd is only set during authentication. Forwarded
|
||||||
|
agent sessions have their own file descriptors */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_CLI_NETCAT
|
#ifdef ENABLE_CLI_NETCAT
|
||||||
|
Loading…
Reference in New Issue
Block a user