comparison common-session.c @ 4:fe6bca95afa7

Makefile.in contains updated files required
author Matt Johnston <matt@ucc.asn.au>
date Tue, 01 Jun 2004 02:46:09 +0000
parents
children ab00ef513e97
comparison
equal deleted inserted replaced
-1:000000000000 4:fe6bca95afa7
1 /*
2 * Dropbear - a SSH2 server
3 *
4 * Copyright (c) 2002,2003 Matt Johnston
5 * All rights reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE. */
24
25 #include "includes.h"
26 #include "session.h"
27 #include "dbutil.h"
28 #include "packet.h"
29 #include "algo.h"
30 #include "buffer.h"
31 #include "dss.h"
32 #include "ssh.h"
33 #include "random.h"
34 #include "kex.h"
35 #include "channel.h"
36 #include "atomicio.h"
37
38 struct sshsession ses;
39
40 /* need to know if the session struct has been initialised, this way isn't the
41 * cleanest, but works OK */
42 int sessinitdone = 0;
43
44 /* this is set when we get SIGINT or SIGTERM, the handler is in main.c */
45 int exitflag = 0;
46
47 static int ident_readln(int fd, char* buf, int count);
48
49
50 void(*session_remoteclosed)() = NULL;
51
52
53 /* called only at the start of a session, set up initial state */
54 void common_session_init(int sock, runopts *opts) {
55
56 TRACE(("enter session_init"));
57
58 ses.remoteaddr = NULL;
59 ses.remotehost = NULL;
60
61 ses.sock = sock;
62 ses.maxfd = sock;
63
64 ses.opts = opts;
65
66 ses.connecttimeout = 0;
67
68 kexinitialise(); /* initialise the kex state */
69 chaninitialise(); /* initialise the channel state */
70
71 ses.writepayload = buf_new(MAX_TRANS_PAYLOAD_LEN);
72 ses.transseq = 0;
73
74 ses.readbuf = NULL;
75 ses.decryptreadbuf = NULL;
76 ses.payload = NULL;
77 ses.recvseq = 0;
78
79 ses.expecting = SSH_MSG_KEXINIT;
80 ses.dataallowed = 0; /* don't send data yet, we'll wait until after kex */
81 ses.ignorenext = 0;
82
83 /* set all the algos to none */
84 ses.keys = (struct key_context*)m_malloc(sizeof(struct key_context));
85 ses.newkeys = NULL;
86 ses.keys->recv_algo_crypt = &dropbear_nocipher;
87 ses.keys->trans_algo_crypt = &dropbear_nocipher;
88
89 ses.keys->recv_algo_mac = &dropbear_nohash;
90 ses.keys->trans_algo_mac = &dropbear_nohash;
91
92 ses.keys->algo_kex = -1;
93 ses.keys->algo_hostkey = -1;
94 ses.keys->recv_algo_comp = DROPBEAR_COMP_NONE;
95 ses.keys->trans_algo_comp = DROPBEAR_COMP_NONE;
96
97 #ifndef DISABLE_ZLIB
98 ses.keys->recv_zstream = NULL;
99 ses.keys->trans_zstream = NULL;
100 #endif
101
102 /* key exchange buffers */
103 ses.session_id = NULL;
104 ses.kexhashbuf = NULL;
105 ses.transkexinit = NULL;
106 ses.dh_K = NULL;
107 ses.remoteident = NULL;
108
109
110 TRACE(("leave session_init"));
111 }
112
113 /* clean up a session on exit */
114 void common_session_cleanup() {
115
116 TRACE(("enter session_cleanup"));
117
118 /* we can't cleanup if we don't know the session state */
119 if (!sessinitdone) {
120 TRACE(("leave session_cleanup: !sessinitdone"));
121 return;
122 }
123
124 m_free(ses.session_id);
125 freerunopts(ses.opts);
126 m_burn(ses.keys, sizeof(struct key_context));
127 m_free(ses.keys);
128
129 chancleanup();
130
131 TRACE(("leave session_cleanup"));
132 }
133
134 /* Check all timeouts which are required. Currently these are the time for
135 * user authentication, and the automatic rekeying. */
136 void checktimeouts() {
137
138 struct timeval tv;
139 long secs;
140
141 if (gettimeofday(&tv, 0) < 0) {
142 dropbear_exit("Error getting time");
143 }
144
145 secs = tv.tv_sec;
146
147 if (ses.connecttimeout != 0 && secs > ses.connecttimeout) {
148 dropbear_close("Timeout before auth");
149 }
150
151 /* we can't rekey if we haven't done remote ident exchange yet */
152 if (ses.remoteident == NULL) {
153 return;
154 }
155
156 if (!ses.kexstate.sentkexinit
157 && (secs - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT
158 || ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)){
159 TRACE(("rekeying after timeout or max data reached"));
160 send_msg_kexinit();
161 }
162 }
163 void session_identification() {
164
165 /* max length of 255 chars */
166 char linebuf[256];
167 int len = 0;
168 char done = 0;
169
170 /* write our version string, this blocks */
171 if (atomicio(write, ses.sock, LOCAL_IDENT "\r\n",
172 strlen(LOCAL_IDENT "\r\n")) == DROPBEAR_FAILURE) {
173 dropbear_exit("Error writing ident string");
174 }
175
176 len = ident_readln(ses.sock, linebuf, 256);
177 if (len >= 4 && memcmp(linebuf, "SSH-", 4) == 0) {
178 /* start of line matches */
179 done = 1;
180 }
181
182 if (!done) {
183 dropbear_exit("Failed to get client version");
184 } else {
185 /* linebuf is already null terminated */
186 ses.remoteident = m_malloc(len);
187 memcpy(ses.remoteident, linebuf, len);
188 }
189
190 TRACE(("remoteident: %s", ses.remoteident));
191
192 }
193
194 /* returns the length including null-terminating zero on success,
195 * or -1 on failure */
196 static int ident_readln(int fd, char* buf, int count) {
197
198 char in;
199 int pos = 0;
200 int num = 0;
201 fd_set fds;
202 struct timeval timeout;
203
204 TRACE(("enter ident_readln"));
205
206 if (count < 1) {
207 return -1;
208 }
209
210 FD_ZERO(&fds);
211
212 /* select since it's a non-blocking fd */
213
214 /* leave space to null-terminate */
215 while (pos < count-1) {
216
217 FD_SET(fd, &fds);
218
219 timeout.tv_sec = 1;
220 timeout.tv_usec = 0;
221 if (select(fd+1, &fds, NULL, NULL, &timeout) < 0) {
222 if (errno == EINTR) {
223 continue;
224 }
225 TRACE(("leave ident_readln: select error"));
226 return -1;
227 }
228
229 checktimeouts();
230
231 /* Have to go one byte at a time, since we don't want to read past
232 * the end, and have to somehow shove bytes back into the normal
233 * packet reader */
234 if (FD_ISSET(fd, &fds)) {
235 num = read(fd, &in, 1);
236 /* a "\n" is a newline, "\r" we want to read in and keep going
237 * so that it won't be read as part of the next line */
238 if (num < 0) {
239 /* error */
240 if (errno == EINTR) {
241 continue; /* not a real error */
242 }
243 TRACE(("leave ident_readln: read error"));
244 return -1;
245 }
246 if (num == 0) {
247 /* EOF */
248 TRACE(("leave ident_readln: EOF"));
249 return -1;
250 }
251 if (in == '\n') {
252 /* end of ident string */
253 break;
254 }
255 /* we don't want to include '\r's */
256 if (in != '\r') {
257 buf[pos] = in;
258 pos++;
259 }
260 }
261 }
262
263 buf[pos] = '\0';
264 TRACE(("leave ident_readln: return %d", pos+1));
265 return pos+1;
266 }
267