[Secure-testing-team] Bug#483410: CVE-2008-1105: Boundary failure when parsing SMB responses can result in a buffer overrun

Christian Perrier bubulle at debian.org
Wed May 28 18:20:10 UTC 2008


Package: samba
Version: 3.0.14a-3sarge11
Severity: critical
Tags: security patch
Justification: root security hole

Patch 1 is for etch
Patch 2 is the official patch released by the Samba Team. Applies cleanly on
Debian's 3.0.29. However, we'll fix unstable/testing by building samba 3.0.30

To security team: as I said, I'm unsure that I'll be able to work on
packages for etch. I'll at least try building with that patch. As usual, I
may need guidance to upload to the right place if you're OK for us to upload
for etch.

What about sarge? It is affected as well (samba is 3.0.14 there) but is it
still officially supported wrt security updates?


>From the announcement:

==========================================================
== Subject:     Boundary failure when parsing SMB responses
==              can result in a buffer overrun
==
== CVE ID#:     CVE-2008-1105
==
== Versions:    Samba 3.0.0 - 3.0.29 (inclusive)
==
== Summary:     Specifically crafted SMB responses can result
==              in a heap overflow in the Samba client code.
==              Because the server process, smbd, can itself
==              act as a client during operations such as
==              printer notification and domain authentication,
==              this issue affects both Samba client and server
==              installations.
==
==========================================================

===========
Description
===========

Secunia Research reported a vulnerability that allows for
the execution of arbitrary code in smbd.  This defect is
is a result of an incorrect buffer size when parsing SMB
replies in the routine receive_smb_raw().


==================
Patch Availability
==================

A patch addressing this defect has been posted to

  http://www.samba.org/samba/security/
  
  Additionally, Samba 3.0.30 has been issued as a security
  release to correct the defect.  Samba administrators are
  advised to upgrade to 3.0.30 or apply the patch as soon
  as possible.
  
  
  =======
  Credits
  =======
  
  This vulnerability was reported to Samba developers by
  Alin Rad Pop, Secunia Research.
  
  The time line is as follows:
  
  * May 15, 2008: Initial report to security at samba.org.
  * May 15, 2008: First response from Samba developers confirming
    the bug along with a proposed patch.
    * May 28, 2008: Public security advisory made available.
    
    
    ==========================================================
    == Our Code, Our Bugs, Our Responsibility.
    == The Samba Team
    ==========================================================
    


-- System Information:
Debian Release: lenny/sid
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: i386 (i686)

Kernel: Linux 2.6.24-1-686 (SMP w/1 CPU core)
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages samba depends on:
ii  adduser                3.107             add and remove users and groups
ii  debconf [debconf-2.0]  1.5.22            Debian configuration management sy
ii  libacl1                2.2.47-2          Access control list shared library
ii  libattr1               1:2.4.41-1        Extended attribute shared library
ii  libc6                  2.7-11            GNU C Library: Shared libraries
ii  libcomerr2             1.40.8-2          common error description library
ii  libcupsys2             1.3.7-5           Common UNIX Printing System(tm) - 
ii  libgnutls26            2.2.5-1           the GNU TLS library - runtime libr
ii  libkrb53               1.6.dfsg.3-2      MIT Kerberos runtime libraries
ii  libldap-2.4-2          2.4.9-1           OpenLDAP libraries
ii  libpam-modules         0.99.7.1-6        Pluggable Authentication Modules f
ii  libpam-runtime         0.99.7.1-6        Runtime support for the PAM librar
ii  libpam0g               0.99.7.1-6        Pluggable Authentication Modules l
ii  libpopt0               1.10-3            lib for parsing cmdline parameters
ii  logrotate              3.7.1-3           Log rotation utility
ii  lsb-base               3.2-12            Linux Standard Base 3.2 init scrip
ii  procps                 1:3.2.7-8         /proc file system utilities
ii  samba-common           1:3.0.29-1        Samba common files used by both th
ii  update-inetd           4.30              inetd configuration file updater
ii  zlib1g                 1:1.2.3.3.dfsg-12 compression library - runtime

samba recommends no packages.

-- debconf information excluded
-------------- next part --------------
commit 7e191387d64de2c965fc2c999bc7d1ccf4aae010
Author: Gerald W. Carter <jerry at samba.org>
Date:   Wed May 28 07:30:19 2008 -0500

    Security: Patche for CVE-2008-1105.
    
        -- Summary --
        Specifically crafted SMB responses can result
        in a heap overflow in the Samba client code.
        Because the server process, smbd, can itself
        act as a client during operations such as
        printer notification and domain authentication,
        this issue affects both Samba client and server
        installations.
    
    Ensure that we specify the buffer size used to store incoming SMB
    packets.  This bug was originally introduced in Samba 2.2.4.  Patch from
    Jeremy Allison.

