static void channel_rcv_change_window(SSH_SESSION *session) { CHANNEL *channel; u32 bytes; int rc; enter_function(); channel = channel_from_msg(session); if (channel == NULL) { ssh_log(session, SSH_LOG_FUNCTIONS, ssh_get_error(session)); } rc = buffer_get_u32(session->in_buffer, &bytes); if (channel == NULL || rc != sizeof(u32)) { ssh_log(session, SSH_LOG_PACKET, "Error getting a window adjust message: invalid packet"); leave_function(); return; } bytes = ntohl(bytes); ssh_log(session, SSH_LOG_PROTOCOL, "Adding %d bytes to channel (%d:%d) (from %d bytes)", bytes, channel->local_channel, channel->remote_channel, channel->remote_window); channel->remote_window += bytes; leave_function(); }
static int kbdauth_info_get(SSH_SESSION *session){ STRING *name; /* name of the "asking" window showed to client */ STRING *instruction; STRING *tmp; u32 nprompts; u32 i; enter_function(); name=buffer_get_ssh_string(session->in_buffer); instruction=buffer_get_ssh_string(session->in_buffer); tmp=buffer_get_ssh_string(session->in_buffer); buffer_get_u32(session->in_buffer,&nprompts); if(!name || !instruction || !tmp){ if(name) free(name); if(instruction) free(instruction); // tmp must be empty if we got here ssh_set_error(session,SSH_FATAL,"Invalid USERAUTH_INFO_REQUEST msg"); leave_function(); return SSH_AUTH_ERROR; } if(tmp) free(tmp); // no use if(!session->kbdint) session->kbdint=kbdint_new(); else kbdint_clean(session->kbdint); session->kbdint->name=string_to_char(name); free(name); session->kbdint->instruction=string_to_char(instruction); free(instruction); nprompts=ntohl(nprompts); if(nprompts>KBDINT_MAX_PROMPT){ ssh_set_error(session,SSH_FATAL,"Too much prompt asked from server: %lu(0x%.8lx)",nprompts,nprompts); leave_function(); return SSH_AUTH_ERROR; } session->kbdint->nprompts=nprompts; session->kbdint->prompts=malloc(nprompts*sizeof(char *)); memset(session->kbdint->prompts,0,nprompts*sizeof(char *)); session->kbdint->echo=malloc(nprompts); memset(session->kbdint->echo,0,nprompts); for(i=0;i<nprompts;++i){ tmp=buffer_get_ssh_string(session->in_buffer); buffer_get_u8(session->in_buffer,&session->kbdint->echo[i]); if(!tmp){ ssh_set_error(session,SSH_FATAL,"Short INFO_REQUEST packet"); leave_function(); return SSH_AUTH_ERROR; } session->kbdint->prompts[i]=string_to_char(tmp); free(tmp); } leave_function(); return SSH_AUTH_INFO; /* we are not auth. but we parsed the packet */ }
/* * Test the behavior of buffer_prepend_data */ static void torture_buffer_prepend(void **state) { ssh_buffer buffer = *state; uint32_t v; buffer_add_data(buffer,"abcdef",6); buffer_prepend_data(buffer,"xyz",3); assert_int_equal(buffer_get_rest_len(buffer),9); assert_int_equal(memcmp(buffer_get_rest(buffer), "xyzabcdef", 9), 0); // Now remove 4 bytes and see if we can replace them buffer_get_u32(buffer,&v); assert_int_equal(buffer_get_rest_len(buffer),5); assert_int_equal(memcmp(buffer_get_rest(buffer), "bcdef", 5), 0); buffer_prepend_data(buffer,"aris",4); assert_int_equal(buffer_get_rest_len(buffer),9); assert_int_equal(memcmp(buffer_get_rest(buffer), "arisbcdef", 9), 0); /* same thing but we add 5 bytes now */ buffer_get_u32(buffer,&v); assert_int_equal(buffer_get_rest_len(buffer),5); assert_int_equal(memcmp(buffer_get_rest(buffer), "bcdef", 5), 0); buffer_prepend_data(buffer,"12345",5); assert_int_equal(buffer_get_rest_len(buffer),10); assert_int_equal(memcmp(buffer_get_rest(buffer), "12345bcdef", 10), 0); }
static CHANNEL *channel_from_msg(SSH_SESSION *session) { CHANNEL *channel; u32 chan; if (buffer_get_u32(session->in_buffer, &chan) != sizeof(u32)) { ssh_set_error(session, SSH_FATAL, "Getting channel from message: short read"); return NULL; } channel = ssh_channel_from_local(session, ntohl(chan)); if (channel == NULL) { ssh_set_error(session, SSH_FATAL, "Server specified invalid channel %lu", (long unsigned int) ntohl(chan)); } return channel; }
static int channel_rcv_close1(ssh_session session) { ssh_channel channel = session->channels; uint32_t status; buffer_get_u32(session->in_buffer, &status); /* * It's much more than a channel closing. spec says it's the last * message sent by server (strange) */ /* actually status is lost somewhere */ channel->open = 0; channel->remote_eof = 1; if (buffer_add_u8(session->out_buffer, SSH_CMSG_EXIT_CONFIRMATION) < 0) { return -1; } if (packet_send(session) != SSH_OK) { return -1; } return 0; }
int ssh_agent_get_ident_count(struct ssh_session_struct *session) { ssh_buffer request = NULL; ssh_buffer reply = NULL; unsigned int type = 0; unsigned int c1 = 0, c2 = 0; uint32_t buf = 0; switch (session->version) { case 1: c1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES; c2 = SSH_AGENT_RSA_IDENTITIES_ANSWER; break; case 2: c1 = SSH2_AGENTC_REQUEST_IDENTITIES; c2 = SSH2_AGENT_IDENTITIES_ANSWER; break; default: return 0; } /* send message to the agent requesting the list of identities */ request = ssh_buffer_new(); if (buffer_add_u8(request, c1) < 0) { ssh_set_error(session, SSH_FATAL, "Not enough space"); return -1; } reply = ssh_buffer_new(); if (reply == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); return -1; } if (agent_talk(session, request, reply) < 0) { ssh_buffer_free(request); return 0; } ssh_buffer_free(request); /* get message type and verify the answer */ buffer_get_u8(reply, (uint8_t *) &type); SSH_LOG(session, SSH_LOG_WARN, "Answer type: %d, expected answer: %d", type, c2); if (agent_failed(type)) { return 0; } else if (type != c2) { ssh_set_error(session, SSH_FATAL, "Bad authentication reply message type: %d", type); return -1; } buffer_get_u32(reply, &buf); session->agent->count = agent_get_u32((uint8_t*)&buf); SSH_LOG(session, SSH_LOG_DEBUG, "Agent count: %d", session->agent->count); if (session->agent->count > 1024) { ssh_set_error(session, SSH_FATAL, "Too many identities in authentication reply: %d", session->agent->count); ssh_buffer_free(reply); return -1; } if (session->agent->ident) { buffer_reinit(session->agent->ident); } session->agent->ident = reply; return session->agent->count; }
/** * @internal * * @brief This function parses the last end of a channel request packet. * * This is normally converted to a SSH message and placed in the queue. * * @param[in] session The SSH session. * * @param[in] channel The channel the request is made on. * * @param[in] packet The rest of the packet to be parsed. * * @param[in] request The type of request. * * @param[in] want_reply The want_reply field from the request. * * @returns SSH_OK on success, SSH_ERROR if an error occured. */ int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel, ssh_buffer packet, const char *request, uint8_t want_reply) { ssh_message msg = NULL; enter_function(); msg = ssh_message_new(session); if (msg == NULL) { ssh_set_error_oom(session); goto error; } ssh_log(session, SSH_LOG_PACKET, "Received a %s channel_request for channel (%d:%d) (want_reply=%hhd)", request, channel->local_channel, channel->remote_channel, want_reply); msg->type = SSH_REQUEST_CHANNEL; msg->channel_request.channel = channel; msg->channel_request.want_reply = want_reply; if (strcmp(request, "pty-req") == 0) { ssh_string term = NULL; char *term_c = NULL; term = buffer_get_ssh_string(packet); if (term == NULL) { ssh_set_error_oom(session); goto error; } term_c = ssh_string_to_char(term); if (term_c == NULL) { ssh_set_error_oom(session); ssh_string_free(term); goto error; } ssh_string_free(term); msg->channel_request.type = SSH_CHANNEL_REQUEST_PTY; msg->channel_request.TERM = term_c; buffer_get_u32(packet, &msg->channel_request.width); buffer_get_u32(packet, &msg->channel_request.height); buffer_get_u32(packet, &msg->channel_request.pxwidth); buffer_get_u32(packet, &msg->channel_request.pxheight); msg->channel_request.width = ntohl(msg->channel_request.width); msg->channel_request.height = ntohl(msg->channel_request.height); msg->channel_request.pxwidth = ntohl(msg->channel_request.pxwidth); msg->channel_request.pxheight = ntohl(msg->channel_request.pxheight); msg->channel_request.modes = buffer_get_ssh_string(packet); if (msg->channel_request.modes == NULL) { SAFE_FREE(term_c); goto error; } goto end; } if (strcmp(request, "window-change") == 0) { msg->channel_request.type = SSH_CHANNEL_REQUEST_WINDOW_CHANGE; buffer_get_u32(packet, &msg->channel_request.width); buffer_get_u32(packet, &msg->channel_request.height); buffer_get_u32(packet, &msg->channel_request.pxwidth); buffer_get_u32(packet, &msg->channel_request.pxheight); msg->channel_request.width = ntohl(msg->channel_request.width); msg->channel_request.height = ntohl(msg->channel_request.height); msg->channel_request.pxwidth = ntohl(msg->channel_request.pxwidth); msg->channel_request.pxheight = ntohl(msg->channel_request.pxheight); goto end; } if (strcmp(request, "subsystem") == 0) { ssh_string subsys = NULL; char *subsys_c = NULL; subsys = buffer_get_ssh_string(packet); if (subsys == NULL) { ssh_set_error_oom(session); goto error; } subsys_c = ssh_string_to_char(subsys); if (subsys_c == NULL) { ssh_set_error_oom(session); ssh_string_free(subsys); goto error; } ssh_string_free(subsys); msg->channel_request.type = SSH_CHANNEL_REQUEST_SUBSYSTEM; msg->channel_request.subsystem = subsys_c; goto end; } if (strcmp(request, "shell") == 0) { msg->channel_request.type = SSH_CHANNEL_REQUEST_SHELL; goto end; } if (strcmp(request, "exec") == 0) { ssh_string cmd = NULL; cmd = buffer_get_ssh_string(packet); if (cmd == NULL) { ssh_set_error_oom(session); goto error; } msg->channel_request.type = SSH_CHANNEL_REQUEST_EXEC; msg->channel_request.command = ssh_string_to_char(cmd); ssh_string_free(cmd); if (msg->channel_request.command == NULL) { goto error; } goto end; } if (strcmp(request, "env") == 0) { ssh_string name = NULL; ssh_string value = NULL; name = buffer_get_ssh_string(packet); if (name == NULL) { ssh_set_error_oom(session); goto error; } value = buffer_get_ssh_string(packet); if (value == NULL) { ssh_set_error_oom(session); ssh_string_free(name); goto error; } msg->channel_request.type = SSH_CHANNEL_REQUEST_ENV; msg->channel_request.var_name = ssh_string_to_char(name); msg->channel_request.var_value = ssh_string_to_char(value); if (msg->channel_request.var_name == NULL || msg->channel_request.var_value == NULL) { ssh_string_free(name); ssh_string_free(value); goto error; } ssh_string_free(name); ssh_string_free(value); goto end; } if (strcmp(request, "x11-req") == 0) { ssh_string auth_protocol = NULL; ssh_string auth_cookie = NULL; buffer_get_u8(packet, &msg->channel_request.x11_single_connection); auth_protocol = buffer_get_ssh_string(packet); if (auth_protocol == NULL) { ssh_set_error_oom(session); goto error; } auth_cookie = buffer_get_ssh_string(packet); if (auth_cookie == NULL) { ssh_set_error_oom(session); ssh_string_free(auth_protocol); goto error; } msg->channel_request.type = SSH_CHANNEL_REQUEST_X11; msg->channel_request.x11_auth_protocol = ssh_string_to_char(auth_protocol); msg->channel_request.x11_auth_cookie = ssh_string_to_char(auth_cookie); if (msg->channel_request.x11_auth_protocol == NULL || msg->channel_request.x11_auth_cookie == NULL) { ssh_string_free(auth_protocol); ssh_string_free(auth_cookie); goto error; } ssh_string_free(auth_protocol); ssh_string_free(auth_cookie); buffer_get_u32(packet, &msg->channel_request.x11_screen_number); goto end; } msg->channel_request.type = SSH_CHANNEL_UNKNOWN; end: ssh_message_queue(session,msg); leave_function(); return SSH_OK; error: ssh_message_free(msg); leave_function(); return SSH_ERROR; }
int ssh_get_kex1(SSH_SESSION *session) { STRING *server_exp = NULL; STRING *server_mod = NULL; STRING *host_exp = NULL; STRING *host_mod = NULL; STRING *serverkey = NULL; STRING *hostkey = NULL; STRING *enc_session = NULL; PUBLIC_KEY *srv = NULL; PUBLIC_KEY *host = NULL; u32 server_bits; u32 host_bits; u32 protocol_flags; u32 supported_ciphers_mask; u32 supported_authentications_mask; u16 bits; int rc = -1; int ko; enter_function(); ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_PUBLIC_KEY"); if (packet_wait(session, SSH_SMSG_PUBLIC_KEY, 1) != SSH_OK) { leave_function(); return -1; } ssh_log(session, SSH_LOG_PROTOCOL, "Got a SSH_SMSG_PUBLIC_KEY"); if (buffer_get_data(session->in_buffer, session->server_kex.cookie, 8) != 8) { ssh_set_error(session, SSH_FATAL, "Can't get cookie in buffer"); leave_function(); return -1; } buffer_get_u32(session->in_buffer, &server_bits); server_exp = buffer_get_mpint(session->in_buffer); if (server_exp == NULL) { goto error; } server_mod = buffer_get_mpint(session->in_buffer); if (server_mod == NULL) { goto error; } buffer_get_u32(session->in_buffer, &host_bits); host_exp = buffer_get_mpint(session->in_buffer); if (host_exp == NULL) { goto error; } host_mod = buffer_get_mpint(session->in_buffer); if (host_mod == NULL) { goto error; } buffer_get_u32(session->in_buffer, &protocol_flags); buffer_get_u32(session->in_buffer, &supported_ciphers_mask); ko = buffer_get_u32(session->in_buffer, &supported_authentications_mask); if ((ko != sizeof(u32)) || !host_mod || !host_exp || !server_mod || !server_exp) { ssh_log(session, SSH_LOG_RARE, "Invalid SSH_SMSG_PUBLIC_KEY packet"); ssh_set_error(session, SSH_FATAL, "Invalid SSH_SMSG_PUBLIC_KEY packet"); goto error; } server_bits = ntohl(server_bits); host_bits = ntohl(host_bits); protocol_flags = ntohl(protocol_flags); supported_ciphers_mask = ntohl(supported_ciphers_mask); supported_authentications_mask = ntohl(supported_authentications_mask); ssh_log(session, SSH_LOG_PROTOCOL, "Server bits: %d; Host bits: %d; Protocol flags: %.8lx; " "Cipher mask: %.8lx; Auth mask: %.8lx", server_bits, host_bits, (unsigned long int) protocol_flags, (unsigned long int) supported_ciphers_mask, (unsigned long int) supported_authentications_mask); serverkey = make_rsa1_string(server_exp, server_mod); if (serverkey == NULL) { goto error; } hostkey = make_rsa1_string(host_exp,host_mod); if (serverkey == NULL) { goto error; } if (build_session_id1(session, server_mod, host_mod) < 0) { goto error; } srv = publickey_from_string(session, serverkey); if (srv == NULL) { goto error; } host = publickey_from_string(session, hostkey); if (host == NULL) { goto error; } session->next_crypto->server_pubkey = string_copy(hostkey); if (session->next_crypto->server_pubkey == NULL) { goto error; } session->next_crypto->server_pubkey_type = "ssh-rsa1"; /* now, we must choose an encryption algo */ /* hardcode 3des */ if (!(supported_ciphers_mask & (1 << SSH_CIPHER_3DES))) { ssh_set_error(session, SSH_FATAL, "Remote server doesn't accept 3DES"); goto error; } ssh_log(session, SSH_LOG_PROTOCOL, "Sending SSH_CMSG_SESSION_KEY"); if (buffer_add_u8(session->out_buffer, SSH_CMSG_SESSION_KEY) < 0) { goto error; } if (buffer_add_u8(session->out_buffer, SSH_CIPHER_3DES) < 0) { goto error; } if (buffer_add_data(session->out_buffer, session->server_kex.cookie, 8) < 0) { goto error; } enc_session = encrypt_session_key(session, srv, host, server_bits, host_bits); if (enc_session == NULL) { goto error; } bits = string_len(enc_session) * 8 - 7; ssh_log(session, SSH_LOG_PROTOCOL, "%d bits, %zu bytes encrypted session", bits, string_len(enc_session)); bits = htons(bits); /* the encrypted mpint */ if (buffer_add_data(session->out_buffer, &bits, sizeof(u16)) < 0) { goto error; } if (buffer_add_data(session->out_buffer, enc_session->string, string_len(enc_session)) < 0) { goto error; } /* the protocol flags */ if (buffer_add_u32(session->out_buffer, 0) < 0) { goto error; } if (packet_send(session) != SSH_OK) { goto error; } /* we can set encryption */ if (crypt_set_algorithms(session)) { goto error; } session->current_crypto = session->next_crypto; session->next_crypto = NULL; ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_SUCCESS"); if (packet_wait(session,SSH_SMSG_SUCCESS,1) != SSH_OK) { char buffer[1024] = {0}; snprintf(buffer, sizeof(buffer), "Key exchange failed: %s", ssh_get_error(session)); ssh_set_error(session, SSH_FATAL, "%s",buffer); goto error; } ssh_log(session, SSH_LOG_PROTOCOL, "received SSH_SMSG_SUCCESS\n"); rc = 0; error: string_free(host_mod); string_free(host_exp); string_free(server_mod); string_free(server_exp); string_free(serverkey); string_free(hostkey); publickey_free(srv); publickey_free(host); leave_function(); return rc; }
static void channel_rcv_request(SSH_SESSION *session) { CHANNEL *channel; STRING *request_s; char *request; u32 status; enter_function(); channel = channel_from_msg(session); if (channel == NULL) { ssh_log(session, SSH_LOG_FUNCTIONS, ssh_get_error(session)); leave_function(); return; } request_s = buffer_get_ssh_string(session->in_buffer); if (request_s == NULL) { ssh_log(session, SSH_LOG_PACKET, "Invalid MSG_CHANNEL_REQUEST"); leave_function(); return; } request = string_to_char(request_s); string_free(request_s); if (request == NULL) { leave_function(); return; } buffer_get_u8(session->in_buffer, (u8 *) &status); if (strcmp(request,"exit-status") == 0) { SAFE_FREE(request); ssh_log(session, SSH_LOG_PACKET, "received exit-status"); buffer_get_u32(session->in_buffer, &status); channel->exit_status = ntohl(status); leave_function(); return ; } if (strcmp(request, "exit-signal") == 0) { const char *core = "(core dumped)"; STRING *signal_s; char *signal; u8 i; SAFE_FREE(request); signal_s = buffer_get_ssh_string(session->in_buffer); if (signal_s == NULL) { ssh_log(session, SSH_LOG_PACKET, "Invalid MSG_CHANNEL_REQUEST"); leave_function(); return; } signal = string_to_char(signal_s); string_free(signal_s); if (signal == NULL) { leave_function(); return; } buffer_get_u8(session->in_buffer, &i); if (i == 0) { core = ""; } ssh_log(session, SSH_LOG_PACKET, "Remote connection closed by signal SIG %s %s", signal, core); SAFE_FREE(signal); leave_function(); return; } ssh_log(session, SSH_LOG_PACKET, "Unknown request %s", request); SAFE_FREE(request); leave_function(); }
/* is_stderr is set to 1 if the data are extended, ie stderr */ static void channel_rcv_data(SSH_SESSION *session,int is_stderr) { CHANNEL *channel; STRING *str; size_t len; enter_function(); channel = channel_from_msg(session); if (channel == NULL) { ssh_log(session, SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session)); leave_function(); return; } if (is_stderr) { u32 ignore; /* uint32 data type code. we can ignore it */ buffer_get_u32(session->in_buffer, &ignore); } str = buffer_get_ssh_string(session->in_buffer); if (str == NULL) { ssh_log(session, SSH_LOG_PACKET, "Invalid data packet!"); leave_function(); return; } len = string_len(str); ssh_log(session, SSH_LOG_PROTOCOL, "Channel receiving %zu bytes data in %d (local win=%d remote win=%d)", len, is_stderr, channel->local_window, channel->remote_window); /* What shall we do in this case? Let's accept it anyway */ if (len > channel->local_window) { ssh_log(session, SSH_LOG_RARE, "Data packet too big for our window(%zu vs %d)", len, channel->local_window); } if (channel_default_bufferize(channel, str->string, len, is_stderr) < 0) { string_free(str); leave_function(); return; } if (len <= channel->local_window) { channel->local_window -= len; } else { channel->local_window = 0; /* buggy remote */ } ssh_log(session, SSH_LOG_PROTOCOL, "Channel windows are now (local win=%d remote win=%d)", channel->local_window, channel->remote_window); string_free(str); leave_function(); }
static int channel_open(CHANNEL *channel, const char *type_c, int window, int maxpacket, BUFFER *payload) { SSH_SESSION *session = channel->session; STRING *type = NULL; u32 tmp = 0; enter_function(); channel->local_channel = ssh_channel_new_id(session); channel->local_maxpacket = maxpacket; channel->local_window = window; ssh_log(session, SSH_LOG_RARE, "Creating a channel %d with %d window and %d max packet", channel->local_channel, window, maxpacket); type = string_from_char(type_c); if (type == NULL) { leave_function(); return -1; } if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_OPEN) < 0 || buffer_add_ssh_string(session->out_buffer,type) < 0 || buffer_add_u32(session->out_buffer, htonl(channel->local_channel)) < 0 || buffer_add_u32(session->out_buffer, htonl(channel->local_window)) < 0 || buffer_add_u32(session->out_buffer, htonl(channel->local_maxpacket)) < 0) { string_free(type); leave_function(); return -1; } string_free(type); if (payload != NULL) { if (buffer_add_buffer(session->out_buffer, payload) < 0) { leave_function(); return -1; } } if (packet_send(session) != SSH_OK) { leave_function(); return -1; } ssh_log(session, SSH_LOG_RARE, "Sent a SSH_MSG_CHANNEL_OPEN type %s for channel %d", type_c, channel->local_channel); if (packet_wait(session, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, 1) != SSH_OK) { leave_function(); return -1; } switch(session->in_packet.type) { case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: buffer_get_u32(session->in_buffer, &tmp); if (channel->local_channel != ntohl(tmp)) { ssh_set_error(session, SSH_FATAL, "Server answered with sender channel number %lu instead of given %u", (long unsigned int) ntohl(tmp), channel->local_channel); leave_function(); return -1; } buffer_get_u32(session->in_buffer, &tmp); channel->remote_channel = ntohl(tmp); buffer_get_u32(session->in_buffer, &tmp); channel->remote_window = ntohl(tmp); buffer_get_u32(session->in_buffer,&tmp); channel->remote_maxpacket=ntohl(tmp); ssh_log(session, SSH_LOG_PROTOCOL, "Received a CHANNEL_OPEN_CONFIRMATION for channel %d:%d", channel->local_channel, channel->remote_channel); ssh_log(session, SSH_LOG_PROTOCOL, "Remote window : %lu, maxpacket : %lu", (long unsigned int) channel->remote_window, (long unsigned int) channel->remote_maxpacket); channel->open = 1; leave_function(); return 0; case SSH2_MSG_CHANNEL_OPEN_FAILURE: { STRING *error_s; char *error; u32 code; buffer_get_u32(session->in_buffer, &tmp); buffer_get_u32(session->in_buffer, &code); error_s = buffer_get_ssh_string(session->in_buffer); error = string_to_char(error_s); string_free(error_s); if (error == NULL) { leave_function(); return -1; } ssh_set_error(session, SSH_REQUEST_DENIED, "Channel opening failure: channel %u error (%lu) %s", channel->local_channel, (long unsigned int) ntohl(code), error); SAFE_FREE(error); leave_function(); return -1; } default: ssh_set_error(session, SSH_FATAL, "Received unknown packet %d\n", session->in_packet.type); leave_function(); return -1; } leave_function(); return -1; }
SFTP_CLIENT_MESSAGE *sftp_get_client_message(SFTP_SESSION *sftp) { SFTP_PACKET *packet=sftp_packet_read(sftp); SFTP_CLIENT_MESSAGE *msg=malloc(sizeof (SFTP_CLIENT_MESSAGE)); BUFFER *payload; STRING *tmp; memset(msg,0,sizeof(SFTP_CLIENT_MESSAGE)); if(!packet) return NULL; payload=packet->payload; ssh_say(2,"received sftp packet type %d\n",packet->type); msg->type=packet->type; msg->sftp=sftp; buffer_get_u32(payload,&msg->id); switch(msg->type) { case SSH_FXP_CLOSE: case SSH_FXP_READDIR: msg->handle=buffer_get_ssh_string(payload); break; case SSH_FXP_READ: msg->handle=buffer_get_ssh_string(payload); buffer_get_u64(payload,&msg->offset); buffer_get_u32(payload,&msg->len); break; case SSH_FXP_WRITE: msg->handle=buffer_get_ssh_string(payload); buffer_get_u64(payload,&msg->offset); msg->data=buffer_get_ssh_string(payload); break; case SSH_FXP_REMOVE: case SSH_FXP_RMDIR: case SSH_FXP_OPENDIR: case SSH_FXP_READLINK: case SSH_FXP_REALPATH: tmp=buffer_get_ssh_string(payload); msg->filename=string_to_char(tmp); free(tmp); break; case SSH_FXP_RENAME: case SSH_FXP_SYMLINK: tmp=buffer_get_ssh_string(payload); msg->filename=string_to_char(tmp); free(tmp); msg->data=buffer_get_ssh_string(payload); break; case SSH_FXP_MKDIR: case SSH_FXP_SETSTAT: tmp=buffer_get_ssh_string(payload); msg->filename=string_to_char(tmp); free(tmp); msg->attr=sftp_parse_attr(sftp, payload,0); break; case SSH_FXP_FSETSTAT: msg->handle=buffer_get_ssh_string(payload); msg->attr=sftp_parse_attr(sftp, payload,0); break; case SSH_FXP_LSTAT: case SSH_FXP_STAT: tmp=buffer_get_ssh_string(payload); msg->filename=string_to_char(tmp); free(tmp); if(sftp->version >3) buffer_get_u32(payload,&msg->flags); break; case SSH_FXP_OPEN: tmp=buffer_get_ssh_string(payload); msg->filename=string_to_char(tmp); free(tmp); buffer_get_u32(payload,&msg->flags); msg->attr=sftp_parse_attr(sftp, payload,0); case SSH_FXP_FSTAT: msg->handle=buffer_get_ssh_string(payload); buffer_get_u32(payload,&msg->flags); break; default: printf("Received handled sftp message %d\n",msg->type); } msg->flags=ntohl(msg->flags); msg->offset=ntohll(msg->offset); msg->len=ntohl(msg->len); sftp_packet_free(packet); return msg; }
void packet_parse(SSH_SESSION *session) { STRING *error_s = NULL; char *error = NULL; int type = session->in_packet.type; u32 tmp; #ifdef HAVE_SSH1 if (session->version == 1) { /* SSH-1 */ switch(type) { case SSH_MSG_DISCONNECT: ssh_log(session, SSH_LOG_PACKET, "Received SSH_MSG_DISCONNECT"); ssh_set_error(session, SSH_FATAL, "Received SSH_MSG_DISCONNECT"); ssh_socket_close(session->socket); session->alive = 0; return; case SSH_SMSG_STDOUT_DATA: case SSH_SMSG_STDERR_DATA: case SSH_SMSG_EXITSTATUS: channel_handle1(session,type); return; case SSH_MSG_DEBUG: case SSH_MSG_IGNORE: break; default: ssh_log(session, SSH_LOG_PACKET, "Unexpected message code %d", type); } return; } else { #endif /* HAVE_SSH1 */ switch(type) { case SSH2_MSG_DISCONNECT: buffer_get_u32(session->in_buffer, &tmp); error_s = buffer_get_ssh_string(session->in_buffer); if (error_s == NULL) { return; } error = string_to_char(error_s); string_free(error_s); if (error == NULL) { return; } ssh_log(session, SSH_LOG_PACKET, "Received SSH_MSG_DISCONNECT\n"); ssh_set_error(session, SSH_FATAL, "Received SSH_MSG_DISCONNECT: %s",error); SAFE_FREE(error); ssh_socket_close(session->socket); session->alive = 0; return; 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: channel_handle(session,type); case SSH2_MSG_IGNORE: case SSH2_MSG_DEBUG: return; default: ssh_log(session, SSH_LOG_RARE, "Received unhandled packet %d", type); } #ifdef HAVE_SSH1 } #endif }
static int kbdauth_info_get(ssh_session session) { ssh_string name; /* name of the "asking" window showed to client */ ssh_string instruction; ssh_string tmp; uint32_t nprompts; uint32_t i; enter_function(); name = buffer_get_ssh_string(session->in_buffer); instruction = buffer_get_ssh_string(session->in_buffer); tmp = buffer_get_ssh_string(session->in_buffer); buffer_get_u32(session->in_buffer, &nprompts); if (name == NULL || instruction == NULL || tmp == NULL) { string_free(name); string_free(instruction); /* tmp if empty if we got here */ ssh_set_error(session, SSH_FATAL, "Invalid USERAUTH_INFO_REQUEST msg"); leave_function(); return SSH_AUTH_ERROR; } string_free(tmp); if (session->kbdint == NULL) { session->kbdint = kbdint_new(); if (session->kbdint == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); string_free(name); string_free(instruction); leave_function(); return SSH_AUTH_ERROR; } } else { kbdint_clean(session->kbdint); } session->kbdint->name = string_to_char(name); string_free(name); if (session->kbdint->name == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); kbdint_free(session->kbdint); leave_function(); return SSH_AUTH_ERROR; } session->kbdint->instruction = string_to_char(instruction); string_free(instruction); if (session->kbdint->instruction == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); kbdint_free(session->kbdint); session->kbdint = NULL; leave_function(); return SSH_AUTH_ERROR; } nprompts = ntohl(nprompts); if (nprompts > KBDINT_MAX_PROMPT) { ssh_set_error(session, SSH_FATAL, "Too much prompt asked from server: %u (0x%.4x)", nprompts, nprompts); kbdint_free(session->kbdint); session->kbdint = NULL; leave_function(); return SSH_AUTH_ERROR; } session->kbdint->nprompts = nprompts; session->kbdint->prompts = malloc(nprompts * sizeof(char *)); if (session->kbdint->prompts == NULL) { session->kbdint->nprompts = 0; ssh_set_error(session, SSH_FATAL, "No space left"); kbdint_free(session->kbdint); session->kbdint = NULL; leave_function(); return SSH_AUTH_ERROR; } memset(session->kbdint->prompts, 0, nprompts * sizeof(char *)); session->kbdint->echo = malloc(nprompts); if (session->kbdint->echo == NULL) { session->kbdint->nprompts = 0; ssh_set_error(session, SSH_FATAL, "No space left"); kbdint_free(session->kbdint); session->kbdint = NULL; leave_function(); return SSH_AUTH_ERROR; } memset(session->kbdint->echo, 0, nprompts); for (i = 0; i < nprompts; i++) { tmp = buffer_get_ssh_string(session->in_buffer); buffer_get_u8(session->in_buffer, &session->kbdint->echo[i]); if (tmp == NULL) { ssh_set_error(session, SSH_FATAL, "Short INFO_REQUEST packet"); kbdint_free(session->kbdint); session->kbdint = NULL; leave_function(); return SSH_AUTH_ERROR; } session->kbdint->prompts[i] = string_to_char(tmp); string_free(tmp); if (session->kbdint->prompts[i] == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); kbdint_free(session->kbdint); session->kbdint = NULL; leave_function(); return SSH_AUTH_ERROR; } } leave_function(); return SSH_AUTH_INFO; /* we are not auth. but we parsed the packet */ }
int ssh_get_kex1(SSH_SESSION *session){ u32 server_bits, host_bits, protocol_flags, supported_ciphers_mask, supported_authentications_mask; STRING *server_exp=NULL; STRING *server_mod=NULL; STRING *host_exp=NULL; STRING *host_mod=NULL; STRING *serverkey; STRING *hostkey; STRING *enc_session; PUBLIC_KEY *svr,*host; int ko; u16 bits; ssh_say(3,"Waiting for a SSH_SMSG_PUBLIC_KEY\n"); if(packet_wait(session,SSH_SMSG_PUBLIC_KEY,1)){ return -1; } ssh_say(3,"Got a SSH_SMSG_PUBLIC_KEY\n"); if(buffer_get_data(session->in_buffer,session->server_kex.cookie,8)!=8){ ssh_set_error(NULL,SSH_FATAL,"Can't get cookie in buffer"); return -1; } buffer_get_u32(session->in_buffer,&server_bits); server_exp=buffer_get_mpint(session->in_buffer); server_mod=buffer_get_mpint(session->in_buffer); buffer_get_u32(session->in_buffer,&host_bits); host_exp=buffer_get_mpint(session->in_buffer); host_mod=buffer_get_mpint(session->in_buffer); buffer_get_u32(session->in_buffer,&protocol_flags); buffer_get_u32(session->in_buffer,&supported_ciphers_mask); ko=buffer_get_u32(session->in_buffer,&supported_authentications_mask); if((ko!=sizeof(u32)) || !host_mod || !host_exp || !server_mod || !server_exp){ ssh_say(2,"Invalid SSH_SMSG_PUBLIC_KEY packet\n"); ssh_set_error(NULL,SSH_FATAL,"Invalid SSH_SMSG_PUBLIC_KEY packet"); if(host_mod) free(host_mod); if(host_exp) free(host_exp); if(server_mod) free(server_mod); if(server_exp) free(server_exp); return -1; } server_bits=ntohl(server_bits); host_bits=ntohl(host_bits); protocol_flags=ntohl(protocol_flags); supported_ciphers_mask=ntohl(supported_ciphers_mask); supported_authentications_mask=ntohl(supported_authentications_mask); ssh_say(1,"server bits: %d ; host bits: %d\nProtocol flags : %.8lx ; " "cipher mask : %.8lx ; auth mask: %.8lx\n",server_bits, host_bits,protocol_flags,supported_ciphers_mask, supported_authentications_mask); serverkey=make_rsa1_string(server_exp,server_mod); hostkey=make_rsa1_string(host_exp,host_mod); build_session_id1(session,server_mod,host_mod); free(server_exp); free(server_mod); free(host_exp); free(host_mod); svr=publickey_from_string(serverkey); host=publickey_from_string(hostkey); session->next_crypto->server_pubkey=string_copy(hostkey); session->next_crypto->server_pubkey_type="ssh-rsa1"; /* now, we must choose an encryption algo */ /* hardcode 3des */ if(!(supported_ciphers_mask & (1<<SSH_CIPHER_3DES))){ ssh_set_error(NULL,SSH_FATAL,"Remote server doesn't accept 3des"); return -1; } packet_clear_out(session); buffer_add_u8(session->out_buffer,SSH_CMSG_SESSION_KEY); buffer_add_u8(session->out_buffer,SSH_CIPHER_3DES); buffer_add_data(session->out_buffer,session->server_kex.cookie,8); enc_session=encrypt_session_key(session,svr,host,server_bits, host_bits); bits=string_len(enc_session)*8 - 7; ssh_say(2,"%d bits,%d bytes encrypted session\n",bits,string_len(enc_session)); bits=htons(bits); /* the encrypted mpint */ buffer_add_data(session->out_buffer,&bits,sizeof(u16)); buffer_add_data(session->out_buffer,enc_session->string, string_len(enc_session)); /* the protocol flags */ buffer_add_u32(session->out_buffer,0); packet_send(session); /* we can set encryption */ if(crypt_set_algorithms(session)) return -1; session->current_crypto=session->next_crypto; session->next_crypto=NULL; if(packet_wait(session,SSH_SMSG_SUCCESS,1)){ char buffer[1024]; snprintf(buffer,sizeof(buffer),"Key exchange failed : %s",ssh_get_error(session)); ssh_set_error(session,SSH_FATAL,"%s",buffer); return -1; } ssh_say(1,"received SSH_SMSG_SUCCESS\n"); return 0; }