/* * Test the behavior of ssh_buffer_prepend_data */ static void *thread_buffer_prepend(void *threadid) { ssh_buffer buffer = NULL; uint32_t v; /* Unused */ (void) threadid; /* Setup */ buffer = ssh_buffer_new(); if (buffer == NULL) { pthread_exit((void *)-1); } ssh_buffer_set_secure(buffer); ssh_buffer_add_data(buffer, "abcdef", 6); ssh_buffer_prepend_data(buffer, "xyz", 3); assert_int_equal(ssh_buffer_get_len(buffer), 9); assert_memory_equal(ssh_buffer_get(buffer), "xyzabcdef", 9); /* Now remove 4 bytes and see if we can replace them */ ssh_buffer_get_u32(buffer, &v); assert_int_equal(ssh_buffer_get_len(buffer), 5); assert_memory_equal(ssh_buffer_get(buffer), "bcdef", 5); ssh_buffer_prepend_data(buffer, "aris", 4); assert_int_equal(ssh_buffer_get_len(buffer), 9); assert_memory_equal(ssh_buffer_get(buffer), "arisbcdef", 9); /* same thing but we add 5 bytes now */ ssh_buffer_get_u32(buffer, &v); assert_int_equal(ssh_buffer_get_len(buffer), 5); assert_memory_equal(ssh_buffer_get(buffer), "bcdef", 5); ssh_buffer_prepend_data(buffer, "12345", 5); assert_int_equal(ssh_buffer_get_len(buffer), 10); assert_memory_equal(ssh_buffer_get(buffer), "12345bcdef", 10); /* Teardown */ SSH_BUFFER_FREE(buffer); pthread_exit(NULL); }
int ssh_packet_send1(ssh_session session) { unsigned int blocksize = (session->current_crypto ? session->current_crypto->out_cipher->blocksize : 8); uint32_t currentlen = ssh_buffer_get_len(session->out_buffer) + sizeof(uint32_t); char padstring[32] = {0}; int rc = SSH_ERROR; uint32_t finallen; uint32_t crc; uint8_t padding; SSH_LOG(SSH_LOG_PACKET,"Sending a %d bytes long packet",currentlen); /* TODO FIXME #ifdef WITH_ZLIB if (session->current_crypto && session->current_crypto->do_compress_out) { if (compress_buffer(session, session->out_buffer) < 0) { goto error; } currentlen = ssh_buffer_get_len(session->out_buffer); } #endif */ padding = blocksize - (currentlen % blocksize); if (session->current_crypto) { ssh_get_random(padstring, padding, 0); } else { memset(padstring, 0, padding); } finallen = htonl(currentlen); SSH_LOG(SSH_LOG_PACKET, "%d bytes after comp + %d padding bytes = %d bytes packet", currentlen, padding, ntohl(finallen)); if (ssh_buffer_prepend_data(session->out_buffer, &padstring, padding) < 0) { goto error; } if (ssh_buffer_prepend_data(session->out_buffer, &finallen, sizeof(uint32_t)) < 0) { goto error; } crc = ssh_crc32((char *)ssh_buffer_get(session->out_buffer) + sizeof(uint32_t), ssh_buffer_get_len(session->out_buffer) - sizeof(uint32_t)); if (ssh_buffer_add_u32(session->out_buffer, ntohl(crc)) < 0) { goto error; } #ifdef DEBUG_CRYPTO ssh_print_hexa("Clear packet", ssh_buffer_get(session->out_buffer), ssh_buffer_get_len(session->out_buffer)); #endif /* session->out_buffer should have more than sizeof(uint32_t) bytes in it as required for ssh_packet_encrypt */ ssh_packet_encrypt(session, (unsigned char *)ssh_buffer_get(session->out_buffer) + sizeof(uint32_t), ssh_buffer_get_len(session->out_buffer) - sizeof(uint32_t)); #ifdef DEBUG_CRYPTO ssh_print_hexa("encrypted packet",ssh_buffer_get(session->out_buffer), ssh_buffer_get_len(session->out_buffer)); #endif rc=ssh_socket_write(session->socket, ssh_buffer_get(session->out_buffer), ssh_buffer_get_len(session->out_buffer)); if(rc== SSH_ERROR) { goto error; } session->send_seq++; if (ssh_buffer_reinit(session->out_buffer) < 0) { rc = SSH_ERROR; } error: return rc; /* SSH_OK, AGAIN or ERROR */ }
static int packet_send2(ssh_session session) { unsigned int blocksize = (session->current_crypto ? session->current_crypto->out_cipher->blocksize : 8); unsigned int lenfield_blocksize = (session->current_crypto ? session->current_crypto->out_cipher->lenfield_blocksize : 0); enum ssh_hmac_e hmac_type = (session->current_crypto ? session->current_crypto->out_hmac : session->next_crypto->out_hmac); uint32_t currentlen = ssh_buffer_get_len(session->out_buffer); unsigned char *hmac = NULL; char padstring[32] = { 0 }; int rc = SSH_ERROR; uint32_t finallen,payloadsize,compsize; uint8_t padding; ssh_buffer header_buffer = ssh_buffer_new(); payloadsize = currentlen; #ifdef WITH_ZLIB if (session->current_crypto && session->current_crypto->do_compress_out && ssh_buffer_get_len(session->out_buffer)) { if (compress_buffer(session,session->out_buffer) < 0) { goto error; } currentlen = ssh_buffer_get_len(session->out_buffer); } #endif /* WITH_ZLIB */ compsize = currentlen; /* compressed payload + packet len (4) + padding len (1) */ /* totallen - lenfield_blocksize must be equal to 0 (mod blocksize) */ padding = (blocksize - ((blocksize - lenfield_blocksize + currentlen + 5) % blocksize)); if(padding < 4) { padding += blocksize; } if (session->current_crypto != NULL) { int ok; ok = ssh_get_random(padstring, padding, 0); if (!ok) { ssh_set_error(session, SSH_FATAL, "PRNG error"); goto error; } } if (header_buffer == NULL){ ssh_set_error_oom(session); goto error; } finallen = currentlen + padding + 1; rc = ssh_buffer_pack(header_buffer, "db", finallen, padding); if (rc == SSH_ERROR){ goto error; } rc = ssh_buffer_prepend_data(session->out_buffer, ssh_buffer_get(header_buffer), ssh_buffer_get_len(header_buffer)); if (rc < 0) { goto error; } rc = ssh_buffer_add_data(session->out_buffer, padstring, padding); if (rc < 0) { goto error; } #ifdef WITH_PCAP if (session->pcap_ctx) { ssh_pcap_context_write(session->pcap_ctx, SSH_PCAP_DIR_OUT, ssh_buffer_get(session->out_buffer), ssh_buffer_get_len(session->out_buffer), ssh_buffer_get_len(session->out_buffer)); } #endif hmac = ssh_packet_encrypt(session, ssh_buffer_get(session->out_buffer), ssh_buffer_get_len(session->out_buffer)); if (hmac) { rc = ssh_buffer_add_data(session->out_buffer, hmac, hmac_digest_len(hmac_type)); if (rc < 0) { goto error; } } rc = ssh_packet_write(session); session->send_seq++; if (session->raw_counter != NULL) { session->raw_counter->out_bytes += payloadsize; session->raw_counter->out_packets++; } SSH_LOG(SSH_LOG_PACKET, "packet: wrote [len=%d,padding=%hhd,comp=%d,payload=%d]", finallen, padding, compsize, payloadsize); if (ssh_buffer_reinit(session->out_buffer) < 0) { rc = SSH_ERROR; } error: if (header_buffer != NULL) { ssh_buffer_free(header_buffer); } return rc; /* SSH_OK, AGAIN or ERROR */ }
static int packet_send2(ssh_session session) { unsigned int blocksize = (session->current_crypto ? session->current_crypto->out_cipher->blocksize : 8); enum ssh_hmac_e hmac_type = (session->current_crypto ? session->current_crypto->out_hmac : session->next_crypto->out_hmac); uint32_t currentlen = ssh_buffer_get_len(session->out_buffer); unsigned char *hmac = NULL; char padstring[32] = { 0 }; int rc = SSH_ERROR; uint32_t finallen,payloadsize,compsize; uint8_t padding; uint8_t header[sizeof(padding) + sizeof(finallen)] = { 0 }; payloadsize = currentlen; #ifdef WITH_ZLIB if (session->current_crypto && session->current_crypto->do_compress_out && ssh_buffer_get_len(session->out_buffer)) { if (compress_buffer(session,session->out_buffer) < 0) { goto error; } currentlen = ssh_buffer_get_len(session->out_buffer); } #endif /* WITH_ZLIB */ compsize = currentlen; padding = (blocksize - ((currentlen +5) % blocksize)); if(padding < 4) { padding += blocksize; } if (session->current_crypto) { ssh_get_random(padstring, padding, 0); } finallen = htonl(currentlen + padding + 1); memcpy(&header[0], &finallen, sizeof(finallen)); header[sizeof(finallen)] = padding; rc = ssh_buffer_prepend_data(session->out_buffer, &header, sizeof(header)); if (rc < 0) { goto error; } rc = ssh_buffer_add_data(session->out_buffer, padstring, padding); if (rc < 0) { goto error; } #ifdef WITH_PCAP if(session->pcap_ctx){ ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_OUT, ssh_buffer_get(session->out_buffer),ssh_buffer_get_len(session->out_buffer) ,ssh_buffer_get_len(session->out_buffer)); } #endif hmac = ssh_packet_encrypt(session, ssh_buffer_get(session->out_buffer), ssh_buffer_get_len(session->out_buffer)); if (hmac) { rc = ssh_buffer_add_data(session->out_buffer, hmac, hmac_digest_len(hmac_type)); if (rc < 0) { goto error; } } rc = ssh_packet_write(session); session->send_seq++; if (session->raw_counter != NULL) { session->raw_counter->out_bytes += payloadsize; session->raw_counter->out_packets++; } SSH_LOG(SSH_LOG_PACKET, "packet: wrote [len=%d,padding=%hhd,comp=%d,payload=%d]", ntohl(finallen), padding, compsize, payloadsize); if (ssh_buffer_reinit(session->out_buffer) < 0) { rc = SSH_ERROR; } error: return rc; /* SSH_OK, AGAIN or ERROR */ }