Package: release.debian.org Severity: normal User: release.debian....@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 <bi...@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; }