Mercurial > dropbear
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 |