[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#698976: unblock: libssh/0.5.4-1 (Fix CVE, not uploaded yet)



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Hello,

I'm planning to upload libssh 0.5.4 to unstable. This versions fixes a
security issue (DOS) and some other potential crashes:

version 0.5.4 (released 2013-01-22)
  * CVE-2013-0176 - NULL dereference leads to denial of service
  * Fixed several NULL pointer dereferences in SSHv1.
  * Fixed a free crash bug in options parsing.


$ git diff debian/0.5.3-1|filterdiff -x '*/doc/doxy.config.in.bak' -x '*/*.patch' -x '*/SECFIX_0.5.2.tar.asc' |diffstat 
 /dev/null           |binary
 b/CMakeLists.txt    |    4 +--
 b/CPackConfig.cmake |    2 -
 b/ChangeLog         |    5 ++++
 b/debian/changelog  |    8 ++++++
 b/src/channels1.c   |   65 +++++++++++++++++++++++++++++++++++++++++++++++-----
 b/src/options.c     |   14 ++++++-----
 b/src/server.c      |   13 ++++++++--
 8 files changed, 94 insertions(+), 17 deletions(-)

The previous version was including some patches for reference and several
tarballs (?!), they are now gone.

The 3 separate fixes are available at:

http://git.libssh.org/projects/libssh.git/commit/?h=v0-5&id=ba231d0844d424f48b6dc4c04b3109a0175d0733
http://git.libssh.org/projects/libssh.git/commit/?h=v0-5&id=f128338132e727911f049678c443b73a19204b1e
http://git.libssh.org/projects/libssh.git/commit/?h=v0-5&id=55b09f426417406bb25c0b9c474fbab1398b0dc8

The attached patch has been generated with the same excludes as the
diffstat above.

Would these changes be accepted in wheezy?

unblock libssh/0.5.4-1

-- System Information:
Debian Release: 7.0
  APT prefers unstable
  APT policy: (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.7-trunk-amd64 (SMP w/8 CPU cores)
Locale: LANG=fr_BE.utf8, LC_CTYPE=fr_BE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
diff --git a/0001-CVE-2012-4562-Fix-possible-integer-overflow-in-ssh_g.patch b/0001-CVE-2012-4562-Fix-possible-integer-overflow-in-ssh_g.patch
deleted file mode 100644
index 6689933..0000000
diff --git a/0002-CVE-2012-4562-Fix-multiple-integer-overflows-in-buff.patch b/0002-CVE-2012-4562-Fix-multiple-integer-overflows-in-buff.patch
deleted file mode 100644
index 479a5bd..0000000
diff --git a/0003-CVE-2012-4562-Fix-a-possible-infinite-loop-in-buffer.patch b/0003-CVE-2012-4562-Fix-a-possible-infinite-loop-in-buffer.patch
deleted file mode 100644
index a1ff81c..0000000
diff --git a/0004-CVE-2012-4562-Fix-possible-string-related-integer-ov.patch b/0004-CVE-2012-4562-Fix-possible-string-related-integer-ov.patch
deleted file mode 100644
index 13dea07..0000000
diff --git a/0005-CVE-2012-4560-Fix-a-write-one-past-the-end-of-the-u-.patch b/0005-CVE-2012-4560-Fix-a-write-one-past-the-end-of-the-u-.patch
deleted file mode 100644
index 5948784..0000000
diff --git a/0006-CVE-2012-4560-Fix-a-write-one-past-the-end-of-buf.patch b/0006-CVE-2012-4560-Fix-a-write-one-past-the-end-of-buf.patch
deleted file mode 100644
index cb4ad0c..0000000
diff --git a/0007-CVE-2012-4559-Ensure-we-don-t-free-blob-or-request-t.patch b/0007-CVE-2012-4559-Ensure-we-don-t-free-blob-or-request-t.patch
deleted file mode 100644
index 54bec46..0000000
diff --git a/0008-CVE-2012-4559-Ensure-that-we-don-t-free-req-twice.patch b/0008-CVE-2012-4559-Ensure-that-we-don-t-free-req-twice.patch
deleted file mode 100644
index 386e3b3..0000000
diff --git a/0009-CVE-2012-4559-Make-sure-we-don-t-free-name-and-longn.patch b/0009-CVE-2012-4559-Make-sure-we-don-t-free-name-and-longn.patch
deleted file mode 100644
index ce435c7..0000000
diff --git a/0010-CVE-2012-4561-Fix-error-handling-of-try_publickey_fr.patch b/0010-CVE-2012-4561-Fix-error-handling-of-try_publickey_fr.patch
deleted file mode 100644
index d8f17ba..0000000
diff --git a/0011-CVE-2012-4561-Fix-possible-free-s-on-invalid-pointer.patch b/0011-CVE-2012-4561-Fix-possible-free-s-on-invalid-pointer.patch
deleted file mode 100644
index fb875fb..0000000
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0f00089..3d187cb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
 
 set(APPLICATION_VERSION_MAJOR "0")
 set(APPLICATION_VERSION_MINOR "5")
-set(APPLICATION_VERSION_PATCH "3")
+set(APPLICATION_VERSION_PATCH "4")
 
 set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
 
@@ -19,7 +19,7 @@ set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINO
 #     Increment AGE. Set REVISION to 0
 #   If the source code was changed, but there were no interface changes:
 #     Increment REVISION.
-set(LIBRARY_VERSION "4.2.3")
+set(LIBRARY_VERSION "4.2.4")
 set(LIBRARY_SOVERSION "4")
 
 # where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
diff --git a/CPackConfig.cmake b/CPackConfig.cmake
index 23a9a01..1bbc708 100644
--- a/CPackConfig.cmake
+++ b/CPackConfig.cmake
@@ -13,7 +13,7 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
 ### versions
 set(CPACK_PACKAGE_VERSION_MAJOR "0")
 set(CPACK_PACKAGE_VERSION_MINOR "5")
-set(CPACK_PACKAGE_VERSION_PATCH "3")
+set(CPACK_PACKAGE_VERSION_PATCH "4")
 set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
 
 
diff --git a/ChangeLog b/ChangeLog
index d513613..94603b2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,11 @@
 ChangeLog
 ==========
 
+version 0.5.4 (released 2013-01-22)
+  * CVE-2013-0176 - NULL dereference leads to denial of service
+  * Fixed several NULL pointer dereferences in SSHv1.
+  * Fixed a free crash bug in options parsing.
+
 version 0.5.3 (released 2012-11-20)
   * CVE-2012-4559 Fixed multiple double free() flaws.
   * CVE-2012-4560 Fixed multiple buffer overflow flaws.
diff --git a/SECFIX_0.5.2.tar.asc b/SECFIX_0.5.2.tar.asc
deleted file mode 100644
index 2a0db5e..0000000
diff --git a/SECFIX_0.5.2.tar.gz b/SECFIX_0.5.2.tar.gz
deleted file mode 100644
index 41c9ccd..0000000
Binary files a/SECFIX_0.5.2.tar.gz and /dev/null differ
diff --git a/SECFIX_0.5.tar.gz b/SECFIX_0.5.tar.gz
deleted file mode 100644
index 333771d..0000000
Binary files a/SECFIX_0.5.tar.gz and /dev/null differ
diff --git a/SECFIX_master.tar.gz b/SECFIX_master.tar.gz
deleted file mode 100644
index 9d0cebe..0000000
Binary files a/SECFIX_master.tar.gz and /dev/null differ
diff --git a/debian/changelog b/debian/changelog
index 1c536a7..88931d0 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+libssh (0.5.4-1) UNRELEASED; urgency=low
+
+  * New upstream security release
+    - Fix NULL dereference leads to denial of service
+      (Closes: #698963, CVE-2013-0176)
+
+ -- Laurent Bigonville <bigon@debian.org>  Fri, 25 Jan 2013 21:08:57 +0100
+
 libssh (0.5.3-1) unstable; urgency=high
 
   * New upstream security release
diff --git a/doc/doxy.config.in.bak b/doc/doxy.config.in.bak
deleted file mode 100644
index 9810518..0000000
diff --git a/src/channels1.c b/src/channels1.c
index ca669a4..a9e3ab5 100644
--- a/src/channels1.c
+++ b/src/channels1.c
@@ -50,11 +50,17 @@
  */
 
 int channel_open_session1(ssh_channel chan) {
+  ssh_session session;
+
+  if (chan == NULL) {
+    return -1;
+  }
+  session = chan->session;
+
   /*
    * We guess we are requesting an *exec* channel. It can only have one exec
    * channel. So we abort with an error if we need more than one.
    */
-  ssh_session session = chan->session;
   if (session->exec_channel_opened) {
     ssh_set_error(session, SSH_REQUEST_DENIED,
         "SSH1 supports only one execution channel. "
@@ -85,8 +91,14 @@ int channel_open_session1(ssh_channel chan) {
 
 int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col,
     int row) {
-  ssh_session session = channel->session;
+  ssh_session session;
   ssh_string str = NULL;
+
+  if (channel == NULL) {
+    return SSH_ERROR;
+  }
+  session = channel->session;
+
   if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){
     ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state");
     return SSH_ERROR;
@@ -139,7 +151,13 @@ int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col
 }
 
 int channel_change_pty_size1(ssh_channel channel, int cols, int rows) {
-  ssh_session session = channel->session;
+  ssh_session session;
+
+  if (channel == NULL) {
+    return SSH_ERROR;
+  }
+  session = channel->session;
+
   if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){
     ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state");
     return SSH_ERROR;
@@ -182,7 +200,12 @@ int channel_change_pty_size1(ssh_channel channel, int cols, int rows) {
 }
 
 int channel_request_shell1(ssh_channel channel) {
-  ssh_session session = channel->session;
+  ssh_session session;
+
+  if (channel == NULL) {
+    return -1;
+  }
+  session = channel->session;
 
   if (buffer_add_u8(session->out_buffer,SSH_CMSG_EXEC_SHELL) < 0) {
     return -1;
@@ -198,9 +221,14 @@ int channel_request_shell1(ssh_channel channel) {
 }
 
 int channel_request_exec1(ssh_channel channel, const char *cmd) {
-  ssh_session session = channel->session;
+  ssh_session session;
   ssh_string command = NULL;
 
+  if (channel == NULL) {
+    return -1;
+  }
+  session = channel->session;
+
   command = ssh_string_from_char(cmd);
   if (command == NULL) {
     return -1;
@@ -227,6 +255,11 @@ SSH_PACKET_CALLBACK(ssh_packet_data1){
     ssh_string str = NULL;
     int is_stderr=(type==SSH_SMSG_STDOUT_DATA ? 0 : 1);
     (void)user;
+
+    if (channel == NULL) {
+      return SSH_PACKET_NOT_USED;
+    }
+
     str = buffer_get_ssh_string(packet);
     if (str == NULL) {
       ssh_log(session, SSH_LOG_FUNCTIONS, "Invalid data packet !\n");
@@ -254,6 +287,10 @@ SSH_PACKET_CALLBACK(ssh_packet_close1){
   (void)type;
   (void)user;
 
+  if (channel == NULL) {
+    return SSH_PACKET_NOT_USED;
+  }
+
   buffer_get_u32(packet, &status);
   /*
    * It's much more than a channel closing. spec says it's the last
@@ -275,6 +312,11 @@ SSH_PACKET_CALLBACK(ssh_packet_exist_status1){
   uint32_t status;
   (void)type;
   (void)user;
+
+  if (channel == NULL) {
+    return SSH_PACKET_NOT_USED;
+  }
+
   buffer_get_u32(packet, &status);
   channel->state = SSH_CHANNEL_STATE_CLOSED;
   channel->remote_eof = 1;
@@ -285,10 +327,16 @@ SSH_PACKET_CALLBACK(ssh_packet_exist_status1){
 
 
 int channel_write1(ssh_channel channel, const void *data, int len) {
-  ssh_session session = channel->session;
+  ssh_session session;
   int origlen = len;
   int effectivelen;
   const unsigned char *ptr=data;
+
+  if (channel == NULL) {
+    return -1;
+  }
+  session = channel->session;
+
   while (len > 0) {
     if (buffer_add_u8(session->out_buffer, SSH_CMSG_STDIN_DATA) < 0) {
       return -1;
@@ -314,6 +362,11 @@ int channel_write1(ssh_channel channel, const void *data, int len) {
 
 ssh_channel ssh_get_channel1(ssh_session session){
   struct ssh_iterator *it;
+
+  if (session == NULL) {
+    return NULL;
+  }
+
   /* With SSH1, the channel is always the first one */
   if(session->channels != NULL){
     it = ssh_list_get_iterator(session->channels);
diff --git a/src/options.c b/src/options.c
index 2233ac0..5b3f1d1 100644
--- a/src/options.c
+++ b/src/options.c
@@ -720,12 +720,6 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) {
   int saveoptind = optind; /* need to save 'em */
   int saveopterr = opterr;
 
-  save = malloc(argc * sizeof(char *));
-  if (save == NULL) {
-    ssh_set_error_oom(session);
-    return -1;
-  }
-
   opterr = 0; /* shut up getopt */
   while(cont && ((i = getopt(argc, argv, "c:i:Cl:p:vb:rd12")) != -1)) {
     switch(i) {
@@ -763,8 +757,16 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) {
         break;
       default:
         {
+          char **tmp;
           char opt[3]="- ";
           opt[1] = optopt;
+          tmp = realloc(save, (current + 1) * sizeof(char*));
+          if (tmp == NULL) {
+            SAFE_FREE(save);
+            ssh_set_error_oom(session);
+            return -1;
+          }
+          save = tmp;
           save[current] = strdup(opt);
           if (save[current] == NULL) {
             SAFE_FREE(save);
diff --git a/src/server.c b/src/server.c
index 131a2bc..b4fb189 100644
--- a/src/server.c
+++ b/src/server.c
@@ -184,7 +184,11 @@ static int dh_handshake_server(ssh_session session) {
       prv = session->rsa_key;
       break;
     default:
-      prv = NULL;
+      ssh_set_error(session,
+                    SSH_FATAL,
+                    "Could determine the specified hostkey");
+      ssh_string_free(f);
+      return -1;
   }
 
   pub = publickey_from_privatekey(prv);
@@ -270,6 +274,8 @@ static int dh_handshake_server(ssh_session session) {
  */
 static void ssh_server_connection_callback(ssh_session session){
 	int ssh1,ssh2;
+    int rc;
+
 	enter_function();
 	switch(session->session_state){
 		case SSH_SESSION_STATE_NONE:
@@ -338,7 +344,10 @@ static void ssh_server_connection_callback(ssh_session session){
 		case SSH_SESSION_STATE_KEXINIT_RECEIVED:
 			set_status(session,0.6f);
 			ssh_list_kex(session, &session->client_kex); // log client kex
-            crypt_set_algorithms_server(session);
+            rc = crypt_set_algorithms_server(session);
+            if (rc == SSH_ERROR) {
+                goto error;
+            }
 			if (set_kex(session) < 0) {
 				goto error;
 			}

Reply to: