1
0
mirror of https://github.com/clearml/dropbear synced 2025-04-10 15:35:41 +00:00

New standard linked list to use, rather than adhoc SignKeyList or TCPFwdList

--HG--
branch : agent-client
extra : convert_revision : 5465e639cc3f5ee0c6c55f0de6e7b6d5a8769da3
This commit is contained in:
Matt Johnston 2009-07-06 12:59:13 +00:00
parent 9dc9aff016
commit c742137dc8
17 changed files with 254 additions and 192 deletions

View File

@ -30,7 +30,7 @@ SVROBJS=svr-kex.o svr-algo.o svr-auth.o sshpty.o \
CLIOBJS=cli-algo.o cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \ 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-session.o cli-service.o cli-runopts.o cli-chansession.o \
cli-authpubkey.o cli-tcpfwd.o cli-channel.o cli-authinteract.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 \ CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \
common-channel.o common-chansession.o termcodes.o loginrec.o \ common-channel.o common-chansession.o termcodes.o loginrec.o \

View File

@ -28,6 +28,7 @@
#include "chansession.h" #include "chansession.h"
#include "channel.h" #include "channel.h"
#include "auth.h" #include "auth.h"
#include "list.h"
/* An agent reply can be reasonably large, as it can /* An agent reply can be reasonably large, as it can
* contain a list of all public keys held by the agent. * contain a list of all public keys held by the agent.
@ -35,11 +36,13 @@
#define MAX_AGENT_REPLY 10000 #define MAX_AGENT_REPLY 10000
int agentreq(struct ChanSess * chansess); int agentreq(struct ChanSess * chansess);
void agentsetauth(struct ChanSess *chansess);
void agentcleanup(struct ChanSess * chansess); void agentcleanup(struct ChanSess * chansess);
void agentset(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 #ifdef __hpux
#define seteuid(a) setresuid(-1, (a), -1) #define seteuid(a) setresuid(-1, (a), -1)

20
auth.h
View File

@ -124,26 +124,6 @@ struct AuthState {
}; };
/* 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 #ifdef ENABLE_SVR_PUBKEY_OPTIONS
struct PubKeyOptions; struct PubKeyOptions;
struct PubKeyOptions { struct PubKeyOptions {

View File

@ -223,6 +223,20 @@ unsigned char* buf_getstring(buffer* buf, unsigned int *retlen) {
return ret; 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, /* Just increment the buffer position the same as if we'd used buf_getstring,
* but don't bother copying/malloc()ing for it */ * but don't bother copying/malloc()ing for it */
void buf_eatstring(buffer *buf) { void buf_eatstring(buffer *buf) {

View File

@ -55,6 +55,7 @@ void buf_putbyte(buffer* buf, unsigned char val);
unsigned char* buf_getptr(buffer* buf, unsigned int len); unsigned char* buf_getptr(buffer* buf, unsigned int len);
unsigned char* buf_getwriteptr(buffer* buf, unsigned int len); unsigned char* buf_getwriteptr(buffer* buf, unsigned int len);
unsigned char* buf_getstring(buffer* buf, unsigned int *retlen); unsigned char* buf_getstring(buffer* buf, unsigned int *retlen);
buffer * buf_getstringbuf(buffer *buf);
void buf_eatstring(buffer *buf); void buf_eatstring(buffer *buf);
void buf_putint(buffer* buf, unsigned int val); void buf_putint(buffer* buf, unsigned int val);
void buf_putstring(buffer* buf, const unsigned char* str, unsigned int len); void buf_putstring(buffer* buf, const unsigned char* str, unsigned int len);

View File

@ -22,10 +22,6 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. */ * 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" #include "includes.h"
#ifdef ENABLE_CLI_AGENTFWD #ifdef ENABLE_CLI_AGENTFWD
@ -45,6 +41,9 @@
#include "signkey.h" #include "signkey.h"
#include "auth.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); static int new_agent_chan(struct Channel * channel);
const struct ChanType cli_chan_agent = { const struct ChanType cli_chan_agent = {
@ -161,13 +160,12 @@ out:
return inbuf; 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; buffer * inbuf = NULL;
unsigned int num = 0; unsigned int num = 0;
unsigned char packet_type; unsigned char packet_type;
unsigned int i; unsigned int i;
struct SignKeyList *key = NULL;
int ret; int ret;
inbuf = agent_request(fd, SSH2_AGENTC_REQUEST_IDENTITIES); inbuf = agent_request(fd, SSH2_AGENTC_REQUEST_IDENTITIES);
@ -177,14 +175,11 @@ static void agent_get_key_list(int fd, struct SignKeyList * ret_list)
} }
/* The reply has a format of: /* The reply has a format of:
* byte packet_type byte SSH2_AGENT_IDENTITIES_ANSWER
* int num_keys uint32 num_keys
* Followed by zero or more consecutive keys, encoded as:
* string keyblob1 string key_blob
* string comment1 string key_comment
* ...
* string keyblob(n)
* string comment(n)
*/ */
packet_type = buf_getbyte(inbuf); packet_type = buf_getbyte(inbuf);
if (packet_type != SSH2_AGENT_IDENTITIES_ANSWER) { if (packet_type != SSH2_AGENT_IDENTITIES_ANSWER) {
@ -195,25 +190,24 @@ static void agent_get_key_list(int fd, struct SignKeyList * ret_list)
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
sign_key * pubkey = NULL; sign_key * pubkey = NULL;
int key_type = DROPBEAR_SIGNKEY_ANY; int key_type = DROPBEAR_SIGNKEY_ANY;
buffer * key_buf;
struct SignKeyList *nextkey = NULL; struct SignKeyList *nextkey = NULL;
nextkey = (struct SignKeyList*)m_malloc(sizeof(struct SignKeyList)); /* each public key is encoded as a string */
ret_list->next = nextkey; key_buf = buf_getstringbuf(inbuf);
ret_list = nextkey;
pubkey = new_sign_key(); 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) { if (ret != DROPBEAR_SUCCESS) {
/* This is slack, properly would cleanup vars etc */ /* This is slack, properly would cleanup vars etc */
dropbear_exit("Bad pubkey received from agent"); dropbear_exit("Bad pubkey received from agent");
} }
pubkey->type = key_type;
pubkey->source = SIGNKEY_SOURCE_AGENT;
key->key = pubkey; list_append(ret_list, pubkey);
key->next = NULL;
key->type = key_type;
key->source = SIGNKEY_SOURCE_AGENT;
/* We'll ignore the comment */ /* We'll ignore the comment for now. might want it later.*/
buf_eatstring(inbuf); buf_eatstring(inbuf);
} }
@ -224,8 +218,9 @@ out:
} }
} }
/* Returned keys are appended to ret_list */ /* Returned keys are prepended to ret_list, which will
void load_agent_keys(struct SignKeyList * ret_list) be updated. */
void load_agent_keys(m_list *ret_list)
{ {
int fd; int fd;
fd = connect_agent(); fd = connect_agent();
@ -238,12 +233,8 @@ void load_agent_keys(struct SignKeyList * ret_list)
close(fd); close(fd);
} }
// general procedure: void agent_buf_sign(buffer *sigblob, sign_key *key,
// - get the list of keys from the agent const unsigned char *data, unsigned int len) {
// - 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.
//
#endif #endif

