Mercurial > dropbear
changeset 551:c3f2ec71e3d4 agent-client
New standard linked list to use, rather than adhoc SignKeyList or TCPFwdList
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 06 Jul 2009 12:59:13 +0000 |
parents | 61c3513825b0 |
children | de3653483ac0 |
files | Makefile.in agentfwd.h auth.h buffer.c buffer.h cli-agentfwd.c cli-authpubkey.c cli-chansession.c cli-runopts.c cli-tcpfwd.c list.c list.h runopts.h session.h signkey.c signkey.h tcpfwd.h |
diffstat | 17 files changed, 254 insertions(+), 192 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile.in Wed Jul 01 06:27:27 2009 +0000 +++ b/Makefile.in Mon Jul 06 12:59:13 2009 +0000 @@ -20,7 +20,7 @@ dss.o bignum.o \ signkey.o rsa.o random.o \ queue.o \ - atomicio.o compat.o fake-rfc2553.o + atomicio.o compat.o fake-rfc2553.o SVROBJS=svr-kex.o svr-algo.o svr-auth.o sshpty.o \ svr-authpasswd.o svr-authpubkey.o svr-authpubkeyoptions.o svr-session.o svr-service.o \ @@ -30,7 +30,7 @@ CLIOBJS=cli-algo.o cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \ cli-session.o cli-service.o cli-runopts.o cli-chansession.o \ cli-authpubkey.o cli-tcpfwd.o cli-channel.o cli-authinteract.o \ - cli-agentfwd.o + cli-agentfwd.o list.o CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \ common-channel.o common-chansession.o termcodes.o loginrec.o \
--- a/agentfwd.h Wed Jul 01 06:27:27 2009 +0000 +++ b/agentfwd.h Mon Jul 06 12:59:13 2009 +0000 @@ -28,6 +28,7 @@ #include "chansession.h" #include "channel.h" #include "auth.h" +#include "list.h" /* An agent reply can be reasonably large, as it can * contain a list of all public keys held by the agent. @@ -35,11 +36,13 @@ #define MAX_AGENT_REPLY 10000 int agentreq(struct ChanSess * chansess); -void agentsetauth(struct ChanSess *chansess); void agentcleanup(struct ChanSess * chansess); void agentset(struct ChanSess *chansess); -void load_agent_keys(struct SignKeyList * ret_list); +/* client functions */ +void load_agent_keys(m_list * ret_list); +void agent_buf_sign(buffer *sigblob, sign_key *key, + const unsigned char *data, unsigned int len); #ifdef __hpux #define seteuid(a) setresuid(-1, (a), -1)
--- a/auth.h Wed Jul 01 06:27:27 2009 +0000 +++ b/auth.h Mon Jul 06 12:59:13 2009 +0000 @@ -124,26 +124,6 @@ }; -/* Sources for signing keys */ -typedef enum { - SIGNKEY_SOURCE_RAW_FILE, - SIGNKEY_SOURCE_AGENT, -} signkey_source; - -struct SignKeyList; -/* A singly linked list of signing keys */ -struct SignKeyList { - - sign_key *key; - int type; /* The type of key */ - struct SignKeyList *next; - signkey_source source; - char *filename; - /* the buffer? for encrypted keys, so we can later get - * the private key portion */ - -}; - #ifdef ENABLE_SVR_PUBKEY_OPTIONS struct PubKeyOptions; struct PubKeyOptions {
--- a/buffer.c Wed Jul 01 06:27:27 2009 +0000 +++ b/buffer.c Mon Jul 06 12:59:13 2009 +0000 @@ -223,6 +223,20 @@ return ret; } +/* Return a string as a newly allocated buffer */ +buffer * buf_getstringbuf(buffer *buf) { + buffer *ret; + unsigned char* str; + unsigned int len; + str = buf_getstring(buf, &len); + ret = m_malloc(sizeof(*ret)); + ret->data = str; + ret->len = len; + ret->size = len; + ret->pos = 0; + return ret; +} + /* Just increment the buffer position the same as if we'd used buf_getstring, * but don't bother copying/malloc()ing for it */ void buf_eatstring(buffer *buf) {
--- a/buffer.h Wed Jul 01 06:27:27 2009 +0000 +++ b/buffer.h Mon Jul 06 12:59:13 2009 +0000 @@ -55,6 +55,7 @@ unsigned char* buf_getptr(buffer* buf, unsigned int len); unsigned char* buf_getwriteptr(buffer* buf, unsigned int len); unsigned char* buf_getstring(buffer* buf, unsigned int *retlen); +buffer * buf_getstringbuf(buffer *buf); void buf_eatstring(buffer *buf); void buf_putint(buffer* buf, unsigned int val); void buf_putstring(buffer* buf, const unsigned char* str, unsigned int len);
--- a/cli-agentfwd.c Wed Jul 01 06:27:27 2009 +0000 +++ b/cli-agentfwd.c Mon Jul 06 12:59:13 2009 +0000 @@ -22,10 +22,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -/* The basic protocol use to communicate with the agent is defined in - * draft-ylonen-ssh-protocol-00.txt, with the ssh2 extensions defined through - * openssh's implementation. */ - #include "includes.h" #ifdef ENABLE_CLI_AGENTFWD @@ -45,6 +41,9 @@ #include "signkey.h" #include "auth.h" +/* The protocol implemented to talk to OpenSSH's SSH2 agent is documented in + PROTOCOL.agent in recent OpenSSH source distributions (5.1p1 has it). */ + static int new_agent_chan(struct Channel * channel); const struct ChanType cli_chan_agent = { @@ -161,13 +160,12 @@ return inbuf; } -static void agent_get_key_list(int fd, struct SignKeyList * ret_list) +static void agent_get_key_list(int fd, m_list * ret_list) { buffer * inbuf = NULL; unsigned int num = 0; unsigned char packet_type; unsigned int i; - struct SignKeyList *key = NULL; int ret; inbuf = agent_request(fd, SSH2_AGENTC_REQUEST_IDENTITIES); @@ -177,14 +175,11 @@ } /* The reply has a format of: - * byte packet_type - * int num_keys - * - * string keyblob1 - * string comment1 - * ... - * string keyblob(n) - * string comment(n) + byte SSH2_AGENT_IDENTITIES_ANSWER + uint32 num_keys + Followed by zero or more consecutive keys, encoded as: + string key_blob + string key_comment */ packet_type = buf_getbyte(inbuf); if (packet_type != SSH2_AGENT_IDENTITIES_ANSWER) { @@ -195,25 +190,24 @@ for (i = 0; i < num; i++) { sign_key * pubkey = NULL; int key_type = DROPBEAR_SIGNKEY_ANY; + buffer * key_buf; struct SignKeyList *nextkey = NULL; - nextkey = (struct SignKeyList*)m_malloc(sizeof(struct SignKeyList)); - ret_list->next = nextkey; - ret_list = nextkey; - + /* each public key is encoded as a string */ + key_buf = buf_getstringbuf(inbuf); pubkey = new_sign_key(); - ret = buf_get_pub_key(inbuf, pubkey, &key_type); + ret = buf_get_pub_key(key_buf, pubkey, &key_type); + buf_free(key_buf); if (ret != DROPBEAR_SUCCESS) { /* This is slack, properly would cleanup vars etc */ dropbear_exit("Bad pubkey received from agent"); } + pubkey->type = key_type; + pubkey->source = SIGNKEY_SOURCE_AGENT; - key->key = pubkey; - key->next = NULL; - key->type = key_type; - key->source = SIGNKEY_SOURCE_AGENT; + list_append(ret_list, pubkey); - /* We'll ignore the comment */ + /* We'll ignore the comment for now. might want it later.*/ buf_eatstring(inbuf); } @@ -224,8 +218,9 @@ } } -/* Returned keys are appended to ret_list */ -void load_agent_keys(struct SignKeyList * ret_list) +/* Returned keys are prepended to ret_list, which will + be updated. */ +void load_agent_keys(m_list *ret_list) { int fd; fd = connect_agent(); @@ -237,13 +232,9 @@ agent_get_key_list(fd, ret_list); close(fd); } - -// general procedure: -// - get the list of keys from the agent -// - foreach, send a dummy userauth_pubkey message to the server and see -// if it lets us in -// - if it does, sign and auth -// - if not, repeat. -// + +void agent_buf_sign(buffer *sigblob, sign_key *key, + const unsigned char *data, unsigned int len) { +} #endif
--- a/cli-authpubkey.c Wed Jul 01 06:27:27 2009 +0000 +++ b/cli-authpubkey.c Mon Jul 06 12:59:13 2009 +0000 @@ -30,6 +30,7 @@ #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); @@ -37,31 +38,23 @@ /* Called when we receive a SSH_MSG_USERAUTH_FAILURE for a pubkey request. * We use it to remove the key we tried from the list */ void cli_pubkeyfail() { - - struct SignKeyList *keyitem; - struct SignKeyList **previtem; - - TRACE(("enter cli_pubkeyfail")) - previtem = &cli_opts.privkeys; - - /* Find the key we failed with, and remove it */ - for (keyitem = cli_opts.privkeys; keyitem != NULL; keyitem = keyitem->next) { - if (keyitem == cli_ses.lastprivkey) { - *previtem = keyitem->next; + 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) + { + /* found the failing key */ + list_remove(iter); + sign_key_free(iter_key); + cli_ses.lastprivkey = NULL; + return; } - previtem = &keyitem; } - - sign_key_free(cli_ses.lastprivkey->key); /* It won't be used again */ - m_free(cli_ses.lastprivkey->filename); - m_free(cli_ses.lastprivkey); - - TRACE(("leave cli_pubkeyfail")) } void recv_msg_userauth_pk_ok() { - - struct SignKeyList *keyitem = NULL; + m_list_elem *iter; buffer* keybuf = NULL; char* algotype = NULL; unsigned int algolen; @@ -81,9 +74,9 @@ /* Iterate through our keys, find which one it was that matched, and * send a real request with that key */ - for (keyitem = cli_opts.privkeys; keyitem != NULL; keyitem = keyitem->next) { - - if (keyitem->type != keytype) { + for (iter = cli_opts.privkeys->first; iter; iter = iter->next) { + sign_key *key = (sign_key*)iter->item; + if (key->type != keytype) { /* Types differed */ TRACE(("types differed")) continue; @@ -91,7 +84,7 @@ /* Now we compare the contents of the key */ keybuf->pos = keybuf->len = 0; - buf_put_pub_key(keybuf, keyitem->key, keytype); + buf_put_pub_key(keybuf, key, keytype); buf_setpos(keybuf, 0); buf_incrpos(keybuf, 4); /* first int is the length of the remainder (ie remotelen) which has already been taken from @@ -115,11 +108,11 @@ } buf_free(keybuf); - if (keyitem != NULL) { + if (iter != NULL) { TRACE(("matching key")) /* XXX TODO: if it's an encrypted key, here we ask for their * password */ - send_msg_userauth_pubkey(keyitem->key, keytype, 1); + 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")) } @@ -127,6 +120,25 @@ TRACE(("leave recv_msg_userauth_pk_ok")) } +void cli_buf_put_sign(buffer* buf, sign_key *key, int type, + const unsigned char *data, unsigned int len) +{ + if (key->source == SIGNKEY_SOURCE_AGENT) { + /* Format the agent signature ourselves, as buf_put_sign would. */ + buffer *sigblob; + sigblob = buf_new(MAX_PUBKEY_SIZE); + agent_buf_sign(sigblob, key, data, len); + buf_setpos(sigblob, 0); + buf_putstring(buf, buf_getptr(sigblob, sigblob->len), + sigblob->len); + + buf_free(sigblob); + } else { + buf_put_sign(buf, key, type, data, len); + } + +} + /* TODO: make it take an agent reference to use as well */ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) { @@ -170,6 +182,7 @@ TRACE(("leave send_msg_userauth_pubkey")) } +/* Returns 1 if a key was tried */ int cli_auth_pubkey() { TRACE(("enter cli_auth_pubkey")) @@ -177,15 +190,15 @@ if (cli_opts.agent_fwd && !cli_opts.agent_keys_loaded) { /* get the list of available keys from the agent */ - load_agent_keys(&cli_opts.privkeys); + load_agent_keys(cli_opts.privkeys); cli_opts.agent_keys_loaded = 1; } - if (cli_opts.privkeys != NULL) { + if (cli_opts.privkeys->first) { + sign_key * key = (sign_key*)cli_opts.privkeys->first->item; /* Send a trial request */ - send_msg_userauth_pubkey(cli_opts.privkeys->key, - cli_opts.privkeys->type, 0); - cli_ses.lastprivkey = cli_opts.privkeys; + send_msg_userauth_pubkey(key, key->type, 0); + cli_ses.lastprivkey = key; TRACE(("leave cli_auth_pubkey-success")) return 1; } else {
--- a/cli-chansession.c Wed Jul 01 06:27:27 2009 +0000 +++ b/cli-chansession.c Mon Jul 06 12:59:13 2009 +0000 @@ -424,16 +424,3 @@ TRACE(("leave cli_send_chansess_request")) } - - -#if 0 - while (cli_opts.localfwds != NULL) { - ret = cli_localtcp(cli_opts.localfwds->listenport, - cli_opts.localfwds->connectaddr, - cli_opts.localfwds->connectport); - if (ret == DROPBEAR_FAILURE) { - dropbear_log(LOG_WARNING, "Failed local port forward %d:%s:%d", - cli_opts.localfwds->listenport, - cli_opts.localfwds->connectaddr, - cli_opts.localfwds->connectport); -#endif
--- a/cli-runopts.c Wed Jul 01 06:27:27 2009 +0000 +++ b/cli-runopts.c Mon Jul 06 12:59:13 2009 +0000 @@ -29,6 +29,7 @@ #include "dbutil.h" #include "algo.h" #include "tcpfwd.h" +#include "list.h" cli_runopts cli_opts; /* GLOBAL */ @@ -40,7 +41,7 @@ static void loadidentityfile(const char* filename); #endif #ifdef ENABLE_CLI_ANYTCPFWD -static void addforward(const char* str, struct TCPFwdList** fwdlist); +static void addforward(const char* str, m_list *fwdlist); #endif #ifdef ENABLE_CLI_NETCAT static void add_netcat(const char *str); @@ -128,14 +129,14 @@ cli_opts.always_accept_key = 0; cli_opts.is_subsystem = 0; #ifdef ENABLE_CLI_PUBKEY_AUTH - cli_opts.privkeys = NULL; + cli_opts.privkeys = list_new(); #endif #ifdef ENABLE_CLI_LOCALTCPFWD - cli_opts.localfwds = NULL; + cli_opts.localfwds = list_new(); opts.listen_fwd_all = 0; #endif #ifdef ENABLE_CLI_REMOTETCPFWD - cli_opts.remotefwds = NULL; + cli_opts.remotefwds = list_new(); #endif #ifdef ENABLE_CLI_AGENTFWD cli_opts.agent_fwd = 0; @@ -165,7 +166,7 @@ #ifdef ENABLE_CLI_REMOTETCPFWD if (nextisremote) { TRACE(("nextisremote true")) - addforward(argv[i], &cli_opts.remotefwds); + addforward(argv[i], cli_opts.remotefwds); nextisremote = 0; continue; } @@ -173,7 +174,7 @@ #ifdef ENABLE_CLI_LOCALTCPFWD if (nextislocal) { TRACE(("nextislocal true")) - addforward(argv[i], &cli_opts.localfwds); + addforward(argv[i], cli_opts.localfwds); nextislocal = 0; continue; } @@ -406,8 +407,6 @@ #ifdef ENABLE_CLI_PUBKEY_AUTH static void loadidentityfile(const char* filename) { - - struct SignKeyList * nextkey; sign_key *key; int keytype; @@ -417,13 +416,10 @@ fprintf(stderr, "Failed loading keyfile '%s'\n", filename); sign_key_free(key); } else { - nextkey = (struct SignKeyList*)m_malloc(sizeof(struct SignKeyList)); - nextkey->key = key; - nextkey->filename = m_strdup(filename); - nextkey->next = cli_opts.privkeys; - nextkey->type = keytype; - nextkey->source = SIGNKEY_SOURCE_RAW_FILE; - cli_opts.privkeys = nextkey; + key->type = keytype; + key->source = SIGNKEY_SOURCE_RAW_FILE; + key->filename = m_strdup(filename); + list_append(cli_opts.privkeys, key); } } #endif @@ -435,12 +431,13 @@ char *ret; int total; unsigned int len = 0; - struct SignKeyList *nextkey; + m_list_elem *iter; /* Fill out -i and -W options that make sense for all * the intermediate processes */ - for (nextkey = cli_opts.privkeys; nextkey; nextkey = nextkey->next) + for (iter = cli_opts.privkeys->first; iter; iter = iter->next) { - len += 3 + strlen(nextkey->filename); + sign_key * key = (sign_key*)iter->item; + len += 3 + strlen(key->filename); } len += 20; // space for -W <size>, terminator. ret = m_malloc(len); @@ -452,10 +449,11 @@ total += written; } - for (nextkey = cli_opts.privkeys; nextkey; nextkey = nextkey->next) + for (iter = cli_opts.privkeys->first; iter; iter = iter->next) { + sign_key * key = (sign_key*)iter->item; const size_t size = len - total; - int written = snprintf(ret+total, size, "-i %s", nextkey->filename); + int written = snprintf(ret+total, size, "-i %s", key->filename); dropbear_assert(written < size); total += written; } @@ -621,12 +619,12 @@ #ifdef ENABLE_CLI_ANYTCPFWD /* Turn a "listenport:remoteaddr:remoteport" string into into a forwarding * set, and add it to the forwarding list */ -static void addforward(const char* origstr, struct TCPFwdList** fwdlist) { +static void addforward(const char* origstr, m_list *fwdlist) { char * listenport = NULL; char * connectport = NULL; char * connectaddr = NULL; - struct TCPFwdList* newfwd = NULL; + struct TCPFwdEntry* newfwd = NULL; char * str = NULL; TRACE(("enter addforward")) @@ -653,7 +651,7 @@ *connectport = '\0'; connectport++; - newfwd = (struct TCPFwdList*)m_malloc(sizeof(struct TCPFwdList)); + newfwd = m_malloc(sizeof(struct TCPFwdEntry)); /* Now we check the ports - note that the port ints are unsigned, * the check later only checks for >= MAX_PORT */ @@ -680,8 +678,7 @@ } newfwd->have_reply = 0; - newfwd->next = *fwdlist; - *fwdlist = newfwd; + list_append(fwdlist, newfwd); TRACE(("leave addforward: done")) return;
--- a/cli-tcpfwd.c Wed Jul 01 06:27:27 2009 +0000 +++ b/cli-tcpfwd.c Mon Jul 06 12:59:13 2009 +0000 @@ -59,27 +59,22 @@ #ifdef ENABLE_CLI_LOCALTCPFWD void setup_localtcp() { - + m_list_elem *iter; int ret; TRACE(("enter setup_localtcp")) - if (cli_opts.localfwds == NULL) { - TRACE(("cli_opts.localfwds == NULL")) - } - - while (cli_opts.localfwds != NULL) { - ret = cli_localtcp(cli_opts.localfwds->listenport, - cli_opts.localfwds->connectaddr, - cli_opts.localfwds->connectport); + for (iter = cli_opts.localfwds->first; iter; iter = iter->next) { + struct TCPFwdEntry * fwd = (struct TCPFwdEntry*)iter->item; + ret = cli_localtcp(fwd->listenport, + fwd->connectaddr, + fwd->connectport); if (ret == DROPBEAR_FAILURE) { dropbear_log(LOG_WARNING, "Failed local port forward %d:%s:%d", - cli_opts.localfwds->listenport, - cli_opts.localfwds->connectaddr, - cli_opts.localfwds->connectport); - } - - cli_opts.localfwds = cli_opts.localfwds->next; + fwd->listenport, + fwd->connectaddr, + fwd->connectport); + } } TRACE(("leave setup_localtcp")) @@ -148,60 +143,47 @@ * being in the same order as we sent the requests. This is the ordering * of the cli_opts.remotefwds list */ void cli_recv_msg_request_success() { - /* Nothing in the packet. We just mark off that we have received the reply, * so that we can report failure for later ones. */ - struct TCPFwdList * iter = NULL; - - iter = cli_opts.remotefwds; - while (iter != NULL) { - if (!iter->have_reply) - { - iter->have_reply = 1; + m_list_elem * iter = NULL; + for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) { + struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item; + if (!fwd->have_reply) { + fwd->have_reply = 1; return; } - iter = iter->next; } } void cli_recv_msg_request_failure() { - struct TCPFwdList * iter = NULL; - - iter = cli_opts.remotefwds; - while (iter != NULL) { - if (!iter->have_reply) - { - iter->have_reply = 1; - dropbear_log(LOG_WARNING, "Remote TCP forward request failed (port %d -> %s:%d)", iter->listenport, iter->connectaddr, iter->connectport); + m_list_elem *iter; + for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) { + struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item; + if (!fwd->have_reply) { + fwd->have_reply = 1; + dropbear_log(LOG_WARNING, "Remote TCP forward request failed (port %d -> %s:%d)", fwd->listenport, fwd->connectaddr, fwd->connectport); return; } - iter = iter->next; } }