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,2003 Matt Johnston
5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * All rights reserved.
6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy
8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal
9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * in the Software without restriction, including without limitation the rights
10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is
12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * furnished to do so, subject to the following conditions:
13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The above copyright notice and this permission notice shall be included in
15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * all copies or substantial portions of the Software.
16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * SOFTWARE. */
24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "includes.h"
26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "session.h"
27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "dbutil.h"
28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "packet.h"
29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "algo.h"
30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "buffer.h"
31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "dss.h"
32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "ssh.h"
33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "random.h"
34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "kex.h"
35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "channel.h"
36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "atomicio.h"
37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void checktimeouts();
39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int ident_readln(int fd, char* buf, int count);
40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstruct sshsession ses; /* GLOBAL */
42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* need to know if the session struct has been initialised, this way isn't the
44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * cleanest, but works OK */
45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint sessinitdone = 0; /* GLOBAL */
46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* this is set when we get SIGINT or SIGTERM, the handler is in main.c */
48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint exitflag = 0; /* GLOBAL */
49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* called only at the start of a session, set up initial state */
53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid common_session_init(int sock, char* remotehost) {
54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter session_init"))
56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.remotehost = remotehost;
58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.sock = sock;
60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.maxfd = sock;
61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.connecttimeout = 0;
63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (pipe(ses.signal_pipe) < 0) {
65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_exit("signal pipe failed");
66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	setnonblocking(ses.signal_pipe[0]);
68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	setnonblocking(ses.signal_pipe[1]);
69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	kexfirstinitialise(); /* initialise the kex state */
71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.writepayload = buf_new(MAX_TRANS_PAYLOAD_LEN);
73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.transseq = 0;
74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.readbuf = NULL;
76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.decryptreadbuf = NULL;
77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.payload = NULL;
78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.recvseq = 0;
79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	initqueue(&ses.writequeue);
81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.requirenext = SSH_MSG_KEXINIT;
83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.dataallowed = 0; /* don't send data yet, we'll wait until after kex */
84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.ignorenext = 0;
85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.lastpacket = 0;
86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* set all the algos to none */
88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.keys = (struct key_context*)m_malloc(sizeof(struct key_context));
89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.newkeys = NULL;
90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.keys->recv_algo_crypt = &dropbear_nocipher;
91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.keys->trans_algo_crypt = &dropbear_nocipher;
92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.keys->recv_algo_mac = &dropbear_nohash;
94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.keys->trans_algo_mac = &dropbear_nohash;
95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.keys->algo_kex = -1;
97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.keys->algo_hostkey = -1;
98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.keys->recv_algo_comp = DROPBEAR_COMP_NONE;
99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.keys->trans_algo_comp = DROPBEAR_COMP_NONE;
100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifndef DISABLE_ZLIB
102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.keys->recv_zstream = NULL;
103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.keys->trans_zstream = NULL;
104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* key exchange buffers */
107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.session_id = NULL;
108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.kexhashbuf = NULL;
109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.transkexinit = NULL;
110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.dh_K = NULL;
111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.remoteident = NULL;
112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.chantypes = NULL;
114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.allowprivport = 0;
116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave session_init"))
118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid session_loop(void(*loophandler)()) {
121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	fd_set readfd, writefd;
123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct timeval timeout;
124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int val;
125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* main loop, select()s for all sockets in use */
127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	for(;;) {
128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		timeout.tv_sec = SELECT_TIMEOUT;
130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		timeout.tv_usec = 0;
131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		FD_ZERO(&writefd);
132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		FD_ZERO(&readfd);
133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_assert(ses.payload == NULL);
134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (ses.sock != -1) {
135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			FD_SET(ses.sock, &readfd);
136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			if (!isempty(&ses.writequeue)) {
137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				FD_SET(ses.sock, &writefd);
138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			}
139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* We get woken up when signal handlers write to this pipe.
142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		   SIGCHLD in svr-chansession is the only one currently. */
143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		FD_SET(ses.signal_pipe[0], &readfd);
144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* set up for channels which require reading/writing */
146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (ses.dataallowed) {
147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			setchannelfds(&readfd, &writefd);
148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		val = select(ses.maxfd+1, &readfd, &writefd, NULL, &timeout);
150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (exitflag) {
152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			dropbear_exit("Terminated by signal");
153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (val < 0 && errno != EINTR) {
156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			dropbear_exit("Error in select");
157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (val <= 0) {
160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			/* If we were interrupted or the select timed out, we still
161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			 * want to iterate over channels etc for reading, to handle
162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			 * server processes exiting etc.
163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			 * We don't want to read/write FDs. */
164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			FD_ZERO(&writefd);
165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			FD_ZERO(&readfd);
166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* We'll just empty out the pipe if required. We don't do
169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		any thing with the data, since the pipe's purpose is purely to
170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		wake up the select() above. */
171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (FD_ISSET(ses.signal_pipe[0], &readfd)) {
172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			char x;
173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			while (read(ses.signal_pipe[0], &x, 1) > 0) {}
174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* check for auth timeout, rekeying required etc */
177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		checktimeouts();
178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* process session socket's incoming/outgoing data */
180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (ses.sock != -1) {
181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			if (FD_ISSET(ses.sock, &writefd) && !isempty(&ses.writequeue)) {
182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				write_packet();
183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			}
184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			if (FD_ISSET(ses.sock, &readfd)) {
186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				read_packet();
187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			}
188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			/* Process the decrypted packet. After this, the read buffer
190f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			 * will be ready for a new packet */
191f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			if (ses.payload != NULL) {
192f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				process_packet();
193f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			}
194f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
195f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
196f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* process pipes etc for the channels, ses.dataallowed == 0
197f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		 * during rekeying ) */
198f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (ses.dataallowed) {
199f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			channelio(&readfd, &writefd);
200f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
201f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
202f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (loophandler) {
203f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			loophandler();
204f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
205f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
206f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	} /* for(;;) */
207f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
208f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* Not reached */
209f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
210f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
211f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* clean up a session on exit */
212f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid common_session_cleanup() {
213f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
214f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter session_cleanup"))
215f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
216f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* we can't cleanup if we don't know the session state */
217f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (!sessinitdone) {
218f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("leave session_cleanup: !sessinitdone"))
219f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		return;
220f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
221f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
222f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_free(ses.session_id);
223f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_burn(ses.keys, sizeof(struct key_context));
224f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_free(ses.keys);
225f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
226f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	chancleanup();
227f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
228f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave session_cleanup"))
229f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
230f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
231f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
232f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid session_identification() {
233f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
234f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* max length of 255 chars */
235f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	char linebuf[256];
236f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int len = 0;
237f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	char done = 0;
238f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int i;
239f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
240f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* write our version string, this blocks */
241f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (atomicio(write, ses.sock, LOCAL_IDENT "\r\n",
242f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				strlen(LOCAL_IDENT "\r\n")) == DROPBEAR_FAILURE) {
243f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		ses.remoteclosed();
244f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
245f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
246f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* If they send more than 50 lines, something is wrong */
247f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	for (i = 0; i < 50; i++) {
248f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		len = ident_readln(ses.sock, linebuf, sizeof(linebuf));
249f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
250f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (len < 0 && errno != EINTR) {
251f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			/* It failed */
252f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			break;
253f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
254f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
255f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (len >= 4 && memcmp(linebuf, "SSH-", 4) == 0) {
256f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			/* start of line matches */
257f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			done = 1;
258f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			break;
259f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
260f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
261f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
262f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (!done) {
263f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("err: %s for '%s'\n", strerror(errno), linebuf))
264f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		ses.remoteclosed();
265f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	} else {
266f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* linebuf is already null terminated */
267f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		ses.remoteident = m_malloc(len);
268f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		memcpy(ses.remoteident, linebuf, len);
269f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
270f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
271f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* Shall assume that 2.x will be backwards compatible. */
272f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if (strncmp(ses.remoteident, "SSH-2.", 6) != 0
273f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project            && strncmp(ses.remoteident, "SSH-1.99-", 9) != 0) {
274f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        dropbear_exit("Incompatible remote version '%s'", ses.remoteident);
275f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
276f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
277f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("remoteident: %s", ses.remoteident))
278f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
279f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
280f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
281f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* returns the length including null-terminating zero on success,
282f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * or -1 on failure */
283f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int ident_readln(int fd, char* buf, int count) {
284f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
285f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	char in;
286f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int pos = 0;
287f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int num = 0;
288f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	fd_set fds;
289f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct timeval timeout;
290f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
291f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter ident_readln"))
292f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
293f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (count < 1) {
294f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		return -1;
295f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
296f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
297f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	FD_ZERO(&fds);
298f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
299f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* select since it's a non-blocking fd */
300f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
301f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* leave space to null-terminate */
302f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	while (pos < count-1) {
303f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
304f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		FD_SET(fd, &fds);
305f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
306f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		timeout.tv_sec = 1;
307f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		timeout.tv_usec = 0;
308f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (select(fd+1, &fds, NULL, NULL, &timeout) < 0) {
309f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			if (errno == EINTR) {
310f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				continue;
311f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			}
312f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			TRACE(("leave ident_readln: select error"))
313f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			return -1;
314f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
315f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
316f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		checktimeouts();
317f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
318f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* Have to go one byte at a time, since we don't want to read past
319f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		 * the end, and have to somehow shove bytes back into the normal
320f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		 * packet reader */
321f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (FD_ISSET(fd, &fds)) {
322f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			num = read(fd, &in, 1);
323f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			/* a "\n" is a newline, "\r" we want to read in and keep going
324f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			 * so that it won't be read as part of the next line */
325f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			if (num < 0) {
326f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				/* error */
327f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				if (errno == EINTR) {
328f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project					continue; /* not a real error */
329f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				}
330f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				TRACE(("leave ident_readln: read error"))
331f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				return -1;
332f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			}
333f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			if (num == 0) {
334f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				/* EOF */
335f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				TRACE(("leave ident_readln: EOF"))
336f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				return -1;
337f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			}
338f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			if (in == '\n') {
339f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				/* end of ident string */
340f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				break;
341f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			}
342f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			/* we don't want to include '\r's */
343f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			if (in != '\r') {
344f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				buf[pos] = in;
345f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				pos++;
346f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			}
347f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
348f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
349f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
350f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf[pos] = '\0';
351f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave ident_readln: return %d", pos+1))
352f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	return pos+1;
353f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
354f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
355f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Check all timeouts which are required. Currently these are the time for
356f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * user authentication, and the automatic rekeying. */
357f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void checktimeouts() {
358f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
359f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct timeval tv;
360f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	long secs;
361f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
362f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (gettimeofday(&tv, 0) < 0) {
363f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_exit("Error getting time");
364f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
365f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
366f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	secs = tv.tv_sec;
367f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
368f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (ses.connecttimeout != 0 && secs > ses.connecttimeout) {
369f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			dropbear_close("Timeout before auth");
370f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
371f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
372f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* we can't rekey if we haven't done remote ident exchange yet */
373f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (ses.remoteident == NULL) {
374f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		return;
375f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
376f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
377f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (!ses.kexstate.sentkexinit
378f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			&& (secs - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT
379f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			|| ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)){
380f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("rekeying after timeout or max data reached"))
381f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		send_msg_kexinit();
382f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
383f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
384f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
385