Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • Geofferey/dropbear
1 result
Show changes
Loading
@@ -133,8 +133,8 @@ Can be used to give options in the format used by OpenSSH config file. This is
Loading
@@ -133,8 +133,8 @@ Can be used to give options in the format used by OpenSSH config file. This is
useful for specifying options for which there is no separate command-line flag. useful for specifying options for which there is no separate command-line flag.
For full details of the options listed below, and their possible values, see For full details of the options listed below, and their possible values, see
ssh_config(5). ssh_config(5).
The following options have currently been implemented:
   
For now following options have been implemented:
.RS .RS
.TP .TP
.B ExitOnForwardFailure .B ExitOnForwardFailure
Loading
@@ -147,6 +147,10 @@ Send dbclient log messages to syslog in addition to stderr.
Loading
@@ -147,6 +147,10 @@ Send dbclient log messages to syslog in addition to stderr.
.B \-s .B \-s
The specified command will be requested as a subsystem, used for sftp. Dropbear doesn't implement sftp itself but the OpenSSH sftp client can be used eg \fIsftp -S dbclient user@host\fR The specified command will be requested as a subsystem, used for sftp. Dropbear doesn't implement sftp itself but the OpenSSH sftp client can be used eg \fIsftp -S dbclient user@host\fR
.TP .TP
.B \-b \fI[address][:port]
Bind to a specific local address when connecting to the remote host. This can be used to choose from
multiple outgoing interfaces. Either address or port (or both) can be given.
.TP
.B \-V .B \-V
Print the version Print the version
   
Loading
Loading
Loading
@@ -141,7 +141,7 @@ out:
Loading
@@ -141,7 +141,7 @@ out:
return ret; return ret;
} }
   
