aboutsummaryrefslogtreecommitdiff
path: root/libssh/packet.c
diff options
context:
space:
mode:
authorAndreas Schneider <mail@cynapses.org>2009-04-14 08:47:37 +0000
committerAndreas Schneider <mail@cynapses.org>2009-04-14 08:47:37 +0000
commit640cf4cc93f92296fc6a8a4f64a7e2be0983f76e (patch)
treeccdd445d605bde12b367b5048a3238b6bd671b05 /libssh/packet.c
parente0ae9635ea829b15782de4dd43e31ae67ef7fffe (diff)
downloadlibssh-640cf4cc93f92296fc6a8a4f64a7e2be0983f76e.tar.gz
libssh-640cf4cc93f92296fc6a8a4f64a7e2be0983f76e.tar.xz
libssh-640cf4cc93f92296fc6a8a4f64a7e2be0983f76e.zip
Add more error checks to packet_read1().
git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@455 7dcaeef0-15fb-0310-b436-a5af3365683c
Diffstat (limited to 'libssh/packet.c')
-rw-r--r--libssh/packet.c246
1 files changed, 138 insertions, 108 deletions
diff --git a/libssh/packet.c b/libssh/packet.c
index 1b19b82..1895578 100644
--- a/libssh/packet.c
+++ b/libssh/packet.c
@@ -214,133 +214,163 @@ error:
#ifdef HAVE_SSH1
/* a slighty modified packet_read2() for SSH-1 protocol */
-static int packet_read1(SSH_SESSION *session){
- u32 len;
- void *packet=NULL;
- int ret;
- int to_be_read;
- u32 padding;
- u32 crc;
- enter_function();
- if(!session->alive){
- leave_function();
- return SSH_ERROR; // the error message was already set
- }
- switch (session->packet_state){
- case PACKET_STATE_INIT:
- memset(&session->in_packet,0,sizeof(PACKET));
- if(session->in_buffer)
- buffer_reinit(session->in_buffer);
- else
- session->in_buffer=buffer_new();
- ret=ssh_socket_read(session->socket,&len,sizeof(u32));
- if(ret!=SSH_OK){
- leave_function();
- return ret; // could be SSH_AGAIN
- }
- /* len is not encrypted */
- len=ntohl(len);
- if(len> MAX_PACKET_LEN){
- ssh_set_error(session,SSH_FATAL,"read_packet(): Packet len too high(%u %.8x)",len,len);
- leave_function();
- return SSH_ERROR;
- }
- ssh_log(session,SSH_LOG_PACKET,"reading a %d bytes packet",len);
- session->in_packet.len=len;
- session->packet_state=PACKET_STATE_SIZEREAD;
- case PACKET_STATE_SIZEREAD:
- len=session->in_packet.len;
- /* SSH-1 has a fixed padding lenght */
- padding=8-(len % 8);
- to_be_read=len+padding;
- /* it is *not* possible that to_be_read be < 8. */
- packet = malloc(to_be_read);
- if (packet == NULL) {
- ssh_set_error(session, SSH_FATAL,"No space left");
- leave_function();
- return SSH_ERROR;
- }
- ret=ssh_socket_read(session->socket,packet,to_be_read);
- if(ret != SSH_OK){
- free(packet);
- leave_function();
- return ret; // can be SSH_ERROR or SSH_AGAIN
- }
- buffer_add_data(session->in_buffer,packet,to_be_read);
- free(packet);
-
+static int packet_read1(SSH_SESSION *session) {
+ void *packet = NULL;
+ int rc = SSH_ERROR;
+ int to_be_read;
+ u32 padding;
+ u32 crc;
+ u32 len;
+
+ enter_function();
+
+ if(!session->alive) {
+ goto error;
+ }
+
+ switch (session->packet_state){
+ case PACKET_STATE_INIT:
+ memset(&session->in_packet, 0, sizeof(PACKET));
+
+ if (session->in_buffer) {
+ if (buffer_reinit(session->in_buffer) < 0) {
+ goto error;
+ }
+ } else {
+ session->in_buffer = buffer_new();
+ if (session->in_buffer == NULL) {
+ goto error;
+ }
+ }
+
+ rc = ssh_socket_read(session->socket, &len, sizeof(u32));
+ if (rc != SSH_OK) {
+ goto error;
+ }
+
+ rc = SSH_ERROR;
+
+ /* len is not encrypted */
+ len = ntohl(len);
+ if (len > MAX_PACKET_LEN) {
+ ssh_set_error(session, SSH_FATAL,
+ "read_packet(): Packet len too high (%u %.8x)", len, len);
+ goto error;
+ }
+
+ ssh_log(session, SSH_LOG_PACKET, "Reading a %d bytes packet", len);
+
+ session->in_packet.len = len;
+ session->packet_state = PACKET_STATE_SIZEREAD;
+ case PACKET_STATE_SIZEREAD:
+ len = session->in_packet.len;
+ /* SSH-1 has a fixed padding lenght */
+ padding = 8 - (len % 8);
+ to_be_read = len + padding;
+
+ /* it is _not_ possible that to_be_read be < 8. */
+ packet = malloc(to_be_read);
+ if (packet == NULL) {
+ ssh_set_error(session, SSH_FATAL, "Not enough space");
+ goto error;
+ }
+
+ rc = ssh_socket_read(session->socket, packet, to_be_read);
+ if(rc != SSH_OK) {
+ SAFE_FREE(packet);
+ goto error;
+ }
+ rc = SSH_ERROR;
+
+ if (buffer_add_data(session->in_buffer,packet,to_be_read) < 0) {
+ SAFE_FREE(packet);
+ goto error;
+ }
+ SAFE_FREE(packet);
+
#ifdef DEBUG_CRYPTO
- ssh_print_hexa("read packet:",buffer_get(session->in_buffer),
- buffer_get_len(session->in_buffer));
+ ssh_print_hexa("read packet:", buffer_get(session->in_buffer),
+ buffer_get_len(session->in_buffer));
#endif
- if (session->current_crypto) {
- /* we decrypt everything, missing the lenght part (which was
- * previously read, unencrypted, and is not part of the buffer
- */
- if (packet_decrypt(session,
- buffer_get(session->in_buffer),
- buffer_get_len(session->in_buffer)) < 0) {
- ssh_set_error(session, SSH_FATAL, "Packet decrypt error");
- leave_function();
- return SSH_ERROR;
- }
- }
+ if (session->current_crypto) {
+ /*
+ * We decrypt everything, missing the lenght part (which was
+ * previously read, unencrypted, and is not part of the buffer
+ */
+ if (packet_decrypt(session,
+ buffer_get(session->in_buffer),
+ buffer_get_len(session->in_buffer)) < 0) {
+ ssh_set_error(session, SSH_FATAL, "Packet decrypt error");
+ goto error;
+ }
+ }
#ifdef DEBUG_CRYPTO
- ssh_print_hexa("read packet decrypted:",
- buffer_get(session->in_buffer),buffer_get_len(session->in_buffer));
+ ssh_print_hexa("read packet decrypted:", buffer_get(session->in_buffer),
+ buffer_get_len(session->in_buffer));
#endif
- ssh_log(session,SSH_LOG_PACKET,"%d bytes padding",padding);
- if((len+padding) != buffer_get_rest_len(session->in_buffer) || (len+padding) < sizeof(u32)){
- ssh_log(session,SSH_LOG_RARE,"no crc32 in packet");
- ssh_set_error(session,SSH_FATAL,"no crc32 in packet");
- leave_function();
- return SSH_ERROR;
- }
- memcpy(&crc,buffer_get_rest(session->in_buffer)+(len+padding)-sizeof(u32),
- sizeof(u32));
- buffer_pass_bytes_end(session->in_buffer,sizeof(u32));
- crc=ntohl(crc);
- if(ssh_crc32(buffer_get_rest(session->in_buffer),(len+padding)-sizeof(u32))!=crc){
+ ssh_log(session, SSH_LOG_PACKET, "%d bytes padding", padding);
+ if(((len + padding) != buffer_get_rest_len(session->in_buffer)) ||
+ ((len + padding) < sizeof(u32))) {
+ ssh_log(session, SSH_LOG_RARE, "no crc32 in packet");
+ ssh_set_error(session, SSH_FATAL, "no crc32 in packet");
+ goto error;
+ }
+
+ memcpy(&crc,
+ buffer_get_rest(session->in_buffer) + (len+padding) - sizeof(u32),
+ sizeof(u32));
+ buffer_pass_bytes_end(session->in_buffer, sizeof(u32));
+ crc = ntohl(crc);
+ if (ssh_crc32(buffer_get_rest(session->in_buffer),
+ (len + padding) - sizeof(u32)) != crc) {
#ifdef DEBUG_CRYPTO
- ssh_print_hexa("crc32 on",buffer_get_rest(session->in_buffer),
- len + padding - sizeof(u32));
+ ssh_print_hexa("crc32 on",buffer_get_rest(session->in_buffer),
+ len + padding - sizeof(u32));
#endif
- ssh_log(session,SSH_LOG_RARE,"invalid crc32");
- ssh_set_error(session,SSH_FATAL,"invalid crc32 : expected %.8x, "
- "got %.8x",crc,
- ssh_crc32(buffer_get_rest(session->in_buffer),len+padding-sizeof(u32)) );
- leave_function();
- return SSH_ERROR;
- }
- buffer_pass_bytes(session->in_buffer,padding); /*pass the padding*/
- ssh_log(session,SSH_LOG_PACKET,"the packet is valid");
-/* will do that later
+ ssh_log(session, SSH_LOG_RARE, "Invalid crc32");
+ ssh_set_error(session, SSH_FATAL,
+ "Invalid crc32: expected %.8x, got %.8x",
+ crc,
+ ssh_crc32(buffer_get_rest(session->in_buffer),
+ len + padding - sizeof(u32)));
+ goto error;
+ }
+ /* pass the padding */
+ buffer_pass_bytes(session->in_buffer, padding);
+ ssh_log(session, SSH_LOG_PACKET, "The packet is valid");
+
+/* TODO FIXME
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
if(session->current_crypto && session->current_crypto->do_compress_in){
decompress_buffer(session,session->in_buffer);
}
#endif
*/
- session->recv_seq++;
- session->packet_state=PACKET_STATE_INIT;
- leave_function();
- return SSH_OK;
- }
- ssh_set_error(session,SSH_FATAL,"Invalid state into packet_read1() : %d",session->packet_state);
- leave_function();
- return SSH_ERROR;
+ session->recv_seq++;
+ session->packet_state=PACKET_STATE_INIT;
+
+ leave_function();
+ return SSH_OK;
+ } /* switch */
+
+ ssh_set_error(session, SSH_FATAL,
+ "Invalid state into packet_read1(): %d",
+ session->packet_state);
+error:
+ leave_function();
+ return rc;
}
#endif /* HAVE_SSH1 */
/* that's where i'd like C to be object ... */
-int packet_read(SSH_SESSION *session){
+int packet_read(SSH_SESSION *session) {
#ifdef HAVE_SSH1
- if(session->version==1)
- return packet_read1(session);
- else
+ if (session->version == 1) {
+ return packet_read1(session);
+ }
#endif
- return packet_read2(session);
+ return packet_read2(session);
}
int packet_translate(SSH_SESSION *session){