Index: samba-3.0.24/source/client/client.c
===================================================================
--- samba-3.0.24.orig/source/client/client.c
+++ samba-3.0.24/source/client/client.c
@@ -3230,7 +3230,7 @@
 	   session keepalives and then drop them here.
 	*/
 	if (FD_ISSET(cli->fd,&fds)) {
-		if (!receive_smb(cli->fd,cli->inbuf,0)) {
+		if (!receive_smb(cli->fd,cli->inbuf,cli->bufsize,0)) {
 			DEBUG(0, ("Read from server failed, maybe it closed the "
 				"connection\n"));
 			return;
Index: samba-3.0.24/source/client/smbctool.c
===================================================================
--- samba-3.0.24.orig/source/client/smbctool.c
+++ samba-3.0.24/source/client/smbctool.c
@@ -3304,7 +3304,7 @@
 	   session keepalives and then drop them here.
 	*/
 	if (FD_ISSET(cli->fd,&fds)) {
-		receive_smb(cli->fd,cli->inbuf,0);
+		receive_smb(cli->fd,cli->inbuf,cli->bufsize,0);
 		goto again;
 	}
 	  
Index: samba-3.0.24/source/lib/util_sock.c
===================================================================
--- samba-3.0.24.orig/source/lib/util_sock.c
+++ samba-3.0.24/source/lib/util_sock.c
@@ -654,14 +654,13 @@
 }
 
 /****************************************************************************
- Read an smb from a fd. Note that the buffer *MUST* be of size
- BUFFER_SIZE+SAFETY_MARGIN.
+ Read an smb from a fd. 
  The timeout is in milliseconds. 
  This function will return on receipt of a session keepalive packet.
  Doesn't check the MAC on signed packets.
 ****************************************************************************/
 
-BOOL receive_smb_raw(int fd, char *buffer, unsigned int timeout)
+BOOL receive_smb_raw(int fd, char *buffer, size_t buflen, unsigned int timeout)
 {
 	ssize_t len,ret;
 
@@ -682,25 +681,18 @@
 		return False;
 	}
 
-	/*
-	 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
-	 * of header. Don't print the error if this fits.... JRA.
-	 */
-
-	if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
+	if (len > buflen) {
 		DEBUG(0,("Invalid packet length! (%lu bytes).\n",(unsigned long)len));
-		if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) {
 
-			/*
-			 * Correct fix. smb_read_error may have already been
-			 * set. Only set it here if not already set. Global
-			 * variables still suck :-). JRA.
-			 */
+		/*
+		 * smb_read_error may have already been
+		 * set. Only set it here if not already set. Global
+		 * variables still suck :-). JRA.
+		 */
 
-			if (smb_read_error == 0)
-				smb_read_error = READ_ERROR;
-			return False;
-		}
+		if (smb_read_error == 0)
+			smb_read_error = READ_ERROR;
+		return False;
 	}
 
 	if(len > 0) {
@@ -730,9 +722,9 @@
  Checks the MAC on signed packets.
 ****************************************************************************/
 
-BOOL receive_smb(int fd, char *buffer, unsigned int timeout)
+BOOL receive_smb(int fd, char *buffer, size_t buflen, unsigned int timeout)
 {
-	if (!receive_smb_raw(fd, buffer, timeout)) {
+	if (!receive_smb_raw(fd, buffer, buflen, timeout)) {
 		return False;
 	}
 
Index: samba-3.0.24/source/libsmb/clientgen.c
===================================================================
--- samba-3.0.24.orig/source/libsmb/clientgen.c
+++ samba-3.0.24/source/libsmb/clientgen.c
@@ -42,8 +42,7 @@
 }
 
 /****************************************************************************
- Read an smb from a fd ignoring all keepalive packets. Note that the buffer 
- *MUST* be of size BUFFER_SIZE+SAFETY_MARGIN.
+ Read an smb from a fd ignoring all keepalive packets.
  The timeout is in milliseconds
 
  This is exactly the same as receive_smb except that it never returns
@@ -52,12 +51,12 @@
  should never go into a blocking read.
 ****************************************************************************/
 
-static BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout)
+static BOOL client_receive_smb(int fd,char *buffer, size_t bufsize, unsigned int timeout)
 {
 	BOOL ret;
 
 	for(;;) {
-		ret = receive_smb_raw(fd, buffer, timeout);
+		ret = receive_smb_raw(fd, buffer, bufsize, timeout);
 
 		if (!ret) {
 			DEBUG(10,("client_receive_smb failed\n"));
@@ -87,7 +86,7 @@
 		return False; 
 
  again:
-	ret = client_receive_smb(cli->fd,cli->inbuf,cli->timeout);
+	ret = client_receive_smb(cli->fd,cli->inbuf, cli->bufsize, cli->timeout);
 	
 	if (ret) {
 		/* it might be an oplock break request */
Index: samba-3.0.24/source/smbd/process.c
===================================================================
--- samba-3.0.24.orig/source/smbd/process.c
+++ samba-3.0.24/source/smbd/process.c
@@ -508,7 +508,8 @@
 		goto again;
 	}
 	
-	return receive_smb(smbd_server_fd(), buffer, 0);
+	return receive_smb(smbd_server_fd(), buffer,
+			BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE, 0);
 }
 
 /*
Index: samba-3.0.24/source/utils/smbfilter.c
===================================================================
--- samba-3.0.24.orig/source/utils/smbfilter.c
+++ samba-3.0.24/source/utils/smbfilter.c
@@ -140,7 +140,7 @@
 		if (num <= 0) continue;
 		
 		if (c != -1 && FD_ISSET(c, &fds)) {
-			if (!receive_smb(c, packet, 0)) {
+			if (!receive_smb(c, packet, BUFFER_SIZE, 0)) {
 				d_printf("client closed connection\n");
 				exit(0);
 			}
@@ -151,7 +151,7 @@
 			}			
 		}
 		if (s != -1 && FD_ISSET(s, &fds)) {
-			if (!receive_smb(s, packet, 0)) {
+			if (!receive_smb(s, packet, BUFFER_SIZE, 0)) {
 				d_printf("server closed connection\n");
 				exit(0);
 			}
-------------- next part --------------
commit 7e191387d64de2c965fc2c999bc7d1ccf4aae010
Author: Gerald W. Carter <jerry at samba.org>
Date:   Wed May 28 07:30:19 2008 -0500

    Security: Patche for CVE-2008-1105.
    
        -- Summary --
        Specifically crafted SMB responses can result
        in a heap overflow in the Samba client code.
        Because the server process, smbd, can itself
        act as a client during operations such as
        printer notification and domain authentication,
        this issue affects both Samba client and server
        installations.
    
    Ensure that we specify the buffer size used to store incoming SMB
    packets.  This bug was originally introduced in Samba 2.2.4.  Patch from
    Jeremy Allison.

diff --git a/source/client/client.c b/source/client/client.c
index 3f96f63..e87623a 100644
--- a/source/client/client.c
+++ b/source/client/client.c
@@ -3626,7 +3626,7 @@ static void readline_callback(void)
 	   session keepalives and then drop them here.
 	*/
 	if (FD_ISSET(cli->fd,&fds)) {
-		if (!receive_smb(cli->fd,cli->inbuf,0)) {
+		if (!receive_smb(cli->fd,cli->inbuf,cli->bufsize,0)) {
 			DEBUG(0, ("Read from server failed, maybe it closed the "
 				"connection\n"));
 			return;
diff --git a/source/client/smbctool.c b/source/client/smbctool.c
index 2063418..a18505b 100644
--- a/source/client/smbctool.c
+++ b/source/client/smbctool.c
@@ -3304,7 +3304,7 @@ static void readline_callback(void)
 	   session keepalives and then drop them here.
 	*/
 	if (FD_ISSET(cli->fd,&fds)) {
-		receive_smb(cli->fd,cli->inbuf,0);
+		receive_smb(cli->fd,cli->inbuf,cli->bufsize,0);
 		goto again;
 	}
 	  
diff --git a/source/lib/util_sock.c b/source/lib/util_sock.c
index 94c5e82..4715ca7 100644
--- a/source/lib/util_sock.c
+++ b/source/lib/util_sock.c
@@ -654,14 +654,13 @@ ssize_t read_smb_length(int fd, char *inbuf, unsigned int timeout)
 }
 
 /****************************************************************************
- Read an smb from a fd. Note that the buffer *MUST* be of size
- BUFFER_SIZE+SAFETY_MARGIN.
+ Read an smb from a fd. 
  The timeout is in milliseconds. 
  This function will return on receipt of a session keepalive packet.
  Doesn't check the MAC on signed packets.
 ****************************************************************************/
 
-BOOL receive_smb_raw(int fd, char *buffer, unsigned int timeout)
+BOOL receive_smb_raw(int fd, char *buffer, size_t buflen, unsigned int timeout)
 {
 	ssize_t len,ret;
 
@@ -682,25 +681,18 @@ BOOL receive_smb_raw(int fd, char *buffer, unsigned int timeout)
 		return False;
 	}
 
-	/*
-	 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
-	 * of header. Don't print the error if this fits.... JRA.
-	 */
-
-	if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
+	if (len > buflen) {
 		DEBUG(0,("Invalid packet length! (%lu bytes).\n",(unsigned long)len));
-		if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) {
 
-			/*
-			 * Correct fix. smb_read_error may have already been
-			 * set. Only set it here if not already set. Global
-			 * variables still suck :-). JRA.
-			 */
+		/*
+		 * smb_read_error may have already been
+		 * set. Only set it here if not already set. Global
+		 * variables still suck :-). JRA.
+		 */
 
-			if (smb_read_error == 0)
-				smb_read_error = READ_ERROR;
-			return False;
-		}
+		if (smb_read_error == 0)
+			smb_read_error = READ_ERROR;
+		return False;
 	}
 
 	if(len > 0) {
@@ -730,9 +722,9 @@ BOOL receive_smb_raw(int fd, char *buffer, unsigned int timeout)
  Checks the MAC on signed packets.
 ****************************************************************************/
 
-BOOL receive_smb(int fd, char *buffer, unsigned int timeout)
+BOOL receive_smb(int fd, char *buffer, size_t buflen, unsigned int timeout)
 {
-	if (!receive_smb_raw(fd, buffer, timeout)) {
+	if (!receive_smb_raw(fd, buffer, buflen, timeout)) {
 		return False;
 	}
 
diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c
index c6cef08..7d7ab9e 100644
--- a/source/libsmb/clientgen.c
+++ b/source/libsmb/clientgen.c
@@ -44,8 +44,7 @@ int cli_set_port(struct cli_state *cli, int port)
 }
 
 /****************************************************************************
- Read an smb from a fd ignoring all keepalive packets. Note that the buffer 
- *MUST* be of size BUFFER_SIZE+SAFETY_MARGIN.
+ Read an smb from a fd ignoring all keepalive packets.
  The timeout is in milliseconds
 
  This is exactly the same as receive_smb except that it never returns
@@ -54,12 +53,12 @@ int cli_set_port(struct cli_state *cli, int port)
  should never go into a blocking read.
 ****************************************************************************/
 
-static BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout)
+static BOOL client_receive_smb(int fd,char *buffer, size_t bufsize, unsigned int timeout)
 {
 	BOOL ret;
 
 	for(;;) {
-		ret = receive_smb_raw(fd, buffer, timeout);
+		ret = receive_smb_raw(fd, buffer, bufsize, timeout);
 
 		if (!ret) {
 			DEBUG(10,("client_receive_smb failed\n"));
@@ -88,7 +87,7 @@ BOOL cli_receive_smb(struct cli_state *cli)
 		return False; 
 
  again:
-	ret = client_receive_smb(cli->fd,cli->inbuf,cli->timeout);
+	ret = client_receive_smb(cli->fd,cli->inbuf, cli->bufsize, cli->timeout);
 	
 	if (ret) {
 		/* it might be an oplock break request */
diff --git a/source/smbd/process.c b/source/smbd/process.c
index 8dec719..3d31c29 100644
--- a/source/smbd/process.c
+++ b/source/smbd/process.c
@@ -521,7 +521,8 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
 		goto again;
 	}
 
-	return receive_smb(smbd_server_fd(), buffer, 0);
+	return receive_smb(smbd_server_fd(), buffer,
+			BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE, 0);
 }
 
 /*
diff --git a/source/utils/smbfilter.c b/source/utils/smbfilter.c
index 97d2223..2152e53 100644
--- a/source/utils/smbfilter.c
+++ b/source/utils/smbfilter.c
@@ -140,7 +140,7 @@ static void filter_child(int c, struct in_addr dest_ip)
 		if (num <= 0) continue;
 		
 		if (c != -1 && FD_ISSET(c, &fds)) {
-			if (!receive_smb(c, packet, 0)) {
+			if (!receive_smb(c, packet, BUFFER_SIZE, 0)) {
 				d_printf("client closed connection\n");
 				exit(0);
 			}
@@ -151,7 +151,7 @@ static void filter_child(int c, struct in_addr dest_ip)
 			}			
 		}
 		if (s != -1 && FD_ISSET(s, &fds)) {
-			if (!receive_smb(s, packet, 0)) {
+			if (!receive_smb(s, packet, BUFFER_SIZE, 0)) {
 				d_printf("server closed connection\n");
 				exit(0);
 			}


More information about the Secure-testing-team mailing list