#include "includes.h"
#include "buffer.h"
#include "dbutil.h"
#include "session.h"
#include "ssh.h"
#include "runopts.h"
#include "auth.h"
#include "agentfwd.h"
#ifdef ENABLE_CLI_PUBKEY_AUTH
static
void
send_msg_userauth_pubkey(sign_key *key,
int
type,
int
realsign);
void
cli_pubkeyfail() {
m_list_elem *iter;
for
(iter = cli_opts.privkeys->first; iter; iter = iter->next) {
sign_key *iter_key = (sign_key*)iter->item;
if
(iter_key == cli_ses.lastprivkey)
{
list_remove(iter);
sign_key_free(iter_key);
cli_ses.lastprivkey = NULL;
return
;
}
}
}
void
recv_msg_userauth_pk_ok() {
m_list_elem *iter;
buffer* keybuf = NULL;
char
* algotype = NULL;
unsigned
int
algolen;
enum
signkey_type keytype;
unsigned
int
remotelen;
TRACE((
"enter recv_msg_userauth_pk_ok"
))
algotype = buf_getstring(ses.payload, &algolen);
keytype = signkey_type_from_name(algotype, algolen);
TRACE((
"recv_msg_userauth_pk_ok: type %d"
, keytype))
m_free(algotype);
keybuf = buf_new(MAX_PUBKEY_SIZE);
remotelen = buf_getint(ses.payload);
for
(iter = cli_opts.privkeys->first; iter; iter = iter->next) {
sign_key *key = (sign_key*)iter->item;
if
(key->type != keytype) {
TRACE((
"types differed"
))
continue
;
}
keybuf->pos = keybuf->len = 0;
buf_put_pub_key(keybuf, key, keytype);
buf_setpos(keybuf, 0);
buf_incrpos(keybuf, 4);
if
(keybuf->len-4 != remotelen) {
TRACE((
"lengths differed: localh %d remote %d"
, keybuf->len, remotelen))
continue
;
}
if
(
memcmp
(buf_getptr(keybuf, remotelen),
buf_getptr(ses.payload, remotelen), remotelen) != 0) {
TRACE((
"data differed"
))
continue
;
}
break
;
}
buf_free(keybuf);
if
(iter != NULL) {
TRACE((
"matching key"
))
send_msg_userauth_pubkey((sign_key*)iter->item, keytype, 1);
}
else
{
TRACE((
"That was whacky. We got told that a key was valid, but it didn't match our list. Sounds like dodgy code on Dropbear's part"
))
}
TRACE((
"leave recv_msg_userauth_pk_ok"
))
}
void
cli_buf_put_sign(buffer* buf, sign_key *key,
int
type,
buffer *data_buf) {
#ifdef ENABLE_CLI_AGENTFWD
if
(key->source == SIGNKEY_SOURCE_AGENT) {
buffer *sigblob;
sigblob = buf_new(MAX_PUBKEY_SIZE);
agent_buf_sign(sigblob, key, data_buf);
buf_putbufstring(buf, sigblob);
buf_free(sigblob);
}
else
#endif /* ENABLE_CLI_AGENTFWD */
{
buf_put_sign(buf, key, type, data_buf);
}
}
static
void
send_msg_userauth_pubkey(sign_key *key,
int
type,
int
realsign) {
const
char
*algoname = NULL;
unsigned
int
algolen;
buffer* sigbuf = NULL;
TRACE((
"enter send_msg_userauth_pubkey"
))
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
buf_putstring(ses.writepayload, cli_opts.username,
strlen
(cli_opts.username));
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
SSH_SERVICE_CONNECTION_LEN);
buf_putstring(ses.writepayload, AUTH_METHOD_PUBKEY,
AUTH_METHOD_PUBKEY_LEN);
buf_putbyte(ses.writepayload, realsign);
algoname = signkey_name_from_type(type, &algolen);
buf_putstring(ses.writepayload, algoname, algolen);
buf_put_pub_key(ses.writepayload, key, type);
if
(realsign) {
TRACE((
"realsign"
))
sigbuf = buf_new(4 + ses.session_id->len + ses.writepayload->len);
buf_putbufstring(sigbuf, ses.session_id);
buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len);
cli_buf_put_sign(ses.writepayload, key, type, sigbuf);
buf_free(sigbuf);
}
encrypt_packet();
TRACE((
"leave send_msg_userauth_pubkey"
))
}
int
cli_auth_pubkey() {
TRACE((
"enter cli_auth_pubkey"
))
#ifdef ENABLE_CLI_AGENTFWD
if
(!cli_opts.agent_keys_loaded) {
cli_load_agent_keys(cli_opts.privkeys);
cli_opts.agent_keys_loaded = 1;
}
#endif
if
(cli_opts.privkeys->first) {
sign_key * key = (sign_key*)cli_opts.privkeys->first->item;
send_msg_userauth_pubkey(key, key->type, 0);
cli_ses.lastprivkey = key;
TRACE((
"leave cli_auth_pubkey-success"
))
return
1;
}
else
{
TRACE((
"leave cli_auth_pubkey-failure"
))
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 */