void addrandom(unsigned char * buf, unsigned int len) void addrandom(const unsigned char * buf, unsigned int len)
{ {
hash_state hs; hash_state hs;
   
Loading
Loading
Loading
@@ -29,7 +29,7 @@
Loading
@@ -29,7 +29,7 @@
   
void seedrandom(void); void seedrandom(void);
void genrandom(unsigned char* buf, unsigned int len); void genrandom(unsigned char* buf, unsigned int len);
void addrandom(unsigned char * buf, unsigned int len); void addrandom(const unsigned char * buf, unsigned int len);
void gen_random_mpint(mp_int *max, mp_int *rand); void gen_random_mpint(mp_int *max, mp_int *rand);
   
#endif /* DROPBEAR_RANDOM_H_ */ #endif /* DROPBEAR_RANDOM_H_ */
Loading
@@ -241,7 +241,7 @@ int connect_unix(const char* path) {
Loading
@@ -241,7 +241,7 @@ int connect_unix(const char* path) {
* it will be run after the child has fork()ed, and is passed exec_data. * it will be run after the child has fork()ed, and is passed exec_data.
* If ret_errfd == NULL then stderr will not be captured. * If ret_errfd == NULL then stderr will not be captured.
* ret_pid can be passed as NULL to discard the pid. */ * ret_pid can be passed as NULL to discard the pid. */
int spawn_command(void(*exec_fn)(void *user_data), void *exec_data, int spawn_command(void(*exec_fn)(const void *user_data), const void *exec_data,
int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) { int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) {
int infds[2]; int infds[2];
int outfds[2]; int outfds[2];
Loading
Loading
Loading
@@ -56,7 +56,7 @@ extern int debug_trace;
Loading
@@ -56,7 +56,7 @@ extern int debug_trace;
   
char * stripcontrol(const char * text); char * stripcontrol(const char * text);
   
int spawn_command(void(*exec_fn)(void *user_data), void *exec_data, int spawn_command(void(*exec_fn)(const void *user_data), const void *exec_data,
int *writefd, int *readfd, int *errfd, pid_t *pid); int *writefd, int *readfd, int *errfd, pid_t *pid);
void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell); void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell);
#ifdef ENABLE_CONNECT_UNIX #ifdef ENABLE_CONNECT_UNIX
Loading
Loading
Loading
@@ -241,7 +241,7 @@ int main(int argc, char ** argv) {
Loading
@@ -241,7 +241,7 @@ int main(int argc, char ** argv) {
} }
   
genbits = signkey_generate_get_bits(keytype, bits); genbits = signkey_generate_get_bits(keytype, bits);
fprintf(stderr, "Generating %d bit %s key, this may take a while...\n", genbits, typetext); fprintf(stderr, "Generating %u bit %s key, this may take a while...\n", genbits, typetext);
if (signkey_generate(keytype, bits, filename, 0) == DROPBEAR_FAILURE) if (signkey_generate(keytype, bits, filename, 0) == DROPBEAR_FAILURE)
{ {
dropbear_exit("Failed to generate key.\n"); dropbear_exit("Failed to generate key.\n");
Loading
Loading
Loading
@@ -127,7 +127,7 @@ void dss_key_free(dropbear_dss_key *key) {
Loading
@@ -127,7 +127,7 @@ void dss_key_free(dropbear_dss_key *key) {
* mpint g * mpint g
* mpint y * mpint y
*/ */
void buf_put_dss_pub_key(buffer* buf, dropbear_dss_key *key) { void buf_put_dss_pub_key(buffer* buf, const dropbear_dss_key *key) {
   
dropbear_assert(key != NULL); dropbear_assert(key != NULL);
buf_putstring(buf, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN); buf_putstring(buf, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN);
Loading
@@ -139,7 +139,7 @@ void buf_put_dss_pub_key(buffer* buf, dropbear_dss_key *key) {
Loading
@@ -139,7 +139,7 @@ void buf_put_dss_pub_key(buffer* buf, dropbear_dss_key *key) {
} }
   
/* Same as buf_put_dss_pub_key, but with the private "x" key appended */ /* Same as buf_put_dss_pub_key, but with the private "x" key appended */
void buf_put_dss_priv_key(buffer* buf, dropbear_dss_key *key) { void buf_put_dss_priv_key(buffer* buf, const dropbear_dss_key *key) {
   
dropbear_assert(key != NULL); dropbear_assert(key != NULL);
buf_put_dss_pub_key(buf, key); buf_put_dss_pub_key(buf, key);
Loading
@@ -150,7 +150,7 @@ void buf_put_dss_priv_key(buffer* buf, dropbear_dss_key *key) {
Loading
@@ -150,7 +150,7 @@ void buf_put_dss_priv_key(buffer* buf, dropbear_dss_key *key) {
#if DROPBEAR_SIGNKEY_VERIFY #if DROPBEAR_SIGNKEY_VERIFY
/* Verify a DSS signature (in buf) made on data by the key given. /* Verify a DSS signature (in buf) made on data by the key given.
* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ * returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
int buf_dss_verify(buffer* buf, dropbear_dss_key *key, buffer *data_buf) { int buf_dss_verify(buffer* buf, const dropbear_dss_key *key, const buffer *data_buf) {
unsigned char msghash[SHA1_HASH_SIZE]; unsigned char msghash[SHA1_HASH_SIZE];
hash_state hs; hash_state hs;
int ret = DROPBEAR_FAILURE; int ret = DROPBEAR_FAILURE;
Loading
@@ -255,7 +255,7 @@ out:
Loading
@@ -255,7 +255,7 @@ out:
   
/* 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 */
void buf_put_dss_sign(buffer* buf, dropbear_dss_key *key, buffer *data_buf) { void buf_put_dss_sign(buffer* buf, const dropbear_dss_key *key, const buffer *data_buf) {
unsigned char msghash[SHA1_HASH_SIZE]; unsigned char msghash[SHA1_HASH_SIZE];
unsigned int writelen; unsigned int writelen;
unsigned int i; unsigned int i;
Loading
Loading
Loading
@@ -44,14 +44,14 @@ typedef struct {
Loading
@@ -44,14 +44,14 @@ typedef struct {
#define DSS_P_BITS 1024 #define DSS_P_BITS 1024
#define DSS_Q_BITS 160 #define DSS_Q_BITS 160
   
void buf_put_dss_sign(buffer* buf, dropbear_dss_key *key, buffer *data_buf); void buf_put_dss_sign(buffer* buf, const dropbear_dss_key *key, const buffer *data_buf);
#if DROPBEAR_SIGNKEY_VERIFY #if DROPBEAR_SIGNKEY_VERIFY
int buf_dss_verify(buffer* buf, dropbear_dss_key *key, buffer *data_buf); int buf_dss_verify(buffer* buf, const dropbear_dss_key *key, const buffer *data_buf);
#endif #endif
int buf_get_dss_pub_key(buffer* buf, dropbear_dss_key *key); int buf_get_dss_pub_key(buffer* buf, dropbear_dss_key *key);
int buf_get_dss_priv_key(buffer* buf, dropbear_dss_key *key); int buf_get_dss_priv_key(buffer* buf, dropbear_dss_key *key);
void buf_put_dss_pub_key(buffer* buf, dropbear_dss_key *key); void buf_put_dss_pub_key(buffer* buf, const dropbear_dss_key *key);
void buf_put_dss_priv_key(buffer* buf, dropbear_dss_key *key); void buf_put_dss_priv_key(buffer* buf, const dropbear_dss_key *key);
void dss_key_free(dropbear_dss_key *key); void dss_key_free(dropbear_dss_key *key);
   
#endif /* DROPBEAR_DSS */ #endif /* DROPBEAR_DSS */
Loading
Loading
Loading
@@ -82,7 +82,7 @@ ecc_key * new_ecc_key(void) {
Loading
@@ -82,7 +82,7 @@ ecc_key * new_ecc_key(void) {
   
/* Copied from libtomcrypt ecc_import.c (version there is static), modified /* Copied from libtomcrypt ecc_import.c (version there is static), modified
for different mp_int pointer without LTC_SOURCE */ for different mp_int pointer without LTC_SOURCE */
static int ecc_is_point(ecc_key *key) static int ecc_is_point(const ecc_key *key)
{ {
mp_int *prime, *b, *t1, *t2; mp_int *prime, *b, *t1, *t2;
int err; int err;
Loading
@@ -213,7 +213,7 @@ ecc_key * buf_get_ecc_raw_pubkey(buffer *buf, const struct dropbear_ecc_curve *c
Loading
@@ -213,7 +213,7 @@ ecc_key * buf_get_ecc_raw_pubkey(buffer *buf, const struct dropbear_ecc_curve *c
   
/* a modified version of libtomcrypt's "ecc_shared_secret" to output /* a modified version of libtomcrypt's "ecc_shared_secret" to output
a mp_int instead. */ a mp_int instead. */
mp_int * dropbear_ecc_shared_secret(ecc_key *public_key, ecc_key *private_key) mp_int * dropbear_ecc_shared_secret(ecc_key *public_key, const ecc_key *private_key)
{ {
ecc_point *result = NULL; ecc_point *result = NULL;
mp_int *prime = NULL, *shared_secret = NULL; mp_int *prime = NULL, *shared_secret = NULL;
Loading
Loading
Loading
@@ -29,7 +29,7 @@ void buf_put_ecc_raw_pubkey_string(buffer *buf, ecc_key *key);
Loading
@@ -29,7 +29,7 @@ void buf_put_ecc_raw_pubkey_string(buffer *buf, ecc_key *key);
ecc_key * buf_get_ecc_raw_pubkey(buffer *buf, const struct dropbear_ecc_curve *curve); ecc_key * buf_get_ecc_raw_pubkey(buffer *buf, const struct dropbear_ecc_curve *curve);
int buf_get_ecc_privkey_string(buffer *buf, ecc_key *key); int buf_get_ecc_privkey_string(buffer *buf, ecc_key *key);
   
mp_int * dropbear_ecc_shared_secret(ecc_key *pub_key, ecc_key *priv_key); mp_int * dropbear_ecc_shared_secret(ecc_key *pub_key, const ecc_key *priv_key);
   
#endif #endif
   
Loading
Loading
Loading
@@ -15,7 +15,7 @@ int signkey_is_ecdsa(enum signkey_type type)
Loading
@@ -15,7 +15,7 @@ int signkey_is_ecdsa(enum signkey_type type)
|| type == DROPBEAR_SIGNKEY_ECDSA_NISTP521; || type == DROPBEAR_SIGNKEY_ECDSA_NISTP521;
} }
   
enum signkey_type ecdsa_signkey_type(ecc_key * key) { enum signkey_type ecdsa_signkey_type(const ecc_key * key) {
#if DROPBEAR_ECC_256 #if DROPBEAR_ECC_256
if (key->dp == ecc_curve_nistp256.dp) { if (key->dp == ecc_curve_nistp256.dp) {
return DROPBEAR_SIGNKEY_ECDSA_NISTP256; return DROPBEAR_SIGNKEY_ECDSA_NISTP256;
Loading
@@ -154,7 +154,7 @@ void buf_put_ecdsa_priv_key(buffer *buf, ecc_key *key) {
Loading
@@ -154,7 +154,7 @@ void buf_put_ecdsa_priv_key(buffer *buf, ecc_key *key) {
buf_putmpint(buf, key->k); buf_putmpint(buf, key->k);
} }
   
void buf_put_ecdsa_sign(buffer *buf, ecc_key *key, buffer *data_buf) { void buf_put_ecdsa_sign(buffer *buf, const ecc_key *key, const buffer *data_buf) {
/* Based on libtomcrypt's ecc_sign_hash but without the asn1 */ /* Based on libtomcrypt's ecc_sign_hash but without the asn1 */
int err = DROPBEAR_FAILURE; int err = DROPBEAR_FAILURE;
struct dropbear_ecc_curve *curve = NULL; struct dropbear_ecc_curve *curve = NULL;
Loading
@@ -272,7 +272,7 @@ out:
Loading
@@ -272,7 +272,7 @@ out:
} }
   
   
int buf_ecdsa_verify(buffer *buf, ecc_key *key, buffer *data_buf) { int buf_ecdsa_verify(buffer *buf, const ecc_key *key, const buffer *data_buf) {
/* Based on libtomcrypt's ecc_verify_hash but without the asn1 */ /* Based on libtomcrypt's ecc_verify_hash but without the asn1 */
int ret = DROPBEAR_FAILURE; int ret = DROPBEAR_FAILURE;
hash_state hs; hash_state hs;
Loading
Loading
Loading
@@ -23,10 +23,10 @@ ecc_key *buf_get_ecdsa_pub_key(buffer* buf);
Loading
@@ -23,10 +23,10 @@ ecc_key *buf_get_ecdsa_pub_key(buffer* buf);
ecc_key *buf_get_ecdsa_priv_key(buffer *buf); ecc_key *buf_get_ecdsa_priv_key(buffer *buf);
void buf_put_ecdsa_pub_key(buffer *buf, ecc_key *key); void buf_put_ecdsa_pub_key(buffer *buf, ecc_key *key);
void buf_put_ecdsa_priv_key(buffer *buf, ecc_key *key); void buf_put_ecdsa_priv_key(buffer *buf, ecc_key *key);
enum signkey_type ecdsa_signkey_type(ecc_key * key); enum signkey_type ecdsa_signkey_type(const ecc_key * key);
   
void buf_put_ecdsa_sign(buffer *buf, ecc_key *key, buffer *data_buf); void buf_put_ecdsa_sign(buffer *buf, const ecc_key *key, const buffer *data_buf);
int buf_ecdsa_verify(buffer *buf, ecc_key *key, buffer *data_buf); int buf_ecdsa_verify(buffer *buf, const ecc_key *key, const buffer *data_buf);
/* Returns 1 on success */ /* Returns 1 on success */
int signkey_is_ecdsa(enum signkey_type type); int signkey_is_ecdsa(enum signkey_type type);
   
Loading
Loading
Loading
@@ -37,11 +37,11 @@
Loading
@@ -37,11 +37,11 @@
   
#if DROPBEAR_DSS #if DROPBEAR_DSS
   
static void getq(dropbear_dss_key *key); static void getq(const dropbear_dss_key *key);
static void getp(dropbear_dss_key *key, unsigned int size); static void getp(const dropbear_dss_key *key, unsigned int size);
static void getg(dropbear_dss_key *key); static void getg(const dropbear_dss_key *key);
static void getx(dropbear_dss_key *key); static void getx(const dropbear_dss_key *key);
static void gety(dropbear_dss_key *key); static void gety(const dropbear_dss_key *key);
   
dropbear_dss_key * gen_dss_priv_key(unsigned int size) { dropbear_dss_key * gen_dss_priv_key(unsigned int size) {
   
Loading
@@ -65,7 +65,7 @@ dropbear_dss_key * gen_dss_priv_key(unsigned int size) {
Loading
@@ -65,7 +65,7 @@ dropbear_dss_key * gen_dss_priv_key(unsigned int size) {
} }
   
static void getq(dropbear_dss_key *key) { static void getq(const dropbear_dss_key *key) {
   
unsigned char buf[QSIZE]; unsigned char buf[QSIZE];
   
Loading
@@ -83,7 +83,7 @@ static void getq(dropbear_dss_key *key) {
Loading
@@ -83,7 +83,7 @@ static void getq(dropbear_dss_key *key) {
} }
} }
   
static void getp(dropbear_dss_key *key, unsigned int size) { static void getp(const dropbear_dss_key *key, unsigned int size) {
   
DEF_MP_INT(tempX); DEF_MP_INT(tempX);
DEF_MP_INT(tempC); DEF_MP_INT(tempC);
Loading
@@ -142,7 +142,7 @@ static void getp(dropbear_dss_key *key, unsigned int size) {
Loading
@@ -142,7 +142,7 @@ static void getp(dropbear_dss_key *key, unsigned int size) {
m_free(buf); m_free(buf);
} }
   
static void getg(dropbear_dss_key * key) { static void getg(const dropbear_dss_key * key) {
   
DEF_MP_INT(div); DEF_MP_INT(div);
DEF_MP_INT(h); DEF_MP_INT(h);
Loading
@@ -179,12 +179,12 @@ static void getg(dropbear_dss_key * key) {
Loading
@@ -179,12 +179,12 @@ static void getg(dropbear_dss_key * key) {
mp_clear_multi(&div, &h, &val, NULL); mp_clear_multi(&div, &h, &val, NULL);
} }
   
static void getx(dropbear_dss_key *key) { static void getx(const dropbear_dss_key *key) {
   
gen_random_mpint(key->q, key->x); gen_random_mpint(key->q, key->x);
} }
   
static void gety(dropbear_dss_key *key) { static void gety(const dropbear_dss_key *key) {
   
if (mp_exptmod(key->g, key->x, key->p, key->y) != MP_OKAY) { if (mp_exptmod(key->g, key->x, key->p, key->y) != MP_OKAY) {
fprintf(stderr, "DSS key generation failed\n"); fprintf(stderr, "DSS key generation failed\n");
Loading
Loading
Loading
@@ -50,7 +50,7 @@ void kexecdh_comb_key(struct kex_ecdh_param *param, buffer *pub_them,
Loading
@@ -50,7 +50,7 @@ void kexecdh_comb_key(struct kex_ecdh_param *param, buffer *pub_them,
#if DROPBEAR_CURVE25519 #if DROPBEAR_CURVE25519
struct kex_curve25519_param *gen_kexcurve25519_param(void); struct kex_curve25519_param *gen_kexcurve25519_param(void);
void free_kexcurve25519_param(struct kex_curve25519_param *param); void free_kexcurve25519_param(struct kex_curve25519_param *param);
void kexcurve25519_comb_key(struct kex_curve25519_param *param, buffer *pub_them, void kexcurve25519_comb_key(const struct kex_curve25519_param *param, const buffer *pub_them,
sign_key *hostkey); sign_key *hostkey);
#endif #endif
   
Loading
Loading
Loading
@@ -55,9 +55,9 @@ static const unsigned char OID_SEC521R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x23};
Loading
@@ -55,9 +55,9 @@ static const unsigned char OID_SEC521R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x23};
((unsigned long)(unsigned char)(cp)[3])) ((unsigned long)(unsigned char)(cp)[3]))
   
static int openssh_encrypted(const char *filename); static int openssh_encrypted(const char *filename);
static sign_key *openssh_read(const char *filename, char *passphrase); static sign_key *openssh_read(const char *filename, const char *passphrase);
static int openssh_write(const char *filename, sign_key *key, static int openssh_write(const char *filename, sign_key *key,
char *passphrase); const char *passphrase);
   
static int dropbear_write(const char*filename, sign_key * key); static int dropbear_write(const char*filename, sign_key * key);
static sign_key *dropbear_read(const char* filename); static sign_key *dropbear_read(const char* filename);
Loading
@@ -83,7 +83,7 @@ int import_encrypted(const char* filename, int filetype) {
Loading
@@ -83,7 +83,7 @@ int import_encrypted(const char* filename, int filetype) {
return 0; return 0;
} }
   
sign_key *import_read(const char *filename, char *passphrase, int filetype) { sign_key *import_read(const char *filename, const char *passphrase, int filetype) {
   
if (filetype == KEYFILE_OPENSSH) { if (filetype == KEYFILE_OPENSSH) {
return openssh_read(filename, passphrase); return openssh_read(filename, passphrase);
Loading
@@ -97,7 +97,7 @@ sign_key *import_read(const char *filename, char *passphrase, int filetype) {
Loading
@@ -97,7 +97,7 @@ sign_key *import_read(const char *filename, char *passphrase, int filetype) {
return NULL; return NULL;
} }
   
int import_write(const char *filename, sign_key *key, char *passphrase, int import_write(const char *filename, sign_key *key, const char *passphrase,
int filetype) { int filetype) {
   
if (filetype == KEYFILE_OPENSSH) { if (filetype == KEYFILE_OPENSSH) {
Loading
@@ -194,7 +194,7 @@ out:
Loading
@@ -194,7 +194,7 @@ out:
) )
   
/* cpl has to be less than 100 */ /* cpl has to be less than 100 */
static void base64_encode_fp(FILE * fp, unsigned char *data, static void base64_encode_fp(FILE * fp, const unsigned char *data,
int datalen, int cpl) int datalen, int cpl)
{ {
unsigned char out[100]; unsigned char out[100];
Loading
@@ -509,7 +509,7 @@ static int openssh_encrypted(const char *filename)
Loading
@@ -509,7 +509,7 @@ static int openssh_encrypted(const char *filename)
return ret; return ret;
} }
   
static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase)) static sign_key *openssh_read(const char *filename, const char * UNUSED(passphrase))
{ {
struct openssh_key *key; struct openssh_key *key;
unsigned char *p; unsigned char *p;
Loading
@@ -828,7 +828,7 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase))
Loading
@@ -828,7 +828,7 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase))
} }
   
static int openssh_write(const char *filename, sign_key *key, static int openssh_write(const char *filename, sign_key *key,
char *passphrase) const char *passphrase)
{ {
buffer * keyblob = NULL; buffer * keyblob = NULL;
buffer * extrablob = NULL; /* used for calculated values to write */ buffer * extrablob = NULL; /* used for calculated values to write */
Loading
Loading
Loading
@@ -34,9 +34,9 @@ enum {
Loading
@@ -34,9 +34,9 @@ enum {
KEYFILE_SSHCOM KEYFILE_SSHCOM
}; };
   
int import_write(const char *filename, sign_key *key, char *passphrase, int import_write(const char *filename, sign_key *key, const char *passphrase,
int filetype); int filetype);
sign_key *import_read(const char *filename, char *passphrase, int filetype); sign_key *import_read(const char *filename, const char *passphrase, int filetype);
int import_encrypted(const char* filename, int filetype); int import_encrypted(const char* filename, int filetype);
   
#endif /* DROPBEAR_KEYIMPORT_H_ */ #endif /* DROPBEAR_KEYIMPORT_H_ */
Loading
@@ -53,7 +53,7 @@ void set_listener_fds(fd_set * readfds) {
Loading
@@ -53,7 +53,7 @@ void set_listener_fds(fd_set * readfds) {
} }
   
   
void handle_listeners(fd_set * readfds) { void handle_listeners(const fd_set * readfds) {
   
unsigned int i, j; unsigned int i, j;
struct Listener *listener; struct Listener *listener;
Loading
@@ -76,10 +76,10 @@ void handle_listeners(fd_set * readfds) {
Loading
@@ -76,10 +76,10 @@ void handle_listeners(fd_set * readfds) {
   
/* acceptor(int fd, void* typedata) is a function to accept connections, /* acceptor(int fd, void* typedata) is a function to accept connections,
* cleanup(void* typedata) happens when cleaning up */ * cleanup(void* typedata) happens when cleaning up */
struct Listener* new_listener(int socks[], unsigned int nsocks, struct Listener* new_listener(const int socks[], unsigned int nsocks,
int type, void* typedata, int type, void* typedata,
void (*acceptor)(struct Listener* listener, int sock), void (*acceptor)(const struct Listener* listener, int sock),
void (*cleanup)(struct Listener*)) { void (*cleanup)(const struct Listener*)) {
   
unsigned int i, j; unsigned int i, j;
struct Listener *newlisten = NULL; struct Listener *newlisten = NULL;
Loading
@@ -132,8 +132,8 @@ struct Listener* new_listener(int socks[], unsigned int nsocks,
Loading
@@ -132,8 +132,8 @@ struct Listener* new_listener(int socks[], unsigned int nsocks,
   
/* Return the first listener which matches the type-specific comparison /* Return the first listener which matches the type-specific comparison
* function. Particularly needed for global requests, like tcp */ * function. Particularly needed for global requests, like tcp */
struct Listener * get_listener(int type, void* typedata, struct Listener * get_listener(int type, const void* typedata,
int (*match)(void*, void*)) { int (*match)(const void*, const void*)) {
   
unsigned int i; unsigned int i;
struct Listener* listener; struct Listener* listener;
Loading
Loading
Loading
@@ -35,8 +35,8 @@ struct Listener {
Loading
@@ -35,8 +35,8 @@ struct Listener {
   
int index; /* index in the array of listeners */ int index; /* index in the array of listeners */
   
void (*acceptor)(struct Listener*, int sock); void (*acceptor)(const struct Listener*, int sock);
void (*cleanup)(struct Listener*); void (*cleanup)(const struct Listener*);
   
int type; /* CHANNEL_ID_X11, CHANNEL_ID_AGENT, int type; /* CHANNEL_ID_X11, CHANNEL_ID_AGENT,
CHANNEL_ID_TCPDIRECT (for clients), CHANNEL_ID_TCPDIRECT (for clients),
Loading
@@ -47,16 +47,16 @@ struct Listener {
Loading
@@ -47,16 +47,16 @@ struct Listener {
}; };
   
void listeners_initialise(void); void listeners_initialise(void);
void handle_listeners(fd_set * readfds); void handle_listeners(const fd_set * readfds);
void set_listener_fds(fd_set * readfds); void set_listener_fds(fd_set * readfds);
   
struct Listener* new_listener(int socks[], unsigned int nsocks, struct Listener* new_listener(const int socks[], unsigned int nsocks,
int type, void* typedata, int type, void* typedata,
void (*acceptor)(struct Listener* listener, int sock), void (*acceptor)(const struct Listener* listener, int sock),
void (*cleanup)(struct Listener*)); void (*cleanup)(const struct Listener*));
   
struct Listener * get_listener(int type, void* typedata, struct Listener * get_listener(int type, const void* typedata,
int (*match)(void*, void*)); int (*match)(const void*, const void*));
   
void remove_listener(struct Listener* listener); void remove_listener(struct Listener* listener);
   
Loading
Loading
Loading
@@ -19,6 +19,7 @@ struct dropbear_progress_connection {
Loading
@@ -19,6 +19,7 @@ struct dropbear_progress_connection {
int sock; int sock;
   
char* errstring; char* errstring;
char *bind_address, *bind_port;
}; };
   
/* Deallocate a progress connection. Removes from the pending list if iter!=NULL. /* Deallocate a progress connection. Removes from the pending list if iter!=NULL.
Loading
@@ -30,6 +31,8 @@ static void remove_connect(struct dropbear_progress_connection *c, m_list_elem *
Loading
@@ -30,6 +31,8 @@ static void remove_connect(struct dropbear_progress_connection *c, m_list_elem *
m_free(c->remotehost); m_free(c->remotehost);
m_free(c->remoteport); m_free(c->remoteport);
m_free(c->errstring); m_free(c->errstring);
m_free(c->bind_address);
m_free(c->bind_port);
m_free(c); m_free(c);
   
if (iter) { if (iter) {
Loading
@@ -51,6 +54,7 @@ void cancel_connect(struct dropbear_progress_connection *c) {
Loading
@@ -51,6 +54,7 @@ void cancel_connect(struct dropbear_progress_connection *c) {
   
static void connect_try_next(struct dropbear_progress_connection *c) { static void connect_try_next(struct dropbear_progress_connection *c) {
struct addrinfo *r; struct addrinfo *r;
int err;
int res = 0; int res = 0;
int fastopen = 0; int fastopen = 0;
#if DROPBEAR_CLIENT_TCP_FAST_OPEN #if DROPBEAR_CLIENT_TCP_FAST_OPEN
Loading
@@ -66,6 +70,44 @@ static void connect_try_next(struct dropbear_progress_connection *c) {
Loading
@@ -66,6 +70,44 @@ static void connect_try_next(struct dropbear_progress_connection *c) {
continue; continue;
} }
   
if (c->bind_address || c->bind_port) {
/* bind to a source port/address */
struct addrinfo hints;
struct addrinfo *bindaddr = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = r->ai_family;
hints.ai_flags = AI_PASSIVE;
err = getaddrinfo(c->bind_address, c->bind_port, &hints, &bindaddr);
if (err) {
int len = 100 + strlen(gai_strerror(err));
m_free(c->errstring);
c->errstring = (char*)m_malloc(len);
snprintf(c->errstring, len, "Error resolving bind address '%s' (port %s). %s",
c->bind_address, c->bind_port, gai_strerror(err));
TRACE(("Error resolving bind: %s", gai_strerror(err)))
close(c->sock);
c->sock = -1;
continue;
}
res = bind(c->sock, bindaddr->ai_addr, bindaddr->ai_addrlen);
freeaddrinfo(bindaddr);
bindaddr = NULL;
if (res < 0) {
/* failure */
int keep_errno = errno;
int len = 300;
m_free(c->errstring);
c->errstring = m_malloc(len);
snprintf(c->errstring, len, "Error binding local address '%s' (port %s). %s",
c->bind_address, c->bind_port, strerror(keep_errno));
close(c->sock);
c->sock = -1;
continue;
}
}
ses.maxfd = MAX(ses.maxfd, c->sock); ses.maxfd = MAX(ses.maxfd, c->sock);
set_sock_nodelay(c->sock); set_sock_nodelay(c->sock);
setnonblocking(c->sock); setnonblocking(c->sock);
Loading
@@ -130,7 +172,8 @@ static void connect_try_next(struct dropbear_progress_connection *c) {
Loading
@@ -130,7 +172,8 @@ static void connect_try_next(struct dropbear_progress_connection *c) {
   
/* Connect via TCP to a host. */ /* Connect via TCP to a host. */
struct dropbear_progress_connection *connect_remote(const char* remotehost, const char* remoteport, struct dropbear_progress_connection *connect_remote(const char* remotehost, const char* remoteport,
connect_callback cb, void* cb_data) connect_callback cb, void* cb_data,
const char* bind_address, const char* bind_port)
{ {
struct dropbear_progress_connection *c = NULL; struct dropbear_progress_connection *c = NULL;
int err; int err;
Loading
@@ -160,6 +203,13 @@ struct dropbear_progress_connection *connect_remote(const char* remotehost, cons
Loading
@@ -160,6 +203,13 @@ struct dropbear_progress_connection *connect_remote(const char* remotehost, cons
} else { } else {
c->res_iter = c->res; c->res_iter = c->res;
} }
if (bind_address) {
c->bind_address = m_strdup(bind_address);
}
if (bind_port) {
c->bind_port = m_strdup(bind_port);
}
   
return c; return c;
} }
Loading
@@ -197,7 +247,7 @@ void set_connect_fds(fd_set *writefd) {
Loading
@@ -197,7 +247,7 @@ void set_connect_fds(fd_set *writefd) {
} }
} }
   
void handle_connect_fds(fd_set *writefd) { void handle_connect_fds(const fd_set *writefd) {
m_list_elem *iter; m_list_elem *iter;
TRACE(("enter handle_connect_fds")) TRACE(("enter handle_connect_fds"))
for (iter = ses.conn_pending.first; iter; iter = iter->next) { for (iter = ses.conn_pending.first; iter; iter = iter->next) {
Loading
@@ -240,7 +290,7 @@ void connect_set_writequeue(struct dropbear_progress_connection *c, struct Queue
Loading
@@ -240,7 +290,7 @@ void connect_set_writequeue(struct dropbear_progress_connection *c, struct Queue
c->writequeue = writequeue; c->writequeue = writequeue;
} }
   
void packet_queue_to_iovec(struct Queue *queue, struct iovec *iov, unsigned int *iov_count) { void packet_queue_to_iovec(const struct Queue *queue, struct iovec *iov, unsigned int *iov_count) {
struct Link *l; struct Link *l;
unsigned int i; unsigned int i;
int len; int len;
Loading
@@ -348,6 +398,37 @@ void set_sock_priority(int sock, enum dropbear_prio prio) {
Loading
@@ -348,6 +398,37 @@ void set_sock_priority(int sock, enum dropbear_prio prio) {
   
} }
   
/* from openssh/canohost.c avoid premature-optimization */
int get_sock_port(int sock) {
struct sockaddr_storage from;
socklen_t fromlen;
char strport[NI_MAXSERV];
int r;
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) {
TRACE(("getsockname failed: %d", errno))
return 0;
}
/* Work around Linux IPv6 weirdness */
if (from.ss_family == AF_INET6)
fromlen = sizeof(struct sockaddr_in6);
/* Non-inet sockets don't have a port number. */
if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
return 0;
/* Return port number. */
if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
strport, sizeof(strport), NI_NUMERICSERV)) != 0) {
TRACE(("netio.c/get_sock_port/getnameinfo NI_NUMERICSERV failed: %d", r))
}
return atoi(strport);
}
/* Listen on address:port. /* Listen on address:port.
* Special cases are address of "" listening on everything, * Special cases are address of "" listening on everything,
* and address of NULL listening on localhost only. * and address of NULL listening on localhost only.
Loading
@@ -400,11 +481,29 @@ int dropbear_listen(const char* address, const char* port,
Loading
@@ -400,11 +481,29 @@ int dropbear_listen(const char* address, const char* port,
return -1; return -1;
} }
   
/*
* when listening on server-assigned-port 0
* the assigned ports may differ for address families (v4/v6)
* causing problems for tcpip-forward
* caller can do a get_socket_address to discover assigned-port
* hence, use same port for all address families
*/
u_int16_t *allocated_lport_p = 0;
int allocated_lport = 0;
   
nsock = 0; nsock = 0;
for (res = res0; res != NULL && nsock < sockcount; for (res = res0; res != NULL && nsock < sockcount;
res = res->ai_next) { res = res->ai_next) {
   
if (allocated_lport > 0) {
if (AF_INET == res->ai_family) {
allocated_lport_p = &((struct sockaddr_in *)res->ai_addr)->sin_port;
} else if (AF_INET6 == res->ai_family) {
allocated_lport_p = &((struct sockaddr_in6 *)res->ai_addr)->sin6_port;
}
*allocated_lport_p = htons(allocated_lport);
}
/* Get a socket */ /* Get a socket */
socks[nsock] = socket(res->ai_family, res->ai_socktype, socks[nsock] = socket(res->ai_family, res->ai_socktype,
res->ai_protocol); res->ai_protocol);
Loading
@@ -451,6 +550,10 @@ int dropbear_listen(const char* address, const char* port,
Loading
@@ -451,6 +550,10 @@ int dropbear_listen(const char* address, const char* port,
continue; continue;
} }
   
if (0 == allocated_lport) {
allocated_lport = get_sock_port(sock);
}
*maxfd = MAX(*maxfd, sock); *maxfd = MAX(*maxfd, sock);
   
nsock++; nsock++;
Loading
Loading
Loading
@@ -14,6 +14,7 @@ enum dropbear_prio {
Loading
@@ -14,6 +14,7 @@ enum dropbear_prio {
void set_sock_nodelay(int sock); void set_sock_nodelay(int sock);
void set_sock_priority(int sock, enum dropbear_prio prio); void set_sock_priority(int sock, enum dropbear_prio prio);
   
int get_sock_port(int sock);
void get_socket_address(int fd, char **local_host, char **local_port, void get_socket_address(int fd, char **local_host, char **local_port,
char **remote_host, char **remote_port, int host_lookup); char **remote_host, char **remote_port, int host_lookup);
void getaddrstring(struct sockaddr_storage* addr, void getaddrstring(struct sockaddr_storage* addr,
Loading
@@ -29,12 +30,12 @@ typedef void(*connect_callback)(int result, int sock, void* data, const char* er
Loading
@@ -29,12 +30,12 @@ typedef void(*connect_callback)(int result, int sock, void* data, const char* er
   
/* Always returns a progress connection, if it fails it will call the callback at a later point */ /* Always returns a progress connection, if it fails it will call the callback at a later point */
struct dropbear_progress_connection * connect_remote (const char* remotehost, const char* remoteport, struct dropbear_progress_connection * connect_remote (const char* remotehost, const char* remoteport,
connect_callback cb, void *cb_data); connect_callback cb, void *cb_data, const char* bind_address, const char* bind_port);
   
/* Sets up for select() */ /* Sets up for select() */
void set_connect_fds(fd_set *writefd); void set_connect_fds(fd_set *writefd);
/* Handles ready sockets after select() */ /* Handles ready sockets after select() */
void handle_connect_fds(fd_set *writefd); void handle_connect_fds(const fd_set *writefd);
/* Cleanup */ /* Cleanup */
void remove_connect_pending(void); void remove_connect_pending(void);
   
Loading
@@ -45,7 +46,7 @@ void connect_set_writequeue(struct dropbear_progress_connection *c, struct Queue
Loading
@@ -45,7 +46,7 @@ void connect_set_writequeue(struct dropbear_progress_connection *c, struct Queue
   
/* TODO: writev #ifdef guard */ /* TODO: writev #ifdef guard */
/* Fills out iov which contains iov_count slots, returning the number filled in iov_count */ /* Fills out iov which contains iov_count slots, returning the number filled in iov_count */
void packet_queue_to_iovec(struct Queue *queue, struct iovec *iov, unsigned int *iov_count); void packet_queue_to_iovec(const struct Queue *queue, struct iovec *iov, unsigned int *iov_count);
void packet_queue_consume(struct Queue *queue, ssize_t written); void packet_queue_consume(struct Queue *queue, ssize_t written);
   
#if DROPBEAR_SERVER_TCP_FAST_OPEN #if DROPBEAR_SERVER_TCP_FAST_OPEN
Loading
Loading