/* Check all timeouts which are required. Currently these are the time for * user authentication, and the automatic rekeying. */ static void checktimeouts() { struct timeval tv; long secs; if (gettimeofday(&tv, 0) < 0) { dropbear_exit("Error getting time"); } secs = tv.tv_sec; if (!ses.authstate.authdone) { if (secs - ses.connecttime >= AUTH_TIMEOUT) { dropbear_close("Timeout before userauth"); } } /* we can't rekey if we haven't done remote ident exchange yet */ if (ses.remoteident == NULL) { return; } if (!ses.kexstate.sentkexinit && (secs - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT || ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)){ TRACE(("rekeying after timeout or max data reached")); send_msg_kexinit(); } }
void cli_session(int sock_in, int sock_out) { seedrandom(); crypto_init(); common_session_init(sock_in, sock_out); chaninitialise(cli_chantypes); /* Set up cli_ses vars */ cli_session_init(); /* Ready to go */ sessinitdone = 1; /* Exchange identification */ session_identification(); send_msg_kexinit(); session_loop(cli_sessionloop); /* Not reached */ }
void cli_session(int sock_in, int sock_out, struct dropbear_progress_connection *progress, pid_t proxy_cmd_pid) { common_session_init(sock_in, sock_out); if (progress) { connect_set_writequeue(progress, &ses.writequeue); } chaninitialise(cli_chantypes); /* Set up cli_ses vars */ cli_session_init(proxy_cmd_pid); /* Ready to go */ sessinitdone = 1; /* Exchange identification */ send_session_identification(); kexfirstinitialise(); /* initialise the kex state */ send_msg_kexinit(); session_loop(cli_sessionloop); /* Not reached */ }
void svr_session(int sock, int childpipe) { char *host, *port; size_t len; common_session_init(sock, sock); svr_ses.connect_time = monotonic_now();; /* Initialise server specific parts of the session */ svr_ses.childpipe = childpipe; #ifdef USE_VFORK svr_ses.server_pid = getpid(); #endif svr_authinitialise(); chaninitialise(svr_chantypes); svr_chansessinitialise(); /* for logging the remote address */ get_socket_address(ses.sock_in, NULL, NULL, &host, &port, 0); len = strlen(host) + strlen(port) + 2; svr_ses.addrstring = m_malloc(len); snprintf(svr_ses.addrstring, len, "%s:%s", host, port); m_free(host); m_free(port); get_socket_address(ses.sock_in, NULL, NULL, &svr_ses.remotehost, NULL, 1); /* set up messages etc */ ses.remoteclosed = svr_remoteclosed; ses.extra_session_cleanup = svr_session_cleanup; /* packet handlers */ ses.packettypes = svr_packettypes; ses.isserver = 1; /* We're ready to go now */ sessinitdone = 1; /* exchange identification, version etc */ send_session_identification(); kexfirstinitialise(); /* initialise the kex state */ /* start off with key exchange */ send_msg_kexinit(); /* Run the main for loop. NULL is for the dispatcher - only the client * code makes use of it */ session_loop(svr_sessionloop); /* Not reached */ }
void svr_session(int sock, int childpipe, char* remotehost, char *addrstring) { struct timeval timeout; reseedrandom(); crypto_init(); common_session_init(sock, remotehost); /* Initialise server specific parts of the session */ svr_ses.childpipe = childpipe; svr_ses.addrstring = addrstring; svr_authinitialise(); chaninitialise(svr_chantypes); svr_chansessinitialise(); if (gettimeofday(&timeout, 0) < 0) { dropbear_exit("Error getting time"); } ses.connecttimeout = timeout.tv_sec + AUTH_TIMEOUT; /* set up messages etc */ ses.remoteclosed = svr_remoteclosed; /* packet handlers */ ses.packettypes = svr_packettypes; ses.buf_match_algo = svr_buf_match_algo; ses.isserver = 1; /* We're ready to go now */ sessinitdone = 1; /* exchange identification, version etc */ session_identification(); /* start off with key exchange */ send_msg_kexinit(); /* Run the main for loop. NULL is for the dispatcher - only the client * code makes use of it */ session_loop(NULL); /* Not reached */ }
void svr_session(int sock, int childpipe, char* remotehost, char *addrstring) { reseedrandom(); crypto_init(); common_session_init(sock, sock, remotehost); /* Initialise server specific parts of the session */ svr_ses.childpipe = childpipe; svr_ses.addrstring = addrstring; #ifdef __uClinux__ svr_ses.server_pid = getpid(); #endif svr_ses.addrstring = addrstring; svr_authinitialise(); chaninitialise(svr_chantypes); svr_chansessinitialise(); ses.connect_time = time(NULL); /* set up messages etc */ ses.remoteclosed = svr_remoteclosed; /* packet handlers */ ses.packettypes = svr_packettypes; ses.buf_match_algo = svr_buf_match_algo; ses.isserver = 1; /* We're ready to go now */ sessinitdone = 1; /* exchange identification, version etc */ session_identification(); /* start off with key exchange */ send_msg_kexinit(); /* Run the main for loop. NULL is for the dispatcher - only the client * code makes use of it */ session_loop(NULL); /* Not reached */ }
/* Executed upon receiving a kexinit message from the client to initiate * key exchange. If we haven't already done so, we send the list of our * preferred algorithms. The client's requested algorithms are processed, * and we calculate the first portion of the key-exchange-hash for used * later in the key exchange. No response is sent, as the client should * initiate the diffie-hellman key exchange */ void recv_msg_kexinit() { TRACE(("enter recv_msg_kexinit")); if (!ses.kexstate.sentkexinit) { /* we need to send a kex packet */ send_msg_kexinit(); TRACE(("continue recv_msg_kexinit: sent kexinit")); } /* read the client's choice of algos */ read_kex(); /* start the kex hash */ ses.kexhashbuf = buf_new(MAX_KEXHASHBUF); /* V_C, the client's version string (CR and NL excluded) */ buf_putstring(ses.kexhashbuf, ses.remoteident, strlen((char*)ses.remoteident)); /* V_S, the server's version string (CR and NL excluded) */ buf_putstring(ses.kexhashbuf, (unsigned char*)LOCAL_IDENT, strlen(LOCAL_IDENT)); /* I_C, the payload of the client's SSH_MSG_KEXINIT */ buf_setpos(ses.payload, 0); buf_putstring(ses.kexhashbuf, buf_getptr(ses.payload, ses.payload->len), ses.payload->len); /* I_S, the payload of the server's SSH_MSG_KEXINIT */ buf_putstring(ses.kexhashbuf, buf_getptr(ses.transkexinit, ses.transkexinit->len), ses.transkexinit->len); buf_free(ses.transkexinit); ses.transkexinit = NULL; /* the rest of ses.kexhashbuf will be done after DH exchange */ ses.kexstate.recvkexinit = 1; ses.expecting = SSH_MSG_KEXDH_INIT; TRACE(("leave recv_msg_kexinit")); }
void child_session(int sock, runopts *opts, int childpipe, struct sockaddr *remoteaddr) { fd_set readfd, writefd; struct timeval timeout; int val; crypto_init(); session_init(sock, opts, childpipe, remoteaddr); /* exchange identification, version etc */ session_identification(); seedrandom(); /* start off with key exchange */ send_msg_kexinit(); FD_ZERO(&readfd); FD_ZERO(&writefd); /* main loop, select()s for all sockets in use */ for(;;) { timeout.tv_sec = SELECT_TIMEOUT; timeout.tv_usec = 0; FD_ZERO(&writefd); FD_ZERO(&readfd); assert(ses.payload == NULL); if (ses.sock != -1) { FD_SET(ses.sock, &readfd); if (!isempty(&ses.writequeue)) { FD_SET(ses.sock, &writefd); } } /* set up for channels which require reading/writing */ if (ses.dataallowed) { setchannelfds(&readfd, &writefd); } val = select(ses.maxfd+1, &readfd, &writefd, NULL, &timeout); if (exitflag) { dropbear_exit("Terminated by signal"); } if (val < 0) { if (errno == EINTR) { continue; } else { dropbear_exit("Error in select"); } } /* check for auth timeout, rekeying required etc */ checktimeouts(); if (val == 0) { /* timeout */ TRACE(("select timeout")); continue; } /* process session socket's incoming/outgoing data */ if (ses.sock != -1) { if (FD_ISSET(ses.sock, &writefd) && !isempty(&ses.writequeue)) { write_packet(); } if (FD_ISSET(ses.sock, &readfd)) { read_packet(); } /* Process the decrypted packet. After this, the read buffer * will be ready for a new packet */ if (ses.payload != NULL) { process_packet(); } } /* process pipes etc for the channels, ses.dataallowed == 0 * during rekeying ) */ if (ses.dataallowed) { channelio(&readfd, &writefd); } } /* for(;;) */ }