summaryrefslogtreecommitdiff
path: root/svr-runopts.c
diff options
context:
space:
mode:
Diffstat (limited to 'svr-runopts.c')
-rw-r--r--svr-runopts.c153
1 files changed, 109 insertions, 44 deletions
diff --git a/svr-runopts.c b/svr-runopts.c
index f6ce86c..2db88c2 100644
--- a/svr-runopts.c
+++ b/svr-runopts.c
@@ -28,11 +28,14 @@
#include "buffer.h"
#include "dbutil.h"
#include "algo.h"
+#include "ecdsa.h"
svr_runopts svr_opts; /* GLOBAL */
static void printhelp(const char * progname);
static void addportandaddress(char* spec);
+static void loadhostkey(const char *keyfile, int fatal_duplicate);
+static void addhostkey(const char *keyfile);
static void printhelp(const char * progname) {
@@ -105,10 +108,10 @@ void svr_getopts(int argc, char ** argv) {
char* recv_window_arg = NULL;
char* keepalive_arg = NULL;
char* idle_timeout_arg = NULL;
+ char* keyfile = NULL;
+
/* see printhelp() for options */
- svr_opts.rsakeyfile = NULL;
- svr_opts.dsskeyfile = NULL;
svr_opts.bannerfile = NULL;
svr_opts.banner = NULL;
svr_opts.forkbg = 1;
@@ -160,6 +163,11 @@ void svr_getopts(int argc, char ** argv) {
dropbear_exit("Invalid null argument");
}
next = 0x00;
+
+ if (keyfile) {
+ addhostkey(keyfile);
+ keyfile = NULL;
+ }
continue;
}
@@ -168,16 +176,10 @@ void svr_getopts(int argc, char ** argv) {
case 'b':
next = &svr_opts.bannerfile;
break;
-#ifdef DROPBEAR_DSS
case 'd':
- next = &svr_opts.dsskeyfile;
- break;
-#endif
-#ifdef DROPBEAR_RSA
case 'r':
- next = &svr_opts.rsakeyfile;
+ next = &keyfile;
break;
-#endif
case 'F':
svr_opts.forkbg = 0;
break;
@@ -267,13 +269,6 @@ void svr_getopts(int argc, char ** argv) {
svr_opts.portcount = 1;
}
- if (svr_opts.dsskeyfile == NULL) {
- svr_opts.dsskeyfile = DSS_PRIV_FILENAME;
- }
- if (svr_opts.rsakeyfile == NULL) {
- svr_opts.rsakeyfile = RSA_PRIV_FILENAME;
- }
-
if (svr_opts.bannerfile) {
struct stat buf;
if (stat(svr_opts.bannerfile, &buf) != 0) {
@@ -292,7 +287,6 @@ void svr_getopts(int argc, char ** argv) {
svr_opts.bannerfile);
}
buf_setpos(svr_opts.banner, 0);
-
}
if (recv_window_arg) {
@@ -370,55 +364,126 @@ static void addportandaddress(char* spec) {
}
}
-static void disablekey(int type, const char* filename) {
-
+static void disablekey(int type) {
int i;
-
+ TRACE(("Disabling key type %d", type))
for (i = 0; sshhostkey[i].name != NULL; i++) {
if (sshhostkey[i].val == type) {
sshhostkey[i].usable = 0;
break;
}
}
- dropbear_log(LOG_WARNING, "Failed reading '%s', disabling %s", filename,
- type == DROPBEAR_SIGNKEY_DSS ? "DSS" : "RSA");
}
-/* Must be called after syslog/etc is working */
-void loadhostkeys() {
-
- int ret;
- int type;
+static void loadhostkey_helper(const char *name, void** src, void** dst, int fatal_duplicate) {
+ if (*dst) {
+ if (fatal_duplicate) {
+ dropbear_exit("Only one %s key can be specified", name);
+ }
+ } else {
+ *dst = *src;
+ *src = NULL;
+ }
- TRACE(("enter loadhostkeys"))
+}
- svr_opts.hostkey = new_sign_key();
+/* 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;
+ if (readhostkey(keyfile, read_key, &type) == DROPBEAR_FAILURE) {
+ dropbear_log(LOG_WARNING, "Failed loading %s", keyfile);
+ }
#ifdef DROPBEAR_RSA
- type = DROPBEAR_SIGNKEY_RSA;
- ret = readhostkey(svr_opts.rsakeyfile, svr_opts.hostkey, &type);
- if (ret == DROPBEAR_FAILURE) {
- disablekey(DROPBEAR_SIGNKEY_RSA, svr_opts.rsakeyfile);
+ if (type == DROPBEAR_SIGNKEY_RSA) {
+ loadhostkey_helper("RSA", &read_key->rsakey, &svr_opts.hostkey->rsakey, fatal_duplicate);
}
#endif
+
#ifdef DROPBEAR_DSS
- type = DROPBEAR_SIGNKEY_DSS;
- ret = readhostkey(svr_opts.dsskeyfile, svr_opts.hostkey, &type);
- if (ret == DROPBEAR_FAILURE) {
- disablekey(DROPBEAR_SIGNKEY_DSS, svr_opts.dsskeyfile);
+ if (type == DROPBEAR_SIGNKEY_DSS) {
+ loadhostkey_helper("DSS", &read_key->dsskey, &svr_opts.hostkey->dsskey, fatal_duplicate);
}
#endif
- if ( 1
+#ifdef DROPBEAR_ECDSA
+#ifdef DROPBEAR_ECC_256
+ if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP256) {
+ loadhostkey_helper("ECDSA256", &read_key->ecckey256, &svr_opts.hostkey->ecckey256, fatal_duplicate);
+ }
+#endif
+#ifdef DROPBEAR_ECC_384
+ if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP384) {
+ loadhostkey_helper("ECDSA384", &read_key->ecckey384, &svr_opts.hostkey->ecckey384, fatal_duplicate);
+ }
+#endif
+#ifdef DROPBEAR_ECC_521
+ if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP521) {
+ loadhostkey_helper("ECDSA521", &read_key->ecckey521, &svr_opts.hostkey->ecckey521, fatal_duplicate);
+ }
+#endif
+#endif // DROPBEAR_ECDSA
+ sign_key_free(read_key);
+ TRACE(("leave loadhostkey"))
+}
+
+static void addhostkey(const char *keyfile) {
+ if (svr_opts.num_hostkey_files >= MAX_HOSTKEYS) {
+ dropbear_exit("Too many hostkeys");
+ }
+ svr_opts.hostkey_files[svr_opts.num_hostkey_files] = m_strdup(keyfile);
+ svr_opts.num_hostkey_files++;
+}
+
+void load_all_hostkeys() {
+ int i;
+
+ svr_opts.hostkey = new_sign_key();
+
+ for (i = 0; i < svr_opts.num_hostkey_files; i++) {
+ char *hostkey_file = svr_opts.hostkey_files[i];
+ loadhostkey(hostkey_file, 1);
+ m_free(hostkey_file);
+ }
+
+#ifdef DROPBEAR_RSA
+ loadhostkey(RSA_PRIV_FILENAME, 0);
+#endif
+
#ifdef DROPBEAR_DSS
- && svr_opts.hostkey->dsskey == NULL
+ loadhostkey(DSS_PRIV_FILENAME, 0);
#endif
+
+#ifdef DROPBEAR_ECDSA
+ loadhostkey(ECDSA_PRIV_FILENAME, 0);
+#endif
+
#ifdef DROPBEAR_RSA
- && svr_opts.hostkey->rsakey == NULL
+ if (!svr_opts.hostkey->rsakey) {
+ disablekey(DROPBEAR_SIGNKEY_RSA);
+ }
#endif
- ) {
- dropbear_exit("No hostkeys available");
+#ifdef DROPBEAR_DSS
+ if (!svr_opts.hostkey->dsskey) {
+ disablekey(DROPBEAR_SIGNKEY_RSA);
}
-
- TRACE(("leave loadhostkeys"))
+#endif
+#ifdef DROPBEAR_ECDSA
+#ifdef DROPBEAR_ECC_256
+ if (!svr_opts.hostkey->ecckey256) {
+ disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP256);
+ }
+#endif
+#ifdef DROPBEAR_ECC_384
+ if (!svr_opts.hostkey->ecckey384) {
+ disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP384);
+ }
+#endif
+#ifdef DROPBEAR_ECC_521
+ if (!svr_opts.hostkey->ecckey521) {
+ disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP521);
+ }
+#endif
+#endif
}