int ssh_execute_message_callbacks(ssh_session session){ ssh_message msg=NULL; int ret; ssh_handle_packets(session, SSH_TIMEOUT_NONBLOCKING); if(!session->ssh_message_list) return SSH_OK; if(session->ssh_message_callback){ while((msg=ssh_message_pop_head(session)) != NULL) { ret=session->ssh_message_callback(session,msg, session->ssh_message_callback_data); if(ret==1){ ret = ssh_message_reply_default(msg); ssh_message_free(msg); if(ret != SSH_OK) return ret; } else { ssh_message_free(msg); } } } else { while((msg=ssh_message_pop_head(session)) != NULL) { ret = ssh_message_reply_default(msg); ssh_message_free(msg); if(ret != SSH_OK) return ret; } } return SSH_OK; }
int channel_write1(ssh_channel channel, const void *data, int len) { ssh_session session; int origlen = len; int effectivelen; const unsigned char *ptr=data; if (channel == NULL) { return -1; } session = channel->session; while (len > 0) { if (buffer_add_u8(session->out_buffer, SSH_CMSG_STDIN_DATA) < 0) { return -1; } effectivelen = len > 32000 ? 32000 : len; if (buffer_add_u32(session->out_buffer, htonl(effectivelen)) < 0 || buffer_add_data(session->out_buffer, ptr, effectivelen) < 0) { return -1; } ptr += effectivelen; len -= effectivelen; if (packet_send(session) == SSH_ERROR) { return -1; } ssh_handle_packets(session, SSH_TIMEOUT_NONBLOCKING); } if (ssh_blocking_flush(session,SSH_TIMEOUT_USER) == SSH_ERROR) return -1; return origlen; }
int ssh_send_keepalive(ssh_session session) { int rc; rc = ssh_buffer_pack(session->out_buffer, "bsb", SSH2_MSG_GLOBAL_REQUEST, "*****@*****.**", 1); if (rc != SSH_OK) { goto err; } if (packet_send(session) == SSH_ERROR) { goto err; } ssh_handle_packets(session, SSH_TIMEOUT_NONBLOCKING); SSH_LOG(SSH_LOG_PACKET, "Sent a keepalive"); return SSH_OK; err: ssh_set_error_oom(session); ssh_buffer_reinit(session->out_buffer); return SSH_ERROR; }
int ssh_send_keepalive(ssh_session session) { /* TODO check the reply and all that */ struct ssh_string_struct *req; int reply = 1; int rc = SSH_ERROR; enter_function(); req = ssh_string_from_char("*****@*****.**"); if (req == NULL) { ssh_set_error_oom(session); goto out; } if (buffer_add_u8(session->out_buffer, SSH2_MSG_GLOBAL_REQUEST) < 0 || buffer_add_ssh_string(session->out_buffer, req) < 0 || buffer_add_u8(session->out_buffer, reply == 0 ? 0 : 1) < 0) { ssh_set_error_oom(session); goto out; } if (packet_send(session) == SSH_ERROR) goto out; ssh_handle_packets(session, 0); ssh_log(session, SSH_LOG_PACKET, "Sent a keepalive"); rc = SSH_OK; out: ssh_string_free(req); leave_function(); return rc; }
int ssh_get_kex1(ssh_session session) { SSH_LOG(SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_PUBLIC_KEY"); /* Here the callback is called */ while(session->session_state==SSH_SESSION_STATE_INITIAL_KEX){ ssh_handle_packets(session, SSH_TIMEOUT_USER); } if (session->session_state==SSH_SESSION_STATE_ERROR) { return SSH_ERROR; } SSH_LOG(SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_SUCCESS"); /* Waiting for SSH_SMSG_SUCCESS */ while(session->session_state==SSH_SESSION_STATE_KEXINIT_RECEIVED){ ssh_handle_packets(session, SSH_TIMEOUT_USER); } if(session->session_state==SSH_SESSION_STATE_ERROR) { return SSH_ERROR; } SSH_LOG(SSH_LOG_PROTOCOL, "received SSH_SMSG_SUCCESS\n"); return SSH_OK; }
int ssh_get_kex1(ssh_session session) { int ret=SSH_ERROR; enter_function(); ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_PUBLIC_KEY"); /* Here the callback is called */ while(session->session_state==SSH_SESSION_STATE_INITIAL_KEX){ ssh_handle_packets(session, -2); } if(session->session_state==SSH_SESSION_STATE_ERROR) goto error; ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_SUCCESS"); /* Waiting for SSH_SMSG_SUCCESS */ while(session->session_state==SSH_SESSION_STATE_KEXINIT_RECEIVED){ ssh_handle_packets(session, -2); } if(session->session_state==SSH_SESSION_STATE_ERROR) goto error; ssh_log(session, SSH_LOG_PROTOCOL, "received SSH_SMSG_SUCCESS\n"); ret=SSH_OK; error: leave_function(); return ret; }
int channel_change_pty_size1(ssh_channel channel, int cols, int rows) { ssh_session session; if (channel == NULL) { return SSH_ERROR; } session = channel->session; if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){ ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state"); return SSH_ERROR; } if (buffer_add_u8(session->out_buffer, SSH_CMSG_WINDOW_SIZE) < 0 || buffer_add_u32(session->out_buffer, ntohl(rows)) < 0 || buffer_add_u32(session->out_buffer, ntohl(cols)) < 0 || buffer_add_u32(session->out_buffer, 0) < 0 || buffer_add_u32(session->out_buffer, 0) < 0) { return SSH_ERROR; } channel->request_state=SSH_CHANNEL_REQ_STATE_PENDING; if (packet_send(session) == SSH_ERROR) { return SSH_ERROR; } ssh_log(session, SSH_LOG_PROTOCOL, "Change pty size send"); while(channel->request_state==SSH_CHANNEL_REQ_STATE_PENDING){ ssh_handle_packets(session, SSH_TIMEOUT_INFINITE); } switch(channel->request_state){ case SSH_CHANNEL_REQ_STATE_ERROR: case SSH_CHANNEL_REQ_STATE_PENDING: case SSH_CHANNEL_REQ_STATE_NONE: channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; return SSH_ERROR; case SSH_CHANNEL_REQ_STATE_ACCEPTED: channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; ssh_log(session, SSH_LOG_PROTOCOL, "pty size changed"); return SSH_OK; case SSH_CHANNEL_REQ_STATE_DENIED: channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; ssh_log(session, SSH_LOG_RARE, "pty size change denied"); ssh_set_error(session, SSH_REQUEST_DENIED, "pty size change denied"); return SSH_ERROR; } // Not reached return SSH_ERROR; }
/* * This function acts as a meta select. * * First, channels are analyzed to seek potential can-write or can-read ones, * then if no channel has been elected, it goes in a loop with the posix * select(2). * This is made in two parts: protocol select and network select. The protocol * select does not use the network functions at all */ static int channel_protocol_select(CHANNEL **rchans, CHANNEL **wchans, CHANNEL **echans, CHANNEL **rout, CHANNEL **wout, CHANNEL **eout) { CHANNEL *chan; int i; int j = 0; for (i = 0; rchans[i] != NULL; i++) { chan = rchans[i]; while (chan->open && ssh_socket_data_available(chan->session->socket)) { ssh_handle_packets(chan->session); } if ((chan->stdout_buffer && buffer_get_len(chan->stdout_buffer) > 0) || (chan->stderr_buffer && buffer_get_len(chan->stderr_buffer) > 0) || chan->remote_eof) { rout[j] = chan; j++; } } rout[j] = NULL; j = 0; for(i = 0; wchans[i] != NULL; i++) { chan = wchans[i]; /* It's not our business to seek if the file descriptor is writable */ if (ssh_socket_data_writable(chan->session->socket) && chan->open && (chan->remote_window > 0)) { wout[j] = chan; j++; } } wout[j] = NULL; j = 0; for (i = 0; echans[i] != NULL; i++) { chan = echans[i]; if (!ssh_socket_is_open(chan->session->socket) || !chan->open) { eout[j] = chan; j++; } } eout[j] = NULL; return 0; }
static int wait_auth1_status(ssh_session session) { enter_function(); /* wait for a packet */ while(session->auth_state == SSH_AUTH_STATE_NONE) if (ssh_handle_packets(session, -2) != SSH_OK) break; ssh_log(session,SSH_LOG_PROTOCOL,"Auth state : %d",session->auth_state); leave_function(); switch(session->auth_state) { case SSH_AUTH_STATE_SUCCESS: return SSH_AUTH_SUCCESS; case SSH_AUTH_STATE_FAILED: return SSH_AUTH_DENIED; default: return SSH_AUTH_ERROR; } return SSH_AUTH_ERROR; }
/* Do the banner and key exchange */ int ssh_handle_key_exchange(ssh_session session) { int rc; rc = ssh_send_banner(session, 1); if (rc < 0) { return SSH_ERROR; } session->alive = 1; session->ssh_connection_callback = ssh_server_connection_callback; session->session_state = SSH_SESSION_STATE_SOCKET_CONNECTED; ssh_socket_set_callbacks(session->socket,&session->socket_callbacks); session->socket_callbacks.data=callback_receive_banner; session->socket_callbacks.exception=ssh_socket_exception_callback; session->socket_callbacks.userdata=session; rc = server_set_kex(session); if (rc < 0) { return SSH_ERROR; } while (session->session_state != SSH_SESSION_STATE_ERROR && session->session_state != SSH_SESSION_STATE_AUTHENTICATING && session->session_state != SSH_SESSION_STATE_DISCONNECTED) { /* * loop until SSH_SESSION_STATE_BANNER_RECEIVED or * SSH_SESSION_STATE_ERROR */ ssh_handle_packets(session, -2); ssh_log(session,SSH_LOG_PACKET, "ssh_handle_key_exchange: Actual state : %d", session->session_state); } if (session->session_state == SSH_SESSION_STATE_ERROR || session->session_state == SSH_SESSION_STATE_DISCONNECTED) { return SSH_ERROR; } return SSH_OK; }
int ssh_send_keepalive(ssh_session session) { struct ssh_string_struct *req; int rc; rc = buffer_add_u8(session->out_buffer, SSH2_MSG_GLOBAL_REQUEST); if (rc < 0) { goto err; } req = ssh_string_from_char("*****@*****.**"); if (req == NULL) { goto err; } rc = buffer_add_ssh_string(session->out_buffer, req); ssh_string_free(req); if (rc < 0) { goto err; } rc = buffer_add_u8(session->out_buffer, 1); if (rc < 0) { goto err; } if (packet_send(session) == SSH_ERROR) { goto err; } ssh_handle_packets(session, 0); SSH_LOG(SSH_LOG_PACKET, "Sent a keepalive"); return SSH_OK; err: ssh_set_error_oom(session); ssh_buffer_reinit(session->out_buffer); return SSH_ERROR; }
/** * @brief Retrieve a SSH message from a SSH session. * * @param[in] session The SSH session to get the message. * * @returns The SSH message received, NULL in case of error. * * @warning This function blocks until a message has been received. Betterset up * a callback if this behavior is unwanted. */ ssh_message ssh_message_get(ssh_session session) { ssh_message msg = NULL; enter_function(); msg=ssh_message_pop_head(session); if(msg) { leave_function(); return msg; } if(session->ssh_message_list == NULL) { session->ssh_message_list = ssh_list_new(); } do { if (ssh_handle_packets(session,-1) == SSH_ERROR) { leave_function(); return NULL; } msg=ssh_list_pop_head(ssh_message, session->ssh_message_list); } while(msg==NULL); leave_function(); return msg; }
/** * @brief Polls a channel for data to read. * * @param channel The channel to poll. * * @param is_stderr A boolean to select the stderr stream. * * @return The number of bytes available for reading, 0 if nothing is available * or SSH_ERROR on error. * * @warning When the channel is in EOF state, the function returns SSH_EOF. * * @see channel_is_eof() */ int channel_poll(CHANNEL *channel, int is_stderr){ SSH_SESSION *session = channel->session; BUFFER *stdbuf = channel->stdout_buffer; enter_function(); if (is_stderr) { stdbuf = channel->stderr_buffer; } while (buffer_get_rest_len(stdbuf) == 0 && channel->remote_eof == 0) { if (ssh_handle_packets(channel->session) <= 0) { break; } } if (channel->remote_eof) { leave_function(); return SSH_EOF; } leave_function(); return buffer_get_rest_len(stdbuf); }
int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col, int row) { ssh_session session; ssh_string str = NULL; if (channel == NULL) { return SSH_ERROR; } session = channel->session; if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){ ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state"); return SSH_ERROR; } str = ssh_string_from_char(terminal); if (str == NULL) { ssh_set_error_oom(session); return -1; } if (buffer_add_u8(session->out_buffer, SSH_CMSG_REQUEST_PTY) < 0 || buffer_add_ssh_string(session->out_buffer, str) < 0) { ssh_string_free(str); return -1; } ssh_string_free(str); if (buffer_add_u32(session->out_buffer, ntohl(row)) < 0 || buffer_add_u32(session->out_buffer, ntohl(col)) < 0 || buffer_add_u32(session->out_buffer, 0) < 0 || /* x */ buffer_add_u32(session->out_buffer, 0) < 0 || /* y */ buffer_add_u8(session->out_buffer, 0) < 0) { /* tty things */ return -1; } ssh_log(session, SSH_LOG_FUNCTIONS, "Opening a ssh1 pty"); channel->request_state = SSH_CHANNEL_REQ_STATE_PENDING; if (packet_send(session) == SSH_ERROR) { return -1; } while (channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING) { ssh_handle_packets(session, SSH_TIMEOUT_INFINITE); } switch(channel->request_state){ case SSH_CHANNEL_REQ_STATE_ERROR: case SSH_CHANNEL_REQ_STATE_PENDING: case SSH_CHANNEL_REQ_STATE_NONE: channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; return SSH_ERROR; case SSH_CHANNEL_REQ_STATE_ACCEPTED: channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; ssh_log(session, SSH_LOG_RARE, "PTY: Success"); return SSH_OK; case SSH_CHANNEL_REQ_STATE_DENIED: channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; ssh_set_error(session, SSH_REQUEST_DENIED, "Server denied PTY allocation"); ssh_log(session, SSH_LOG_RARE, "PTY: denied\n"); return SSH_ERROR; } // Not reached return SSH_ERROR; }