summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--algo.h11
-rw-r--r--buffer.c22
-rw-r--r--buffer.h1
-rw-r--r--cli-authpubkey.c78
-rw-r--r--cli-kex.c25
-rw-r--r--cli-main.c1
-rw-r--r--cli-session.c5
-rw-r--r--common-algo.c119
-rw-r--r--common-kex.c30
-rw-r--r--fuzzer-verify.c4
-rw-r--r--kex.h2
-rw-r--r--session.h11
-rw-r--r--signkey.c21
-rw-r--r--signkey.h2
-rw-r--r--ssh.h6
-rw-r--r--svr-session.c7
16 files changed, 255 insertions, 90 deletions
diff --git a/algo.h b/algo.h
index 1a6d384..1565665 100644
--- a/algo.h
+++ b/algo.h
@@ -114,18 +114,11 @@ struct dropbear_kex {
void buf_put_algolist(buffer * buf, const algo_type localalgos[]);
-enum kexguess2_used {
- KEXGUESS2_LOOK,
- KEXGUESS2_NO,
- KEXGUESS2_YES,
-};
-
#define KEXGUESS2_ALGO_NAME "kexguess2@matt.ucc.asn.au"
-#define KEXGUESS2_ALGO_ID 99
-
+int buf_has_algo(buffer *buf, const char *algo);
algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
- enum kexguess2_used *kexguess2, int *goodguess);
+ int kexguess2, int *goodguess);
#if DROPBEAR_USER_ALGO_LIST
int check_user_algos(const char* user_algo_list, algo_type * algos,
diff --git a/buffer.c b/buffer.c
index e70ec29..dc8b909 100644
--- a/buffer.c
+++ b/buffer.c
@@ -228,19 +228,37 @@ char* buf_getstring(buffer* buf, unsigned int *retlen) {
}
/* Return a string as a newly allocated buffer */
-buffer * buf_getstringbuf(buffer *buf) {
+static buffer * buf_getstringbuf_int(buffer *buf, int incllen) {
buffer *ret = NULL;
unsigned int len = buf_getint(buf);
+ int extra = 0;
if (len > MAX_STRING_LEN) {
dropbear_exit("String too long");
}
- ret = buf_new(len);
+ if (incllen) {
+ extra = 4;
+ }
+ ret = buf_new(len+extra);
+ if (incllen) {
+ buf_putint(ret, len);
+ }
memcpy(buf_getwriteptr(ret, len), buf_getptr(buf, len), len);
buf_incrpos(buf, len);
buf_incrlen(ret, len);
+ buf_setpos(ret, 0);
return ret;
}
+/* Return a string as a newly allocated buffer */
+buffer * buf_getstringbuf(buffer *buf) {
+ return buf_getstringbuf_int(buf, 0);
+}
+
+/* Returns a string in a new buffer, including the length */
+buffer * buf_getbuf(buffer *buf) {
+ return buf_getstringbuf_int(buf, 1);
+}
+
/* Just increment the buffer position the same as if we'd used buf_getstring,
* but don't bother copying/malloc()ing for it */
void buf_eatstring(buffer *buf) {
diff --git a/buffer.h b/buffer.h
index befe1c7..85f913d 100644
--- a/buffer.h
+++ b/buffer.h
@@ -58,6 +58,7 @@ unsigned char* buf_getptr(const buffer* buf, unsigned int len);
unsigned char* buf_getwriteptr(const buffer* buf, unsigned int len);
char* buf_getstring(buffer* buf, unsigned int *retlen);
buffer * buf_getstringbuf(buffer *buf);
+buffer * buf_getbuf(buffer *buf);
void buf_eatstring(buffer *buf);
void buf_putint(buffer* buf, unsigned int val);
void buf_putstring(buffer* buf, const char* str, unsigned int len);
diff --git a/cli-authpubkey.c b/cli-authpubkey.c
index 0ad80ea..8426e84 100644
--- a/cli-authpubkey.c
+++ b/cli-authpubkey.c
@@ -184,6 +184,7 @@ static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype,
/* Returns 1 if a key was tried */
int cli_auth_pubkey() {
+ enum signature_type sigtype;
TRACE(("enter cli_auth_pubkey"))
#if DROPBEAR_CLI_AGENTFWD
@@ -191,28 +192,77 @@ int cli_auth_pubkey() {
/* get the list of available keys from the agent */
cli_load_agent_keys(cli_opts.privkeys);
cli_opts.agent_keys_loaded = 1;
+ TRACE(("cli_auth_pubkey: agent keys loaded"))
}
#endif
- /* TODO iterate through privkeys to skip ones not in server-sig-algs */
-
- /* TODO: testing */
+ /* iterate through privkeys to remove ones not allowed in server-sig-algs */
+ while (cli_opts.privkeys->first) {
+ sign_key * key = (sign_key*)cli_opts.privkeys->first->item;
+ if (cli_ses.server_sig_algs) {
+#ifdef DROPBEAR_RSA
+ if (key->type == DROPBEAR_SIGNKEY_RSA) {
#if DROPBEAR_RSA_SHA256
- cli_ses.preferred_rsa_sigtype = DROPBEAR_SIGNATURE_RSA_SHA256;
-#elif DROPBEAR_RSA_SHA1
- cli_ses.preferred_rsa_sigtype = DROPBEAR_SIGNATURE_RSA_SHA1;
+ if (buf_has_algo(cli_ses.server_sig_algs, SSH_SIGNATURE_RSA_SHA256)
+ == DROPBEAR_SUCCESS) {
+ sigtype = DROPBEAR_SIGNATURE_RSA_SHA256;
+ TRACE(("server-sig-algs allows rsa sha256"))
+ break;
+ }
+#endif /* DROPBEAR_RSA_SHA256 */
+#if DROPBEAR_RSA_SHA1
+ if (buf_has_algo(cli_ses.server_sig_algs, SSH_SIGNKEY_RSA)
+ == DROPBEAR_SUCCESS) {
+ sigtype = DROPBEAR_SIGNATURE_RSA_SHA1;
+ TRACE(("server-sig-algs allows rsa sha1"))
+ break;
+ }
+#endif /* DROPBEAR_RSA_SHA256 */
+ } else
+#endif /* DROPBEAR_RSA */
+ {
+ /* Not RSA */
+ const char *name = NULL;
+ sigtype = signature_type_from_signkey(key->type);
+ name = signature_name_from_type(sigtype, NULL);
+ if (buf_has_algo(cli_ses.server_sig_algs, name)
+ == DROPBEAR_SUCCESS) {
+ TRACE(("server-sig-algs allows %s", name))
+ break;
+ }
+ }
+
+ /* No match, skip this key */
+ TRACE(("server-sig-algs no match keytype %d, skipping", key->type))
+ key = list_remove(cli_opts.privkeys->first);
+ sign_key_free(key);
+ continue;
+ } else {
+ /* Server didn't provide a server-sig-algs list, we'll
+ assume all except rsa-sha256 are OK. */
+#if DROPBEAR_RSA
+ if (key->type == DROPBEAR_SIGNKEY_RSA) {
+#ifdef DROPBEAR_RSA_SHA1
+ sigtype = DROPBEAR_SIGNATURE_RSA_SHA1;
+ TRACE(("no server-sig-algs, using rsa sha1"))
+ break;
+#else
+ /* only support rsa-sha256, skip this key */
+ TRACE(("no server-sig-algs, skipping rsa sha256"))
+ key = list_remove(cli_opts.privkeys->first);
+ sign_key_free(key);
+ continue;
#endif
+ } /* key->type == DROPBEAR_SIGNKEY_RSA */
+#endif /* DROPBEAR_RSA */
+ sigtype = signature_type_from_signkey(key->type);
+ TRACE(("no server-sig-algs, using key"))
+ break;
+ }
+ }
if (cli_opts.privkeys->first) {
sign_key * key = (sign_key*)cli_opts.privkeys->first->item;
- /* Determine the signature type to use */
- enum signature_type sigtype = (enum signature_type)key->type;
-#if DROPBEAR_RSA
- if (key->type == DROPBEAR_SIGNKEY_RSA) {
- sigtype = cli_ses.preferred_rsa_sigtype;
- }
-#endif
-
/* Send a trial request */
send_msg_userauth_pubkey(key, sigtype, 0);
cli_ses.lastprivkey = key;
diff --git a/cli-kex.c b/cli-kex.c
index 7337ffd..99370eb 100644
--- a/cli-kex.c
+++ b/cli-kex.c
@@ -411,3 +411,28 @@ out:
}
m_free(fingerprint);
}
+
+void recv_msg_ext_info(void) {
+ /* This message is not client-specific in the protocol but Dropbear only handles
+ a server-sent message at present. */
+ unsigned int num_ext;
+ unsigned int i;
+
+ num_ext = buf_getint(ses.payload);
+ TRACE(("received SSH_MSG_EXT_INFO with %d items", num_ext))
+
+ for (i = 0; i < num_ext; i++) {
+ unsigned int name_len;
+ char *ext_name = buf_getstring(ses.payload, &name_len);
+ TRACE(("extension %d name '%s'", i, ext_name))
+ if (cli_ses.server_sig_algs == NULL
+ && name_len == strlen(SSH_SERVER_SIG_ALGS)
+ && strcmp(ext_name, SSH_SERVER_SIG_ALGS) == 0) {
+ cli_ses.server_sig_algs = buf_getbuf(ses.payload);
+ } else {
+ /* valid extension values could be >MAX_STRING_LEN */
+ buf_eatstring(ses.payload);
+ }
+ m_free(ext_name);
+ }
+}
diff --git a/cli-main.c b/cli-main.c
index 713cb09..b43b1e2 100644
--- a/cli-main.c
+++ b/cli-main.c
@@ -106,6 +106,7 @@ static void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
/* Render the formatted exit message */
vsnprintf(exitmsg, sizeof(exitmsg), format, param);
+ TRACE(("Exited, cleaning up: %s", exitmsg))
/* Add the prefix depending on session/auth state */
if (!ses.init_done) {
diff --git a/cli-session.c b/cli-session.c
index 56dd4af..fc81e2d 100644
--- a/cli-session.c
+++ b/cli-session.c
@@ -81,6 +81,7 @@ static const packettype cli_packettypes[] = {
{SSH_MSG_REQUEST_SUCCESS, ignore_recv_response},
{SSH_MSG_REQUEST_FAILURE, ignore_recv_response},
#endif
+ {SSH_MSG_EXT_INFO, recv_msg_ext_info},
{0, NULL} /* End */
};
@@ -352,7 +353,9 @@ static void cli_session_cleanup(void) {
(void)fcntl(cli_ses.stderrcopy, F_SETFL, cli_ses.stderrflags);
cli_tty_cleanup();
-
+ if (cli_ses.server_sig_algs) {
+ buf_free(cli_ses.server_sig_algs);
+ }
}
static void cli_finished() {
diff --git a/common-algo.c b/common-algo.c
index 2a1047e..938695d 100644
--- a/common-algo.c
+++ b/common-algo.c
@@ -30,6 +30,7 @@
#include "dh_groups.h"
#include "ltc_prng.h"
#include "ecc.h"
+#include "ssh.h"
/* This file (algo.c) organises the ciphers which can be used, and is used to
* decide which ciphers/hashes/compression/signing to use during key exchange*/
@@ -280,6 +281,7 @@ static const struct dropbear_kex kex_ecdh_nistp521 = {DROPBEAR_KEX_ECDH, NULL, 0
static const struct dropbear_kex kex_curve25519 = {DROPBEAR_KEX_CURVE25519, NULL, 0, NULL, &sha256_desc };
#endif
+/* data == NULL for non-kex algorithm identifiers */
algo_type sshkex[] = {
#if DROPBEAR_CURVE25519
{"curve25519-sha256", 0, &kex_curve25519, 1, NULL},
@@ -309,7 +311,11 @@ algo_type sshkex[] = {
{"diffie-hellman-group16-sha512", 0, &kex_dh_group16_sha512, 1, NULL},
#endif
#if DROPBEAR_KEXGUESS2
- {KEXGUESS2_ALGO_NAME, KEXGUESS2_ALGO_ID, NULL, 1, NULL},
+ {KEXGUESS2_ALGO_NAME, 0, NULL, 1, NULL},
+#endif
+#if DROPBEAR_CLIENT
+ /* Set unusable by svr_algos_initialise() */
+ {SSH_EXT_INFO_C, 0, NULL, 1, NULL},
#endif
{NULL, 0, NULL, 0, NULL}
};
@@ -336,15 +342,79 @@ void buf_put_algolist(buffer * buf, const algo_type localalgos[]) {
buf_free(algolist);
}
+/* returns a list of pointers into algolist, of null-terminated names.
+ ret_list should be passed in with space for *ret_count elements,
+ on return *ret_count has the number of names filled.
+ algolist is modified. */
+static void get_algolist(char* algolist, unsigned int algolist_len,
+ const char* *ret_list, unsigned int *ret_count) {
+ unsigned int max_count = *ret_count;
+ unsigned int i;
+
+ if (*ret_count == 0) {
+ return;
+ }
+ if (algolist_len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
+ *ret_count = 0;
+ }
+
+ /* ret_list will contain a list of the strings parsed out.
+ We will have at least one string (even if it's just "") */
+ ret_list[0] = algolist;
+ *ret_count = 1;
+ for (i = 0; i < algolist_len; i++) {
+ if (algolist[i] == '\0') {
+ /* someone is trying something strange */
+ *ret_count = 0;
+ return;
+ }
+
+ if (algolist[i] == ',') {
+ if (*ret_count >= max_count) {
+ /* Too many */
+ *ret_count = 0;
+ return;
+ }
+ algolist[i] = '\0';
+ ret_list[*ret_count] = &algolist[i+1];
+ (*ret_count)++;
+ }
+ }
+}
+
+/* Return DROPBEAR_SUCCESS if the namelist contains algo,
+DROPBEAR_FAILURE otherwise. buf position is not incremented. */
+int buf_has_algo(buffer *buf, const char *algo) {
+ unsigned char* algolist = NULL;
+ unsigned int orig_pos = buf->pos;
+ unsigned int len, remotecount, i;
+ const char *remotenames[MAX_PROPOSED_ALGO];
+ int ret = DROPBEAR_FAILURE;
+
+ algolist = buf_getstring(buf, &len);
+ remotecount = MAX_PROPOSED_ALGO;
+ get_algolist(algolist, len, remotenames, &remotecount);
+ for (i = 0; i < remotecount; i++)
+ {
+ if (strcmp(remotenames[i], algo) == 0) {
+ ret = DROPBEAR_SUCCESS;
+ break;
+ }
+ }
+ if (algolist) {
+ m_free(algolist);
+ }
+ buf_setpos(buf, orig_pos);
+ return ret;
+}
+
/* match the first algorithm in the comma-separated list in buf which is
* also in localalgos[], or return NULL on failure.
* (*goodguess) is set to 1 if the preferred client/server algos match,
* 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are
* guessed correctly */
algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
- enum kexguess2_used *kexguess2, int *goodguess)
-{
-
+ int kexguess2, int *goodguess) {
char * algolist = NULL;
const char *remotenames[MAX_PROPOSED_ALGO], *localnames[MAX_PROPOSED_ALGO];
unsigned int len;
@@ -359,40 +429,8 @@ algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
/* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
algolist = buf_getstring(buf, &len);
TRACE(("buf_match_algo: %s", algolist))
- if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
- goto out;
- }
-
- /* remotenames will contain a list of the strings parsed out */
- /* We will have at least one string (even if it's just "") */
- remotenames[0] = algolist;
- remotecount = 1;
- for (i = 0; i < len; i++) {
- if (algolist[i] == '\0') {
- /* someone is trying something strange */
- goto out;
- }
- if (algolist[i] == ',') {
- algolist[i] = '\0';
- remotenames[remotecount] = &algolist[i+1];
- remotecount++;
- }
- if (remotecount >= MAX_PROPOSED_ALGO) {
- break;
- }
- }
- if (kexguess2 && *kexguess2 == KEXGUESS2_LOOK) {
- for (i = 0; i < remotecount; i++)
- {
- if (strcmp(remotenames[i], KEXGUESS2_ALGO_NAME) == 0) {
- *kexguess2 = KEXGUESS2_YES;
- break;
- }
- }
- if (*kexguess2 == KEXGUESS2_LOOK) {
- *kexguess2 = KEXGUESS2_NO;
- }
- }
+ remotecount = MAX_PROPOSED_ALGO;
+ get_algolist(algolist, len, remotenames, &remotecount);
for (i = 0; localalgos[i].name != NULL; i++) {
if (localalgos[i].usable) {
@@ -424,12 +462,11 @@ algo_type * buf_match_algo(buffer* buf, algo_type localalgos[],
}
if (strcmp(servnames[j], clinames[i]) == 0) {
/* set if it was a good guess */
- if (goodguess && kexguess2) {
- if (*kexguess2 == KEXGUESS2_YES) {
+ if (goodguess != NULL) {
+ if (kexguess2) {
if (i == 0) {
*goodguess = 1;
}
-
} else {
if (i == 0 && j == 0) {
*goodguess = 1;
diff --git a/common-kex.c b/common-kex.c
index c1392c1..8172796 100644
--- a/common-kex.c
+++ b/common-kex.c
@@ -820,21 +820,33 @@ static void read_kex_algos() {
int goodguess = 0;
int allgood = 1; /* we AND this with each goodguess and see if its still
true after */
-
-#if DROPBEAR_KEXGUESS2
- enum kexguess2_used kexguess2 = KEXGUESS2_LOOK;
-#else
- enum kexguess2_used kexguess2 = KEXGUESS2_NO;
-#endif
+ int kexguess2 = 0;
buf_incrpos(ses.payload, 16); /* start after the cookie */
memset(ses.newkeys, 0x0, sizeof(*ses.newkeys));
/* kex_algorithms */
- algo = buf_match_algo(ses.payload, sshkex, &kexguess2, &goodguess);
+#if DROPBEAR_KEXGUESS2
+ if (buf_has_algo(ses.payload, KEXGUESS2_ALGO_NAME) == DROPBEAR_SUCCESS) {
+ kexguess2 = 1;
+ }
+#endif
+
+ /* Determine if SSH_MSG_EXT_INFO messages should be sent.
+ Should be done for the first key exchange. */
+ if (!ses.kexstate.donefirstkex) {
+ if (IS_DROPBEAR_SERVER) {
+ if (buf_has_algo(ses.payload, SSH_EXT_INFO_C) == DROPBEAR_SUCCESS) {
+ ses.allow_ext_info = 1;
+ }
+ }
+ }
+
+ algo = buf_match_algo(ses.payload, sshkex, kexguess2, &goodguess);
allgood &= goodguess;
- if (algo == NULL || algo->val == KEXGUESS2_ALGO_ID) {
+ if (algo == NULL || algo->data == NULL) {
+ /* kexguess2, ext-info-c, ext-info-s should not match negotiation */
erralgo = "kex";
goto error;
}
@@ -843,7 +855,7 @@ static void read_kex_algos() {
ses.newkeys->algo_kex = algo->data;
/* server_host_key_algorithms */
- algo = buf_match_algo(ses.payload, sshhostkey, &kexguess2, &goodguess);
+ algo = buf_match_algo(ses.payload, sshhostkey, kexguess2, &goodguess);
allgood &= goodguess;
if (algo == NULL) {
erralgo = "hostkey";
diff --git a/fuzzer-verify.c b/fuzzer-verify.c
index cda7723..cdf7804 100644
--- a/fuzzer-verify.c
+++ b/fuzzer-verify.c
@@ -29,7 +29,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
sign_key *key = new_sign_key();
enum signkey_type keytype = DROPBEAR_SIGNKEY_ANY;
if (buf_get_pub_key(fuzz.input, key, &keytype) == DROPBEAR_SUCCESS) {
- enum signature_type sigtype = (enum signature_type)keytype;
+ enum signature_type sigtype;
if (keytype == DROPBEAR_SIGNKEY_RSA) {
/* Flip a coin to decide rsa signature type */
int flag = buf_getbyte(fuzz_input);
@@ -38,6 +38,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
} else {
sigtype = DROPBEAR_SIGNATURE_RSA_SHA1;
}
+ } else {
+ sigtype = signature_type_from_signkey(keytype);
}
if (buf_verify(fuzz.input, key, sigtype, verifydata) == DROPBEAR_SUCCESS) {
/* The fuzzer is capable of generating keys with a signature to match.
diff --git a/kex.h b/kex.h
index 03dcbb1..3b0ec62 100644
--- a/kex.h
+++ b/kex.h
@@ -65,6 +65,8 @@ void recv_msg_kexdh_init(void); /* server */
void send_msg_kexdh_init(void); /* client */
void recv_msg_kexdh_reply(void); /* client */
+void recv_msg_ext_info(void);
+
struct KEXState {
unsigned sentkexinit : 1; /*set when we've sent/recv kexinit packet */
diff --git a/session.h b/session.h
index cbe9cb5..1059537 100644
--- a/session.h
+++ b/session.h
@@ -185,6 +185,9 @@ struct sshsession {
/* Enables/disables compression */
algo_type *compress_algos;
+
+ /* Other side allows SSH_MSG_EXT_INFO */
+ int allow_ext_info;
/* a list of queued replies that should be sent after a KEX has
concluded (ie, while dataallowed was unset)*/
@@ -313,13 +316,7 @@ struct clientsession {
#endif
sign_key *lastprivkey;
- enum signature_type server_sig_algs[DROPBEAR_SIGNKEY_NUM_NAMED+1];
- int server_sig_algs_count;
-#if DROPBEAR_RSA
- /* Set to DROPBEAR_SIGNATURE_RSA_SHA256 or DROPBEAR_SIGNATURE_RSA_SHA1
- if depending which the server accepts */
- enum signature_type preferred_rsa_sigtype;
-#endif
+ buffer *server_sig_algs;
int retval; /* What the command exit status was - we emulate it */
#if 0
diff --git a/signkey.c b/signkey.c
index 47c8c8e..6ed1667 100644
--- a/signkey.c
+++ b/signkey.c
@@ -114,13 +114,17 @@ enum signkey_type signkey_type_from_name(const char* name, unsigned int namelen)
const char* signature_name_from_type(enum signature_type type, unsigned int *namelen) {
#if DROPBEAR_RSA_SHA256
if (type == DROPBEAR_SIGNATURE_RSA_SHA256) {
- *namelen = strlen(SSH_SIGNATURE_RSA_SHA256);
+ if (namelen) {
+ *namelen = strlen(SSH_SIGNATURE_RSA_SHA256);
+ }
return SSH_SIGNATURE_RSA_SHA256;
}
#endif
#if DROPBEAR_RSA_SHA1
if (type == DROPBEAR_SIGNATURE_RSA_SHA1) {
- *namelen = strlen(SSH_SIGNKEY_RSA);
+ if (namelen) {
+ *namelen = strlen(SSH_SIGNKEY_RSA);
+ }
return SSH_SIGNKEY_RSA;
}
#endif
@@ -144,6 +148,16 @@ enum signature_type signature_type_from_name(const char* name, unsigned int name
return (enum signature_type)signkey_type_from_name(name, namelen);
}
+/* Returns the signature type from a key type. Must not be called
+ with RSA keytype */
+enum signature_type signature_type_from_signkey(enum signkey_type keytype) {
+#if DROPBEAR_RSA
+ assert(keytype != DROPBEAR_SIGNKEY_RSA);
+#endif
+ assert(keytype < DROPBEAR_SIGNKEY_NUM_NAMED);
+ return (enum signature_type)keytype;
+}
+
enum signkey_type signkey_type_from_signature(enum signature_type sigtype) {
#if DROPBEAR_RSA_SHA256
if (sigtype == DROPBEAR_SIGNATURE_RSA_SHA256) {
@@ -587,8 +601,7 @@ void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype,
#if DEBUG_TRACE
{
- int namelen;
- const char* signame = signature_name_from_type(sigtype, &namelen);
+ const char* signame = signature_name_from_type(sigtype, NULL);
TRACE(("buf_put_sign type %d %s", sigtype, signame));
}
#endif
diff --git a/signkey.h b/signkey.h
index 9468509..2640171 100644
--- a/signkey.h
+++ b/signkey.h
@@ -120,6 +120,8 @@ enum signkey_type signkey_type_from_name(const char* name, unsigned int namelen)
const char* signature_name_from_type(enum signature_type type, unsigned int *namelen);
enum signature_type signature_type_from_name(const char* name, unsigned int namelen);
enum signkey_type signkey_type_from_signature(enum signature_type sigtype);
+enum signature_type signature_type_from_signkey(enum signkey_type keytype);
+
int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type);
int buf_get_priv_key(buffer* buf, sign_key *key, enum signkey_type *type);
void buf_put_pub_key(buffer* buf, sign_key *key, enum signkey_type type);
diff --git a/ssh.h b/ssh.h
index 5030fe9..ee4a960 100644
--- a/ssh.h
+++ b/ssh.h
@@ -32,6 +32,7 @@
#define SSH_MSG_DEBUG 4
#define SSH_MSG_SERVICE_REQUEST 5
#define SSH_MSG_SERVICE_ACCEPT 6
+#define SSH_MSG_EXT_INFO 7
#define SSH_MSG_KEXINIT 20
#define SSH_MSG_NEWKEYS 21
#define SSH_MSG_KEXDH_INIT 30
@@ -94,6 +95,11 @@
#define SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14
#define SSH_DISCONNECT_ILLEGAL_USER_NAME 15
+/* rfc8308 */
+#define SSH_EXT_INFO_S "ext-info-s"
+#define SSH_EXT_INFO_C "ext-info-c"
+#define SSH_SERVER_SIG_ALGS "server-sig-algs"
+
/* service types */
#define SSH_SERVICE_USERAUTH "ssh-userauth"
#define SSH_SERVICE_USERAUTH_LEN 12
diff --git a/svr-session.c b/svr-session.c
index 0b9eac7..8bc8744 100644
--- a/svr-session.c
+++ b/svr-session.c
@@ -330,13 +330,16 @@ static void svr_remoteclosed() {
}
static void svr_algos_initialise(void) {
-#if DROPBEAR_DH_GROUP1 && DROPBEAR_DH_GROUP1_CLIENTONLY
algo_type *algo;
for (algo = sshkex; algo->name; algo++) {
+#if DROPBEAR_DH_GROUP1 && DROPBEAR_DH_GROUP1_CLIENTONLY
if (strcmp(algo->name, "diffie-hellman-group1-sha1") == 0) {
algo->usable = 0;
}
- }
#endif
+ if (strcmp(algo->name, SSH_EXT_INFO_C) == 0) {
+ algo->usable = 0;
+ }
+ }
}