View File

@ -30,6 +30,7 @@
#include "ssh.h" #include "ssh.h"
#include "runopts.h" #include "runopts.h"
#include "auth.h" #include "auth.h"
#include "agentfwd.h"
#ifdef ENABLE_CLI_PUBKEY_AUTH #ifdef ENABLE_CLI_PUBKEY_AUTH
static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign); static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign);
@ -37,31 +38,23 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign);
/* Called when we receive a SSH_MSG_USERAUTH_FAILURE for a pubkey request. /* 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 */ * We use it to remove the key we tried from the list */
void cli_pubkeyfail() { 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;
struct SignKeyList *keyitem; if (iter_key == cli_ses.lastprivkey)
struct SignKeyList **previtem; {
/* found the failing key */
TRACE(("enter cli_pubkeyfail")) list_remove(iter);
previtem = &cli_opts.privkeys; sign_key_free(iter_key);
cli_ses.lastprivkey = NULL;
/* Find the key we failed with, and remove it */ return;
for (keyitem = cli_opts.privkeys; keyitem != NULL; keyitem = keyitem->next) {
if (keyitem == cli_ses.lastprivkey) {
*previtem = keyitem->next;
} }
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() { void recv_msg_userauth_pk_ok() {
m_list_elem *iter;
struct SignKeyList *keyitem = NULL;
buffer* keybuf = NULL; buffer* keybuf = NULL;
char* algotype = NULL; char* algotype = NULL;
unsigned int algolen; unsigned int algolen;
@ -81,9 +74,9 @@ void recv_msg_userauth_pk_ok() {
/* Iterate through our keys, find which one it was that matched, and /* Iterate through our keys, find which one it was that matched, and
* send a real request with that key */ * send a real request with that key */
for (keyitem = cli_opts.privkeys; keyitem != NULL; keyitem = keyitem->next) { for (iter = cli_opts.privkeys->first; iter; iter = iter->next) {
sign_key *key = (sign_key*)iter->item;
if (keyitem->type != keytype) { if (key->type != keytype) {
/* Types differed */ /* Types differed */
TRACE(("types differed")) TRACE(("types differed"))
continue; continue;
@ -91,7 +84,7 @@ void recv_msg_userauth_pk_ok() {
/* Now we compare the contents of the key */ /* Now we compare the contents of the key */
keybuf->pos = keybuf->len = 0; 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_setpos(keybuf, 0);
buf_incrpos(keybuf, 4); /* first int is the length of the remainder (ie buf_incrpos(keybuf, 4); /* first int is the length of the remainder (ie
remotelen) which has already been taken from remotelen) which has already been taken from
@ -115,11 +108,11 @@ void recv_msg_userauth_pk_ok() {
} }
buf_free(keybuf); buf_free(keybuf);
if (keyitem != NULL) { if (iter != NULL) {
TRACE(("matching key")) TRACE(("matching key"))
/* XXX TODO: if it's an encrypted key, here we ask for their /* XXX TODO: if it's an encrypted key, here we ask for their
* password */ * password */
send_msg_userauth_pubkey(keyitem->key, keytype, 1); send_msg_userauth_pubkey((sign_key*)iter->item, keytype, 1);
} else { } 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(("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 @@ void recv_msg_userauth_pk_ok() {
TRACE(("leave recv_msg_userauth_pk_ok")) 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 */ /* TODO: make it take an agent reference to use as well */
static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) { static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
@ -170,6 +182,7 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
TRACE(("leave send_msg_userauth_pubkey")) TRACE(("leave send_msg_userauth_pubkey"))
} }
/* Returns 1 if a key was tried */
int cli_auth_pubkey() { int cli_auth_pubkey() {
TRACE(("enter cli_auth_pubkey")) TRACE(("enter cli_auth_pubkey"))
@ -177,15 +190,15 @@ int cli_auth_pubkey() {
if (cli_opts.agent_fwd && if (cli_opts.agent_fwd &&
!cli_opts.agent_keys_loaded) { !cli_opts.agent_keys_loaded) {
/* get the list of available keys from the agent */ /* 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; 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 a trial request */
send_msg_userauth_pubkey(cli_opts.privkeys->key, send_msg_userauth_pubkey(key, key->type, 0);
cli_opts.privkeys->type, 0); cli_ses.lastprivkey = key;
cli_ses.lastprivkey = cli_opts.privkeys;
TRACE(("leave cli_auth_pubkey-success")) TRACE(("leave cli_auth_pubkey-success"))
return 1; return 1;
} else { } else {

View File

@ -424,16 +424,3 @@ void cli_send_chansess_request() {
TRACE(("leave cli_send_chansess_request")) 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

View File

@ -29,6 +29,7 @@
#include "dbutil.h" #include "dbutil.h"
#include "algo.h" #include "algo.h"
#include "tcpfwd.h" #include "tcpfwd.h"
#include "list.h"
cli_runopts cli_opts; /* GLOBAL */ cli_runopts cli_opts; /* GLOBAL */
@ -40,7 +41,7 @@ static void fill_own_user();
static void loadidentityfile(const char* filename); static void loadidentityfile(const char* filename);
#endif #endif
#ifdef ENABLE_CLI_ANYTCPFWD #ifdef ENABLE_CLI_ANYTCPFWD
static void addforward(const char* str, struct TCPFwdList** fwdlist); static void addforward(const char* str, m_list *fwdlist);
#endif #endif
#ifdef ENABLE_CLI_NETCAT #ifdef ENABLE_CLI_NETCAT
static void add_netcat(const char *str); static void add_netcat(const char *str);
@ -128,14 +129,14 @@ void cli_getopts(int argc, char ** argv) {
cli_opts.always_accept_key = 0; cli_opts.always_accept_key = 0;
cli_opts.is_subsystem = 0; cli_opts.is_subsystem = 0;
#ifdef ENABLE_CLI_PUBKEY_AUTH #ifdef ENABLE_CLI_PUBKEY_AUTH
cli_opts.privkeys = NULL; cli_opts.privkeys = list_new();
#endif #endif
#ifdef ENABLE_CLI_LOCALTCPFWD #ifdef ENABLE_CLI_LOCALTCPFWD
cli_opts.localfwds = NULL; cli_opts.localfwds = list_new();
opts.listen_fwd_all = 0; opts.listen_fwd_all = 0;
#endif #endif
#ifdef ENABLE_CLI_REMOTETCPFWD #ifdef ENABLE_CLI_REMOTETCPFWD
cli_opts.remotefwds = NULL; cli_opts.remotefwds = list_new();
#endif #endif
#ifdef ENABLE_CLI_AGENTFWD #ifdef ENABLE_CLI_AGENTFWD
cli_opts.agent_fwd = 0; cli_opts.agent_fwd = 0;
@ -165,7 +166,7 @@ void cli_getopts(int argc, char ** argv) {
#ifdef ENABLE_CLI_REMOTETCPFWD #ifdef ENABLE_CLI_REMOTETCPFWD
if (nextisremote) { if (nextisremote) {
TRACE(("nextisremote true")) TRACE(("nextisremote true"))
addforward(argv[i], &cli_opts.remotefwds); addforward(argv[i], cli_opts.remotefwds);
nextisremote = 0; nextisremote = 0;
continue; continue;
} }
@ -173,7 +174,7 @@ void cli_getopts(int argc, char ** argv) {
#ifdef ENABLE_CLI_LOCALTCPFWD #ifdef ENABLE_CLI_LOCALTCPFWD
if (nextislocal) { if (nextislocal) {
TRACE(("nextislocal true")) TRACE(("nextislocal true"))
addforward(argv[i], &cli_opts.localfwds); addforward(argv[i], cli_opts.localfwds);
nextislocal = 0; nextislocal = 0;
continue; continue;
} }
@ -406,8 +407,6 @@ void cli_getopts(int argc, char ** argv) {
#ifdef ENABLE_CLI_PUBKEY_AUTH #ifdef ENABLE_CLI_PUBKEY_AUTH
static void loadidentityfile(const char* filename) { static void loadidentityfile(const char* filename) {
struct SignKeyList * nextkey;
sign_key *key; sign_key *key;
int keytype; int keytype;
@ -417,13 +416,10 @@ static void loadidentityfile(const char* filename) {
fprintf(stderr, "Failed loading keyfile '%s'\n", filename); fprintf(stderr, "Failed loading keyfile '%s'\n", filename);
sign_key_free(key); sign_key_free(key);
} else { } else {
nextkey = (struct SignKeyList*)m_malloc(sizeof(struct SignKeyList)); key->type = keytype;
nextkey->key = key; key->source = SIGNKEY_SOURCE_RAW_FILE;
nextkey->filename = m_strdup(filename); key->filename = m_strdup(filename);
nextkey->next = cli_opts.privkeys; list_append(cli_opts.privkeys, key);
nextkey->type = keytype;
nextkey->source = SIGNKEY_SOURCE_RAW_FILE;
cli_opts.privkeys = nextkey;
} }
} }
#endif #endif
@ -435,12 +431,13 @@ multihop_passthrough_args() {
char *ret; char *ret;
int total; int total;
unsigned int len = 0; unsigned int len = 0;
struct SignKeyList *nextkey; m_list_elem *iter;
/* Fill out -i and -W options that make sense for all /* Fill out -i and -W options that make sense for all
* the intermediate processes */ * 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. len += 20; // space for -W <size>, terminator.
ret = m_malloc(len); ret = m_malloc(len);
@ -452,10 +449,11 @@ multihop_passthrough_args() {
total += written; 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; 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); dropbear_assert(written < size);
total += written; total += written;
} }
@ -621,12 +619,12 @@ static void fill_own_user() {
#ifdef ENABLE_CLI_ANYTCPFWD #ifdef ENABLE_CLI_ANYTCPFWD
/* Turn a "listenport:remoteaddr:remoteport" string into into a forwarding /* Turn a "listenport:remoteaddr:remoteport" string into into a forwarding
* set, and add it to the forwarding list */ * 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 * listenport = NULL;
char * connectport = NULL; char * connectport = NULL;
char * connectaddr = NULL; char * connectaddr = NULL;
struct TCPFwdList* newfwd = NULL; struct TCPFwdEntry* newfwd = NULL;
char * str = NULL; char * str = NULL;
TRACE(("enter addforward")) TRACE(("enter addforward"))
@ -653,7 +651,7 @@ static void addforward(const char* origstr, struct TCPFwdList** fwdlist) {
*connectport = '\0'; *connectport = '\0';
connectport++; 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, /* Now we check the ports - note that the port ints are unsigned,
* the check later only checks for >= MAX_PORT */ * the check later only checks for >= MAX_PORT */
@ -680,8 +678,7 @@ static void addforward(const char* origstr, struct TCPFwdList** fwdlist) {
} }
newfwd->have_reply = 0; newfwd->have_reply = 0;
newfwd->next = *fwdlist; list_append(fwdlist, newfwd);
*fwdlist = newfwd;
TRACE(("leave addforward: done")) TRACE(("leave addforward: done"))
return; return;

View File

@ -59,27 +59,22 @@ static const struct ChanType cli_chan_tcplocal = {
#ifdef ENABLE_CLI_LOCALTCPFWD #ifdef ENABLE_CLI_LOCALTCPFWD
void setup_localtcp() { void setup_localtcp() {
m_list_elem *iter;
int ret; int ret;
TRACE(("enter setup_localtcp")) TRACE(("enter setup_localtcp"))
if (cli_opts.localfwds == NULL) { for (iter = cli_opts.localfwds->first; iter; iter = iter->next) {
TRACE(("cli_opts.localfwds == NULL")) struct TCPFwdEntry * fwd = (struct TCPFwdEntry*)iter->item;
} ret = cli_localtcp(fwd->listenport,
fwd->connectaddr,
while (cli_opts.localfwds != NULL) { fwd->connectport);
ret = cli_localtcp(cli_opts.localfwds->listenport,
cli_opts.localfwds->connectaddr,
cli_opts.localfwds->connectport);
if (ret == DROPBEAR_FAILURE) { if (ret == DROPBEAR_FAILURE) {
dropbear_log(LOG_WARNING, "Failed local port forward %d:%s:%d", dropbear_log(LOG_WARNING, "Failed local port forward %d:%s:%d",
cli_opts.localfwds->listenport, fwd->listenport,
cli_opts.localfwds->connectaddr, fwd->connectaddr,
cli_opts.localfwds->connectport); fwd->connectport);
} }
cli_opts.localfwds = cli_opts.localfwds->next;
} }
TRACE(("leave setup_localtcp")) TRACE(("leave setup_localtcp"))
@ -148,60 +143,47 @@ static void send_msg_global_request_remotetcp(int port) {
* being in the same order as we sent the requests. This is the ordering * being in the same order as we sent the requests. This is the ordering
* of the cli_opts.remotefwds list */ * of the cli_opts.remotefwds list */
void cli_recv_msg_request_success() { void cli_recv_msg_request_success() {
/* Nothing in the packet. We just mark off that we have received the reply, /* Nothing in the packet. We just mark off that we have received the reply,
* so that we can report failure for later ones. */ * so that we can report failure for later ones. */
struct TCPFwdList * iter = NULL; m_list_elem * iter = NULL;
for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
iter = cli_opts.remotefwds; struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item;
while (iter != NULL) { if (!fwd->have_reply) {
if (!iter->have_reply) fwd->have_reply = 1;
{
iter->have_reply = 1;
return; return;
} }
iter = iter->next;
} }
} }
void cli_recv_msg_request_failure() { void cli_recv_msg_request_failure() {
struct TCPFwdList * iter = NULL; m_list_elem *iter;
for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
iter = cli_opts.remotefwds; struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item;
while (iter != NULL) { if (!fwd->have_reply) {
if (!iter->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);
iter->have_reply = 1;
dropbear_log(LOG_WARNING, "Remote TCP forward request failed (port %d -> %s:%d)", iter->listenport, iter->connectaddr, iter->connectport);
return; return;
} }
iter = iter->next;
} }
} }
void setup_remotetcp() { void setup_remotetcp() {
m_list_elem *iter;
struct TCPFwdList * iter = NULL;
TRACE(("enter setup_remotetcp")) TRACE(("enter setup_remotetcp"))
if (cli_opts.remotefwds == NULL) { for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
TRACE(("cli_opts.remotefwds == NULL")) struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item;
send_msg_global_request_remotetcp(fwd->listenport);
} }
iter = cli_opts.remotefwds;
while (iter != NULL) {
send_msg_global_request_remotetcp(iter->listenport);
iter = iter->next;
}
TRACE(("leave setup_remotetcp")) TRACE(("leave setup_remotetcp"))
} }
static int newtcpforwarded(struct Channel * channel) { static int newtcpforwarded(struct Channel * channel) {
unsigned int origport; unsigned int origport;
struct TCPFwdList * iter = NULL; m_list_elem * iter = NULL;
struct TCPFwdEntry *fwd;
char portstring[NI_MAXSERV]; char portstring[NI_MAXSERV];
int sock; int sock;
int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
@ -212,13 +194,11 @@ static int newtcpforwarded(struct Channel * channel) {
origport = buf_getint(ses.payload); origport = buf_getint(ses.payload);
/* Find which port corresponds */ /* Find which port corresponds */
iter = cli_opts.remotefwds; for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) {
fwd = (struct TCPFwdEntry*)iter->item;
while (iter != NULL) { if (origport == fwd->listenport) {
if (origport == iter->listenport) {
break; break;
} }
iter = iter->next;
} }
if (iter == NULL) { if (iter == NULL) {
@ -228,8 +208,8 @@ static int newtcpforwarded(struct Channel * channel) {
goto out; goto out;
} }
snprintf(portstring, sizeof(portstring), "%d", iter->connectport); snprintf(portstring, sizeof(portstring), "%d", fwd->connectport);
sock = connect_remote(iter->connectaddr, portstring, 1, NULL); sock = connect_remote(fwd->connectaddr, portstring, 1, NULL);
if (sock < 0) { if (sock < 0) {
TRACE(("leave newtcpdirect: sock failed")) TRACE(("leave newtcpdirect: sock failed"))
err = SSH_OPEN_CONNECT_FAILED; err = SSH_OPEN_CONNECT_FAILED;

49
list.c Normal file
View File

@ -0,0 +1,49 @@
#include "options.h"
#include "dbutil.h"
#include "list.h"
void list_append(m_list *list, void *item) {
m_list_elem *elem;
elem = m_malloc(sizeof(*elem));
elem->item = item;
elem->list = list;
elem->next = NULL;
if (!list->first) {
list->first = elem;
elem->prev = NULL;
} else {
elem->prev = list->last;
list->last->next = elem;
}
list->last = elem;
}
m_list * list_new() {
m_list *ret = m_malloc(sizeof(m_list));
ret->first = ret->last = NULL;
return ret;
}
void * list_remove(m_list_elem *elem) {
void *item = elem->item;
m_list *list = elem->list;
if (list->first == elem)
{
list->first = elem->next;
}
if (list->last == elem)
{
list->last = elem->prev;
}
if (elem->prev)
{
elem->prev->next = elem->next;
}
if (elem->next)
{
elem->next->prev = elem->prev;
}
m_free(elem);
return item;
}

28
list.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef _DROPBEAR_LIST_H
#define _DROPBEAR_LIST_H
struct _m_list;
struct _m_list_elem {
void *item;
struct _m_list_elem *next;
struct _m_list_elem *prev;
struct _m_list *list;
};
typedef struct _m_list_elem m_list_elem;
struct _m_list {
m_list_elem *first;
m_list_elem *last;
};
typedef struct _m_list m_list;
m_list * list_new();
void list_append(m_list *list, void *item);
/* returns the item for the element removed */
void * list_remove(m_list_elem *elem);
#endif /* _DROPBEAR_LIST_H */

View File

@ -112,13 +112,13 @@ typedef struct cli_runopts {
int backgrounded; int backgrounded;
int is_subsystem; int is_subsystem;
#ifdef ENABLE_CLI_PUBKEY_AUTH #ifdef ENABLE_CLI_PUBKEY_AUTH
struct SignKeyList *privkeys; /* Keys to use for public-key auth */ m_list *privkeys; /* Keys to use for public-key auth */
#endif #endif
#ifdef ENABLE_CLI_REMOTETCPFWD #ifdef ENABLE_CLI_REMOTETCPFWD
struct TCPFwdList * remotefwds; m_list * remotefwds;
#endif #endif
#ifdef ENABLE_CLI_LOCALTCPFWD #ifdef ENABLE_CLI_LOCALTCPFWD
struct TCPFwdList * localfwds; m_list * localfwds;
#endif #endif
#ifdef ENABLE_CLI_AGENTFWD #ifdef ENABLE_CLI_AGENTFWD
int agent_fwd; int agent_fwd;

View File

@ -261,7 +261,7 @@ struct clientsession {
info request from the server for info request from the server for
interactive auth.*/ interactive auth.*/
#endif #endif
struct SignKeyList *lastprivkey; sign_key *lastprivkey;
int retval; /* What the command exit status was - we emulate it */ int retval; /* What the command exit status was - we emulate it */
#if 0 #if 0

View File

@ -40,8 +40,10 @@ sign_key * new_sign_key() {
#ifdef DROPBEAR_RSA #ifdef DROPBEAR_RSA
ret->rsakey = NULL; ret->rsakey = NULL;
#endif #endif
ret->filename = NULL;
ret->type = DROPBEAR_SIGNKEY_NONE;
ret->source = SIGNKEY_SOURCE_INVALID;
return ret; return ret;
} }
/* Returns "ssh-dss" or "ssh-rsa" corresponding to the type. Exits fatally /* Returns "ssh-dss" or "ssh-rsa" corresponding to the type. Exits fatally
@ -81,6 +83,9 @@ int signkey_type_from_name(const char* name, int namelen) {
} }
#endif #endif
TRACE(("signkey_type_from_name unexpected key type."))
printhex("Key type", name, namelen);
return DROPBEAR_SIGNKEY_NONE; return DROPBEAR_SIGNKEY_NONE;
} }
@ -101,9 +106,12 @@ int buf_get_pub_key(buffer *buf, sign_key *key, int *type) {
m_free(ident); m_free(ident);
if (*type != DROPBEAR_SIGNKEY_ANY && *type != keytype) { if (*type != DROPBEAR_SIGNKEY_ANY && *type != keytype) {
TRACE(("buf_get_pub_key bad type - got %d, expected %d", keytype, type))
return DROPBEAR_FAILURE; return DROPBEAR_FAILURE;
} }
TRACE(("buf_get_pub_key keytype is %d"))
*type = keytype; *type = keytype;
/* Rewind the buffer back before "ssh-rsa" etc */ /* Rewind the buffer back before "ssh-rsa" etc */
@ -255,6 +263,8 @@ void sign_key_free(sign_key *key) {
key->rsakey = NULL; key->rsakey = NULL;
#endif #endif
m_free(key->filename);
m_free(key); m_free(key);
TRACE(("leave sign_key_free")) TRACE(("leave sign_key_free"))
} }
@ -358,7 +368,6 @@ void buf_put_sign(buffer* buf, sign_key *key, int type,
const unsigned char *data, unsigned int len) { const unsigned char *data, unsigned int len) {
buffer *sigblob; buffer *sigblob;
sigblob = buf_new(MAX_PUBKEY_SIZE); sigblob = buf_new(MAX_PUBKEY_SIZE);
#ifdef DROPBEAR_DSS #ifdef DROPBEAR_DSS
@ -374,7 +383,6 @@ void buf_put_sign(buffer* buf, sign_key *key, int type,
if (sigblob->len == 0) { if (sigblob->len == 0) {
dropbear_exit("non-matching signing type"); dropbear_exit("non-matching signing type");
} }
buf_setpos(sigblob, 0); buf_setpos(sigblob, 0);
buf_putstring(buf, buf_getptr(sigblob, sigblob->len), buf_putstring(buf, buf_getptr(sigblob, sigblob->len),
sigblob->len); sigblob->len);

View File

@ -29,8 +29,22 @@
#include "dss.h" #include "dss.h"
#include "rsa.h" #include "rsa.h"
/* Sources for signing keys */
typedef enum {
SIGNKEY_SOURCE_RAW_FILE,
SIGNKEY_SOURCE_AGENT,
SIGNKEY_SOURCE_INVALID,
} signkey_source;
struct SIGN_key { struct SIGN_key {
int type; /* The type of key (dss or rsa) */
signkey_source source;
char *filename;
/* the buffer? for encrypted keys, so we can later get
* the private key portion */
#ifdef DROPBEAR_DSS #ifdef DROPBEAR_DSS
dss_key * dsskey; dss_key * dsskey;
#endif #endif

View File

@ -25,6 +25,7 @@
#define _TCPFWD_H #define _TCPFWD_H
#include "channel.h" #include "channel.h"
#include "list.h"
struct TCPListener { struct TCPListener {
@ -43,16 +44,13 @@ struct TCPListener {
enum {direct, forwarded} tcp_type; enum {direct, forwarded} tcp_type;
}; };
/* A link in a list of forwards */ /* A forwarding entry */
struct TCPFwdList { struct TCPFwdEntry {
const unsigned char* connectaddr; const unsigned char* connectaddr;
unsigned int connectport; unsigned int connectport;
unsigned int listenport; unsigned int listenport;
unsigned int have_reply; /* is set to 1 after a reply has been received unsigned int have_reply; /* is set to 1 after a reply has been received
when setting up the forwarding */ when setting up the forwarding */
struct TCPFwdList * next;
}; };
/* Server */ /* Server */
@ -70,5 +68,4 @@ void cli_recv_msg_request_failure();
/* Common */ /* Common */
int listen_tcpfwd(struct TCPListener* tcpinfo); int listen_tcpfwd(struct TCPListener* tcpinfo);
#endif #endif