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