Mercurial > dropbear
changeset 51:095d689fed16
- Hostkey checking is mostly there, just aren't appending yet.
- Rearranged various bits of the fingerprint/base64 type code, so it
can be shared between versions
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sun, 08 Aug 2004 16:17:05 +0000 (2004-08-08) |
parents | cc59bfcdee17 |
children | c8fcd4841956 |
files | cli-kex.c dbutil.c options.h signkey.c signkey.h svr-authpubkey.c |
diffstat | 6 files changed, 258 insertions(+), 111 deletions(-) [+] |
line wrap: on
line diff
--- a/cli-kex.c Sat Aug 07 15:50:58 2004 +0000 +++ b/cli-kex.c Sun Aug 08 16:17:05 2004 +0000 @@ -37,6 +37,8 @@ #include "signkey.h" +static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen); +#define MAX_KNOWNHOSTS_LINE 4500 void send_msg_kexdh_init() { @@ -58,14 +60,22 @@ mp_int dh_f; sign_key *hostkey = NULL; - int type, keylen; + unsigned int type, keybloblen; + unsigned char* keyblob = NULL; + TRACE(("enter recv_msg_kexdh_reply")); type = ses.newkeys->algo_hostkey; TRACE(("type is %d", type)); hostkey = new_sign_key(); - keylen = buf_getint(ses.payload); + keybloblen = buf_getint(ses.payload); + + keyblob = buf_getptr(ses.payload, keybloblen); + if (!ses.kexstate.donefirstkex) { + /* Only makes sense the first time */ + checkhostkey(keyblob, keybloblen); + } if (buf_get_pub_key(ses.payload, hostkey, &type) != DROPBEAR_SUCCESS) { TRACE(("failed getting pubkey")); @@ -86,9 +96,6 @@ dropbear_exit("Bad hostkey signature"); } - /* XXX TODO */ - dropbear_log(LOG_WARNING,"Not checking hostkey fingerprint for the moment"); - sign_key_free(hostkey); hostkey = NULL; @@ -96,3 +103,123 @@ ses.requirenext = SSH_MSG_NEWKEYS; TRACE(("leave recv_msg_kexdh_init")); } + +static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen) { + + char* fp = NULL; + + fp = sign_key_fingerprint(keyblob, keybloblen); + fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(fingerprint %s)\nDo you want to continue connecting? (y/n)\n", + cli_opts.remotehost, + fp); + + if (getc(stdin) == 'y') { + m_free(fp); + return; + } + + dropbear_exit("Didn't validate host key"); +} + +static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) { + + char * filename = NULL; + FILE *hostsfile = NULL; + struct passwd *pw = NULL; + unsigned int len, hostlen; + const char *algoname = NULL; + buffer * line = NULL; + int ret; + + pw = getpwuid(getuid()); + + if (pw == NULL) { + dropbear_exit("Failed to get homedir"); + } + + len = strlen(pw->pw_dir); + filename = m_malloc(len + 18); /* "/.ssh/known_hosts" and null-terminator*/ + + snprintf(filename, len+18, "%s/.ssh", pw->pw_dir); + /* Check that ~/.ssh exists - easiest way is just to mkdir */ + if (mkdir(filename, S_IRWXU) != 0) { + if (errno != EEXIST) { + ask_to_confirm(keyblob, keybloblen); + goto out; /* only get here on success */ + } + } + + snprintf(filename, len+18, "%s/.ssh/known_hosts", pw->pw_dir); + hostsfile = fopen(filename, "r+"); + if (hostsfile == NULL) { + ask_to_confirm(keyblob, keybloblen); + goto out; /* We only get here on success */ + } + + line = buf_new(MAX_KNOWNHOSTS_LINE); + hostlen = strlen(cli_opts.remotehost); + + do { + if (buf_getline(line, hostsfile) == DROPBEAR_FAILURE) { + TRACE(("failed reading line: prob EOF")); + break; + } + + /* The line is too short to be sensible */ + /* "30" is 'enough to hold ssh-dss plus the spaces, ie so we don't