Mercurial > dropbear
comparison common-session.c @ 1069:2fa71c3b2827 pam
merge pam branch up to date
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 16 Mar 2015 21:34:05 +0800 |
parents | 9a6395ddb1b6 4c733310c21d |
children | 16379795f80b |
comparison
equal
deleted
inserted
replaced
1068:9a6395ddb1b6 | 1069:2fa71c3b2827 |
---|---|
32 #include "ssh.h" | 32 #include "ssh.h" |
33 #include "dbrandom.h" | 33 #include "dbrandom.h" |
34 #include "kex.h" | 34 #include "kex.h" |
35 #include "channel.h" | 35 #include "channel.h" |
36 #include "runopts.h" | 36 #include "runopts.h" |
37 #include "netio.h" | |
37 | 38 |
38 static void checktimeouts(); | 39 static void checktimeouts(); |
39 static long select_timeout(); | 40 static long select_timeout(); |
40 static int ident_readln(int fd, char* buf, int count); | 41 static int ident_readln(int fd, char* buf, int count); |
41 static void read_session_identification(); | 42 static void read_session_identification(); |
50 int exitflag = 0; /* GLOBAL */ | 51 int exitflag = 0; /* GLOBAL */ |
51 | 52 |
52 /* called only at the start of a session, set up initial state */ | 53 /* called only at the start of a session, set up initial state */ |
53 void common_session_init(int sock_in, int sock_out) { | 54 void common_session_init(int sock_in, int sock_out) { |
54 time_t now; | 55 time_t now; |
56 | |
57 #ifdef DEBUG_TRACE | |
58 debug_start_net(); | |
59 #endif | |
55 | 60 |
56 TRACE(("enter session_init")) | 61 TRACE(("enter session_init")) |
57 | 62 |
58 ses.sock_in = sock_in; | 63 ses.sock_in = sock_in; |
59 ses.sock_out = sock_out; | 64 ses.sock_out = sock_out; |
148 timeout.tv_usec = 0; | 153 timeout.tv_usec = 0; |
149 FD_ZERO(&writefd); | 154 FD_ZERO(&writefd); |
150 FD_ZERO(&readfd); | 155 FD_ZERO(&readfd); |
151 dropbear_assert(ses.payload == NULL); | 156 dropbear_assert(ses.payload == NULL); |
152 | 157 |
153 /* during initial setup we flush out the KEXINIT packet before | 158 /* We delay reading from the input socket during initial setup until |
154 * attempting to read the remote version string, which might block */ | 159 after we have written out our initial KEXINIT packet (empty writequeue). |
160 This means our initial packet can be in-flight while we're doing a blocking | |
161 read for the remote ident */ | |
155 if (ses.sock_in != -1 && (ses.remoteident || isempty(&ses.writequeue))) { | 162 if (ses.sock_in != -1 && (ses.remoteident || isempty(&ses.writequeue))) { |
156 FD_SET(ses.sock_in, &readfd); | 163 FD_SET(ses.sock_in, &readfd); |
157 } | 164 } |
158 if (ses.sock_out != -1 && !isempty(&ses.writequeue)) { | 165 if (ses.sock_out != -1 && !isempty(&ses.writequeue)) { |
159 FD_SET(ses.sock_out, &writefd); | 166 FD_SET(ses.sock_out, &writefd); |
163 SIGCHLD in svr-chansession is the only one currently. */ | 170 SIGCHLD in svr-chansession is the only one currently. */ |
164 FD_SET(ses.signal_pipe[0], &readfd); | 171 FD_SET(ses.signal_pipe[0], &readfd); |
165 | 172 |
166 /* set up for channels which can be read/written */ | 173 /* set up for channels which can be read/written */ |
167 setchannelfds(&readfd, &writefd); | 174 setchannelfds(&readfd, &writefd); |
175 | |
176 /* Pending connections to test */ | |
177 set_connect_fds(&writefd); | |
168 | 178 |
169 val = select(ses.maxfd+1, &readfd, &writefd, NULL, &timeout); | 179 val = select(ses.maxfd+1, &readfd, &writefd, NULL, &timeout); |
170 | 180 |
171 if (exitflag) { | 181 if (exitflag) { |
172 dropbear_exit("Terminated by signal"); | 182 dropbear_exit("Terminated by signal"); |
211 * will be ready for a new packet */ | 221 * will be ready for a new packet */ |
212 if (ses.payload != NULL) { | 222 if (ses.payload != NULL) { |
213 process_packet(); | 223 process_packet(); |
214 } | 224 } |
215 } | 225 } |
216 | 226 |
217 /* if required, flush out any queued reply packets that | 227 /* if required, flush out any queued reply packets that |
218 were being held up during a KEX */ | 228 were being held up during a KEX */ |
219 maybe_flush_reply_queue(); | 229 maybe_flush_reply_queue(); |
230 | |
231 handle_connect_fds(&writefd); | |
220 | 232 |
221 /* process pipes etc for the channels, ses.dataallowed == 0 | 233 /* process pipes etc for the channels, ses.dataallowed == 0 |
222 * during rekeying ) */ | 234 * during rekeying ) */ |
223 channelio(&readfd, &writefd); | 235 channelio(&readfd, &writefd); |
224 | 236 |
237 } /* for(;;) */ | 249 } /* for(;;) */ |
238 ses.recursion_count--; | 250 ses.recursion_count--; |
239 ses.exit_recursion = 0; | 251 ses.exit_recursion = 0; |
240 } | 252 } |
241 | 253 |
254 static void cleanup_buf(buffer **buf) { | |
255 if (!*buf) { | |
256 return; | |
257 } | |
258 buf_burn(*buf); | |
259 buf_free(*buf); | |
260 *buf = NULL; | |
261 } | |
262 | |
242 /* clean up a session on exit */ | 263 /* clean up a session on exit */ |
243 void session_cleanup() { | 264 void session_cleanup() { |
244 | 265 |
245 TRACE(("enter session_cleanup")) | 266 TRACE(("enter session_cleanup")) |
246 | 267 |
248 if (!sessinitdone) { | 269 if (!sessinitdone) { |
249 TRACE(("leave session_cleanup: !sessinitdone")) | 270 TRACE(("leave session_cleanup: !sessinitdone")) |
250 return; | 271 return; |
251 } | 272 } |
252 | 273 |
274 /* Beware of changing order of functions here. */ | |
275 | |
276 /* Must be before extra_session_cleanup() */ | |
277 chancleanup(); | |
278 | |
253 if (ses.extra_session_cleanup) { | 279 if (ses.extra_session_cleanup) { |
254 ses.extra_session_cleanup(); | 280 ses.extra_session_cleanup(); |
255 } | 281 } |
256 | 282 |
257 chancleanup(); | 283 /* After these are freed most functions will exit */ |
258 | 284 #ifdef DROPBEAR_CLEANUP |
259 /* Cleaning up keys must happen after other cleanup | 285 /* listeners call cleanup functions, this should occur before |
260 functions which might queue packets */ | 286 other session state is freed. */ |
261 if (ses.session_id) { | 287 remove_all_listeners(); |
262 buf_burn(ses.session_id); | 288 |
263 buf_free(ses.session_id); | 289 remove_connect_pending(); |
264 ses.session_id = NULL; | 290 |
265 } | 291 while (!isempty(&ses.writequeue)) { |
266 if (ses.hash) { | 292 buf_free(dequeue(&ses.writequeue)); |
267 buf_burn(ses.hash); | 293 } |
268 buf_free(ses.hash); | 294 |
269 ses.hash = NULL; | 295 m_free(ses.remoteident); |
270 } | 296 m_free(ses.authstate.pw_dir); |
297 m_free(ses.authstate.pw_name); | |
298 m_free(ses.authstate.pw_shell); | |
299 m_free(ses.authstate.pw_passwd); | |
300 m_free(ses.authstate.username); | |
301 #endif | |
302 | |
303 cleanup_buf(&ses.session_id); | |
304 cleanup_buf(&ses.hash); | |
305 cleanup_buf(&ses.payload); | |
306 cleanup_buf(&ses.readbuf); | |
307 cleanup_buf(&ses.writepayload); | |
308 cleanup_buf(&ses.kexhashbuf); | |
309 cleanup_buf(&ses.transkexinit); | |
310 if (ses.dh_K) { | |
311 mp_clear(ses.dh_K); | |
312 } | |
313 m_free(ses.dh_K); | |
314 | |
271 m_burn(ses.keys, sizeof(struct key_context)); | 315 m_burn(ses.keys, sizeof(struct key_context)); |
272 m_free(ses.keys); | 316 m_free(ses.keys); |
273 | 317 |
274 TRACE(("leave session_cleanup")) | 318 TRACE(("leave session_cleanup")) |
275 } | 319 } |
396 TRACE(("leave ident_readln: return %d", pos+1)) | 440 TRACE(("leave ident_readln: return %d", pos+1)) |
397 return pos+1; | 441 return pos+1; |
398 } | 442 } |
399 | 443 |
400 void ignore_recv_response() { | 444 void ignore_recv_response() { |
401 // Do nothing | 445 /* Do nothing */ |
402 TRACE(("Ignored msg_request_response")) | 446 TRACE(("Ignored msg_request_response")) |
403 } | 447 } |
404 | 448 |
405 static void send_msg_keepalive() { | 449 static void send_msg_keepalive() { |
450 time_t old_time_idle = ses.last_packet_time_idle; | |
451 struct Channel *chan = get_any_ready_channel(); | |
452 | |
406 CHECKCLEARTOWRITE(); | 453 CHECKCLEARTOWRITE(); |
407 time_t old_time_idle = ses.last_packet_time_idle; | |
408 | |
409 struct Channel *chan = get_any_ready_channel(); | |
410 | 454 |
411 if (chan) { | 455 if (chan) { |
412 /* Channel requests are preferable, more implementations | 456 /* Channel requests are preferable, more implementations |
413 handle them than SSH_MSG_GLOBAL_REQUEST */ | 457 handle them than SSH_MSG_GLOBAL_REQUEST */ |
414 TRACE(("keepalive channel request %d", chan->index)) | 458 TRACE(("keepalive channel request %d", chan->index)) |
544 int any = 0; | 588 int any = 0; |
545 unsigned int i; | 589 unsigned int i; |
546 | 590 |
547 TRACE(("update_channel_prio")) | 591 TRACE(("update_channel_prio")) |
548 | 592 |
593 if (ses.sock_out < 0) { | |
594 TRACE(("leave update_channel_prio: no socket")) | |
595 return; | |
596 } | |
597 | |
549 new_prio = DROPBEAR_PRIO_BULK; | 598 new_prio = DROPBEAR_PRIO_BULK; |
550 for (i = 0; i < ses.chansize; i++) { | 599 for (i = 0; i < ses.chansize; i++) { |
551 struct Channel *channel = ses.channels[i]; | 600 struct Channel *channel = ses.channels[i]; |
552 if (!channel || channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) { | 601 if (!channel || channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) { |
553 if (channel && channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) { | 602 if (channel && channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) { |
574 TRACE(("update_channel_prio: not any")) | 623 TRACE(("update_channel_prio: not any")) |
575 new_prio = DROPBEAR_PRIO_LOWDELAY; | 624 new_prio = DROPBEAR_PRIO_LOWDELAY; |
576 } | 625 } |
577 | 626 |
578 if (new_prio != ses.socket_prio) { | 627 if (new_prio != ses.socket_prio) { |
579 TRACE(("Dropbear priority transitioning %4.4s -> %4.4s", (char*)&ses.socket_prio, (char*)&new_prio)) | 628 TRACE(("Dropbear priority transitioning %d -> %d", ses.socket_prio, new_prio)) |
580 set_sock_priority(ses.sock_out, new_prio); | 629 set_sock_priority(ses.sock_out, new_prio); |
581 ses.socket_prio = new_prio; | 630 ses.socket_prio = new_prio; |
582 } | 631 } |
583 } | 632 } |
584 | 633 |