Net-Dropbear
view release on metacpan or search on metacpan
dropbear/cli-session.c view on Meta::CPAN
NULL /* Null termination */
};
void cli_connected(int result, int sock, void* userdata, const char *errstring)
{
struct sshsession *myses = userdata;
if (result == DROPBEAR_FAILURE) {
dropbear_exit("Connect failed: %s", errstring);
}
myses->sock_in = myses->sock_out = sock;
DEBUG1(("cli_connected"))
ses.socket_prio = DROPBEAR_PRIO_NORMAL;
/* switches to lowdelay */
update_channel_prio();
}
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 */
ses.init_done = 1;
/* Exchange identification */
send_session_identification();
kexfirstinitialise(); /* initialise the kex state */
send_msg_kexinit();
session_loop(cli_sessionloop);
/* Not reached */
}
#if DROPBEAR_KEX_FIRST_FOLLOWS
static void cli_send_kex_first_guess() {
send_msg_kexdh_init();
}
#endif
static void cli_session_init(pid_t proxy_cmd_pid) {
cli_ses.state = STATE_NOTHING;
cli_ses.kex_state = KEX_NOTHING;
cli_ses.tty_raw_mode = 0;
cli_ses.winchange = 0;
/* We store std{in,out,err}'s flags, so we can set them back on exit
* (otherwise busybox's ash isn't happy */
cli_ses.stdincopy = dup(STDIN_FILENO);
cli_ses.stdinflags = fcntl(STDIN_FILENO, F_GETFL, 0);
cli_ses.stdoutcopy = dup(STDOUT_FILENO);
cli_ses.stdoutflags = fcntl(STDOUT_FILENO, F_GETFL, 0);
cli_ses.stderrcopy = dup(STDERR_FILENO);
cli_ses.stderrflags = fcntl(STDERR_FILENO, F_GETFL, 0);
cli_ses.retval = EXIT_SUCCESS; /* Assume it's clean if we don't get a
specific exit status */
cli_ses.proxy_cmd_pid = proxy_cmd_pid;
TRACE(("proxy command PID='%d'", proxy_cmd_pid));
/* Auth */
cli_ses.lastprivkey = NULL;
cli_ses.lastauthtype = 0;
cli_ses.is_trivial_auth = 1;
/* For printing "remote host closed" for the user */
ses.remoteclosed = cli_remoteclosed;
ses.extra_session_cleanup = cli_session_cleanup;
/* packet handlers */
ses.packettypes = cli_packettypes;
ses.isserver = 0;
#if DROPBEAR_KEX_FIRST_FOLLOWS
ses.send_kex_first_guess = cli_send_kex_first_guess;
#endif
}
static void send_msg_service_request(const char* servicename) {
TRACE(("enter send_msg_service_request: servicename='%s'", servicename))
CHECKCLEARTOWRITE();
buf_putbyte(ses.writepayload, SSH_MSG_SERVICE_REQUEST);
buf_putstring(ses.writepayload, servicename, strlen(servicename));
encrypt_packet();
TRACE(("leave send_msg_service_request"))
}
static void recv_msg_service_accept(void) {
/* do nothing, if it failed then the server MUST have disconnected */
}
/* This function drives the progress of the session - it initiates KEX,
* service, userauth and channel requests */
static void cli_sessionloop() {
TRACE2(("enter cli_sessionloop"))
if (ses.lastpacket == 0) {
TRACE2(("exit cli_sessionloop: no real packets yet"))
return;
}
dropbear/cli-session.c view on Meta::CPAN
#if DROPBEAR_CLI_NETCAT
if (cli_opts.netcat_host) {
cli_send_netcat_request();
} else
#endif
if (!cli_opts.no_cmd) {
cli_send_chansess_request();
}
#if DROPBEAR_CLI_LOCALTCPFWD
setup_localtcp();
#endif
#if DROPBEAR_CLI_REMOTETCPFWD
setup_remotetcp();
#endif
TRACE(("leave cli_sessionloop: running"))
cli_ses.state = SESSION_RUNNING;
return;
case SESSION_RUNNING:
if (ses.chancount < 1 && !cli_opts.no_cmd) {
cli_finished();
}
if (cli_ses.winchange) {
cli_chansess_winchange();
}
return;
/* XXX more here needed */
default:
break;
}
TRACE2(("leave cli_sessionloop: fell out"))
}
void kill_proxy_command(void) {
/*
* Send SIGHUP to proxy command if used. We don't wait() in
* case it hangs and instead rely on init to reap the child
*/
if (cli_ses.proxy_cmd_pid > 1) {
TRACE(("killing proxy command with PID='%d'", cli_ses.proxy_cmd_pid));
kill(cli_ses.proxy_cmd_pid, SIGHUP);
}
}
static void cli_session_cleanup(void) {
if (!ses.init_done) {
return;
}
kill_proxy_command();
/* Set std{in,out,err} back to non-blocking - busybox ash dies nastily if
* we don't revert the flags */
/* Ignore return value since there's nothing we can do */
(void)fcntl(cli_ses.stdincopy, F_SETFL, cli_ses.stdinflags);
(void)fcntl(cli_ses.stdoutcopy, F_SETFL, cli_ses.stdoutflags);
(void)fcntl(cli_ses.stderrcopy, F_SETFL, cli_ses.stderrflags);
/* Don't leak */
m_close(cli_ses.stdincopy);
m_close(cli_ses.stdoutcopy);
m_close(cli_ses.stderrcopy);
cli_tty_cleanup();
if (cli_ses.server_sig_algs) {
buf_free(cli_ses.server_sig_algs);
}
}
static void cli_finished() {
TRACE(("cli_finished()"))
session_cleanup();
fprintf(stderr, "Connection to %s@%s:%s closed.\n", cli_opts.username,
cli_opts.remotehost, cli_opts.remoteport);
exit(cli_ses.retval);
}
/* called when the remote side closes the connection */
static void cli_remoteclosed() {
/* XXX TODO perhaps print a friendlier message if we get this but have
* already sent/received disconnect message(s) ??? */
m_close(ses.sock_in);
m_close(ses.sock_out);
ses.sock_in = -1;
ses.sock_out = -1;
dropbear_exit("Remote closed the connection");
}
/* Operates in-place turning dirty (untrusted potentially containing control
* characters) text into clean text.
* Note: this is safe only with ascii - other charsets could have problems. */
void cleantext(char* dirtytext) {
unsigned int i, j;
char c;
j = 0;
for (i = 0; dirtytext[i] != '\0'; i++) {
c = dirtytext[i];
/* We can ignore '\r's */
if ( (c >= ' ' && c <= '~') || c == '\n' || c == '\t') {
dirtytext[j] = c;
j++;
}
}
/* Null terminate */
dirtytext[j] = '\0';
}
( run in 0.856 second using v1.01-cache-2.11-cpan-39bf76dae61 )