1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* 2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Dropbear - a SSH2 server 3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Copyright (c) 2002-2004 Matt Johnston 5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Copyright (c) 2004 by Mihnea Stoenescu 6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * All rights reserved. 7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy 9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal 10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * in the Software without restriction, including without limitation the rights 11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is 13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * furnished to do so, subject to the following conditions: 14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The above copyright notice and this permission notice shall be included in 16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * all copies or substantial portions of the Software. 17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * SOFTWARE. */ 25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "includes.h" 27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "session.h" 28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "dbutil.h" 29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "algo.h" 30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "buffer.h" 31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "session.h" 32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "kex.h" 33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "ssh.h" 34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "packet.h" 35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "bignum.h" 36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "random.h" 37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "runopts.h" 38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "signkey.h" 39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void checkhostkey(unsigned char* keyblob, unsigned int keybloblen); 42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define MAX_KNOWNHOSTS_LINE 4500 43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid send_msg_kexdh_init() { 45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project cli_ses.dh_e = (mp_int*)m_malloc(sizeof(mp_int)); 47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project cli_ses.dh_x = (mp_int*)m_malloc(sizeof(mp_int)); 48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_mp_init_multi(cli_ses.dh_e, cli_ses.dh_x, NULL); 49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project gen_kexdh_vals(cli_ses.dh_e, cli_ses.dh_x); 51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project CHECKCLEARTOWRITE(); 53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT); 54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putmpint(ses.writepayload, cli_ses.dh_e); 55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project encrypt_packet(); 56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ses.requirenext = SSH_MSG_KEXDH_REPLY; 57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Handle a diffie-hellman key exchange reply. */ 60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid recv_msg_kexdh_reply() { 61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project DEF_MP_INT(dh_f); 63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project sign_key *hostkey = NULL; 64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned int type, keybloblen; 65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char* keyblob = NULL; 66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("enter recv_msg_kexdh_reply")) 69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (cli_ses.kex_state != KEXDH_INIT_SENT) { 71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_exit("Received out-of-order kexdhreply"); 72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_mp_init(&dh_f); 74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project type = ses.newkeys->algo_hostkey; 75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("type is %d", type)) 76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project hostkey = new_sign_key(); 78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project keybloblen = buf_getint(ses.payload); 79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project keyblob = buf_getptr(ses.payload, keybloblen); 81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!ses.kexstate.donefirstkex) { 82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* Only makes sense the first time */ 83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project checkhostkey(keyblob, keybloblen); 84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (buf_get_pub_key(ses.payload, hostkey, &type) != DROPBEAR_SUCCESS) { 87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("failed getting pubkey")) 88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_exit("Bad KEX packet"); 89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (buf_getmpint(ses.payload, &dh_f) != DROPBEAR_SUCCESS) { 92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("failed getting mpint")) 93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_exit("Bad KEX packet"); 94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project kexdh_comb_key(cli_ses.dh_e, cli_ses.dh_x, &dh_f, hostkey); 97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project mp_clear(&dh_f); 98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project mp_clear_multi(cli_ses.dh_e, cli_ses.dh_x, NULL); 99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(cli_ses.dh_e); 100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(cli_ses.dh_x); 101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (buf_verify(ses.payload, hostkey, ses.hash, SHA1_HASH_SIZE) 103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project != DROPBEAR_SUCCESS) { 104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_exit("Bad hostkey signature"); 105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project sign_key_free(hostkey); 108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project hostkey = NULL; 109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project send_msg_newkeys(); 111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ses.requirenext = SSH_MSG_NEWKEYS; 112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("leave recv_msg_kexdh_init")) 113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void ask_to_confirm(unsigned char* keyblob, unsigned int keybloblen) { 116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char* fp = NULL; 118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project FILE *tty = NULL; 119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char response = 'z'; 120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fp = sign_key_fingerprint(keyblob, keybloblen); 122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (cli_opts.always_accept_key) { 123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fprintf(stderr, "\nHost '%s' key accepted unconditionally.\n(fingerprint %s)\n", 124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project cli_opts.remotehost, 125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fp); 126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(fp); 127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return; 128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fprintf(stderr, "\nHost '%s' is not in the trusted hosts file.\n(fingerprint %s)\nDo you want to continue connecting? (y/n)\n", 130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project cli_opts.remotehost, 131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fp); 132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(fp); 133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project tty = fopen(_PATH_TTY, "r"); 135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (tty) { 136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project response = getc(tty); 137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fclose(tty); 138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project response = getc(stdin); 140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (response == 'y') { 143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return; 144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_exit("Didn't validate host key"); 147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic FILE* open_known_hosts_file(int * readonly) 150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project FILE * hostsfile = NULL; 152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char * filename = NULL; 153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char * homedir = NULL; 154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project homedir = getenv("HOME"); 156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!homedir) { 158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct passwd * pw = NULL; 159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pw = getpwuid(getuid()); 160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (pw) { 161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project homedir = pw->pw_dir; 162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (homedir) { 166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned int len; 167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len = strlen(homedir); 168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project filename = m_malloc(len + 18); /* "/.ssh/known_hosts" and null-terminator*/ 169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project snprintf(filename, len+18, "%s/.ssh", homedir); 171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* Check that ~/.ssh exists - easiest way is just to mkdir */ 172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (mkdir(filename, S_IRWXU) != 0) { 173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (errno != EEXIST) { 174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_log(LOG_INFO, "Warning: failed creating %s/.ssh: %s", 175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project homedir, strerror(errno)); 176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("mkdir didn't work: %s", strerror(errno))) 177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto out; 178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project snprintf(filename, len+18, "%s/.ssh/known_hosts", homedir); 182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project hostsfile = fopen(filename, "a+"); 183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (hostsfile != NULL) { 185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *readonly = 0; 186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fseek(hostsfile, 0, SEEK_SET); 187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* We mightn't have been able to open it if it was read-only */ 189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (errno == EACCES || errno == EROFS) { 190f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("trying readonly: %s", strerror(errno))) 191f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *readonly = 1; 192f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project hostsfile = fopen(filename, "r"); 193f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 194f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 195f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 196f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 197f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (hostsfile == NULL) { 198f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("hostsfile didn't open: %s", strerror(errno))) 199f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_log(LOG_WARNING, "Failed to open %s/.ssh/known_hosts", 200f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project homedir); 201f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto out; 202f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 203f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 204f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectout: 205f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(filename); 206f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return hostsfile; 207f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 208f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 209f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void checkhostkey(unsigned char* keyblob, unsigned int keybloblen) { 210f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 211f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project FILE *hostsfile = NULL; 212f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int readonly = 0; 213f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned int hostlen, algolen; 214f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned long len; 215f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project const char *algoname = NULL; 216f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char * fingerprint = NULL; 217f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buffer * line = NULL; 218f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int ret; 219f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 220f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project hostsfile = open_known_hosts_file(&readonly); 221f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!hostsfile) { 222f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ask_to_confirm(keyblob, keybloblen); 223f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* ask_to_confirm will exit upon failure */ 224f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return; 225f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 226f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 227f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project line = buf_new(MAX_KNOWNHOSTS_LINE); 228f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project hostlen = strlen(cli_opts.remotehost); 229f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project algoname = signkey_name_from_type(ses.newkeys->algo_hostkey, &algolen); 230f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 231f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project do { 232f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (buf_getline(line, hostsfile) == DROPBEAR_FAILURE) { 233f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("failed reading line: prob EOF")) 234f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; 235f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 236f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 237f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* The line is too short to be sensible */ 238f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* "30" is 'enough to hold ssh-dss plus the spaces, ie so we don't 239f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * buf_getfoo() past the end and die horribly - the base64 parsing 240f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * code is what tiptoes up to the end nicely */ 241f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (line->len < (hostlen+30) ) { 242f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("line is too short to be sensible")) 243f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project continue; 244f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 245f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 246f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* Compare hostnames */ 247f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (strncmp(cli_opts.remotehost, buf_getptr(line, hostlen), 248f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project hostlen) != 0) { 249f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("hosts don't match")) 250f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project continue; 251f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 252f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 253f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(line, hostlen); 254f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (buf_getbyte(line) != ' ') { 255f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* there wasn't a space after the hostname, something dodgy */ 256f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("missing space afte matching hostname")) 257f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project continue; 258f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 259f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 260f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (strncmp(buf_getptr(line, algolen), algoname, algolen) != 0) { 261f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("algo doesn't match")) 262f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project continue; 263f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 264f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 265f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(line, algolen); 266f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (buf_getbyte(line) != ' ') { 267f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("missing space after algo")) 268f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project continue; 269f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 270f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 271f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* Now we're at the interesting hostkey */ 272f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret = cmp_base64_key(keyblob, keybloblen, algoname, algolen, 273f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project line, &fingerprint); 274f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 275f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ret == DROPBEAR_SUCCESS) { 276f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* Good matching key */ 277f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("good matching key")) 278f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto out; 279f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 280f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 281f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* The keys didn't match. eep. Note that we're "leaking" 282f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project the fingerprint strings here, but we're exiting anyway */ 283f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_exit("\n\nHost key mismatch for %s !\n" 284f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project "Fingerprint is %s\n" 285f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project "Expected %s\n" 286f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project "If you know that the host key is correct you can\nremove the bad entry from ~/.ssh/known_hosts", 287f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project cli_opts.remotehost, 288f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project sign_key_fingerprint(keyblob, keybloblen), 289f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fingerprint ? fingerprint : "UNKNOWN"); 290f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } while (1); /* keep going 'til something happens */ 291f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 292f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* Key doesn't exist yet */ 293f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ask_to_confirm(keyblob, keybloblen); 294f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 295f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* If we get here, they said yes */ 296f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 297f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (readonly) { 298f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("readonly")) 299f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto out; 300f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 301f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 302f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!cli_opts.always_accept_key) { 303f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* put the new entry in the file */ 304f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fseek(hostsfile, 0, SEEK_END); /* In case it wasn't opened append */ 305f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_setpos(line, 0); 306f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_setlen(line, 0); 307f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putbytes(line, ses.remotehost, hostlen); 308f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putbyte(line, ' '); 309f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putbytes(line, algoname, algolen); 310f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putbyte(line, ' '); 311f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len = line->size - line->pos; 312f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("keybloblen %d, len %d", keybloblen, len)) 313f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* The only failure with base64 is buffer_overflow, but buf_getwriteptr 314f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * will die horribly in the case anyway */ 315f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project base64_encode(keyblob, keybloblen, buf_getwriteptr(line, len), &len); 316f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrwritepos(line, len); 317f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putbyte(line, '\n'); 318f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_setpos(line, 0); 319f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fwrite(buf_getptr(line, line->len), line->len, 1, hostsfile); 320f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* We ignore errors, since there's not much we can do about them */ 321f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 322f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 323f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectout: 324f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (hostsfile != NULL) { 325f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fclose(hostsfile); 326f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 327f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (line != NULL) { 328f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_free(line); 329f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 330f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 331