summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--algo.h7
-rw-r--r--cli-runopts.c22
-rw-r--r--common-algo.c82
-rw-r--r--common-kex.c1
-rw-r--r--common-runopts.c40
-rw-r--r--options.h7
-rw-r--r--runopts.h8
7 files changed, 163 insertions, 4 deletions
diff --git a/algo.h b/algo.h
index 87e524d..ad57037 100644
--- a/algo.h
+++ b/algo.h
@@ -88,4 +88,11 @@ algo_type * svr_buf_match_algo(buffer* buf, algo_type localalgos[],
algo_type * cli_buf_match_algo(buffer* buf, algo_type localalgos[],
int *goodguess);
+#ifdef ENABLE_USER_ALGO_LIST
+int check_user_algos(const char* user_algo_list, algo_type * algos,
+ const char *algo_desc);
+char * algolist_string(algo_type algos[]);
+#endif
+
+
#endif /* _ALGO_H_ */
diff --git a/cli-runopts.c b/cli-runopts.c
index 44d2b24..140b0cf 100644
--- a/cli-runopts.c
+++ b/cli-runopts.c
@@ -86,6 +86,10 @@ static void printhelp() {
#ifdef ENABLE_CLI_PROXYCMD
"-J <proxy_program> Use program pipe rather than TCP connection\n"
#endif
+#ifdef ENABLE_USER_ALGO_LIST
+ "-c <cipher list> Specify preferred ciphers ('-c help' to list options)\n"
+ "-m <MAC list> Specify preferred MACs for packet verification (or '-m help')\n"
+#endif
#ifdef DEBUG_TRACE
"-v verbose (compiled with DEBUG_TRACE)\n"
#endif
@@ -149,6 +153,10 @@ void cli_getopts(int argc, char ** argv) {
#ifndef DISABLE_ZLIB
opts.enable_compress = 1;
#endif
+#ifdef ENABLE_USER_ALGO_LIST
+ opts.cipher_list = NULL;
+ opts.mac_list = NULL;
+#endif
/* not yet
opts.ipv4 = 1;
opts.ipv6 = 1;
@@ -283,6 +291,14 @@ void cli_getopts(int argc, char ** argv) {
cli_opts.agent_fwd = 1;
break;
#endif
+#ifdef ENABLE_USER_ALGO_LIST
+ case 'c':
+ next = &opts.cipher_list;
+ break;
+ case 'm':
+ next = &opts.mac_list;
+ break;
+#endif
#ifdef DEBUG_TRACE
case 'v':
debug_trace = 1;
@@ -290,8 +306,10 @@ void cli_getopts(int argc, char ** argv) {
#endif
case 'F':
case 'e':
+#ifndef ENABLE_USER_ALGO_LIST
case 'c':
case 'm':
+#endif
case 'D':
#ifndef ENABLE_CLI_REMOTETCPFWD
case 'R':
@@ -351,6 +369,10 @@ void cli_getopts(int argc, char ** argv) {
/* And now a few sanity checks and setup */
+#ifdef ENABLE_USER_ALGO_LIST
+ parse_ciphers_macs();
+#endif
+
if (host_arg == NULL) {
printhelp();
exit(EXIT_FAILURE);
diff --git a/common-algo.c b/common-algo.c
index 4383bca..0e1a64c 100644
--- a/common-algo.c
+++ b/common-algo.c
@@ -280,8 +280,6 @@ int have_algo(char* algo, size_t algolen, algo_type algos[]) {
return DROPBEAR_FAILURE;
}
-
-
/* Output a comma separated list of algorithms to a buffer */
void buf_put_algolist(buffer * buf, algo_type localalgos[]) {
@@ -302,3 +300,83 @@ void buf_put_algolist(buffer * buf, algo_type localalgos[]) {
buf_putstring(buf, algolist->data, algolist->len);
buf_free(algolist);
}
+
+#ifdef ENABLE_USER_ALGO_LIST
+
+char *
+algolist_string(algo_type algos[])
+{
+ char *ret_list;
+ buffer *b = buf_new(200);
+ buf_put_algolist(b, algos);
+ buf_setpos(b, b->len);
+ buf_putbyte(b, '\0');
+ buf_setpos(b, 4);
+ ret_list = m_strdup(buf_getptr(b, b->len - b->pos));
+ buf_free(b);
+ return ret_list;
+}
+
+static algo_type*
+check_algo(const char* algo_name, algo_type *algos)
+{
+ algo_type *a;
+ for (a = algos; a->name != NULL; a++)
+ {
+ if (strcmp(a->name, algo_name) == 0)
+ {
+ return a;
+ }
+ }
+
+ return NULL;
+}
+
+static void
+try_add_algo(const char *algo_name, algo_type *algos,
+ const char *algo_desc, algo_type * new_algos, int *num_ret)
+{
+ algo_type *match_algo = check_algo(algo_name, algos);
+ if (!match_algo)
+ {
+ dropbear_log(LOG_WARNING, "This Dropbear program does not support '%s' %s algorithm", algo_name, algo_desc);
+ return;
+ }
+
+ new_algos[*num_ret] = *match_algo;
+ (*num_ret)++;
+}
+
+/* Checks a user provided comma-separated algorithm list for available
+ * options. Any that are not acceptable are removed in-place. Returns the
+ * number of valid algorithms. */
+int
+check_user_algos(const char* user_algo_list, algo_type * algos,
+ const char *algo_desc)
+{
+ algo_type new_algos[MAX_PROPOSED_ALGO];
+ /* this has two passes. first we sweep through the given list of
+ * algorithms and mark them as usable=2 in the algo_type[] array... */
+ int num_ret = 0;
+ char *work_list = m_strdup(user_algo_list);
+ char *last_name = work_list;
+ char *c;
+ for (c = work_list; *c; c++)
+ {
+ if (*c == ',')
+ {
+ *c = '\0';
+ try_add_algo(last_name, algos, algo_desc, new_algos, &num_ret);
+ last_name = c++;
+ }
+ }
+ try_add_algo(last_name, algos, algo_desc, new_algos, &num_ret);
+ m_free(work_list);
+
+ new_algos[num_ret].name = NULL;
+
+ /* Copy one more as a blank delimiter */
+ memcpy(algos, new_algos, sizeof(*new_algos) * (num_ret+1));
+ return num_ret;
+}
+#endif // ENABLE_USER_ALGO_LIST
diff --git a/common-kex.c b/common-kex.c
index bf39ca9..a7fbb70 100644
--- a/common-kex.c
+++ b/common-kex.c
@@ -118,6 +118,7 @@ void send_msg_kexinit() {
/* mac_algorithms_server_to_client */
buf_put_algolist(ses.writepayload, sshhashes);
+
/* compression_algorithms_client_to_server */
buf_put_algolist(ses.writepayload, ses.compress_algos);
diff --git a/common-runopts.c b/common-runopts.c
index 2de036e..784055a 100644
--- a/common-runopts.c
+++ b/common-runopts.c
@@ -28,6 +28,7 @@
#include "buffer.h"
#include "dbutil.h"
#include "auth.h"
+#include "algo.h"
runopts opts; /* GLOBAL */
@@ -55,3 +56,42 @@ out:
buf_free(buf);
return ret;
}
+
+#ifdef ENABLE_USER_ALGO_LIST
+void
+parse_ciphers_macs()
+{
+ if (opts.cipher_list)
+ {
+ if (strcmp(opts.cipher_list, "help") == 0)
+ {
+ char *ciphers = algolist_string(sshciphers);
+ dropbear_log(LOG_INFO, "Available ciphers:\n%s\n", ciphers);
+ m_free(ciphers);
+ dropbear_exit(".");
+ }
+
+ if (check_user_algos(opts.cipher_list, sshciphers, "cipher") == 0)
+ {
+ dropbear_exit("No valid ciphers specified for '-c'");
+ }
+ }
+
+ if (opts.mac_list)
+ {
+ if (strcmp(opts.mac_list, "help") == 0)
+ {
+ char *macs = algolist_string(sshhashes);
+ dropbear_log(LOG_INFO, "Available MACs:\n%s\n", macs);
+ m_free(macs);
+ dropbear_exit(".");
+ }
+
+ if (check_user_algos(opts.mac_list, sshhashes, "MAC") == 0)
+ {
+ dropbear_exit("No valid MACs specified for '-m'");
+ }
+ }
+}
+#endif
+
diff --git a/options.h b/options.h
index 2350b6b..ecbae05 100644
--- a/options.h
+++ b/options.h
@@ -80,6 +80,9 @@ much traffic. */
* to a remote TCP-forwarded connection */
#define ENABLE_CLI_NETCAT
+/* Whether to support "-c" and "-m" flags to choose ciphers/MACs at runtime */
+#define ENABLE_USER_ALGO_LIST
+
/* Encryption - at least one required.
* Protocol RFC requires 3DES and recommends AES128 for interoperability.
* Including multiple keysize variants the same cipher
@@ -107,7 +110,7 @@ much traffic. */
* The best way to do things is probably make normal compile of dropbear with
* all ciphers including "none" as the server, then recompile a special
* "dbclient-insecure" client. */
-/* #define DROPBEAR_NONE_CIPHER */
+#define DROPBEAR_NONE_CIPHER
/* Message Integrity - at least one required.
* Protocol RFC requires sha1 and recommends sha1-96.
@@ -132,7 +135,7 @@ much traffic. */
* simple to run arbitrary commands on the remote host. Beware.
* Note again, for the client you will have to disable other hashes above
* to use this. */
-/* #define DROPBEAR_NONE_INTEGRITY */
+#define DROPBEAR_NONE_INTEGRITY
/* Hostkey/public key algorithms - at least one required, these are used
* for hostkey as well as for verifying signatures with pubkey auth.
diff --git a/runopts.h b/runopts.h
index 83b5861..6d1086b 100644
--- a/runopts.h
+++ b/runopts.h
@@ -47,6 +47,10 @@ typedef struct runopts {
int enable_compress;
#endif
+#ifdef ENABLE_USER_ALGO_LIST
+ char *cipher_list;
+ char *mac_list;
+#endif
} runopts;
@@ -148,4 +152,8 @@ typedef struct cli_runopts {
extern cli_runopts cli_opts;
void cli_getopts(int argc, char ** argv);
+#ifdef ENABLE_USER_ALGO_LIST
+void parse_ciphers_macs();
+#endif
+
#endif /* _RUNOPTS_H_ */