Mercurial > dropbear
view cli-kex.c @ 775:2f1c199b6e4b
requirenext fixup for firstkexfollows
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sun, 14 Apr 2013 23:16:16 +0800 |
parents | a9f2a6ae4eb5 |
children | 7dcb46da72d9 |
line wrap: on
line source
/* * Dropbear - a SSH2 server * * Copyright (c) 2002-2004 Matt Johnston * Copyright (c) 2004 by Mihnea Stoenescu * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "includes.h" #include "session.h" #include "dbutil.h" #include "algo.h" #include "buffer.h" #include "session.h" #include "kex.h" #include "ssh.h" #include "packet.h" #include "bignum.h" #include "random.h" #include "runopts.h" #include "signkey.h" static void checkhostkey(unsigned char* keyblob, unsigned int keybloblen); #define MAX_KNOWNHOSTS_LINE 4500 void send_msg_kexdh_init() { TRACE(("send_msg_kexdh_init()")) if ((cli_ses.dh_e && cli_ses.dh_x && cli_ses.dh_val_algo == ses.newkeys->algo_kex)) { TRACE(("reusing existing dh_e from first_kex_packet_follows")) } else { if (!cli_ses.dh_e || !cli_ses.dh_e) { cli_ses.dh_e = (mp_int*)m_malloc(sizeof(mp_int)); cli_ses.dh_x = (mp_int*)m_malloc(sizeof(mp_int)); m_mp_init_multi(cli_ses.dh_e, cli_ses.dh_x, NULL); } gen_kexdh_vals(cli_ses.dh_e, cli_ses.dh_x); cli_ses.dh_val_algo = ses.newkeys->algo_kex; } CHECKCLEARTOWRITE(); buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT); buf_putmpint(ses.writepayload, cli_ses.dh_e); encrypt_packet(); ses.requirenext[0] = SSH_MSG_KEXDH_REPLY; ses.requirenext[1] = SSH_MSG_KEXINIT; } /* Handle a diffie-hellman key exchange reply. */ void recv_msg_kexdh_reply() { DEF_MP_INT(dh_f); sign_key *hostkey = NULL; unsigned int type, keybloblen; unsigned char* keyblob = NULL; TRACE(("enter recv_msg_kexdh_reply")) if (cli_ses.kex_state != KEXDH_INIT_SENT) { dropbear_exit("Received out-of-order kexdhreply"); } m_mp_init(&dh_f); type = ses.newkeys->algo_hostkey; TRACE(("type is %d", type)) hostkey = new_sign_key(); 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")) dropbear_exit("Bad KEX packet"); } if (buf_getmpint(ses.payload, &dh_f) != DROPBEAR_SUCCESS) { TRACE(("failed getting mpint")) dropbear_exit("Bad KEX packet"); } kexdh_comb_key(cli_ses.dh_e, cli_ses.dh_x, &dh_f, hostkey); mp_clear(&dh_f); mp_clear_multi(cli_ses.dh_e, cli_ses.dh_x, NULL); m_free(cli_ses.dh_e); m_free(cli_ses.dh_x); cli_ses.dh_val_algo = DROPBEAR_KEX_NONE; if (buf_verify(ses.payload, hostkey, ses.hash, SHA1_HASH_SIZE) != DROPBEAR_SUCCESS) { dropbear_exit("Bad hostkey signature"); } sign_key_free(hostkey); hostkey = NULL; send_msg_newkeys(); ses.requirenext[0] = SSH_MSG_NEWKEYS; ses.requirenext[1] = 0; TRACE(("leave recv_msg_kexdh_init")) } static void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen) { char* fp = NULL; FILE *tty = NULL; char response = 'z'; fp = sign_key_fingerprint(keyblob, keybloblen); if (cli_opts.always_accept_key) { fprintf(stderr, "\nHost '%s' key accepted unconditionally.\n(fingerprint %s)\n", cli_opts.remotehost, fp); m_free(fp); return; } fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(fingerprint %s)\nDo you want to continue connecting? (y/n) ", cli_opts.remotehost, fp); m_free(fp); tty = fopen(_PATH_TTY, "r"); if (tty) { response = getc(tty); fclose(tty); } else { response = getc(stdin); } if (response == 'y') { return; } dropbear_exit("Didn't validate host key"); } static FILE* open_known_hosts_file(int * readonly) { FILE * hostsfile = NULL; char * filename = NULL; char * homedir = NULL; homedir = getenv("HOME"); if (!homedir) { struct passwd * pw = NULL; pw = getpwuid(getuid()); if (pw) { homedir = pw->pw_dir; } }