summaryrefslogtreecommitdiffhomepage
path: root/cli-authpubkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'cli-authpubkey.c')
-rw-r--r--cli-authpubkey.c100
1 files changed, 84 insertions, 16 deletions
diff --git a/cli-authpubkey.c b/cli-authpubkey.c
index 7cee164..fef0f27 100644
--- a/cli-authpubkey.c
+++ b/cli-authpubkey.c
@@ -33,7 +33,7 @@
#include "agentfwd.h"
#if DROPBEAR_CLI_PUBKEY_AUTH
-static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign);
+static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype, int realsign);
/* Called when we receive a SSH_MSG_USERAUTH_FAILURE for a pubkey request.
* We use it to remove the key we tried from the list */
@@ -59,13 +59,15 @@ void recv_msg_userauth_pk_ok() {
char* algotype = NULL;
unsigned int algolen;
enum signkey_type keytype;
+ enum signature_type sigtype;
unsigned int remotelen;
TRACE(("enter recv_msg_userauth_pk_ok"))
algotype = buf_getstring(ses.payload, &algolen);
- keytype = signkey_type_from_name(algotype, algolen);
- TRACE(("recv_msg_userauth_pk_ok: type %d", keytype))
+ sigtype = signature_type_from_name(algotype, algolen);
+ keytype = signkey_type_from_signature(sigtype);
+ TRACE(("recv_msg_userauth_pk_ok: type %d", sigtype))
m_free(algotype);
keybuf = buf_new(MAX_PUBKEY_SIZE);
@@ -112,7 +114,7 @@ void recv_msg_userauth_pk_ok() {
TRACE(("matching key"))
/* XXX TODO: if it's an encrypted key, here we ask for their
* password */
- send_msg_userauth_pubkey((sign_key*)iter->item, keytype, 1);
+ send_msg_userauth_pubkey((sign_key*)iter->item, sigtype, 1);
} else {
TRACE(("That was whacky. We got told that a key was valid, but it didn't match our list. Sounds like dodgy code on Dropbear's part"))
}
@@ -120,31 +122,32 @@ void recv_msg_userauth_pk_ok() {
TRACE(("leave recv_msg_userauth_pk_ok"))
}
-void cli_buf_put_sign(buffer* buf, sign_key *key, int type,
+static void cli_buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype,
const buffer *data_buf) {
#if DROPBEAR_CLI_AGENTFWD
+ // TODO: rsa-sha256 agent
if (key->source == SIGNKEY_SOURCE_AGENT) {
/* Format the agent signature ourselves, as buf_put_sign would. */
buffer *sigblob;
sigblob = buf_new(MAX_PUBKEY_SIZE);
- agent_buf_sign(sigblob, key, data_buf);
+ agent_buf_sign(sigblob, key, data_buf, sigtype);
buf_putbufstring(buf, sigblob);
buf_free(sigblob);
} else
#endif /* DROPBEAR_CLI_AGENTFWD */
{
- buf_put_sign(buf, key, type, data_buf);
+ buf_put_sign(buf, key, sigtype, data_buf);
}
}
-/* TODO: make it take an agent reference to use as well */
-static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
+static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype, int realsign) {
const char *algoname = NULL;
unsigned int algolen;
buffer* sigbuf = NULL;
+ enum signkey_type keytype = signkey_type_from_signature(sigtype);
- TRACE(("enter send_msg_userauth_pubkey"))
+ TRACE(("enter send_msg_userauth_pubkey sigtype %d", sigtype))
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
@@ -160,10 +163,9 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
buf_putbyte(ses.writepayload, realsign);
- algoname = signkey_name_from_type(type, &algolen);
-
+ algoname = signature_name_from_type(sigtype, &algolen);
buf_putstring(ses.writepayload, algoname, algolen);
- buf_put_pub_key(ses.writepayload, key, type);
+ buf_put_pub_key(ses.writepayload, key, keytype);
if (realsign) {
TRACE(("realsign"))
@@ -172,7 +174,7 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
sigbuf = buf_new(4 + ses.session_id->len + ses.writepayload->len);
buf_putbufstring(sigbuf, ses.session_id);
buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len);
- cli_buf_put_sign(ses.writepayload, key, type, sigbuf);
+ cli_buf_put_sign(ses.writepayload, key, sigtype, sigbuf);
buf_free(sigbuf); /* Nothing confidential in the buffer */
}
@@ -182,7 +184,7 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
/* Returns 1 if a key was tried */
int cli_auth_pubkey() {
-
+ enum signature_type sigtype;
TRACE(("enter cli_auth_pubkey"))
#if DROPBEAR_CLI_AGENTFWD
@@ -190,13 +192,79 @@ 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
+ /* 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) {
+#if DROPBEAR_RSA
+ if (key->type == DROPBEAR_SIGNKEY_RSA) {
+#if DROPBEAR_RSA_SHA256
+ 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) {
+#if 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;
/* Send a trial request */
- send_msg_userauth_pubkey(key, key->type, 0);
+ send_msg_userauth_pubkey(key, sigtype, 0);
cli_ses.lastprivkey = key;
TRACE(("leave cli_auth_pubkey-success"))
return 1;