comparison common-session.c @ 989:73ea0dce9a57 pam

Merge up to date
author Matt Johnston <matt@ucc.asn.au>
date Fri, 23 Jan 2015 21:38:47 +0800
parents bae0b34bc059 0bb16232e7c4
children 9a6395ddb1b6
comparison
equal deleted inserted replaced
925:bae0b34bc059 989:73ea0dce9a57
49 /* this is set when we get SIGINT or SIGTERM, the handler is in main.c */ 49 /* this is set when we get SIGINT or SIGTERM, the handler is in main.c */
50 int exitflag = 0; /* GLOBAL */ 50 int exitflag = 0; /* GLOBAL */
51 51
52 /* called only at the start of a session, set up initial state */ 52 /* called only at the start of a session, set up initial state */
53 void common_session_init(int sock_in, int sock_out) { 53 void common_session_init(int sock_in, int sock_out) {
54 time_t now;
54 55
55 TRACE(("enter session_init")) 56 TRACE(("enter session_init"))
56 57
57 ses.sock_in = sock_in; 58 ses.sock_in = sock_in;
58 ses.sock_out = sock_out; 59 ses.sock_out = sock_out;
59 ses.maxfd = MAX(sock_in, sock_out); 60 ses.maxfd = MAX(sock_in, sock_out);
60 61
61 ses.connect_time = 0; 62 ses.socket_prio = DROPBEAR_PRIO_DEFAULT;
62 ses.last_trx_packet_time = 0; 63 /* Sets it to lowdelay */
63 ses.last_packet_time = 0; 64 update_channel_prio();
65
66 now = monotonic_now();
67 ses.last_packet_time_keepalive_recv = now;
68 ses.last_packet_time_idle = now;
69 ses.last_packet_time_any_sent = 0;
70 ses.last_packet_time_keepalive_sent = 0;
64 71
65 if (pipe(ses.signal_pipe) < 0) { 72 if (pipe(ses.signal_pipe) < 0) {
66 dropbear_exit("Signal pipe failed"); 73 dropbear_exit("Signal pipe failed");
67 } 74 }
68 setnonblocking(ses.signal_pipe[0]); 75 setnonblocking(ses.signal_pipe[0]);
187 } 194 }
188 195
189 /* check for auth timeout, rekeying required etc */ 196 /* check for auth timeout, rekeying required etc */
190 checktimeouts(); 197 checktimeouts();
191 198
192 /* process session socket's incoming/outgoing data */ 199 /* process session socket's incoming data */
193 if (ses.sock_out != -1) {
194 if (FD_ISSET(ses.sock_out, &writefd) && !isempty(&ses.writequeue)) {
195 write_packet();
196 }
197 }
198
199 if (ses.sock_in != -1) { 200 if (ses.sock_in != -1) {
200 if (FD_ISSET(ses.sock_in, &readfd)) { 201 if (FD_ISSET(ses.sock_in, &readfd)) {
201 if (!ses.remoteident) { 202 if (!ses.remoteident) {
202 /* blocking read of the version string */ 203 /* blocking read of the version string */
203 read_session_identification(); 204 read_session_identification();
219 220
220 /* process pipes etc for the channels, ses.dataallowed == 0 221 /* process pipes etc for the channels, ses.dataallowed == 0
221 * during rekeying ) */ 222 * during rekeying ) */
222 channelio(&readfd, &writefd); 223 channelio(&readfd, &writefd);
223 224
225 <<<<<<< local
224 if (ses.loop_handler) { 226 if (ses.loop_handler) {
225 ses.loop_handler(); 227 ses.loop_handler();
228 =======
229 /* process session socket's outgoing data */
230 if (ses.sock_out != -1) {
231 if (!isempty(&ses.writequeue)) {
232 write_packet();
233 }
234 }
235
236
237 if (loophandler) {
238 loophandler();
239 >>>>>>> other
226 } 240 }
227 241
228 } /* for(;;) */ 242 } /* for(;;) */
229 ses.recursion_count--; 243 ses.recursion_count--;
230 ses.exit_recursion = 0; 244 ses.exit_recursion = 0;
386 buf[pos] = '\0'; 400 buf[pos] = '\0';
387 TRACE(("leave ident_readln: return %d", pos+1)) 401 TRACE(("leave ident_readln: return %d", pos+1))
388 return pos+1; 402 return pos+1;
389 } 403 }
390 404
391 void send_msg_ignore() { 405 void ignore_recv_response() {
406 // Do nothing
407 TRACE(("Ignored msg_request_response"))
408 }
409
410 static void send_msg_keepalive() {
392 CHECKCLEARTOWRITE(); 411 CHECKCLEARTOWRITE();
393 buf_putbyte(ses.writepayload, SSH_MSG_IGNORE); 412 time_t old_time_idle = ses.last_packet_time_idle;
394 buf_putstring(ses.writepayload, "", 0); 413
414 struct Channel *chan = get_any_ready_channel();
415
416 if (chan) {
417 /* Channel requests are preferable, more implementations
418 handle them than SSH_MSG_GLOBAL_REQUEST */
419 TRACE(("keepalive channel request %d", chan->index))
420 start_send_channel_request(chan, DROPBEAR_KEEPALIVE_STRING);
421 } else {
422 TRACE(("keepalive global request"))
423 /* Some peers will reply with SSH_MSG_REQUEST_FAILURE,
424 some will reply with SSH_MSG_UNIMPLEMENTED, some will exit. */
425 buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST);
426 buf_putstring(ses.writepayload, DROPBEAR_KEEPALIVE_STRING,
427 strlen(DROPBEAR_KEEPALIVE_STRING));
428 }
429 buf_putbyte(ses.writepayload, 1); /* want_reply */
395 encrypt_packet(); 430 encrypt_packet();
431
432 ses.last_packet_time_keepalive_sent = monotonic_now();
433
434 /* keepalives shouldn't update idle timeout, reset it back */
435 ses.last_packet_time_idle = old_time_idle;
396 } 436 }
397 437
398 /* Check all timeouts which are required. Currently these are the time for 438 /* Check all timeouts which are required. Currently these are the time for
399 * user authentication, and the automatic rekeying. */ 439 * user authentication, and the automatic rekeying. */
400 static void checktimeouts() { 440 static void checktimeouts() {
401 441
402 time_t now; 442 time_t now;
403 443 now = monotonic_now();
404 now = time(NULL); 444
405
406 if (ses.connect_time != 0 && now - ses.connect_time >= AUTH_TIMEOUT) {
407 dropbear_close("Timeout before auth");
408 }
409
410 /* we can't rekey if we haven't done remote ident exchange yet */ 445 /* we can't rekey if we haven't done remote ident exchange yet */
411 if (ses.remoteident == NULL) { 446 if (ses.remoteident == NULL) {
412 return; 447 return;
413 } 448 }
414 449
417 || ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)) { 452 || ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)) {
418 TRACE(("rekeying after timeout or max data reached")) 453 TRACE(("rekeying after timeout or max data reached"))
419 send_msg_kexinit(); 454 send_msg_kexinit();
420 } 455 }
421 456
422 if (opts.keepalive_secs > 0 457 if (opts.keepalive_secs > 0 && ses.authstate.authdone) {
423 && now - ses.last_trx_packet_time >= opts.keepalive_secs) { 458 /* Avoid sending keepalives prior to auth - those are
424 send_msg_ignore(); 459 not valid pre-auth packet types */
425 } 460
426 461 /* Send keepalives if we've been idle */
427 if (opts.idle_timeout_secs > 0 && ses.last_packet_time > 0 462 if (now - ses.last_packet_time_any_sent >= opts.keepalive_secs) {
428 && now - ses.last_packet_time >= opts.idle_timeout_secs) { 463 send_msg_keepalive();
464 }
465
466 /* Also send an explicit keepalive message to trigger a response
467 if the remote end hasn't sent us anything */
468 if (now - ses.last_packet_time_keepalive_recv >= opts.keepalive_secs
469 && now - ses.last_packet_time_keepalive_sent >= opts.keepalive_secs) {
470 send_msg_keepalive();
471 }
472
473 if (now - ses.last_packet_time_keepalive_recv
474 >= opts.keepalive_secs * DEFAULT_KEEPALIVE_LIMIT) {
475 dropbear_exit("Keepalive timeout");
476 }
477 }
478
479 if (opts.idle_timeout_secs > 0
480 && now - ses.last_packet_time_idle >= opts.idle_timeout_secs) {
429 dropbear_close("Idle timeout"); 481 dropbear_close("Idle timeout");
430 } 482 }
431 } 483 }
432 484
433 static long select_timeout() { 485 static long select_timeout() {
434 /* determine the minimum timeout that might be required, so 486 /* determine the minimum timeout that might be required, so
435 as to avoid waking when unneccessary */ 487 as to avoid waking when unneccessary */
436 long ret = LONG_MAX; 488 long ret = LONG_MAX;
437 if (KEX_REKEY_TIMEOUT > 0) 489 if (KEX_REKEY_TIMEOUT > 0)
438 ret = MIN(KEX_REKEY_TIMEOUT, ret); 490 ret = MIN(KEX_REKEY_TIMEOUT, ret);
439 if (AUTH_TIMEOUT > 0) 491 /* AUTH_TIMEOUT is only relevant before authdone */
492 if (ses.authstate.authdone != 1 && AUTH_TIMEOUT > 0)
440 ret = MIN(AUTH_TIMEOUT, ret); 493 ret = MIN(AUTH_TIMEOUT, ret);
441 if (opts.keepalive_secs > 0) 494 if (opts.keepalive_secs > 0)
442 ret = MIN(opts.keepalive_secs, ret); 495 ret = MIN(opts.keepalive_secs, ret);
443 if (opts.idle_timeout_secs > 0) 496 if (opts.idle_timeout_secs > 0)
444 ret = MIN(opts.idle_timeout_secs, ret); 497 ret = MIN(opts.idle_timeout_secs, ret);
445 return ret; 498 return ret;
446 } 499 }
447 500
448 const char* get_user_shell() { 501 const char* get_user_shell() {
449 /* an empty shell should be interpreted as "/bin/sh" */ 502 /* an empty shell should be interpreted as "/bin/sh" */
488 } 541 }
489 ses.authstate.pw_passwd = m_strdup(passwd_crypt); 542 ses.authstate.pw_passwd = m_strdup(passwd_crypt);
490 } 543 }
491 } 544 }
492 545
546 /* Called when channels are modified */
547 void update_channel_prio() {
548 enum dropbear_prio new_prio;
549 int any = 0;
550 unsigned int i;
551
552 TRACE(("update_channel_prio"))
553
554 new_prio = DROPBEAR_PRIO_BULK;
555 for (i = 0; i < ses.chansize; i++) {
556 struct Channel *channel = ses.channels[i];
557 if (!channel || channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
558 if (channel && channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
559 TRACE(("update_channel_prio: early %d", channel->index))
560 }
561 continue;
562 }
563 any = 1;
564 if (channel->prio == DROPBEAR_CHANNEL_PRIO_INTERACTIVE)
565 {
566 TRACE(("update_channel_prio: lowdelay %d", channel->index))
567 new_prio = DROPBEAR_PRIO_LOWDELAY;
568 break;
569 } else if (channel->prio == DROPBEAR_CHANNEL_PRIO_UNKNOWABLE
570 && new_prio == DROPBEAR_PRIO_BULK)
571 {
572 TRACE(("update_channel_prio: unknowable %d", channel->index))
573 new_prio = DROPBEAR_PRIO_DEFAULT;
574 }
575 }
576
577 if (any == 0) {
578 /* lowdelay during setup */
579 TRACE(("update_channel_prio: not any"))
580 new_prio = DROPBEAR_PRIO_LOWDELAY;
581 }
582
583 if (new_prio != ses.socket_prio) {
584 TRACE(("Dropbear priority transitioning %4.4s -> %4.4s", (char*)&ses.socket_prio, (char*)&new_prio))
585 set_sock_priority(ses.sock_out, new_prio);
586 ses.socket_prio = new_prio;
587 }
588 }
589