Security: Patche for CVE-2008-1105.
authorGerald W. Carter <jerry@samba.org>
Wed, 28 May 2008 12:30:19 +0000 (07:30 -0500)
committerGerald W. Carter <jerry@samba.org>
Wed, 28 May 2008 15:26:27 +0000 (10:26 -0500)
    -- 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.

source/client/client.c
source/client/smbctool.c
source/lib/util_sock.c
source/libsmb/clientgen.c
source/smbd/process.c
source/utils/smbfilter.c

index 3f96f63f90df232ba31986162ace76423a47cf6d..e87623a59d59d4d28ed59906a858ccbde531f464 100644 (file)
@@ -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;
index 2063418a91657be8d46a8b8b4547decb5b1ca5c5..a18505b4b4517bc4ae0480f63f295019aa299036 100644 (file)
@@ -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;
        }
          
index 94c5e82d153d778ec6a908c9804f38f04ccbb257..4715ca7dcb4c3639f863a7b7a4c2e7e7cdc571f1 100644 (file)
@@ -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;
        }
 
index c6cef0870475e19fb6f064bc082802cd4308b4b6..7d7ab9ea3e5b664211c7120a2ff67a7c1fe169c2 100644 (file)
@@ -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 */
index 8dec71958ea1768e5f05dd7b48b46fe96073f878..3d31c297fa7be1b7bf768ff93ade68b348c09fec 100644 (file)
@@ -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);
 }
 
 /*
index 97d22230c4bb56c44086a2d5d4570fe25f04b0e6..2152e539b0ebf4fc6901d0ebb73ace2cf5f7b786 100644 (file)
@@ -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);
                        }