static int packet_wait1(SSH_SESSION *session, int type, int blocking) { enter_function(); ssh_log(session, SSH_LOG_PROTOCOL, "packet_wait1 waiting for %d", type); do { if ((packet_read1(session) != SSH_OK) || (packet_translate(session) != SSH_OK)) { leave_function(); return SSH_ERROR; } ssh_log(session, SSH_LOG_PACKET, "packet_wait1() received a type %d packet", session->in_packet.type); switch (session->in_packet.type) { case SSH_MSG_DISCONNECT: packet_parse(session); leave_function(); return SSH_ERROR; case SSH_SMSG_STDOUT_DATA: case SSH_SMSG_STDERR_DATA: case SSH_SMSG_EXITSTATUS: if (channel_handle1(session,type) < 0) { leave_function(); return SSH_ERROR; } break; case SSH_MSG_DEBUG: case SSH_MSG_IGNORE: break; /* case SSH2_MSG_CHANNEL_CLOSE: packet_parse(session); break;; */ default: if (type && (type != session->in_packet.type)) { ssh_set_error(session, SSH_FATAL, "packet_wait1(): Received a %d type packet, but expected %d\n", session->in_packet.type, type); leave_function(); return SSH_ERROR; } leave_function(); return SSH_OK; } if (blocking == 0) { leave_function(); return SSH_OK; } } while(1); leave_function(); return SSH_OK; }
int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col, int row) { ssh_session session = channel->session; ssh_string str = NULL; str = string_from_char(terminal); if (str == NULL) { return -1; } if (buffer_add_u8(session->out_buffer, SSH_CMSG_REQUEST_PTY) < 0 || buffer_add_ssh_string(session->out_buffer, str) < 0) { string_free(str); return -1; } 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"); if (packet_send(session) != SSH_OK || packet_read(session) != SSH_OK || packet_translate(session) != SSH_OK) { return -1; } switch (session->in_packet.type) { case SSH_SMSG_SUCCESS: ssh_log(session, SSH_LOG_RARE, "PTY: Success"); return 0; break; case SSH_SMSG_FAILURE: ssh_set_error(session, SSH_REQUEST_DENIED, "Server denied PTY allocation"); ssh_log(session, SSH_LOG_RARE, "PTY: denied\n"); break; default: ssh_log(session, SSH_LOG_RARE, "PTY: error\n"); ssh_set_error(session, SSH_FATAL, "Received unexpected packet type %d", session->in_packet.type); return -1; } return -1; }
static int packet_wait2(SSH_SESSION *session, int type, int blocking) { int rc = SSH_ERROR; enter_function(); do { rc = packet_read2(session); if (rc != SSH_OK) { leave_function(); return rc; } if (packet_translate(session) != SSH_OK) { leave_function(); return SSH_ERROR; } switch (session->in_packet.type) { case SSH2_MSG_DISCONNECT: packet_parse(session); ssh_log(session, SSH_LOG_PACKET, "received disconnect packet"); leave_function(); return SSH_ERROR; case SSH2_MSG_CHANNEL_WINDOW_ADJUST: case SSH2_MSG_CHANNEL_DATA: case SSH2_MSG_CHANNEL_EXTENDED_DATA: case SSH2_MSG_CHANNEL_REQUEST: case SSH2_MSG_CHANNEL_EOF: case SSH2_MSG_CHANNEL_CLOSE: packet_parse(session); break; case SSH2_MSG_IGNORE: break; default: if (type && (type != session->in_packet.type)) { ssh_set_error(session, SSH_FATAL, "packet_wait2(): Received a %d type packet, but expected a %d\n", session->in_packet.type, type); leave_function(); return SSH_ERROR; } leave_function(); return SSH_OK; } if (blocking == 0) { leave_function(); return SSH_OK; //shouldn't it return SSH_AGAIN here ? } } while(1); leave_function(); return SSH_OK; }
/** * @brief Reads data from a channel. * * @param channel The channel to read from. * * @param dest The destination buffer which will get the data. * * @param count The count of bytes to be read. * * @param is_stderr A boolean value to mark reading from the stderr flow. * * @return The number of bytes read, 0 on end of file or SSH_ERROR on error. * * @warning The read function using a buffer has been renamed to * channel_read_buffer(). */ int channel_read(CHANNEL *channel, void *dest, u32 count, int is_stderr) { SSH_SESSION *session = channel->session; BUFFER *stdbuf = channel->stdout_buffer; u32 len; enter_function(); if (count == 0) { leave_function(); return 0; } if (is_stderr) { stdbuf=channel->stderr_buffer; } /* * We may have problem if the window is too small to accept as much data * as asked */ ssh_log(session, SSH_LOG_PROTOCOL, "Read (%d) buffered : %d bytes. Window: %d", count, buffer_get_rest_len(stdbuf), channel->local_window); if (count > buffer_get_rest_len(stdbuf) + channel->local_window) { if (grow_window(session, channel, count - buffer_get_rest_len(stdbuf)) < 0) { leave_function(); return -1; } } /* block reading if asked bytes=0 */ while (buffer_get_rest_len(stdbuf) == 0 || buffer_get_rest_len(stdbuf) < count) { if (channel->remote_eof && buffer_get_rest_len(stdbuf) == 0) { leave_function(); return 0; } if (channel->remote_eof) { /* Return the resting bytes in buffer */ break; } if (buffer_get_rest_len(stdbuf) >= count) { /* Stop reading when buffer is full enough */ break; } if ((packet_read(session)) != SSH_OK || (packet_translate(session) != SSH_OK)) { leave_function(); return -1; } packet_parse(session); } if (channel->local_window < WINDOWLIMIT) { if (grow_window(session, channel, 0) < 0) { leave_function(); return -1; } } len = buffer_get_rest_len(stdbuf); /* Read count bytes if len is greater, everything otherwise */ len = (len > count ? count : len); memcpy(dest, buffer_get_rest(stdbuf), len); buffer_pass_bytes(stdbuf,len); leave_function(); return len; }
static int wait_auth_status(SSH_SESSION *session,int kbdint){ int err=SSH_AUTH_ERROR; int cont=1; STRING *auth; u8 partial=0; int todo = 0; char *auth_methods = NULL; enter_function(); while(cont){ if(packet_read(session)) break; if(packet_translate(session)) break; switch(session->in_packet.type){ case SSH2_MSG_USERAUTH_FAILURE: auth = buffer_get_ssh_string(session->in_buffer); if(!auth || buffer_get_u8(session->in_buffer,&partial)!=1 ){ ssh_set_error(session,SSH_FATAL, "invalid SSH_MSG_USERAUTH_FAILURE message"); leave_function(); return SSH_AUTH_ERROR; } auth_methods = string_to_char(auth); if(partial) { err=SSH_AUTH_PARTIAL; ssh_set_error(session,SSH_NO_ERROR,"partial success, authentications that can continue : %s", auth_methods); } else { err=SSH_AUTH_DENIED; ssh_set_error(session,SSH_REQUEST_DENIED,"Access denied. authentications that can continue : %s", auth_methods); session->auth_methods = 0; if (strstr(auth_methods, "password") != NULL) { session->auth_methods |= SSH_AUTH_METHOD_PASSWORD; } if (strstr(auth_methods, "keyboard-interactive") != NULL) { session->auth_methods |= SSH_AUTH_METHOD_INTERACTIVE; } if (strstr(auth_methods, "publickey") != NULL) { session->auth_methods |= SSH_AUTH_METHOD_PUBLICKEY; } if (strstr(auth_methods, "hostbased") != NULL) { session->auth_methods |= SSH_AUTH_METHOD_HOSTBASED; } } free(auth); free(auth_methods); cont=0; break; case SSH2_MSG_USERAUTH_PK_OK: /* SSH monkeys have defined the same number for both */ /* SSH_MSG_USERAUTH_PK_OK and SSH_MSG_USERAUTH_INFO_REQUEST */ /* which is not really smart; */ /*case SSH2_MSG_USERAUTH_INFO_REQUEST: */ if(kbdint){ err=SSH_AUTH_INFO; cont=0; break; } /* continue through success */ case SSH2_MSG_USERAUTH_SUCCESS: err=SSH_AUTH_SUCCESS; cont=0; break; case SSH2_MSG_USERAUTH_BANNER: { STRING *banner=buffer_get_ssh_string(session->in_buffer); if(!banner){ ssh_say(1,"The banner message was invalid. continuing though\n"); break; } ssh_say(2,"Received a message banner\n"); if(session->banner) free(session->banner); /* erase the older one */ session->banner=banner; break; } default: packet_parse(session); break; } } leave_function(); return err; }
static int wait_auth_status(ssh_session session, int kbdint) { char *auth_methods = NULL; ssh_string auth; int rc = SSH_AUTH_ERROR; int cont = 1; uint8_t partial = 0; enter_function(); while (cont) { if (packet_read(session) != SSH_OK) { break; } if (packet_translate(session) != SSH_OK) { break; } switch (session->in_packet.type) { case SSH2_MSG_USERAUTH_FAILURE: auth = buffer_get_ssh_string(session->in_buffer); if (auth == NULL || buffer_get_u8(session->in_buffer, &partial) != 1) { ssh_set_error(session, SSH_FATAL, "Invalid SSH_MSG_USERAUTH_FAILURE message"); leave_function(); return SSH_AUTH_ERROR; } auth_methods = string_to_char(auth); if (auth_methods == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); string_free(auth); leave_function(); return SSH_AUTH_ERROR; } if (partial) { rc = SSH_AUTH_PARTIAL; ssh_set_error(session, SSH_NO_ERROR, "Partial success. Authentication that can continue: %s", auth_methods); } else { rc = SSH_AUTH_DENIED; ssh_set_error(session, SSH_REQUEST_DENIED, "Access denied. Authentication that can continue: %s", auth_methods); session->auth_methods = 0; if (strstr(auth_methods, "password") != NULL) { session->auth_methods |= SSH_AUTH_METHOD_PASSWORD; } if (strstr(auth_methods, "keyboard-interactive") != NULL) { session->auth_methods |= SSH_AUTH_METHOD_INTERACTIVE; } if (strstr(auth_methods, "publickey") != NULL) { session->auth_methods |= SSH_AUTH_METHOD_PUBLICKEY; } if (strstr(auth_methods, "hostbased") != NULL) { session->auth_methods |= SSH_AUTH_METHOD_HOSTBASED; } } string_free(auth); SAFE_FREE(auth_methods); cont = 0; break; case SSH2_MSG_USERAUTH_PK_OK: /* SSH monkeys have defined the same number for both */ /* SSH_MSG_USERAUTH_PK_OK and SSH_MSG_USERAUTH_INFO_REQUEST */ /* which is not really smart; */ /*case SSH2_MSG_USERAUTH_INFO_REQUEST: */ if (kbdint) { rc = SSH_AUTH_INFO; cont = 0; break; } /* continue through success */ case SSH2_MSG_USERAUTH_SUCCESS: rc = SSH_AUTH_SUCCESS; cont = 0; break; case SSH2_MSG_USERAUTH_BANNER: { ssh_string banner; banner = buffer_get_ssh_string(session->in_buffer); if (banner == NULL) { ssh_log(session, SSH_LOG_PACKET, "The banner message was invalid. Continuing though\n"); break; } ssh_log(session, SSH_LOG_PACKET, "Received a message banner\n"); string_free(session->banner); /* erase the older one */ session->banner = banner; break; } default: packet_parse(session); break; } } leave_function(); return rc; }