mirror of
https://github.com/clearml/dropbear
synced 2025-06-26 18:17:32 +00:00
merge of 9522146cb07d4576f161fc4567c2c2fbd6f61fbb
and b11630c15bc4d0649dba51c3572cac6f44e0ab0e --HG-- extra : convert_revision : e0686662cdbee8c0b06e72e6105a390ea4f4c007
This commit is contained in:
commit
aaa0b1ec3c
21
CHANGES
21
CHANGES
@ -1,3 +1,24 @@
|
|||||||
|
0.46
|
||||||
|
|
||||||
|
- Fix long-standing bug which caused connections to be closed if an ssh-agent
|
||||||
|
socket was no longer available
|
||||||
|
|
||||||
|
- print a warning if we seem to be blocking on /dev/random
|
||||||
|
(suggested by Paul Fox)
|
||||||
|
|
||||||
|
- fixed a memory leak in DSS code (thanks to Boris Berezovsky for the patch)
|
||||||
|
|
||||||
|
- dbclient -L no longer segfaults, allocate correct buffer size (thanks
|
||||||
|
to David Cook for reporting it)
|
||||||
|
|
||||||
|
- added RSA blinding (recommended by Dan Kaminsky)
|
||||||
|
|
||||||
|
- rearranged bignum reading/random generation code
|
||||||
|
|
||||||
|
- Reset the non-blocking status on stderr and stdout as well as stdin,
|
||||||
|
fixes a problem where the shell running dbclient will exit (thanks to
|
||||||
|
Brent Roman for reporting it)
|
||||||
|
|
||||||
0.45 - Mon March 7 2005
|
0.45 - Mon March 7 2005
|
||||||
|
|
||||||
- Makefile no longer appends 'static' to statically linked binaries
|
- Makefile no longer appends 'static' to statically linked binaries
|
||||||
|
@ -69,7 +69,7 @@ AR=@AR@
|
|||||||
RANLIB=@RANLIB@
|
RANLIB=@RANLIB@
|
||||||
STRIP=@STRIP@
|
STRIP=@STRIP@
|
||||||
INSTALL=@INSTALL@
|
INSTALL=@INSTALL@
|
||||||
CFLAGS=-I. -I$(srcdir)/libtomcrypt @CFLAGS@
|
CFLAGS=-I. -I$(srcdir)/libtomcrypt/src/headers/ @CFLAGS@
|
||||||
LIBS=$(LTC) $(LTM) @LIBS@
|
LIBS=$(LTC) $(LTM) @LIBS@
|
||||||
LDFLAGS=@LDFLAGS@
|
LDFLAGS=@LDFLAGS@
|
||||||
|
|
||||||
|
8
TODO
8
TODO
@ -2,12 +2,12 @@ Current:
|
|||||||
|
|
||||||
Things which might need doing:
|
Things which might need doing:
|
||||||
|
|
||||||
|
- default private dbclient keys
|
||||||
|
|
||||||
- Make options.h generated from configure perhaps?
|
- Make options.h generated from configure perhaps?
|
||||||
|
|
||||||
- Improved queueing of unauthed connections
|
- Improved queueing of unauthed connections
|
||||||
|
|
||||||
- fix agent fwd problems
|
|
||||||
|
|
||||||
- handle /etc/environment in AIX
|
- handle /etc/environment in AIX
|
||||||
|
|
||||||
- check that there aren't timing issues with valid/invalid user authentication
|
- check that there aren't timing issues with valid/invalid user authentication
|
||||||
@ -15,9 +15,9 @@ Things which might need doing:
|
|||||||
|
|
||||||
- Binding to different interfaces
|
- Binding to different interfaces
|
||||||
|
|
||||||
- possible RSA blinding? need to check whether this is vuln to timing attacks
|
|
||||||
- check PRNG
|
- check PRNG
|
||||||
- CTR mode, SSH_MSG_IGNORE sending to improve CBC security
|
- CTR mode
|
||||||
|
- SSH_MSG_IGNORE sending to improve CBC security
|
||||||
- DH Group Exchange possibly, or just add group14 (whatever it's called today)
|
- DH Group Exchange possibly, or just add group14 (whatever it's called today)
|
||||||
|
|
||||||
- fix scp.c for IRIX
|
- fix scp.c for IRIX
|
||||||
|
4
algo.h
4
algo.h
@ -51,13 +51,13 @@ extern const struct dropbear_cipher dropbear_nocipher;
|
|||||||
extern const struct dropbear_hash dropbear_nohash;
|
extern const struct dropbear_hash dropbear_nohash;
|
||||||
|
|
||||||
struct dropbear_cipher {
|
struct dropbear_cipher {
|
||||||
const struct _cipher_descriptor *cipherdesc;
|
const struct ltc_cipher_descriptor *cipherdesc;
|
||||||
unsigned long keysize;
|
unsigned long keysize;
|
||||||
unsigned char blocksize;
|
unsigned char blocksize;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dropbear_hash {
|
struct dropbear_hash {
|
||||||
const struct _hash_descriptor *hashdesc;
|
const struct ltc_hash_descriptor *hashdesc;
|
||||||
unsigned long keysize;
|
unsigned long keysize;
|
||||||
unsigned char hashsize;
|
unsigned char hashsize;
|
||||||
};
|
};
|
||||||
|
8
auth.h
8
auth.h
@ -84,13 +84,13 @@ struct AuthState {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PubkeyList;
|
struct SignKeyList;
|
||||||
/* A singly linked list of pubkeys */
|
/* A singly linked list of signing keys */
|
||||||
struct PubkeyList {
|
struct SignKeyList {
|
||||||
|
|
||||||
sign_key *key;
|
sign_key *key;
|
||||||
int type; /* The type of key */
|
int type; /* The type of key */
|
||||||
struct PubkeyList *next;
|
struct SignKeyList *next;
|
||||||
/* filename? or the buffer? for encrypted keys, so we can later get
|
/* filename? or the buffer? for encrypted keys, so we can later get
|
||||||
* the private key portion */
|
* the private key portion */
|
||||||
|
|
||||||
|
4
bignum.c
4
bignum.c
@ -52,9 +52,9 @@ void m_mp_init_multi(mp_int *mp, ...)
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bytestomp(mp_int *mp, unsigned char* bytes, unsigned int len) {
|
void bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len) {
|
||||||
|
|
||||||
if (mp_read_unsigned_bin(mp, bytes, len) != MP_OKAY) {
|
if (mp_read_unsigned_bin(mp, (unsigned char*)bytes, len) != MP_OKAY) {
|
||||||
dropbear_exit("mem alloc error");
|
dropbear_exit("mem alloc error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
bignum.h
2
bignum.h
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
void m_mp_init(mp_int *mp);
|
void m_mp_init(mp_int *mp);
|
||||||
void m_mp_init_multi(mp_int *mp, ...);
|
void m_mp_init_multi(mp_int *mp, ...);
|
||||||
void bytestomp(mp_int *mp, unsigned char* bytes, unsigned int len);
|
void bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len);
|
||||||
void sha1_process_mp(hash_state *hs, mp_int *mp);
|
void sha1_process_mp(hash_state *hs, mp_int *mp);
|
||||||
|
|
||||||
#endif /* _BIGNUM_H_ */
|
#endif /* _BIGNUM_H_ */
|
||||||
|
10
buffer.c
10
buffer.c
@ -160,6 +160,16 @@ unsigned char buf_getbyte(buffer* buf) {
|
|||||||
return buf->data[buf->pos++];
|
return buf->data[buf->pos++];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get a bool from the buffer and increment the pos */
|
||||||
|
unsigned char buf_getbool(buffer* buf) {
|
||||||
|
|
||||||
|
unsigned char b;
|
||||||
|
b = buf_getbyte(buf);
|
||||||
|
if (b != 0)
|
||||||
|
b = 1;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
/* put a byte, incrementing the length if required */
|
/* put a byte, incrementing the length if required */
|
||||||
void buf_putbyte(buffer* buf, unsigned char val) {
|
void buf_putbyte(buffer* buf, unsigned char val) {
|
||||||
|
|
||||||
|
1
buffer.h
1
buffer.h
@ -50,6 +50,7 @@ void buf_setpos(buffer* buf, unsigned int pos);
|
|||||||
void buf_incrpos(buffer* buf, int incr); /* -ve is ok, to go backwards */
|
void buf_incrpos(buffer* buf, int incr); /* -ve is ok, to go backwards */
|
||||||
void buf_incrwritepos(buffer* buf, unsigned int incr);
|
void buf_incrwritepos(buffer* buf, unsigned int incr);
|
||||||
unsigned char buf_getbyte(buffer* buf);
|
unsigned char buf_getbyte(buffer* buf);
|
||||||
|
unsigned char buf_getbool(buffer* buf);
|
||||||
void buf_putbyte(buffer* buf, unsigned char val);
|
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);
|
||||||
|
@ -100,7 +100,7 @@ void chaninitialise();
|
|||||||
void chancleanup();
|
void chancleanup();
|
||||||
void setchannelfds(fd_set *readfd, fd_set *writefd);
|
void setchannelfds(fd_set *readfd, fd_set *writefd);
|
||||||
void channelio(fd_set *readfd, fd_set *writefd);
|
void channelio(fd_set *readfd, fd_set *writefd);
|
||||||
struct Channel* getchannel(unsigned int chan);
|
struct Channel* getchannel();
|
||||||
struct Channel* newchannel(unsigned int remotechan,
|
struct Channel* newchannel(unsigned int remotechan,
|
||||||
const struct ChanType *type,
|
const struct ChanType *type,
|
||||||
unsigned int transwindow, unsigned int transmaxpacket);
|
unsigned int transwindow, unsigned int transmaxpacket);
|
||||||
|
@ -127,7 +127,7 @@ void recv_msg_userauth_failure() {
|
|||||||
|
|
||||||
methods = buf_getstring(ses.payload, &methlen);
|
methods = buf_getstring(ses.payload, &methlen);
|
||||||
|
|
||||||
partial = buf_getbyte(ses.payload);
|
partial = buf_getbool(ses.payload);
|
||||||
|
|
||||||
if (partial) {
|
if (partial) {
|
||||||
dropbear_log(LOG_INFO, "Authentication partially succeeded, more attempts required");
|
dropbear_log(LOG_INFO, "Authentication partially succeeded, more attempts required");
|
||||||
|
@ -38,29 +38,29 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign);
|
|||||||
* 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() {
|
||||||
|
|
||||||
struct PubkeyList *keyitem;
|
struct SignKeyList *keyitem;
|
||||||
struct PubkeyList **previtem;
|
struct SignKeyList **previtem;
|
||||||
|
|
||||||
TRACE(("enter cli_pubkeyfail"))
|
TRACE(("enter cli_pubkeyfail"))
|
||||||
previtem = &cli_opts.pubkeys;
|
previtem = &cli_opts.privkeys;
|
||||||
|
|
||||||
/* Find the key we failed with, and remove it */
|
/* Find the key we failed with, and remove it */
|
||||||
for (keyitem = cli_opts.pubkeys; keyitem != NULL; keyitem = keyitem->next) {
|
for (keyitem = cli_opts.privkeys; keyitem != NULL; keyitem = keyitem->next) {
|
||||||
if (keyitem == cli_ses.lastpubkey) {
|
if (keyitem == cli_ses.lastprivkey) {
|
||||||
*previtem = keyitem->next;
|
*previtem = keyitem->next;
|
||||||
}
|
}
|
||||||
previtem = &keyitem;
|
previtem = &keyitem;
|
||||||
}
|
}
|
||||||
|
|
||||||
sign_key_free(cli_ses.lastpubkey->key); /* It won't be used again */
|
sign_key_free(cli_ses.lastprivkey->key); /* It won't be used again */
|
||||||
m_free(cli_ses.lastpubkey);
|
m_free(cli_ses.lastprivkey);
|
||||||
|
|
||||||
TRACE(("leave cli_pubkeyfail"))
|
TRACE(("leave cli_pubkeyfail"))
|
||||||
}
|
}
|
||||||
|
|
||||||
void recv_msg_userauth_pk_ok() {
|
void recv_msg_userauth_pk_ok() {
|
||||||
|
|
||||||
struct PubkeyList *keyitem;
|
struct SignKeyList *keyitem;
|
||||||
buffer* keybuf;
|
buffer* keybuf;
|
||||||
char* algotype = NULL;
|
char* algotype = NULL;
|
||||||
unsigned int algolen;
|
unsigned int algolen;
|
||||||
@ -80,7 +80,7 @@ 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.pubkeys; keyitem != NULL; keyitem = keyitem->next) {
|
for (keyitem = cli_opts.privkeys; keyitem != NULL; keyitem = keyitem->next) {
|
||||||
|
|
||||||
if (keyitem->type != keytype) {
|
if (keyitem->type != keytype) {
|
||||||
/* Types differed */
|
/* Types differed */
|
||||||
@ -172,11 +172,11 @@ int cli_auth_pubkey() {
|
|||||||
|
|
||||||
TRACE(("enter cli_auth_pubkey"))
|
TRACE(("enter cli_auth_pubkey"))
|
||||||
|
|
||||||
if (cli_opts.pubkeys != NULL) {
|
if (cli_opts.privkeys != NULL) {
|
||||||
/* Send a trial request */
|
/* Send a trial request */
|
||||||
send_msg_userauth_pubkey(cli_opts.pubkeys->key,
|
send_msg_userauth_pubkey(cli_opts.privkeys->key,
|
||||||
cli_opts.pubkeys->type, 0);
|
cli_opts.privkeys->type, 0);
|
||||||
cli_ses.lastpubkey = cli_opts.pubkeys;
|
cli_ses.lastprivkey = cli_opts.privkeys;
|
||||||
TRACE(("leave cli_auth_pubkey-success"))
|
TRACE(("leave cli_auth_pubkey-success"))
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -33,15 +33,12 @@
|
|||||||
/* We receive channel data - only used by the client chansession code*/
|
/* We receive channel data - only used by the client chansession code*/
|
||||||
void recv_msg_channel_extended_data() {
|
void recv_msg_channel_extended_data() {
|
||||||
|
|
||||||
unsigned int chan;
|
|
||||||
struct Channel *channel;
|
struct Channel *channel;
|
||||||
unsigned int datatype;
|
unsigned int datatype;
|
||||||
|
|
||||||
TRACE(("enter recv_msg_channel_extended_data"))
|
TRACE(("enter recv_msg_channel_extended_data"))
|
||||||
|
|
||||||
chan = buf_getint(ses.payload);
|
channel = getchannel();
|
||||||
channel = getchannel(chan);
|
|
||||||
|
|
||||||
if (channel == NULL) {
|
if (channel == NULL) {
|
||||||
dropbear_exit("Unknown channel");
|
dropbear_exit("Unknown channel");
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ static void cli_chansessreq(struct Channel *channel) {
|
|||||||
TRACE(("enter cli_chansessreq"))
|
TRACE(("enter cli_chansessreq"))
|
||||||
|
|
||||||
type = buf_getstring(ses.payload, NULL);
|
type = buf_getstring(ses.payload, NULL);
|
||||||
wantreply = buf_getbyte(ses.payload);
|
wantreply = buf_getbool(ses.payload);
|
||||||
|
|
||||||
if (strcmp(type, "exit-status") != 0) {
|
if (strcmp(type, "exit-status") != 0) {
|
||||||
TRACE(("unknown request '%s'", type))
|
TRACE(("unknown request '%s'", type))
|
||||||
|
@ -53,7 +53,7 @@ static void printhelp() {
|
|||||||
"-i <identityfile> (multiple allowed)\n"
|
"-i <identityfile> (multiple allowed)\n"
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_CLI_LOCALTCPFWD
|
#ifdef ENABLE_CLI_LOCALTCPFWD
|
||||||
"-L <listenport:remotehsot:reportport> Local port forwarding\n"
|
"-L <listenport:remotehost:remoteport> Local port forwarding\n"
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_CLI_REMOTETCPFWD
|
#ifdef ENABLE_CLI_REMOTETCPFWD
|
||||||
"-R <listenport:remotehost:remoteport> Remote port forwarding\n"
|
"-R <listenport:remotehost:remoteport> Remote port forwarding\n"
|
||||||
@ -89,7 +89,7 @@ void cli_getopts(int argc, char ** argv) {
|
|||||||
cli_opts.cmd = NULL;
|
cli_opts.cmd = NULL;
|
||||||
cli_opts.wantpty = 9; /* 9 means "it hasn't been touched", gets set later */
|
cli_opts.wantpty = 9; /* 9 means "it hasn't been touched", gets set later */
|
||||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||||
cli_opts.pubkeys = NULL;
|
cli_opts.privkeys = NULL;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_CLI_LOCALTCPFWD
|
#ifdef ENABLE_CLI_LOCALTCPFWD
|
||||||
cli_opts.localfwds = NULL;
|
cli_opts.localfwds = NULL;
|
||||||
@ -271,7 +271,7 @@ 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 PubkeyList * nextkey;
|
struct SignKeyList * nextkey;
|
||||||
sign_key *key;
|
sign_key *key;
|
||||||
int keytype;
|
int keytype;
|
||||||
|
|
||||||
@ -284,11 +284,11 @@ static void loadidentityfile(const char* filename) {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
nextkey = (struct PubkeyList*)m_malloc(sizeof(struct PubkeyList));
|
nextkey = (struct SignKeyList*)m_malloc(sizeof(struct SignKeyList));
|
||||||
nextkey->key = key;
|
nextkey->key = key;
|
||||||
nextkey->next = cli_opts.pubkeys;
|
nextkey->next = cli_opts.privkeys;
|
||||||
nextkey->type = keytype;
|
nextkey->type = keytype;
|
||||||
cli_opts.pubkeys = nextkey;
|
cli_opts.privkeys = nextkey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -113,16 +113,20 @@ static void cli_session_init() {
|
|||||||
cli_ses.tty_raw_mode = 0;
|
cli_ses.tty_raw_mode = 0;
|
||||||
cli_ses.winchange = 0;
|
cli_ses.winchange = 0;
|
||||||
|
|
||||||
/* We store stdin's flags, so we can set them back on exit (otherwise
|
/* We store std{in,out,err}'s flags, so we can set them back on exit
|
||||||
* busybox's ash isn't happy */
|
* (otherwise busybox's ash isn't happy */
|
||||||
cli_ses.stdincopy = dup(STDIN_FILENO);
|
cli_ses.stdincopy = dup(STDIN_FILENO);
|
||||||
cli_ses.stdinflags = fcntl(STDIN_FILENO, F_GETFL, 0);
|
cli_ses.stdinflags = fcntl(STDIN_FILENO, F_GETFL, 0);
|
||||||
|
cli_ses.stdoutcopy = dup(STDOUT_FILENO);
|
||||||
|
cli_ses.stdoutflags = fcntl(STDOUT_FILENO, F_GETFL, 0);
|
||||||
|
cli_ses.stderrcopy = dup(STDERR_FILENO);
|
||||||
|
cli_ses.stderrflags = fcntl(STDERR_FILENO, F_GETFL, 0);
|
||||||
|
|
||||||
cli_ses.retval = EXIT_SUCCESS; /* Assume it's clean if we don't get a
|
cli_ses.retval = EXIT_SUCCESS; /* Assume it's clean if we don't get a
|
||||||
specific exit status */
|
specific exit status */
|
||||||
|
|
||||||
/* Auth */
|
/* Auth */
|
||||||
cli_ses.lastpubkey = NULL;
|
cli_ses.lastprivkey = NULL;
|
||||||
cli_ses.lastauthtype = 0;
|
cli_ses.lastauthtype = 0;
|
||||||
|
|
||||||
/* For printing "remote host closed" for the user */
|
/* For printing "remote host closed" for the user */
|
||||||
@ -250,9 +254,11 @@ void cli_session_cleanup() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set stdin back to non-blocking - busybox ash dies nastily
|
/* Set std{in,out,err} back to non-blocking - busybox ash dies nastily if
|
||||||
* if we don't revert the flags */
|
* we don't revert the flags */
|
||||||
fcntl(cli_ses.stdincopy, F_SETFL, cli_ses.stdinflags);
|
fcntl(cli_ses.stdincopy, F_SETFL, cli_ses.stdinflags);
|
||||||
|
fcntl(cli_ses.stdoutcopy, F_SETFL, cli_ses.stdoutflags);
|
||||||
|
fcntl(cli_ses.stderrcopy, F_SETFL, cli_ses.stderrflags);
|
||||||
|
|
||||||
cli_tty_cleanup();
|
cli_tty_cleanup();
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
|
|||||||
TRACE(("enter cli_localtcp: %d %s %d", listenport, remoteaddr,
|
TRACE(("enter cli_localtcp: %d %s %d", listenport, remoteaddr,
|
||||||
remoteport));
|
remoteport));
|
||||||
|
|
||||||
tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener*));
|
tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener));
|
||||||
tcpinfo->sendaddr = m_strdup(remoteaddr);
|
tcpinfo->sendaddr = m_strdup(remoteaddr);
|
||||||
tcpinfo->sendport = remoteport;
|
tcpinfo->sendport = remoteport;
|
||||||
tcpinfo->listenport = listenport;
|
tcpinfo->listenport = listenport;
|
||||||
|
@ -125,7 +125,7 @@ algo_type sshkex[] = {
|
|||||||
* This should be run before using any of the ciphers/hashes */
|
* This should be run before using any of the ciphers/hashes */
|
||||||
void crypto_init() {
|
void crypto_init() {
|
||||||
|
|
||||||
const struct _cipher_descriptor *regciphers[] = {
|
const struct ltc_cipher_descriptor *regciphers[] = {
|
||||||
#ifdef DROPBEAR_AES128_CBC
|
#ifdef DROPBEAR_AES128_CBC
|
||||||
&aes_desc,
|
&aes_desc,
|
||||||
#endif
|
#endif
|
||||||
@ -141,7 +141,7 @@ void crypto_init() {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct _hash_descriptor *reghashes[] = {
|
const struct ltc_hash_descriptor *reghashes[] = {
|
||||||
/* we need sha1 for hostkey stuff regardless */
|
/* we need sha1 for hostkey stuff regardless */
|
||||||
&sha1_desc,
|
&sha1_desc,
|
||||||
#ifdef DROPBEAR_MD5_HMAC
|
#ifdef DROPBEAR_MD5_HMAC
|
||||||
|
@ -162,8 +162,13 @@ struct Channel* newchannel(unsigned int remotechan,
|
|||||||
return newchan;
|
return newchan;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the channel structure corresponding to a channel number */
|
/* Returns the channel structure corresponding to the channel in the current
|
||||||
struct Channel* getchannel(unsigned int chan) {
|
* data packet (ses.payload must be positioned appropriately) */
|
||||||
|
struct Channel* getchannel() {
|
||||||
|
|
||||||
|
unsigned int chan;
|
||||||
|
|
||||||
|
chan = buf_getint(ses.payload);
|
||||||
if (chan >= ses.chansize || ses.channels[chan] == NULL) {
|
if (chan >= ses.chansize || ses.channels[chan] == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -474,14 +479,11 @@ void setchannelfds(fd_set *readfd, fd_set *writefd) {
|
|||||||
* etc) FD is also EOF */
|
* etc) FD is also EOF */
|
||||||
void recv_msg_channel_eof() {
|
void recv_msg_channel_eof() {
|
||||||
|
|
||||||
unsigned int chan;
|
|
||||||
struct Channel * channel;
|
struct Channel * channel;
|
||||||
|
|
||||||
TRACE(("enter recv_msg_channel_eof"))
|
TRACE(("enter recv_msg_channel_eof"))
|
||||||
|
|
||||||
chan = buf_getint(ses.payload);
|
channel = getchannel();
|
||||||
channel = getchannel(chan);
|
|
||||||
|
|
||||||
if (channel == NULL) {
|
if (channel == NULL) {
|
||||||
dropbear_exit("EOF for unknown channel");
|
dropbear_exit("EOF for unknown channel");
|
||||||
}
|
}
|
||||||
@ -500,15 +502,11 @@ void recv_msg_channel_eof() {
|
|||||||
/* Handle channel closure(), respond in kind and close the channels */
|
/* Handle channel closure(), respond in kind and close the channels */
|
||||||
void recv_msg_channel_close() {
|
void recv_msg_channel_close() {
|
||||||
|
|
||||||
unsigned int chan;
|
|
||||||
struct Channel * channel;
|
struct Channel * channel;
|
||||||
|
|
||||||
TRACE(("enter recv_msg_channel_close"))
|
TRACE(("enter recv_msg_channel_close"))
|
||||||
|
|
||||||
chan = buf_getint(ses.payload);
|
channel = getchannel();
|
||||||
TRACE(("close channel = %d", chan))
|
|
||||||
channel = getchannel(chan);
|
|
||||||
|
|
||||||
if (channel == NULL) {
|
if (channel == NULL) {
|
||||||
/* disconnect ? */
|
/* disconnect ? */
|
||||||
dropbear_exit("Close for unknown channel");
|
dropbear_exit("Close for unknown channel");
|
||||||
@ -567,14 +565,11 @@ static void deletechannel(struct Channel *channel) {
|
|||||||
* such as chansession or x11fwd */
|
* such as chansession or x11fwd */
|
||||||
void recv_msg_channel_request() {
|
void recv_msg_channel_request() {
|
||||||
|
|
||||||
unsigned int chan;
|
|
||||||
struct Channel *channel;
|
struct Channel *channel;
|
||||||
|
|
||||||
TRACE(("enter recv_msg_channel_request"))
|
TRACE(("enter recv_msg_channel_request"))
|
||||||
|
|
||||||
chan = buf_getint(ses.payload);
|
channel = getchannel();
|
||||||
channel = getchannel(chan);
|
|
||||||
|
|
||||||
if (channel == NULL) {
|
if (channel == NULL) {
|
||||||
/* disconnect ? */
|
/* disconnect ? */
|
||||||
dropbear_exit("Unknown channel");
|
dropbear_exit("Unknown channel");
|
||||||
@ -666,12 +661,9 @@ static void send_msg_channel_data(struct Channel *channel, int isextended,
|
|||||||
/* We receive channel data */
|
/* We receive channel data */
|
||||||
void recv_msg_channel_data() {
|
void recv_msg_channel_data() {
|
||||||
|
|
||||||
unsigned int chan;
|
|
||||||
struct Channel *channel;
|
struct Channel *channel;
|
||||||
|
|
||||||
chan = buf_getint(ses.payload);
|
channel = getchannel();
|
||||||
channel = getchannel(chan);
|
|
||||||
|
|
||||||
if (channel == NULL) {
|
if (channel == NULL) {
|
||||||
dropbear_exit("Unknown channel");
|
dropbear_exit("Unknown channel");
|
||||||
}
|
}
|
||||||
@ -738,13 +730,10 @@ void common_recv_msg_channel_data(struct Channel *channel, int fd,
|
|||||||
* as data is sent, and incremented upon receiving window-adjust messages */
|
* as data is sent, and incremented upon receiving window-adjust messages */
|
||||||
void recv_msg_channel_window_adjust() {
|
void recv_msg_channel_window_adjust() {
|
||||||
|
|
||||||
unsigned int chan;
|
|
||||||
struct Channel * channel;
|
struct Channel * channel;
|
||||||
unsigned int incr;
|
unsigned int incr;
|
||||||
|
|
||||||
chan = buf_getint(ses.payload);
|
channel = getchannel();
|
||||||
channel = getchannel(chan);
|
|
||||||
|
|
||||||
if (channel == NULL) {
|
if (channel == NULL) {
|
||||||
dropbear_exit("Unknown channel");
|
dropbear_exit("Unknown channel");
|
||||||
}
|
}
|
||||||
@ -961,14 +950,12 @@ int send_msg_channel_open_init(int fd, const struct ChanType *type) {
|
|||||||
* successful*/
|
* successful*/
|
||||||
void recv_msg_channel_open_confirmation() {
|
void recv_msg_channel_open_confirmation() {
|
||||||
|
|
||||||
unsigned int chan;
|
|
||||||
struct Channel * channel;
|
struct Channel * channel;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
TRACE(("enter recv_msg_channel_open_confirmation"))
|
TRACE(("enter recv_msg_channel_open_confirmation"))
|
||||||
chan = buf_getint(ses.payload);
|
|
||||||
|
|
||||||
channel = getchannel(chan);
|
channel = getchannel();
|
||||||
if (channel == NULL) {
|
if (channel == NULL) {
|
||||||
dropbear_exit("Unknown channel");
|
dropbear_exit("Unknown channel");
|
||||||
}
|
}
|
||||||
@ -977,7 +964,8 @@ void recv_msg_channel_open_confirmation() {
|
|||||||
channel->transwindow = buf_getint(ses.payload);
|
channel->transwindow = buf_getint(ses.payload);
|
||||||
channel->transmaxpacket = buf_getint(ses.payload);
|
channel->transmaxpacket = buf_getint(ses.payload);
|
||||||
|
|
||||||
TRACE(("new chan remote %d localho %d", channel->remotechan, chan))
|
TRACE(("new chan remote %d local %d",
|
||||||
|
channel->remotechan, channel->index))
|
||||||
|
|
||||||
/* Run the inithandler callback */
|
/* Run the inithandler callback */
|
||||||
if (channel->type->inithandler) {
|
if (channel->type->inithandler) {
|
||||||
@ -995,11 +983,9 @@ void recv_msg_channel_open_confirmation() {
|
|||||||
/* Notification that our channel open request failed */
|
/* Notification that our channel open request failed */
|
||||||
void recv_msg_channel_open_failure() {
|
void recv_msg_channel_open_failure() {
|
||||||
|
|
||||||
unsigned int chan;
|
|
||||||
struct Channel * channel;
|
struct Channel * channel;
|
||||||
chan = buf_getbyte(ses.payload);
|
|
||||||
|
|
||||||
channel = getchannel(chan);
|
channel = getchannel();
|
||||||
if (channel == NULL) {
|
if (channel == NULL) {
|
||||||
dropbear_exit("Unknown channel");
|
dropbear_exit("Unknown channel");
|
||||||
}
|
}
|
||||||
|
27
common-kex.c
27
common-kex.c
@ -457,7 +457,6 @@ void recv_msg_kexinit() {
|
|||||||
/* the rest of ses.kexhashbuf will be done after DH exchange */
|
/* the rest of ses.kexhashbuf will be done after DH exchange */
|
||||||
|
|
||||||
ses.kexstate.recvkexinit = 1;
|
ses.kexstate.recvkexinit = 1;
|
||||||
// ses.expecting = 0; // client matt
|
|
||||||
|
|
||||||
TRACE(("leave recv_msg_kexinit"))
|
TRACE(("leave recv_msg_kexinit"))
|
||||||
}
|
}
|
||||||
@ -470,18 +469,13 @@ void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv) {
|
|||||||
DEF_MP_INT(dh_p);
|
DEF_MP_INT(dh_p);
|
||||||
DEF_MP_INT(dh_q);
|
DEF_MP_INT(dh_q);
|
||||||
DEF_MP_INT(dh_g);
|
DEF_MP_INT(dh_g);
|
||||||
unsigned char randbuf[DH_P_LEN];
|
|
||||||
int dh_q_len;
|
|
||||||
|
|
||||||
TRACE(("enter send_msg_kexdh_reply"))
|
TRACE(("enter send_msg_kexdh_reply"))
|
||||||
|
|
||||||
m_mp_init_multi(&dh_g, &dh_p, &dh_q, NULL);
|
m_mp_init_multi(&dh_g, &dh_p, &dh_q, NULL);
|
||||||
|
|
||||||
/* read the prime and generator*/
|
/* read the prime and generator*/
|
||||||
if (mp_read_unsigned_bin(&dh_p, (unsigned char*)dh_p_val, DH_P_LEN)
|
bytes_to_mp(&dh_p, (unsigned char*)dh_p_val, DH_P_LEN);
|
||||||
!= MP_OKAY) {
|
|
||||||
dropbear_exit("Diffie-Hellman error");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mp_set_int(&dh_g, DH_G_VAL) != MP_OKAY) {
|
if (mp_set_int(&dh_g, DH_G_VAL) != MP_OKAY) {
|
||||||
dropbear_exit("Diffie-Hellman error");
|
dropbear_exit("Diffie-Hellman error");
|
||||||
@ -496,16 +490,8 @@ void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv) {
|
|||||||
dropbear_exit("Diffie-Hellman error");
|
dropbear_exit("Diffie-Hellman error");
|
||||||
}
|
}
|
||||||
|
|
||||||
dh_q_len = mp_unsigned_bin_size(&dh_q);
|
/* Generate a private portion 0 < dh_priv < dh_q */
|
||||||
|
gen_random_mpint(&dh_q, dh_priv);
|
||||||
/* calculate our random value dh_y */
|
|
||||||
do {
|
|
||||||
assert((unsigned int)dh_q_len <= sizeof(randbuf));
|
|
||||||
genrandom(randbuf, dh_q_len);
|
|
||||||
if (mp_read_unsigned_bin(dh_priv, randbuf, dh_q_len) != MP_OKAY) {
|
|
||||||
dropbear_exit("Diffie-Hellman error");
|
|
||||||
}
|
|
||||||
} while (mp_cmp(dh_priv, &dh_q) == MP_GT || mp_cmp_d(dh_priv, 0) != MP_GT);
|
|
||||||
|
|
||||||
/* f = g^y mod p */
|
/* f = g^y mod p */
|
||||||
if (mp_exptmod(&dh_g, dh_priv, &dh_p, dh_pub) != MP_OKAY) {
|
if (mp_exptmod(&dh_g, dh_priv, &dh_p, dh_pub) != MP_OKAY) {
|
||||||
@ -527,10 +513,7 @@ void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them,
|
|||||||
|
|
||||||
/* read the prime and generator*/
|
/* read the prime and generator*/
|
||||||
mp_init(&dh_p);
|
mp_init(&dh_p);
|
||||||
if (mp_read_unsigned_bin(&dh_p, (unsigned char*)dh_p_val, DH_P_LEN)
|
bytes_to_mp(&dh_p, dh_p_val, DH_P_LEN);
|
||||||
!= MP_OKAY) {
|
|
||||||
dropbear_exit("Diffie-Hellman error");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check that dh_pub_them (dh_e or dh_f) is in the range [1, p-1] */
|
/* Check that dh_pub_them (dh_e or dh_f) is in the range [1, p-1] */
|
||||||
if (mp_cmp(dh_pub_them, &dh_p) != MP_LT
|
if (mp_cmp(dh_pub_them, &dh_p) != MP_LT
|
||||||
@ -683,7 +666,7 @@ static void read_kex_algos() {
|
|||||||
buf_eatstring(ses.payload);
|
buf_eatstring(ses.payload);
|
||||||
|
|
||||||
/* first_kex_packet_follows */
|
/* first_kex_packet_follows */
|
||||||
if (buf_getbyte(ses.payload)) {
|
if (buf_getbool(ses.payload)) {
|
||||||
ses.kexstate.firstfollows = 1;
|
ses.kexstate.firstfollows = 1;
|
||||||
/* if the guess wasn't good, we ignore the packet sent */
|
/* if the guess wasn't good, we ignore the packet sent */
|
||||||
if (!allgood) {
|
if (!allgood) {
|
||||||
|
69
dbclient.1
Normal file
69
dbclient.1
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
.TH dbclient 1
|
||||||
|
.SH NAME
|
||||||
|
dbclient \- lightweight SSH2 client
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B dbclient
|
||||||
|
[\-Tt] [\-p
|
||||||
|
.I port\fR] [\-i
|
||||||
|
.I id\fR] [\-L
|
||||||
|
.I l\fR:\fIh\fR:\fIr\fR] [\-R
|
||||||
|
.I l\fR:\fIh\fR:\fIr\fR] [\-l
|
||||||
|
.IR user ]
|
||||||
|
.I host
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B dbclient
|
||||||
|
is a SSH 2 client designed to be small enough to be used in small memory
|
||||||
|
environments, while still being functional and secure enough for general use.
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.B \-p \fIport
|
||||||
|
Remote port.
|
||||||
|
Connect to port
|
||||||
|
.I port
|
||||||
|
on the remote host.
|
||||||
|
Default is 22.
|
||||||
|
.TP
|
||||||
|
.B \-i \fIidfile
|
||||||
|
Identity file.
|
||||||
|
Read the identity from file
|
||||||
|
.I idfile
|
||||||
|
(multiple allowed).
|
||||||
|
.TP
|
||||||
|
.B \-L \fIlocalport\fR:\fIremotehost\fR:\fIremoteport\fR
|
||||||
|
Local port forwarding.
|
||||||
|
Forward the port
|
||||||
|
.I localport
|
||||||
|
on the local host to port
|
||||||
|
.I remoteport
|
||||||
|
on the remote host
|
||||||
|
.IR remotehost .
|
||||||
|
.TP
|
||||||
|
.B \-R \fIlocalport\fR:\fIremotehost\fR:\fIremoteport\fR
|
||||||
|
Remote port forwarding.
|
||||||
|
Forward the port
|
||||||
|
.I remoteport
|
||||||
|
on the remote host
|
||||||
|
.I remotehost
|
||||||
|
to port
|
||||||
|
.I localport
|
||||||
|
on the local host.
|
||||||
|
.TP
|
||||||
|
.B \-l \fIuser
|
||||||
|
Username.
|
||||||
|
Login as
|
||||||
|
.I user
|
||||||
|
on the remote host.
|
||||||
|
.TP
|
||||||
|
.B \-t
|
||||||
|
Allocate a pty.
|
||||||
|
.TP
|
||||||
|
.B \-T
|
||||||
|
Don't allocate a pty.
|
||||||
|
.SH AUTHOR
|
||||||
|
Matt Johnston (matt@ucc.asn.au).
|
||||||
|
.br
|
||||||
|
Gerrit Pape (pape@smarden.org) wrote this manual page.
|
||||||
|
.SH SEE ALSO
|
||||||
|
dropbear(8), dropbearkey(8)
|
||||||
|
.P
|
||||||
|
http://matt.ucc.asn.au/dropbear/dropbear.html
|
3
dbutil.c
3
dbutil.c
@ -430,10 +430,11 @@ char* getaddrhostname(struct sockaddr_storage * addr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_TRACE
|
#ifdef DEBUG_TRACE
|
||||||
void printhex(unsigned char* buf, int len) {
|
void printhex(const char * label, const unsigned char * buf, int len) {
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
fprintf(stderr, "%s\n", label);
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
fprintf(stderr, "%02x", buf[i]);
|
fprintf(stderr, "%02x", buf[i]);
|
||||||
if (i % 16 == 15) {
|
if (i % 16 == 15) {
|
||||||
|
2
dbutil.h
2
dbutil.h
@ -41,7 +41,7 @@ void dropbear_close(const char* format, ...);
|
|||||||
void dropbear_log(int priority, const char* format, ...);
|
void dropbear_log(int priority, const char* format, ...);
|
||||||
#ifdef DEBUG_TRACE
|
#ifdef DEBUG_TRACE
|
||||||
void dropbear_trace(const char* format, ...);
|
void dropbear_trace(const char* format, ...);
|
||||||
void printhex(unsigned char* buf, int len);
|
void printhex(const char * label, const unsigned char * buf, int len);
|
||||||
extern int debug_trace;
|
extern int debug_trace;
|
||||||
#endif
|
#endif
|
||||||
char * stripcontrol(const char * text);
|
char * stripcontrol(const char * text);
|
||||||
|
15
debian/README.Debian.diet
vendored
Normal file
15
debian/README.Debian.diet
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
Building with the diet libc
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
This package optionally can be built with the diet libc instead of the
|
||||||
|
glibc to provide small statically linked programs. The resulting package
|
||||||
|
has no dependency on any other package.
|
||||||
|
|
||||||
|
To use the diet libc, make sure the latest versions of the dietlibc-dev
|
||||||
|
package is installed, and set DEB_BUILD_OPTIONS=diet in the environment
|
||||||
|
when building the package, e.g.:
|
||||||
|
|
||||||
|
# apt-get install dietlibc-dev
|
||||||
|
$ DEB_BUILD_OPTIONS=diet fakeroot apt-get source -b dropbear
|
||||||
|
|
||||||
|
-- Gerrit Pape <pape@smarden.org>, Sat, 17 Jul 2004 19:09:34 +0000
|
2
debug.h
2
debug.h
@ -39,7 +39,7 @@
|
|||||||
* Caution: Don't use this in an unfriendly environment (ie unfirewalled),
|
* Caution: Don't use this in an unfriendly environment (ie unfirewalled),
|
||||||
* since the printing may not sanitise strings etc. This will add a reasonable
|
* since the printing may not sanitise strings etc. This will add a reasonable
|
||||||
* amount to your executable size. */
|
* amount to your executable size. */
|
||||||
//#define DEBUG_TRACE
|
/*#define DEBUG_TRACE */
|
||||||
|
|
||||||
/* All functions writing to the cleartext payload buffer call
|
/* All functions writing to the cleartext payload buffer call
|
||||||
* CHECKCLEARTOWRITE() before writing. This is only really useful if you're
|
* CHECKCLEARTOWRITE() before writing. This is only really useful if you're
|
||||||
|
@ -76,6 +76,6 @@ Matt Johnston (matt@ucc.asn.au).
|
|||||||
.br
|
.br
|
||||||
Gerrit Pape (pape@smarden.org) wrote this manual page.
|
Gerrit Pape (pape@smarden.org) wrote this manual page.
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
dropbearkey(8)
|
dropbearkey(8), dbclient(1)
|
||||||
.P
|
.P
|
||||||
http://matt.ucc.asn.au/dropbear/dropbear.html
|
http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||||
|
@ -42,6 +42,6 @@ Matt Johnston (matt@ucc.asn.au).
|
|||||||
.br
|
.br
|
||||||
Gerrit Pape (pape@smarden.org) wrote this manual page.
|
Gerrit Pape (pape@smarden.org) wrote this manual page.
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
dropbear(8)
|
dropbear(8), dbclient(1)
|
||||||
.P
|
.P
|
||||||
http://matt.ucc.asn.au/dropbear/dropbear.html
|
http://matt.ucc.asn.au/dropbear/dropbear.html
|
||||||
|
34
dss.c
34
dss.c
@ -190,10 +190,8 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data,
|
|||||||
/* create the signature - s' and r' are the received signatures in buf */
|
/* create the signature - s' and r' are the received signatures in buf */
|
||||||
/* w = (s')-1 mod q */
|
/* w = (s')-1 mod q */
|
||||||
/* let val1 = s' */
|
/* let val1 = s' */
|
||||||
if (mp_read_unsigned_bin(&val1, &string[SHA1_HASH_SIZE], SHA1_HASH_SIZE)
|
bytes_to_mp(&val1, &string[SHA1_HASH_SIZE], SHA1_HASH_SIZE);
|
||||||
!= MP_OKAY) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (mp_cmp(&val1, key->q) != MP_LT) {
|
if (mp_cmp(&val1, key->q) != MP_LT) {
|
||||||
TRACE(("verify failed, s' >= q"))
|
TRACE(("verify failed, s' >= q"))
|
||||||
goto out;
|
goto out;
|
||||||
@ -205,9 +203,8 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data,
|
|||||||
|
|
||||||
/* u1 = ((SHA(M')w) mod q */
|
/* u1 = ((SHA(M')w) mod q */
|
||||||
/* let val1 = SHA(M') = msghash */
|
/* let val1 = SHA(M') = msghash */
|
||||||
if (mp_read_unsigned_bin(&val1, msghash, SHA1_HASH_SIZE) != MP_OKAY) {
|
bytes_to_mp(&val1, msghash, SHA1_HASH_SIZE);
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
/* let val3 = u1 = ((SHA(M')w) mod q */
|
/* let val3 = u1 = ((SHA(M')w) mod q */
|
||||||
if (mp_mulmod(&val1, &val2, key->q, &val3) != MP_OKAY) {
|
if (mp_mulmod(&val1, &val2, key->q, &val3) != MP_OKAY) {
|
||||||
goto out;
|
goto out;
|
||||||
@ -215,10 +212,7 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data,
|
|||||||
|
|
||||||
/* u2 = ((r')w) mod q */
|
/* u2 = ((r')w) mod q */
|
||||||
/* let val1 = r' */
|
/* let val1 = r' */
|
||||||
if (mp_read_unsigned_bin(&val1, &string[0], SHA1_HASH_SIZE)
|
bytes_to_mp(&val1, &string[0], SHA1_HASH_SIZE);
|
||||||
!= MP_OKAY) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (mp_cmp(&val1, key->q) != MP_LT) {
|
if (mp_cmp(&val1, key->q) != MP_LT) {
|
||||||
TRACE(("verify failed, r' >= q"))
|
TRACE(("verify failed, r' >= q"))
|
||||||
goto out;
|
goto out;
|
||||||
@ -261,6 +255,7 @@ out:
|
|||||||
}
|
}
|
||||||
#endif /* DROPBEAR_SIGNKEY_VERIFY */
|
#endif /* DROPBEAR_SIGNKEY_VERIFY */
|
||||||
|
|
||||||
|
#ifdef DSS_PROTOK
|
||||||
/* convert an unsigned mp into an array of bytes, malloced.
|
/* convert an unsigned mp into an array of bytes, malloced.
|
||||||
* This array must be freed after use, len contains the length of the array,
|
* This array must be freed after use, len contains the length of the array,
|
||||||
* if len != NULL */
|
* if len != NULL */
|
||||||
@ -279,6 +274,7 @@ static unsigned char* mptobytes(mp_int *mp, int *len) {
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Sign the data presented with key, writing the signature contents
|
/* Sign the data presented with key, writing the signature contents
|
||||||
* to the buffer
|
* to the buffer
|
||||||
@ -304,8 +300,6 @@ void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data,
|
|||||||
unsigned char *privkeytmp;
|
unsigned char *privkeytmp;
|
||||||
unsigned char proto_k[SHA512_HASH_SIZE];
|
unsigned char proto_k[SHA512_HASH_SIZE];
|
||||||
DEF_MP_INT(dss_protok);
|
DEF_MP_INT(dss_protok);
|
||||||
#else
|
|
||||||
unsigned char kbuf[SHA1_HASH_SIZE];
|
|
||||||
#endif
|
#endif
|
||||||
DEF_MP_INT(dss_k);
|
DEF_MP_INT(dss_k);
|
||||||
DEF_MP_INT(dss_m);
|
DEF_MP_INT(dss_m);
|
||||||
@ -343,22 +337,16 @@ void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data,
|
|||||||
|
|
||||||
/* generate k */
|
/* generate k */
|
||||||
m_mp_init(&dss_protok);
|
m_mp_init(&dss_protok);
|
||||||
bytestomp(&dss_protok, proto_k, SHA512_HASH_SIZE);
|
bytes_to_mp(&dss_protok, proto_k, SHA512_HASH_SIZE);
|
||||||
mp_mod(&dss_protok, key->q, &dss_k);
|
mp_mod(&dss_protok, key->q, &dss_k);
|
||||||
mp_clear(&dss_protok);
|
mp_clear(&dss_protok);
|
||||||
m_burn(proto_k, SHA512_HASH_SIZE);
|
m_burn(proto_k, SHA512_HASH_SIZE);
|
||||||
#else /* DSS_PROTOK not defined*/
|
#else /* DSS_PROTOK not defined*/
|
||||||
do {
|
gen_random_mpint(key->q, &dss_k);
|
||||||
genrandom(kbuf, SHA1_HASH_SIZE);
|
|
||||||
if (mp_read_unsigned_bin(&dss_k, kbuf, SHA1_HASH_SIZE) != MP_OKAY) {
|
|
||||||
dropbear_exit("dss error");
|
|
||||||
}
|
|
||||||
} while (mp_cmp(&dss_k, key->q) == MP_GT || mp_cmp_d(&dss_k, 0) != MP_GT);
|
|
||||||
m_burn(kbuf, SHA1_HASH_SIZE);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* now generate the actual signature */
|
/* now generate the actual signature */
|
||||||
bytestomp(&dss_m, msghash, SHA1_HASH_SIZE);
|
bytes_to_mp(&dss_m, msghash, SHA1_HASH_SIZE);
|
||||||
|
|
||||||
/* g^k mod p */
|
/* g^k mod p */
|
||||||
if (mp_exptmod(key->g, &dss_k, key->p, &dss_temp1) != MP_OKAY) {
|
if (mp_exptmod(key->g, &dss_k, key->p, &dss_temp1) != MP_OKAY) {
|
||||||
@ -417,7 +405,7 @@ void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data,
|
|||||||
mp_clear(&dss_s);
|
mp_clear(&dss_s);
|
||||||
buf_incrwritepos(buf, writelen);
|
buf_incrwritepos(buf, writelen);
|
||||||
|
|
||||||
mp_clear_multi(&dss_k, &dss_temp1, &dss_temp1, &dss_r, &dss_s,
|
mp_clear_multi(&dss_k, &dss_temp1, &dss_temp2, &dss_r, &dss_s,
|
||||||
&dss_m, NULL);
|
&dss_m, NULL);
|
||||||
|
|
||||||
/* create the signature to return */
|
/* create the signature to return */
|
||||||
|
28
gendss.c
28
gendss.c
@ -77,10 +77,7 @@ static void getq(dss_key *key) {
|
|||||||
buf[0] |= 0x80; /* top bit high */
|
buf[0] |= 0x80; /* top bit high */
|
||||||
buf[QSIZE-1] |= 0x01; /* bottom bit high */
|
buf[QSIZE-1] |= 0x01; /* bottom bit high */
|
||||||
|
|
||||||
if (mp_read_unsigned_bin(key->q, buf, QSIZE) != MP_OKAY) {
|
bytes_to_mp(key->q, buf, QSIZE);
|
||||||
fprintf(stderr, "dss key generation failed\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 18 rounds are required according to HAC */
|
/* 18 rounds are required according to HAC */
|
||||||
if (mp_prime_next_prime(key->q, 18, 0) != MP_OKAY) {
|
if (mp_prime_next_prime(key->q, 18, 0) != MP_OKAY) {
|
||||||
@ -116,10 +113,7 @@ static void getp(dss_key *key, unsigned int size) {
|
|||||||
buf[0] |= 0x80; /* set the top bit high */
|
buf[0] |= 0x80; /* set the top bit high */
|
||||||
|
|
||||||
/* X is a random mp_int */
|
/* X is a random mp_int */
|
||||||
if (mp_read_unsigned_bin(&tempX, buf, size) != MP_OKAY) {
|
bytes_to_mp(&tempX, buf, size);
|
||||||
fprintf(stderr, "dss key generation failed\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* C = X mod 2q */
|
/* C = X mod 2q */
|
||||||
if (mp_mod(&tempX, &temp2q, &tempC) != MP_OKAY) {
|
if (mp_mod(&tempX, &temp2q, &tempC) != MP_OKAY) {
|
||||||
@ -147,6 +141,7 @@ static void getp(dss_key *key, unsigned int size) {
|
|||||||
} while (!result);
|
} while (!result);
|
||||||
|
|
||||||
mp_clear_multi(&tempX, &tempC, &tempP, &temp2q, NULL);
|
mp_clear_multi(&tempX, &tempC, &tempP, &temp2q, NULL);
|
||||||
|
m_burn(buf, size);
|
||||||
m_free(buf);
|
m_free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,22 +184,7 @@ static void getg(dss_key * key) {
|
|||||||
|
|
||||||
static void getx(dss_key *key) {
|
static void getx(dss_key *key) {
|
||||||
|
|
||||||
DEF_MP_INT(val);
|
gen_random_mpint(key->q, key->x);
|
||||||
char buf[QSIZE];
|
|
||||||
|
|
||||||
m_mp_init(&val);
|
|
||||||
|
|
||||||
do {
|
|
||||||
genrandom(buf, QSIZE);
|
|
||||||
|
|
||||||
if (mp_read_unsigned_bin(&val, buf, QSIZE) != MP_OKAY) {
|
|
||||||
fprintf(stderr, "dss key generation failed\n");
|
|
||||||
}
|
|
||||||
} while ((mp_cmp_d(&val, 1) == MP_GT) && (mp_cmp(&val, key->q) == MP_LT));
|
|
||||||
|
|
||||||
mp_copy(&val, key->x);
|
|
||||||
mp_clear(&val);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gety(dss_key *key) {
|
static void gety(dss_key *key) {
|
||||||
|
5
genrsa.c
5
genrsa.c
@ -108,10 +108,7 @@ static void getrsaprime(mp_int* prime, mp_int *primeminus,
|
|||||||
genrandom(buf, size+1);
|
genrandom(buf, size+1);
|
||||||
buf[0] |= 0x80; /* MSB set */
|
buf[0] |= 0x80; /* MSB set */
|
||||||
|
|
||||||
if (mp_read_unsigned_bin(prime, buf, size+1) != MP_OKAY) {
|
bytes_to_mp(prime, buf, size+1);
|
||||||
fprintf(stderr, "rsa generation failed\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find the next integer which is prime, 8 round of miller-rabin */
|
/* find the next integer which is prime, 8 round of miller-rabin */
|
||||||
if (mp_prime_next_prime(prime, 8, 0) != MP_OKAY) {
|
if (mp_prime_next_prime(prime, 8, 0) != MP_OKAY) {
|
||||||
|
@ -111,7 +111,7 @@
|
|||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "libtomcrypt/mycrypt.h"
|
#include "libtomcrypt/src/headers/tomcrypt.h"
|
||||||
#include "libtommath/tommath.h"
|
#include "libtommath/tommath.h"
|
||||||
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
6
kex.h
6
kex.h
@ -37,10 +37,10 @@ void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv);
|
|||||||
void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them,
|
void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them,
|
||||||
sign_key *hostkey);
|
sign_key *hostkey);
|
||||||
|
|
||||||
void recv_msg_kexdh_init(); // server
|
void recv_msg_kexdh_init(); /* server */
|
||||||
|
|
||||||
void send_msg_kexdh_init(); // client
|
void send_msg_kexdh_init(); /* client */
|
||||||
void recv_msg_kexdh_reply(); // client
|
void recv_msg_kexdh_reply(); /* client */
|
||||||
|
|
||||||
extern const unsigned char dh_p_val[];
|
extern const unsigned char dh_p_val[];
|
||||||
#define DH_P_LEN 128 /* The length of the dh_p_val array */
|
#define DH_P_LEN 128 /* The length of the dh_p_val array */
|
||||||
|
16
options.h
16
options.h
@ -90,6 +90,11 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */
|
|||||||
#define DROPBEAR_RSA
|
#define DROPBEAR_RSA
|
||||||
#define DROPBEAR_DSS
|
#define DROPBEAR_DSS
|
||||||
|
|
||||||
|
/* RSA can be vulnerable to timing attacks which use the time required for
|
||||||
|
* signing to guess the private key. Blinding avoids this attack, though makes
|
||||||
|
* signing operations slightly slower. */
|
||||||
|
#define RSA_BLINDING
|
||||||
|
|
||||||
/* Define DSS_PROTOK to use PuTTY's method of generating the value k for dss,
|
/* Define DSS_PROTOK to use PuTTY's method of generating the value k for dss,
|
||||||
* rather than just from the random byte source. Undefining this will save you
|
* rather than just from the random byte source. Undefining this will save you
|
||||||
* ~4k in binary size with static uclibc, but your DSS hostkey could be exposed
|
* ~4k in binary size with static uclibc, but your DSS hostkey could be exposed
|
||||||
@ -313,14 +318,6 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */
|
|||||||
#define DISABLE_AGENTFWD
|
#define DISABLE_AGENTFWD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ENABLE_LOCALTCPFWD
|
|
||||||
#define DISABLE_TCPDIRECT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ENABLE_REMOTETCPFWD
|
|
||||||
#define DISABLE_REMOTETCPFWD
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENABLE_CLI_REMOTETCPFWD) || defined(ENABLE_CLI_LOCALTCPFWD)
|
#if defined(ENABLE_CLI_REMOTETCPFWD) || defined(ENABLE_CLI_LOCALTCPFWD)
|
||||||
#define ENABLE_CLI_ANYTCPFWD
|
#define ENABLE_CLI_ANYTCPFWD
|
||||||
#endif
|
#endif
|
||||||
@ -329,7 +326,8 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */
|
|||||||
#define DROPBEAR_TCP_ACCEPT
|
#define DROPBEAR_TCP_ACCEPT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ENABLE_REMOTETCPFWD) || defined(ENABLE_LOCALTCPFWD) || \
|
#if defined(ENABLE_CLI_REMOTETCPFWD) || defined(ENABLE_CLI_LOCALTCPFWD) || \
|
||||||
|
defined(ENABLE_SVR_REMOTETCPFWD) || defined(ENABLE_SVR_LOCALTCPFWD) || \
|
||||||
defined(ENABLE_AGENTFWD) || defined(ENABLE_X11FWD)
|
defined(ENABLE_AGENTFWD) || defined(ENABLE_X11FWD)
|
||||||
#define USING_LISTENERS
|
#define USING_LISTENERS
|
||||||
#endif
|
#endif
|
||||||
|
3
packet.c
3
packet.c
@ -201,6 +201,7 @@ static void read_packet_init() {
|
|||||||
/* decrypt it */
|
/* decrypt it */
|
||||||
if (cbc_decrypt(buf_getptr(ses.readbuf, blocksize),
|
if (cbc_decrypt(buf_getptr(ses.readbuf, blocksize),
|
||||||
buf_getwriteptr(ses.decryptreadbuf,blocksize),
|
buf_getwriteptr(ses.decryptreadbuf,blocksize),
|
||||||
|
blocksize,
|
||||||
&ses.keys->recv_symmetric_struct) != CRYPT_OK) {
|
&ses.keys->recv_symmetric_struct) != CRYPT_OK) {
|
||||||
dropbear_exit("error decrypting");
|
dropbear_exit("error decrypting");
|
||||||
}
|
}
|
||||||
@ -254,6 +255,7 @@ void decrypt_packet() {
|
|||||||
while (ses.readbuf->pos < ses.readbuf->len - macsize) {
|
while (ses.readbuf->pos < ses.readbuf->len - macsize) {
|
||||||
if (cbc_decrypt(buf_getptr(ses.readbuf, blocksize),
|
if (cbc_decrypt(buf_getptr(ses.readbuf, blocksize),
|
||||||
buf_getwriteptr(ses.decryptreadbuf, blocksize),
|
buf_getwriteptr(ses.decryptreadbuf, blocksize),
|
||||||
|
blocksize,
|
||||||
&ses.keys->recv_symmetric_struct) != CRYPT_OK) {
|
&ses.keys->recv_symmetric_struct) != CRYPT_OK) {
|
||||||
dropbear_exit("error decrypting");
|
dropbear_exit("error decrypting");
|
||||||
}
|
}
|
||||||
@ -491,6 +493,7 @@ void encrypt_packet() {
|
|||||||
while (clearwritebuf->pos < clearwritebuf->len) {
|
while (clearwritebuf->pos < clearwritebuf->len) {
|
||||||
if (cbc_encrypt(buf_getptr(clearwritebuf, blocksize),
|
if (cbc_encrypt(buf_getptr(clearwritebuf, blocksize),
|
||||||
buf_getwriteptr(writebuf, blocksize),
|
buf_getwriteptr(writebuf, blocksize),
|
||||||
|
blocksize,
|
||||||
&ses.keys->trans_symmetric_struct) != CRYPT_OK) {
|
&ses.keys->trans_symmetric_struct) != CRYPT_OK) {
|
||||||
dropbear_exit("error encrypting");
|
dropbear_exit("error encrypting");
|
||||||
}
|
}
|
||||||
|
61
random.c
61
random.c
@ -25,14 +25,15 @@
|
|||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "dbutil.h"
|
#include "dbutil.h"
|
||||||
|
#include "bignum.h"
|
||||||
|
|
||||||
int donerandinit = 0;
|
static int donerandinit = 0;
|
||||||
|
|
||||||
/* this is used to generate unique output from the same hashpool */
|
/* this is used to generate unique output from the same hashpool */
|
||||||
unsigned int counter = 0;
|
static unsigned int counter = 0;
|
||||||
#define MAX_COUNTER 1000000/* the max value for the counter, so it won't loop */
|
#define MAX_COUNTER 1000000/* the max value for the counter, so it won't loop */
|
||||||
|
|
||||||
unsigned char hashpool[SHA1_HASH_SIZE];
|
static unsigned char hashpool[SHA1_HASH_SIZE];
|
||||||
|
|
||||||
#define INIT_SEED_SIZE 32 /* 256 bits */
|
#define INIT_SEED_SIZE 32 /* 256 bits */
|
||||||
|
|
||||||
@ -50,6 +51,7 @@ static void readrand(unsigned char* buf, unsigned int buflen);
|
|||||||
|
|
||||||
static void readrand(unsigned char* buf, unsigned int buflen) {
|
static void readrand(unsigned char* buf, unsigned int buflen) {
|
||||||
|
|
||||||
|
static int already_blocked = 0;
|
||||||
int readfd;
|
int readfd;
|
||||||
unsigned int readpos;
|
unsigned int readpos;
|
||||||
int readlen;
|
int readlen;
|
||||||
@ -92,6 +94,24 @@ static void readrand(unsigned char* buf, unsigned int buflen) {
|
|||||||
/* read the actual random data */
|
/* read the actual random data */
|
||||||
readpos = 0;
|
readpos = 0;
|
||||||
do {
|
do {
|
||||||
|
if (!already_blocked)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct timeval timeout;
|
||||||
|
fd_set read_fds;
|
||||||
|
|
||||||
|
timeout.tv_sec = 2; /* two seconds should be enough */
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
|
FD_ZERO(&read_fds);
|
||||||
|
FD_SET(readfd, &read_fds);
|
||||||
|
ret = select(readfd + 1, &read_fds, NULL, NULL, &timeout);
|
||||||
|
if (ret == 0)
|
||||||
|
{
|
||||||
|
dropbear_log(LOG_INFO, "Warning: Reading the random source seems to have blocked.\nIf you experience problems, you probably need to find a better entropy source.");
|
||||||
|
already_blocked = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
readlen = read(readfd, &buf[readpos], buflen - readpos);
|
readlen = read(readfd, &buf[readpos], buflen - readpos);
|
||||||
if (readlen <= 0) {
|
if (readlen <= 0) {
|
||||||
if (readlen < 0 && errno == EINTR) {
|
if (readlen < 0 && errno == EINTR) {
|
||||||
@ -159,3 +179,38 @@ void genrandom(unsigned char* buf, unsigned int len) {
|
|||||||
}
|
}
|
||||||
m_burn(hash, sizeof(hash));
|
m_burn(hash, sizeof(hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Generates a random mp_int.
|
||||||
|
* max is a *mp_int specifying an upper bound.
|
||||||
|
* rand must be an initialised *mp_int for the result.
|
||||||
|
* the result rand satisfies: 0 < rand < max
|
||||||
|
* */
|
||||||
|
void gen_random_mpint(mp_int *max, mp_int *rand) {
|
||||||
|
|
||||||
|
unsigned char *randbuf = NULL;
|
||||||
|
unsigned int len = 0;
|
||||||
|
const char masks[] = {0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f};
|
||||||
|
|
||||||
|
const int size_bits = mp_count_bits(max);
|
||||||
|
|
||||||
|
len = size_bits / 8;
|
||||||
|
if ((size_bits % 8) != 0) {
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
randbuf = (unsigned char*)m_malloc(len);
|
||||||
|
do {
|
||||||
|
genrandom(randbuf, len);
|
||||||
|
/* Mask out the unrequired bits - mp_read_unsigned_bin expects
|
||||||
|
* MSB first.*/
|
||||||
|
randbuf[0] &= masks[size_bits % 8];
|
||||||
|
|
||||||
|
bytes_to_mp(rand, randbuf, len);
|
||||||
|
|
||||||
|
/* keep regenerating until we get one satisfying
|
||||||
|
* 0 < rand < max */
|
||||||
|
} while ( ( (max != NULL) && (mp_cmp(rand, max) != MP_LT) )
|
||||||
|
|| (mp_cmp_d(rand, 0) != MP_GT) );
|
||||||
|
m_burn(randbuf, len);
|
||||||
|
m_free(randbuf);
|
||||||
|
}
|
||||||
|
3
random.h
3
random.h
@ -25,8 +25,11 @@
|
|||||||
#ifndef _RANDOM_H_
|
#ifndef _RANDOM_H_
|
||||||
#define _RANDOM_H_
|
#define _RANDOM_H_
|
||||||
|
|
||||||
|
struct mp_int;
|
||||||
|
|
||||||
void seedrandom();
|
void seedrandom();
|
||||||
void genrandom(unsigned char* buf, int len);
|
void genrandom(unsigned char* buf, int len);
|
||||||
void addrandom(unsigned char* buf, int len);
|
void addrandom(unsigned char* buf, int len);
|
||||||
|
void gen_random_mpint(mp_int *max, mp_int *rand);
|
||||||
|
|
||||||
#endif /* _RANDOM_H_ */
|
#endif /* _RANDOM_H_ */
|
||||||
|
92
rsa.c
92
rsa.c
@ -38,8 +38,9 @@
|
|||||||
|
|
||||||
#ifdef DROPBEAR_RSA
|
#ifdef DROPBEAR_RSA
|
||||||
|
|
||||||
static mp_int * rsa_pad_em(rsa_key * key,
|
static void rsa_pad_em(rsa_key * key,
|
||||||
const unsigned char * data, unsigned int len);
|
const unsigned char * data, unsigned int len,
|
||||||
|
mp_int * rsa_em);
|
||||||
|
|
||||||
/* Load a public rsa key from a buffer, initialising the values.
|
/* Load a public rsa key from a buffer, initialising the values.
|
||||||
* The key will have the same format as buf_put_rsa_key.
|
* The key will have the same format as buf_put_rsa_key.
|
||||||
@ -203,14 +204,14 @@ int buf_rsa_verify(buffer * buf, rsa_key *key, const unsigned char* data,
|
|||||||
unsigned int slen;
|
unsigned int slen;
|
||||||
DEF_MP_INT(rsa_s);
|
DEF_MP_INT(rsa_s);
|
||||||
DEF_MP_INT(rsa_mdash);
|
DEF_MP_INT(rsa_mdash);
|
||||||
mp_int *rsa_em = NULL;
|
DEF_MP_INT(rsa_em);
|
||||||
int ret = DROPBEAR_FAILURE;
|
int ret = DROPBEAR_FAILURE;
|
||||||
|
|
||||||
TRACE(("enter buf_rsa_verify"))
|
TRACE(("enter buf_rsa_verify"))
|
||||||
|
|
||||||
assert(key != NULL);
|
assert(key != NULL);
|
||||||
|
|
||||||
m_mp_init_multi(&rsa_mdash, &rsa_s, NULL);
|
m_mp_init_multi(&rsa_mdash, &rsa_s, &rsa_em, NULL);
|
||||||
|
|
||||||
slen = buf_getint(buf);
|
slen = buf_getint(buf);
|
||||||
if (slen != (unsigned int)mp_unsigned_bin_size(key->n)) {
|
if (slen != (unsigned int)mp_unsigned_bin_size(key->n)) {
|
||||||
@ -231,29 +232,25 @@ int buf_rsa_verify(buffer * buf, rsa_key *key, const unsigned char* data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* create the magic PKCS padded value */
|
/* create the magic PKCS padded value */
|
||||||
rsa_em = rsa_pad_em(key, data, len);
|
rsa_pad_em(key, data, len, &rsa_em);
|
||||||
|
|
||||||
if (mp_exptmod(&rsa_s, key->e, key->n, &rsa_mdash) != MP_OKAY) {
|
if (mp_exptmod(&rsa_s, key->e, key->n, &rsa_mdash) != MP_OKAY) {
|
||||||
TRACE(("failed exptmod rsa_s"))
|
TRACE(("failed exptmod rsa_s"))
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mp_cmp(rsa_em, &rsa_mdash) == MP_EQ) {
|
if (mp_cmp(&rsa_em, &rsa_mdash) == MP_EQ) {
|
||||||
/* signature is valid */
|
/* signature is valid */
|
||||||
TRACE(("success!"))
|
TRACE(("success!"))
|
||||||
ret = DROPBEAR_SUCCESS;
|
ret = DROPBEAR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (rsa_em) {
|
mp_clear_multi(&rsa_mdash, &rsa_s, &rsa_em, NULL);
|
||||||
mp_clear(rsa_em);
|
|
||||||
m_free(rsa_em);
|
|
||||||
}
|
|
||||||
mp_clear_multi(&rsa_mdash, &rsa_s, NULL);
|
|
||||||
TRACE(("leave buf_rsa_verify: ret %d", ret))
|
TRACE(("leave buf_rsa_verify: ret %d", ret))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* DROPBEAR_SIGNKEY_VERIFY */
|
#endif /* DROPBEAR_SIGNKEY_VERIFY */
|
||||||
|
|
||||||
/* Sign the data presented with key, writing the signature contents
|
/* Sign the data presented with key, writing the signature contents
|
||||||
@ -264,22 +261,55 @@ void buf_put_rsa_sign(buffer* buf, rsa_key *key, const unsigned char* data,
|
|||||||
unsigned int nsize, ssize;
|
unsigned int nsize, ssize;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
DEF_MP_INT(rsa_s);
|
DEF_MP_INT(rsa_s);
|
||||||
mp_int *rsa_em = NULL;
|
DEF_MP_INT(rsa_tmp1);
|
||||||
|
DEF_MP_INT(rsa_tmp2);
|
||||||
|
DEF_MP_INT(rsa_tmp3);
|
||||||
|
unsigned char *tmpbuf;
|
||||||
|
|
||||||
TRACE(("enter buf_put_rsa_sign"))
|
TRACE(("enter buf_put_rsa_sign"))
|
||||||
assert(key != NULL);
|
assert(key != NULL);
|
||||||
|
|
||||||
rsa_em = rsa_pad_em(key, data, len);
|
m_mp_init_multi(&rsa_s, &rsa_tmp1, &rsa_tmp2, &rsa_tmp3, NULL);
|
||||||
|
|
||||||
m_mp_init(&rsa_s);
|
rsa_pad_em(key, data, len, &rsa_tmp1);
|
||||||
|
|
||||||
/* the actual signing of the padded data */
|
/* the actual signing of the padded data */
|
||||||
|
|
||||||
|
#ifdef RSA_BLINDING
|
||||||
|
|
||||||
|
/* With blinding, s = (r^(-1))((em)*r^e)^d mod n */
|
||||||
|
|
||||||
|
/* generate the r blinding value */
|
||||||
|
/* rsa_tmp2 is r */
|
||||||
|
gen_random_mpint(key->n, &rsa_tmp2);
|
||||||
|
|
||||||
|
/* rsa_tmp1 is em */
|
||||||
|
/* em' = em * r^e mod n */
|
||||||
|
|
||||||
|
mp_exptmod(&rsa_tmp2, key->e, key->n, &rsa_s); /* rsa_s used as a temp var*/
|
||||||
|
mp_invmod(&rsa_tmp2, key->n, &rsa_tmp3);
|
||||||
|
mp_mulmod(&rsa_tmp1, &rsa_s, key->n, &rsa_tmp2);
|
||||||
|
|
||||||
|
/* rsa_tmp2 is em' */
|
||||||
|
/* s' = (em')^d mod n */
|
||||||
|
mp_exptmod(&rsa_tmp2, key->d, key->n, &rsa_tmp1);
|
||||||
|
|
||||||
|
/* rsa_tmp1 is s' */
|
||||||
|
/* rsa_tmp3 is r^(-1) mod n */
|
||||||
|
/* s = (s')r^(-1) mod n */
|
||||||
|
mp_mulmod(&rsa_tmp1, &rsa_tmp3, key->n, &rsa_s);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
/* s = em^d mod n */
|
/* s = em^d mod n */
|
||||||
if (mp_exptmod(rsa_em, key->d, key->n, &rsa_s) != MP_OKAY) {
|
/* rsa_tmp1 is em */
|
||||||
|
if (mp_exptmod(&rsa_tmp1, key->d, key->n, &rsa_s) != MP_OKAY) {
|
||||||
dropbear_exit("rsa error");
|
dropbear_exit("rsa error");
|
||||||
}
|
}
|
||||||
mp_clear(rsa_em);
|
|
||||||
m_free(rsa_em);
|
#endif /* RSA_BLINDING */
|
||||||
|
|
||||||
|
mp_clear_multi(&rsa_tmp1, &rsa_tmp2, &rsa_tmp3, NULL);
|
||||||
|
|
||||||
/* create the signature to return */
|
/* create the signature to return */
|
||||||
buf_putstring(buf, SSH_SIGNKEY_RSA, SSH_SIGNKEY_RSA_LEN);
|
buf_putstring(buf, SSH_SIGNKEY_RSA, SSH_SIGNKEY_RSA_LEN);
|
||||||
@ -302,7 +332,7 @@ void buf_put_rsa_sign(buffer* buf, rsa_key *key, const unsigned char* data,
|
|||||||
mp_clear(&rsa_s);
|
mp_clear(&rsa_s);
|
||||||
|
|
||||||
#if defined(DEBUG_RSA) && defined(DEBUG_TRACE)
|
#if defined(DEBUG_RSA) && defined(DEBUG_TRACE)
|
||||||
printhex(buf->data, buf->len);
|
printhex("RSA sig", buf->data, buf->len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -318,19 +348,22 @@ void buf_put_rsa_sign(buffer* buf, rsa_key *key, const unsigned char* data,
|
|||||||
*
|
*
|
||||||
* prefix is the ASN1 designator prefix,
|
* prefix is the ASN1 designator prefix,
|
||||||
* hex 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14
|
* hex 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14
|
||||||
|
*
|
||||||
|
* rsa_em must be a pointer to an initialised mp_int.
|
||||||
*/
|
*/
|
||||||
static mp_int * rsa_pad_em(rsa_key * key,
|
static void rsa_pad_em(rsa_key * key,
|
||||||
const unsigned char * data, unsigned int len) {
|
const unsigned char * data, unsigned int len,
|
||||||
|
mp_int * rsa_em) {
|
||||||
|
|
||||||
/* ASN1 designator (including the 0x00 preceding) */
|
/* ASN1 designator (including the 0x00 preceding) */
|
||||||
const char rsa_asn1_magic[] =
|
const unsigned char rsa_asn1_magic[] =
|
||||||
{0x00, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b,
|
{0x00, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b,
|
||||||
0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14};
|
0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14};
|
||||||
#define RSA_ASN1_MAGIC_LEN 16
|
const unsigned int RSA_ASN1_MAGIC_LEN = 16;
|
||||||
|
|
||||||
buffer * rsa_EM = NULL;
|
buffer * rsa_EM = NULL;
|
||||||
hash_state hs;
|
hash_state hs;
|
||||||
unsigned int nsize;
|
unsigned int nsize;
|
||||||
mp_int * rsa_em = NULL;
|
|
||||||
|
|
||||||
assert(key != NULL);
|
assert(key != NULL);
|
||||||
assert(data != NULL);
|
assert(data != NULL);
|
||||||
@ -358,16 +391,9 @@ static mp_int * rsa_pad_em(rsa_key * key,
|
|||||||
|
|
||||||
/* Create the mp_int from the encoded bytes */
|
/* Create the mp_int from the encoded bytes */
|
||||||
buf_setpos(rsa_EM, 0);
|
buf_setpos(rsa_EM, 0);
|
||||||
rsa_em = (mp_int*)m_malloc(sizeof(mp_int));
|
bytes_to_mp(rsa_em, buf_getptr(rsa_EM, rsa_EM->size),
|
||||||
m_mp_init(rsa_em);
|
rsa_EM->size);
|
||||||
if (mp_read_unsigned_bin(rsa_em, buf_getptr(rsa_EM, rsa_EM->size),
|
|
||||||
rsa_EM->size) != MP_OKAY) {
|
|
||||||
dropbear_exit("rsa error");
|
|
||||||
}
|
|
||||||
buf_free(rsa_EM);
|
buf_free(rsa_EM);
|
||||||
|
|
||||||
return rsa_em;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* DROPBEAR_RSA */
|
#endif /* DROPBEAR_RSA */
|
||||||
|
@ -95,7 +95,7 @@ typedef struct cli_runopts {
|
|||||||
char *cmd;
|
char *cmd;
|
||||||
int wantpty;
|
int wantpty;
|
||||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||||
struct PubkeyList *pubkeys; /* Keys to use for public-key auth */
|
struct SignKeyList *privkeys; /* Keys to use for public-key auth */
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_CLI_REMOTETCPFWD
|
#ifdef ENABLE_CLI_REMOTETCPFWD
|
||||||
struct TCPFwdList * remotefwds;
|
struct TCPFwdList * remotefwds;
|
||||||
|
3
scp.c
3
scp.c
@ -244,9 +244,6 @@ main(int argc, char **argv)
|
|||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
extern int optind;
|
extern int optind;
|
||||||
|
|
||||||
/* hack, seems to work */
|
|
||||||
// __progname = argv[0];
|
|
||||||
|
|
||||||
args.list = NULL;
|
args.list = NULL;
|
||||||
addargs(&args, "ssh"); /* overwritten with ssh_program */
|
addargs(&args, "ssh"); /* overwritten with ssh_program */
|
||||||
addargs(&args, "-x");
|
addargs(&args, "-x");
|
||||||
|
@ -211,19 +211,22 @@ struct clientsession {
|
|||||||
mp_int *dh_e, *dh_x; /* Used during KEX */
|
mp_int *dh_e, *dh_x; /* Used during KEX */
|
||||||
cli_kex_state kex_state; /* Used for progressing KEX */
|
cli_kex_state kex_state; /* Used for progressing KEX */
|
||||||
cli_state state; /* Used to progress auth/channelsession etc */
|
cli_state state; /* Used to progress auth/channelsession etc */
|
||||||
int something; /* XXX */
|
|
||||||
unsigned donefirstkex : 1; /* Set when we set sentnewkeys, never reset */
|
unsigned donefirstkex : 1; /* Set when we set sentnewkeys, never reset */
|
||||||
|
|
||||||
int tty_raw_mode; /* Whether we're in raw mode (and have to clean up) */
|
int tty_raw_mode; /* Whether we're in raw mode (and have to clean up) */
|
||||||
struct termios saved_tio;
|
struct termios saved_tio;
|
||||||
int stdincopy;
|
int stdincopy;
|
||||||
int stdinflags;
|
int stdinflags;
|
||||||
|
int stdoutcopy;
|
||||||
|
int stdoutflags;
|
||||||
|
int stderrcopy;
|
||||||
|
int stderrflags;
|
||||||
|
|
||||||
int winchange; /* Set to 1 when a windowchange signal happens */
|
int winchange; /* Set to 1 when a windowchange signal happens */
|
||||||
|
|
||||||
int lastauthtype; /* either AUTH_TYPE_PUBKEY or AUTH_TYPE_PASSWORD,
|
int lastauthtype; /* either AUTH_TYPE_PUBKEY or AUTH_TYPE_PASSWORD,
|
||||||
for the last type of auth we tried */
|
for the last type of auth we tried */
|
||||||
struct PubkeyList *lastpubkey;
|
struct SignKeyList *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
|
||||||
|
22
signkey.c
22
signkey.c
@ -279,7 +279,7 @@ static char * sign_key_md5_fingerprint(unsigned char* keyblob,
|
|||||||
char * ret;
|
char * ret;
|
||||||
hash_state hs;
|
hash_state hs;
|
||||||
unsigned char hash[MD5_HASH_SIZE];
|
unsigned char hash[MD5_HASH_SIZE];
|
||||||
unsigned int h, i;
|
unsigned int i;
|
||||||
unsigned int buflen;
|
unsigned int buflen;
|
||||||
|
|
||||||
md5_init(&hs);
|
md5_init(&hs);
|
||||||
@ -296,10 +296,11 @@ static char * sign_key_md5_fingerprint(unsigned char* keyblob,
|
|||||||
memset(ret, 'Z', buflen);
|
memset(ret, 'Z', buflen);
|
||||||
strcpy(ret, "md5 ");
|
strcpy(ret, "md5 ");
|
||||||
|
|
||||||
for (i = 4, h = 0; i < buflen; i+=3, h++) {
|
for (i = 0; i < MD5_HASH_SIZE; i++) {
|
||||||
ret[i] = hexdig(hash[h] >> 4);
|
unsigned int pos = 4 + i*3;
|
||||||
ret[i+1] = hexdig(hash[h] & 0x0f);
|
ret[pos] = hexdig(hash[i] >> 4);
|
||||||
ret[i+2] = ':';
|
ret[pos+1] = hexdig(hash[i] & 0x0f);
|
||||||
|
ret[pos+2] = ':';
|
||||||
}
|
}
|
||||||
ret[buflen-1] = 0x0;
|
ret[buflen-1] = 0x0;
|
||||||
|
|
||||||
@ -313,7 +314,7 @@ static char * sign_key_sha1_fingerprint(unsigned char* keyblob,
|
|||||||
char * ret;
|
char * ret;
|
||||||
hash_state hs;
|
hash_state hs;
|
||||||
unsigned char hash[SHA1_HASH_SIZE];
|
unsigned char hash[SHA1_HASH_SIZE];
|
||||||
unsigned int h, i;
|
unsigned int i;
|
||||||
unsigned int buflen;
|
unsigned int buflen;
|
||||||
|
|
||||||
sha1_init(&hs);
|
sha1_init(&hs);
|
||||||
@ -329,10 +330,11 @@ static char * sign_key_sha1_fingerprint(unsigned char* keyblob,
|
|||||||
|
|
||||||
strcpy(ret, "sha1 ");
|
strcpy(ret, "sha1 ");
|
||||||
|
|
||||||
for (i = 5, h = 0; i < buflen; i+=3, h++) {
|
for (i = 0; i < SHA1_HASH_SIZE; i++) {
|
||||||
ret[i] = hexdig(hash[h] >> 4);
|
unsigned int pos = 5 + 3*i;
|
||||||
ret[i+1] = hexdig(hash[h] & 0x0f);
|
ret[pos] = hexdig(hash[i] >> 4);
|
||||||
ret[i+2] = ':';
|
ret[pos+1] = hexdig(hash[i] & 0x0f);
|
||||||
|
ret[pos+2] = ':';
|
||||||
}
|
}
|
||||||
ret[buflen-1] = 0x0;
|
ret[buflen-1] = 0x0;
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ void svr_auth_pam() {
|
|||||||
unsigned char changepw;
|
unsigned char changepw;
|
||||||
|
|
||||||
/* check if client wants to change password */
|
/* check if client wants to change password */
|
||||||
changepw = buf_getbyte(ses.payload);
|
changepw = buf_getbool(ses.payload);
|
||||||
if (changepw) {
|
if (changepw) {
|
||||||
/* not implemented by this server */
|
/* not implemented by this server */
|
||||||
send_msg_userauth_failure(0, 1);
|
send_msg_userauth_failure(0, 1);
|
||||||
|
@ -71,7 +71,7 @@ void svr_auth_password() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check if client wants to change password */
|
/* check if client wants to change password */
|
||||||
changepw = buf_getbyte(ses.payload);
|
changepw = buf_getbool(ses.payload);
|
||||||
if (changepw) {
|
if (changepw) {
|
||||||
/* not implemented by this server */
|
/* not implemented by this server */
|
||||||
send_msg_userauth_failure(0, 1);
|
send_msg_userauth_failure(0, 1);
|
||||||
|
@ -64,7 +64,7 @@ void svr_auth_pubkey() {
|
|||||||
|
|
||||||
/* 0 indicates user just wants to check if key can be used, 1 is an
|
/* 0 indicates user just wants to check if key can be used, 1 is an
|
||||||
* actual attempt*/
|
* actual attempt*/
|
||||||
testkey = (buf_getbyte(ses.payload) == 0);
|
testkey = (buf_getbool(ses.payload) == 0);
|
||||||
|
|
||||||
algo = buf_getstring(ses.payload, &algolen);
|
algo = buf_getstring(ses.payload, &algolen);
|
||||||
keybloblen = buf_getint(ses.payload);
|
keybloblen = buf_getint(ses.payload);
|
||||||
|
@ -305,7 +305,7 @@ static void chansessionrequest(struct Channel *channel) {
|
|||||||
TRACE(("enter chansessionrequest"))
|
TRACE(("enter chansessionrequest"))
|
||||||
|
|
||||||
type = buf_getstring(ses.payload, &typelen);
|
type = buf_getstring(ses.payload, &typelen);
|
||||||
wantreply = buf_getbyte(ses.payload);
|
wantreply = buf_getbool(ses.payload);
|
||||||
|
|
||||||
if (typelen > MAX_NAME_LEN) {
|
if (typelen > MAX_NAME_LEN) {
|
||||||
TRACE(("leave chansessionrequest: type too long")) /* XXX send error?*/
|
TRACE(("leave chansessionrequest: type too long")) /* XXX send error?*/
|
||||||
@ -837,7 +837,7 @@ static void execchild(struct ChanSess *chansess) {
|
|||||||
|
|
||||||
/* close file descriptors except stdin/stdout/stderr
|
/* close file descriptors except stdin/stdout/stderr
|
||||||
* Need to be sure FDs are closed here to avoid reading files as root */
|
* Need to be sure FDs are closed here to avoid reading files as root */
|
||||||
for (i = 3; i < (unsigned int)ses.maxfd; i++) {
|
for (i = 3; i <= (unsigned int)ses.maxfd; i++) {
|
||||||
if (m_close(i) == DROPBEAR_FAILURE) {
|
if (m_close(i) == DROPBEAR_FAILURE) {
|
||||||
dropbear_exit("Error closing file desc");
|
dropbear_exit("Error closing file desc");
|
||||||
}
|
}
|
||||||
@ -862,8 +862,10 @@ static void execchild(struct ChanSess *chansess) {
|
|||||||
|
|
||||||
if ((setgid(ses.authstate.pw->pw_gid) < 0) ||
|
if ((setgid(ses.authstate.pw->pw_gid) < 0) ||
|
||||||
(initgroups(ses.authstate.pw->pw_name,
|
(initgroups(ses.authstate.pw->pw_name,
|
||||||
ses.authstate.pw->pw_gid) < 0) ||
|
ses.authstate.pw->pw_gid) < 0)) {
|
||||||
(setuid(ses.authstate.pw->pw_uid) < 0)) {
|
dropbear_exit("error changing user group");
|
||||||
|
}
|
||||||
|
if (setuid(ses.authstate.pw->pw_uid) < 0) {
|
||||||
dropbear_exit("error changing user");
|
dropbear_exit("error changing user");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -78,7 +78,7 @@ void recv_msg_global_request_remotetcp() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reqname = buf_getstring(ses.payload, &namelen);
|
reqname = buf_getstring(ses.payload, &namelen);
|
||||||
wantreply = buf_getbyte(ses.payload);
|
wantreply = buf_getbool(ses.payload);
|
||||||
|
|
||||||
if (namelen > MAXNAMLEN) {
|
if (namelen > MAXNAMLEN) {
|
||||||
TRACE(("name len is wrong: %d", namelen))
|
TRACE(("name len is wrong: %d", namelen))
|
||||||
|
@ -52,7 +52,7 @@ int x11req(struct ChanSess * chansess) {
|
|||||||
return DROPBEAR_FAILURE;
|
return DROPBEAR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
chansess->x11singleconn = buf_getbyte(ses.payload);
|
chansess->x11singleconn = buf_getbool(ses.payload);
|
||||||
chansess->x11authprot = buf_getstring(ses.payload, NULL);
|
chansess->x11authprot = buf_getstring(ses.payload, NULL);
|
||||||
chansess->x11authcookie = buf_getstring(ses.payload, NULL);
|
chansess->x11authcookie = buf_getstring(ses.payload, NULL);
|
||||||
chansess->x11screennum = buf_getint(ses.payload);
|
chansess->x11screennum = buf_getint(ses.payload);
|
||||||
|
Loading…
Reference in New Issue
Block a user