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