ssh_string ssh_pki_do_sign_agent(ssh_session session, struct ssh_buffer_struct *buf, const ssh_key pubkey) { struct ssh_crypto_struct *crypto; ssh_string session_id; ssh_string sig_blob; ssh_buffer sig_buf; int rc; if (session->current_crypto) { crypto = session->current_crypto; } else { crypto = session->next_crypto; } /* prepend session identifier */ session_id = ssh_string_new(crypto->digest_len); if (session_id == NULL) { return NULL; } ssh_string_fill(session_id, crypto->session_id, crypto->digest_len); sig_buf = ssh_buffer_new(); if (sig_buf == NULL) { ssh_string_free(session_id); return NULL; } rc = buffer_add_ssh_string(sig_buf, session_id); if (rc < 0) { ssh_string_free(session_id); ssh_buffer_free(sig_buf); return NULL; } ssh_string_free(session_id); /* append out buffer */ if (buffer_add_buffer(sig_buf, buf) < 0) { ssh_buffer_free(sig_buf); return NULL; } /* create signature */ sig_blob = ssh_agent_sign_data(session, pubkey, sig_buf); ssh_buffer_free(sig_buf); return sig_blob; }
/** @internal * @brief prepends a packet with the pcap header and writes packet * on file */ int ssh_pcap_file_write_packet(ssh_pcap_file pcap, ssh_buffer packet, uint32_t original_len){ ssh_buffer header=ssh_buffer_new(); struct timeval now; int err; if(header == NULL) return SSH_ERROR; gettimeofday(&now,NULL); buffer_add_u32(header,htonl(now.tv_sec)); buffer_add_u32(header,htonl(now.tv_usec)); buffer_add_u32(header,htonl(buffer_get_rest_len(packet))); buffer_add_u32(header,htonl(original_len)); buffer_add_buffer(header,packet); err=ssh_pcap_file_write(pcap,header); ssh_buffer_free(header); return err; }
ssh_string ssh_do_sign_with_agent(ssh_session session, struct ssh_buffer_struct *buf, struct ssh_public_key_struct *publickey) { struct ssh_buffer_struct *sigbuf = NULL; struct ssh_string_struct *signature = NULL; struct ssh_string_struct *session_id = NULL; struct ssh_crypto_struct *crypto = NULL; if (session->current_crypto) { crypto = session->current_crypto; } else { crypto = session->next_crypto; } /* prepend session identifier */ session_id = ssh_string_new(crypto->digest_len); if (session_id == NULL) { return NULL; } ssh_string_fill(session_id, crypto->session_id, crypto->digest_len); sigbuf = ssh_buffer_new(); if (sigbuf == NULL) { ssh_string_free(session_id); return NULL; } if (buffer_add_ssh_string(sigbuf, session_id) < 0) { ssh_buffer_free(sigbuf); ssh_string_free(session_id); return NULL; } ssh_string_free(session_id); /* append out buffer */ if (buffer_add_buffer(sigbuf, buf) < 0) { ssh_buffer_free(sigbuf); return NULL; } /* create signature */ signature = agent_sign_data(session, sigbuf, publickey); ssh_buffer_free(sigbuf); return signature; }
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; }
/* Needs to be freed with safe_free() */ uint8_t *command_packet_to_bytes(command_packet_t *packet, size_t *length) { buffer_t *buffer = buffer_create(BO_BIG_ENDIAN); buffer_t *buffer_with_size = buffer_create(BO_BIG_ENDIAN); uint16_t packed_id; packed_id = (packet->is_request ? 0x0000 : 0x8000); packed_id |= (packet->request_id & 0x7FFF); buffer_add_int16(buffer, packed_id); buffer_add_int16(buffer, packet->command_id); switch(packet->command_id) { case COMMAND_PING: if(packet->is_request) buffer_add_ntstring(buffer, packet->r.request.body.ping.data); else buffer_add_ntstring(buffer, packet->r.response.body.ping.data); break; case COMMAND_SHELL: if(packet->is_request) buffer_add_ntstring(buffer, packet->r.request.body.shell.name); else buffer_add_int16(buffer, packet->r.response.body.shell.session_id); break; case COMMAND_EXEC: if(packet->is_request) { buffer_add_ntstring(buffer, packet->r.request.body.exec.name); buffer_add_ntstring(buffer, packet->r.request.body.exec.command); } else { buffer_add_int16(buffer, packet->r.response.body.exec.session_id); } break; case COMMAND_DOWNLOAD: if(packet->is_request) { buffer_add_ntstring(buffer, packet->r.request.body.download.filename); } else { buffer_add_bytes(buffer, packet->r.response.body.download.data, packet->r.response.body.download.length); } break; case COMMAND_UPLOAD: if(packet->is_request) { buffer_add_ntstring(buffer, packet->r.request.body.upload.filename); buffer_add_bytes(buffer, packet->r.request.body.upload.data, packet->r.request.body.upload.length); } else { } break; case COMMAND_SHUTDOWN: break; case TUNNEL_CONNECT: if(packet->is_request) { buffer_add_int32(buffer, packet->r.request.body.tunnel_connect.options); buffer_add_ntstring(buffer, packet->r.request.body.tunnel_connect.host); buffer_add_int16(buffer, packet->r.request.body.tunnel_connect.port); } else { buffer_add_int32(buffer, packet->r.response.body.tunnel_connect.tunnel_id); } break; case TUNNEL_DATA: if(packet->is_request) { buffer_add_int32(buffer, packet->r.request.body.tunnel_data.tunnel_id); buffer_add_bytes(buffer, packet->r.request.body.tunnel_data.data, packet->r.request.body.tunnel_data.length); } else { } break; case TUNNEL_CLOSE: if(packet->is_request) { buffer_add_int32(buffer, packet->r.request.body.tunnel_close.tunnel_id); buffer_add_ntstring(buffer, packet->r.request.body.tunnel_close.reason); } else { } break; case COMMAND_ERROR: if(packet->is_request) { buffer_add_int16(buffer, packet->r.request.body.error.status); buffer_add_ntstring(buffer, packet->r.request.body.error.reason); } else { buffer_add_int16(buffer, packet->r.response.body.error.status); buffer_add_ntstring(buffer, packet->r.response.body.error.reason); } break; default: LOG_FATAL("Unknown command_id: 0x%04x", packet->command_id); exit(1); } buffer_add_int32(buffer_with_size, buffer_get_length(buffer)); buffer_add_buffer(buffer_with_size, buffer); buffer_destroy(buffer); return buffer_create_string_and_destroy(buffer_with_size, length); }