summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2013-11-07 23:49:37 +0800
committerMatt Johnston <matt@ucc.asn.au>2013-11-07 23:49:37 +0800
commitbe46b9e5feb342d5a10ee0e7609d7d1efc7e10b9 (patch)
treedb2e0d79d3d769a27bd08c3ee6a7fed7fb8a11d4
parentb71276cdc382a5d43ad433e202eab18900f1c9e8 (diff)
downloaddropbear-keyondemand.tar.gz
Add '-R' for delayed hostkey optionkeyondemand
-rw-r--r--cli-kex.c19
-rw-r--r--dropbearkey.c3
-rw-r--r--gensignkey.c1
-rw-r--r--keyimport.c18
-rw-r--r--options.h19
-rw-r--r--runopts.h2
-rw-r--r--signkey.c6
-rw-r--r--svr-kex.c13
-rw-r--r--svr-runopts.c54
-rw-r--r--sysoptions.h7
10 files changed, 104 insertions, 38 deletions
diff --git a/cli-kex.c b/cli-kex.c
index 0cc730c..2677b0e 100644
--- a/cli-kex.c
+++ b/cli-kex.c
@@ -147,7 +147,8 @@ void recv_msg_kexdh_reply() {
TRACE(("leave recv_msg_kexdh_init"))
}
-static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen) {
+static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen,
+ const char* algoname) {
char* fp = NULL;
FILE *tty = NULL;
@@ -155,14 +156,16 @@ static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen) {
fp = sign_key_fingerprint(keyblob, keybloblen);
if (cli_opts.always_accept_key) {
- fprintf(stderr, "\nHost '%s' key accepted unconditionally.\n(fingerprint %s)\n",
+ fprintf(stderr, "\nHost '%s' key accepted unconditionally.\n(%s fingerprint %s)\n",
cli_opts.remotehost,
+ algoname,
fp);
m_free(fp);
return;
}
- fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(fingerprint %s)\nDo you want to continue connecting? (y/n) ",
+ fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(%s fingerprint %s)\nDo you want to continue connecting? (y/n) ",
cli_opts.remotehost,
+ algoname,
fp);
m_free(fp);
@@ -257,16 +260,17 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
return;
}
+ algoname = signkey_name_from_type(ses.newkeys->algo_hostkey, &algolen);
+
hostsfile = open_known_hosts_file(&readonly);
if (!hostsfile) {
- ask_to_confirm(keyblob, keybloblen);
+ ask_to_confirm(keyblob, keybloblen, algoname);
/* ask_to_confirm will exit upon failure */
return;
}
line = buf_new(MAX_KNOWNHOSTS_LINE);
hostlen = strlen(cli_opts.remotehost);
- algoname = signkey_name_from_type(ses.newkeys->algo_hostkey, &algolen);
do {
if (buf_getline(line, hostsfile) == DROPBEAR_FAILURE) {
@@ -319,17 +323,18 @@ static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) {
/* The keys didn't match. eep. Note that we're "leaking"
the fingerprint strings here, but we're exiting anyway */
- dropbear_exit("\n\nHost key mismatch for %s !\n"
+ dropbear_exit("\n\n%s host key mismatch for %s !\n"
"Fingerprint is %s\n"
"Expected %s\n"
"If you know that the host key is correct you can\nremove the bad entry from ~/.ssh/known_hosts",
+ algoname,
cli_opts.remotehost,
sign_key_fingerprint(keyblob, keybloblen),
fingerprint ? fingerprint : "UNKNOWN");
} while (1); /* keep going 'til something happens */
/* Key doesn't exist yet */
- ask_to_confirm(keyblob, keybloblen);
+ ask_to_confirm(keyblob, keybloblen, algoname);
/* If we get here, they said yes */
diff --git a/dropbearkey.c b/dropbearkey.c
index 9e696b7..01385a1 100644
--- a/dropbearkey.c
+++ b/dropbearkey.c
@@ -54,6 +54,7 @@
#include "ecdsa.h"
#include "crypto_desc.h"
#include "random.h"
+#include "gensignkey.h"
static void printhelp(char * progname);
@@ -133,8 +134,6 @@ int main(int argc, char ** argv) {
int i;
char ** next = 0;
- sign_key *key = NULL;
- buffer *buf = NULL;
char * filename = NULL;
enum signkey_type keytype = DROPBEAR_SIGNKEY_NONE;
char * typetext = NULL;
diff --git a/gensignkey.c b/gensignkey.c
index 10890f4..5726249 100644
--- a/gensignkey.c
+++ b/gensignkey.c
@@ -72,7 +72,6 @@ static int get_default_bits(enum signkey_type keytype)
}
}
-
int signkey_generate(enum signkey_type keytype, int bits, const char* filename)
{
sign_key * key = NULL;
diff --git a/keyimport.c b/keyimport.c
index 7595c1d..7098ae7 100644
--- a/keyimport.c
+++ b/keyimport.c
@@ -709,19 +709,29 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase))
goto error;
}
- if (len == sizeof(OID_SEC256R1_BLOB)
+ if (0) {}
+#ifdef DROPBEAR_ECC_256
+ else if (len == sizeof(OID_SEC256R1_BLOB)
&& memcmp(p, OID_SEC256R1_BLOB, len) == 0) {
retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP256;
curve = &ecc_curve_nistp256;
- } else if (len == sizeof(OID_SEC384R1_BLOB)
+ }
+#endif
+#ifdef DROPBEAR_ECC_384
+ else if (len == sizeof(OID_SEC384R1_BLOB)
&& memcmp(p, OID_SEC384R1_BLOB, len) == 0) {
retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP384;
curve = &ecc_curve_nistp384;
- } else if (len == sizeof(OID_SEC521R1_BLOB)
+ }
+#endif
+#ifdef DROPBEAR_ECC_521
+ else if (len == sizeof(OID_SEC521R1_BLOB)
&& memcmp(p, OID_SEC521R1_BLOB, len) == 0) {
retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP521;
curve = &ecc_curve_nistp521;
- } else {
+ }
+#endif
+ else {
errmsg = "Unknown ECC key type";
goto error;
}
diff --git a/options.h b/options.h
index c5bc7fe..d345601 100644
--- a/options.h
+++ b/options.h
@@ -8,7 +8,7 @@
/* Define compile-time options below - the "#ifndef DROPBEAR_XXX .... #endif"
* parts are to allow for commandline -DDROPBEAR_XXX options etc. */
-/* Important: Many options will require "make clean" after changes */
+/* IMPORTANT: Many options will require "make clean" after changes */
#ifndef DROPBEAR_DEFPORT
#define DROPBEAR_DEFPORT "22"
@@ -129,7 +129,7 @@ much traffic. */
/* You can also disable integrity. Don't bother disabling this if you're
* still using a cipher, it's relatively cheap. If you disable this it's dead
- * simple to run arbitrary commands on the remote host. Beware. */
+ * simple for an attacker to run arbitrary commands on the remote host. Beware. */
/* #define DROPBEAR_NONE_INTEGRITY */
/* Hostkey/public key algorithms - at least one required, these are used
@@ -138,15 +138,22 @@ much traffic. */
* SSH2 RFC Draft requires dss, recommends rsa */
#define DROPBEAR_RSA
#define DROPBEAR_DSS
-
-#define DROPBEAR_ECDH
#define DROPBEAR_ECDSA
+/* Generate hostkeys as-needed when the first connection using that key type occurs.
+ This avoids the need to otherwise run "dropbearkey" and avoids some problems
+ with badly seeded random devices when systems first boot.
+ This also requires a runtime flag "-R". */
+#define DROPBEAR_DELAY_HOSTKEY
+
/* 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
+/* Enable elliptic curve Diffie Hellman key exchange */
+#define DROPBEAR_ECDH
+
/* Control the memory/performance/compression tradeoff for zlib.
* Set windowBits=8 for least memory usage, see your system's
* zlib.h for full details.
@@ -180,9 +187,9 @@ much traffic. */
* PAM challenge/response.
* You can't enable both PASSWORD and PAM. */
-//#define ENABLE_SVR_PASSWORD_AUTH
+#define ENABLE_SVR_PASSWORD_AUTH
/* PAM requires ./configure --enable-pam */
-#define ENABLE_SVR_PAM_AUTH
+/*#define ENABLE_SVR_PAM_AUTH */
#define ENABLE_SVR_PUBKEY_AUTH
/* Whether to take public key options in
diff --git a/runopts.h b/runopts.h
index 59e968a..21fc8e5 100644
--- a/runopts.h
+++ b/runopts.h
@@ -100,6 +100,8 @@ typedef struct svr_runopts {
sign_key *hostkey;
+ int delay_hostkey;
+
char *hostkey_files[MAX_HOSTKEYS];
int num_hostkey_files;
diff --git a/signkey.c b/signkey.c
index edb9400..a7f45d4 100644
--- a/signkey.c
+++ b/signkey.c
@@ -351,19 +351,25 @@ void sign_key_free(sign_key *key) {
key->rsakey = NULL;
#endif
#ifdef DROPBEAR_ECDSA
+#ifdef DROPBEAR_ECC_256
if (key->ecckey256) {
ecc_free(key->ecckey256);
key->ecckey256 = NULL;
}
+#endif
+#ifdef DROPBEAR_ECC_384
if (key->ecckey384) {
ecc_free(key->ecckey384);
key->ecckey384 = NULL;
}
+#endif
+#ifdef DROPBEAR_ECC_521
if (key->ecckey521) {
ecc_free(key->ecckey521);
key->ecckey521 = NULL;
}
#endif
+#endif
m_free(key->filename);
diff --git a/svr-kex.c b/svr-kex.c
index 3d131a1..ca87875 100644
--- a/svr-kex.c
+++ b/svr-kex.c
@@ -77,6 +77,7 @@ void recv_msg_kexdh_init() {
TRACE(("leave recv_msg_kexdh_init"))
}
+#ifdef DROPBEAR_DELAY_HOSTKEY
static void svr_ensure_hostkey() {
const char* fn = NULL;
@@ -141,7 +142,7 @@ out:
if (ret == DROPBEAR_FAILURE)
{
- dropbear_exit("Couldn't read or generate hostkey");
+ dropbear_exit("Couldn't read or generate hostkey %s", fn);
}
// directory for keys.
@@ -152,6 +153,7 @@ out:
// atomic rename, done.
}
+#endif
/* Generate our side of the diffie-hellman key exchange value (dh_f), and
* calculate the session key using the diffie-hellman algorithm. Following
@@ -165,8 +167,13 @@ static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs) {
/* we can start creating the kexdh_reply packet */
CHECKCLEARTOWRITE();
-
- svr_ensure_hostkey();
+
+#ifdef DROPBEAR_DELAY_HOSTKEY
+ if (svr_opts.delay_hostkey)
+ {
+ svr_ensure_hostkey();
+ }
+#endif
buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_REPLY);
buf_put_pub_key(ses.writepayload, svr_opts.hostkey,
diff --git a/svr-runopts.c b/svr-runopts.c
index 53dd9fd..fd05bbe 100644
--- a/svr-runopts.c
+++ b/svr-runopts.c
@@ -44,13 +44,19 @@ static void printhelp(const char * progname) {
"-b bannerfile Display the contents of bannerfile"
" before user login\n"
" (default: none)\n"
+ "-r keyfile Specify hostkeys (repeatable)\n"
+ " defaults: \n"
#ifdef DROPBEAR_DSS
- "-d dsskeyfile Use dsskeyfile for the DSS host key\n"
- " (default: %s)\n"
+ " dss %s\n"
#endif
#ifdef DROPBEAR_RSA
- "-r rsakeyfile Use rsakeyfile for the RSA host key\n"
- " (default: %s)\n"
+ " rsa %s\n"
+#endif
+#ifdef DROPBEAR_ECDSA
+ " ecdsa %s\n"
+#endif
+#ifdef DROPBEAR_DELAY_HOSTKEY
+ "-R Create hostkeys as required\n"
#endif
"-F Don't fork into background\n"
#ifdef DISABLE_SYSLOG
@@ -96,6 +102,9 @@ static void printhelp(const char * progname) {
#ifdef DROPBEAR_RSA
RSA_PRIV_FILENAME,
#endif
+#ifdef DROPBEAR_ECDSA
+ ECDSA_PRIV_FILENAME,
+#endif
DROPBEAR_MAX_PORTS, DROPBEAR_DEFPORT, DROPBEAR_PIDFILE,
DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE, DEFAULT_IDLE_TIMEOUT);
}
@@ -122,6 +131,7 @@ void svr_getopts(int argc, char ** argv) {
svr_opts.inetdmode = 0;
svr_opts.portcount = 0;
svr_opts.hostkey = NULL;
+ svr_opts.delay_hostkey = 0;
svr_opts.pidfile = DROPBEAR_PIDFILE;
#ifdef ENABLE_SVR_LOCALTCPFWD
svr_opts.nolocaltcp = 0;
@@ -180,6 +190,9 @@ void svr_getopts(int argc, char ** argv) {
case 'r':
next = &keyfile;
break;
+ case 'R':
+ svr_opts.delay_hostkey = 1;
+ break;
case 'F':
svr_opts.forkbg = 0;
break;
@@ -390,7 +403,7 @@ static void loadhostkey_helper(const char *name, void** src, void** dst, int fat
/* Must be called after syslog/etc is working */
static void loadhostkey(const char *keyfile, int fatal_duplicate) {
sign_key * read_key = new_sign_key();
- int type = DROPBEAR_SIGNKEY_ANY;
+ enum signkey_type type = DROPBEAR_SIGNKEY_ANY;
if (readhostkey(keyfile, read_key, &type) == DROPBEAR_FAILURE) {
dropbear_log(LOG_WARNING, "Failed loading %s", keyfile);
}
@@ -438,6 +451,7 @@ static void addhostkey(const char *keyfile) {
void load_all_hostkeys() {
int i;
+ int disable_unset_keys = 1;
svr_opts.hostkey = new_sign_key();
@@ -459,31 +473,47 @@ void load_all_hostkeys() {
loadhostkey(ECDSA_PRIV_FILENAME, 0);
#endif
+#ifdef DROPBEAR_DELAY_HOSTKEY
+ if (svr_opts.delay_hostkey)
+ {
+ disable_unset_keys = 0;
+ }
+#endif
+
#ifdef DROPBEAR_RSA
- if (!svr_opts.hostkey->rsakey) {
+ if (disable_unset_keys && !svr_opts.hostkey->rsakey) {
disablekey(DROPBEAR_SIGNKEY_RSA);
}
#endif
+
#ifdef DROPBEAR_DSS
- if (!svr_opts.hostkey->dsskey) {
+ if (disable_unset_keys && !svr_opts.hostkey->dsskey) {
disablekey(DROPBEAR_SIGNKEY_RSA);
}
#endif
+
+
#ifdef DROPBEAR_ECDSA
#ifdef DROPBEAR_ECC_256
- if (!svr_opts.hostkey->ecckey256) {
+ if ((disable_unset_keys || ECDSA_DEFAULT_SIZE != 256)
+ && !svr_opts.hostkey->ecckey256) {
disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP256);
}
#endif
+
#ifdef DROPBEAR_ECC_384
- if (!svr_opts.hostkey->ecckey384) {
+ if ((disable_unset_keys || ECDSA_DEFAULT_SIZE != 384)
+ && !svr_opts.hostkey->ecckey384) {
disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP384);
}
#endif
+
#ifdef DROPBEAR_ECC_521
- if (!svr_opts.hostkey->ecckey521) {
- //disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP521);
+ if ((disable_unset_keys || ECDSA_DEFAULT_SIZE != 521)
+ && !svr_opts.hostkey->ecckey521) {
+ disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP521);
}
#endif
-#endif
+#endif /* DROPBEAR_ECDSA */
+
}
diff --git a/sysoptions.h b/sysoptions.h
index 8d57375..6637ad5 100644
--- a/sysoptions.h
+++ b/sysoptions.h
@@ -104,21 +104,22 @@
#define DROPBEAR_LTC_PRNG
#endif
-// hashes which will be linked and registered
+/* hashes which will be linked and registered */
#if defined(DROPBEAR_SHA2_256_HMAC) || defined(DROPBEAR_ECC_256)
#define DROPBEAR_SHA256
#endif
#if defined(DROPBEAR_ECC_384)
#define DROPBEAR_SHA384
#endif
-#if defined(DROPBEAR_SHA2_512_HMAC) || defined(DROPBEAR_ECC_521)
+/* LTC SHA384 depends on SHA512 */
+#if defined(DROPBEAR_SHA2_512_HMAC) || defined(DROPBEAR_ECC_521) || defined(DROPBEAR_ECC_384)
#define DROPBEAR_SHA512
#endif
#if defined(DROPBEAR_MD5_HMAC)
#define DROPBEAR_MD5
#endif
-// roughly 2x 521 bits
+/* roughly 2x 521 bits */
#define MAX_ECC_SIZE 140
#define MAX_NAME_LEN 64 /* maximum length of a protocol name, isn't