[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Wed Jul 19 23:39:04 UTC 2017


The branch, master has been updated
       via  7313e7c s4-torture: point out why we cannot validate MSZIP compressed files
       via  c60ad39 librpc/ndr: add MSZIP compression for cabinet files
       via  43a1952 librpc/ndr: simplify cabinet file size calculation
       via  7c20a87 librpc/ndr: Use correct value for max compression size
       via  a281612 librpc/ndr: Use MAX_WBITS zlib define and change memLevel in MSZIP code
       via  9ec74a3 librpc/ndr: remove unused ndr_cab_get_compression() function
       via  466d5e8 librpc: use DATA_BLOB in CFDATA structure
       via  1edf126 librpc/ndr: add helper functions to setup and free compression states.
       via  096efc9 librpc/ndr: add new MSZIP compression type for cabinet files
       via  aa33aa6 librpc/ndr: add new ndr_compression_state
       via  a44bce6 libndr/compression: pass down compressed length in ndr_pull_compression_start
       via  3b5442e librpc/ndr: remove trailing whitespace from compression file.
       via  9a2180c librpc:ndr_cab: Cast data pointer correctly
       via  e54adf5 ndr_compression: use MAX_WBITS constant
       via  0181fcc smbd: Fix a connection run-down race condition
      from  1b7b7a9 examples: add winbindd.stp and a shell script to generate it

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 7313e7c10df438fdf980ff9da80637df9f8dcb89
Author: Günther Deschner <gd at samba.org>
Date:   Tue May 23 15:50:55 2017 +0200

    s4-torture: point out why we cannot validate MSZIP compressed files
    
    Guenther
    
    Signed-off-by: Guenther Deschner <gd at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Thu Jul 20 01:38:02 CEST 2017 on sn-devel-144

commit c60ad394fa0da0d8dfbd9f3336b422f26bed8378
Author: Aurelien Aptel <aaptel at suse.com>
Date:   Tue May 23 12:09:28 2017 +0200

    librpc/ndr: add MSZIP compression for cabinet files
    
    Signed-off-by: Aurelien Aptel <aaptel at suse.com>
    Reviewed-by: Guenther Deschner <gd at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 43a1952b17c71b336af79411d9e26b5d91900998
Author: Aurelien Aptel <aaptel at suse.com>
Date:   Tue May 23 15:41:24 2017 +0200

    librpc/ndr: simplify cabinet file size calculation
    
    Signed-off-by: Aurelien Aptel <aaptel at suse.com>
    Reviewed-by: Guenther Deschner <gd at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 7c20a87097f506215423ea7494956fd1d993e36d
Author: Andreas Schneider <asn at samba.org>
Date:   Wed Jun 21 17:01:43 2017 +0200

    librpc/ndr: Use correct value for max compression size
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Guenther Deschner <gd at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit a2816122f9a94b2edc0e464ed44353409357f182
Author: Günther Deschner <gd at samba.org>
Date:   Tue May 23 15:48:42 2017 +0200

    librpc/ndr: Use MAX_WBITS zlib define and change memLevel in MSZIP code
    
    Guenther
    
    Signed-off-by: Günther Deschner <gd at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 9ec74a319fc6cbaf5a0159ef9323cd18e79c010f
Author: Aurelien Aptel <aaptel at suse.com>
Date:   Tue May 23 15:37:13 2017 +0200

    librpc/ndr: remove unused ndr_cab_get_compression() function
    
    Signed-off-by: Aurelien Aptel <aaptel at suse.com>
    Reviewed-by: Guenther Deschner <gd at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 466d5e814727046dd630d5503b43874ec46a365e
Author: Aurelien Aptel <aaptel at suse.com>
Date:   Tue May 23 15:31:44 2017 +0200

    librpc: use DATA_BLOB in CFDATA structure
    
    Signed-off-by: Aurelien Aptel <aaptel at suse.com>
    Reviewed-by: Guenther Deschner <gd at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 1edf126693b8bafe5f94a6ab4d34e0d21a05cb3d
Author: Aurelien Aptel <aaptel at suse.com>
Date:   Tue May 23 12:02:33 2017 +0200

    librpc/ndr: add helper functions to setup and free compression states.
    
    Signed-off-by: Aurelien Aptel <aaptel at suse.com>
    Reviewed-by: Guenther Deschner <gd at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 096efc93df490117b1de3bd2647bad52a7175a7f
Author: Günther Deschner <gd at samba.org>
Date:   Tue May 23 12:02:10 2017 +0200

    librpc/ndr: add new MSZIP compression type for cabinet files
    
    Guenther
    
    Signed-off-by: Guenther Deschner <gd at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit aa33aa6e64b3306ffb777ed690a60c5576e8514b
Author: Aurelien Aptel <aaptel at suse.com>
Date:   Tue May 23 11:59:59 2017 +0200

    librpc/ndr: add new ndr_compression_state
    
    Signed-off-by: Aurelien Aptel <aaptel at suse.com>
    Reviewed-by: Guenther Deschner <gd at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit a44bce6dfab59a6440ccc30ef0968d59b9f43fd3
Author: Günther Deschner <gd at samba.org>
Date:   Tue Sep 20 00:18:43 2016 +0200

    libndr/compression: pass down compressed length in ndr_pull_compression_start
    
    Guenther
    
    Signed-off-by: Guenther Deschner <gd at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 3b5442e77bc80f81a4c5ddd69d1544c25e125f4e
Author: Aurelien Aptel <aaptel at suse.com>
Date:   Tue Jan 24 19:00:53 2017 +0100

    librpc/ndr: remove trailing whitespace from compression file.
    
    Signed-off-by: Aurelien Aptel <aaptel at suse.com>
    Reviewed-by: Guenther Deschner <gd at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 9a2180cd04a2885d519fa3bac6fd2a30a8a1155f
Author: Andreas Schneider <asn at samba.org>
Date:   Tue May 9 16:51:43 2017 +0200

    librpc:ndr_cab: Cast data pointer correctly
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Guenther Deschner <gd at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit e54adf516e5c6546e45fb0efbb43f3c45f8917d1
Author: Aurelien Aptel <aaptel at suse.com>
Date:   Fri Jun 30 15:07:31 2017 +0200

    ndr_compression: use MAX_WBITS constant
    
    Signed-off-by: Aurelien Aptel <aaptel at suse.com>
    Reviewed-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 0181fcc4aaa730e3a88ff5d397145332f4013950
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Jul 19 14:51:33 2017 +0200

    smbd: Fix a connection run-down race condition
    
    When we do a server exit with active aio jobs, we need to keep the
    aio state active for the helper thread. Right now I don't see another
    chance than to leak memory in this case. And, I don't really oversee
    how cancelling requests works in this case, but this does fix crashes
    seen at a customer site.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 librpc/idl/cab.idl                       |   2 +-
 librpc/ndr/libndr.h                      |   7 +
 librpc/ndr/ndr_cab.c                     | 290 ++++++++++++++++----
 librpc/ndr/ndr_cab.h                     |   1 -
 librpc/ndr/ndr_compression.c             | 453 ++++++++++++++++++++++++++++++-
 librpc/ndr/ndr_compression.h             |  13 +-
 pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm |   3 +-
 source3/modules/vfs_default.c            |  33 ++-
 source4/torture/ndr/cabinet.c            |  18 +-
 9 files changed, 732 insertions(+), 88 deletions(-)


Changeset truncated at 500 lines:

diff --git a/librpc/idl/cab.idl b/librpc/idl/cab.idl
index 2174bce..9f3a02c 100644
--- a/librpc/idl/cab.idl
+++ b/librpc/idl/cab.idl
@@ -117,7 +117,7 @@ import "misc.idl";
 #if 0
 		uint8 abReserve[];	/* (optional) per-datablock reserved area */
 #endif
-		uint8 ab[cbData];	/* compressed data bytes */
+		DATA_BLOB ab;	/* compressed data bytes */
 	} CFDATA;
 
 	typedef [nopush,nopull,public,flag(NDR_PAHEX|NDR_LITTLE_ENDIAN|NDR_NOALIGN)] struct {
diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h
index 072fd66..de93893 100644
--- a/librpc/ndr/libndr.h
+++ b/librpc/ndr/libndr.h
@@ -47,6 +47,8 @@ struct ndr_token_list {
 	uint32_t count;
 };
 
+struct ndr_compression_state;
+
 /* this is the base structure passed to routines that
    parse MSRPC formatted data
 
@@ -71,6 +73,8 @@ struct ndr_pull {
 	struct ndr_token_list array_length_list;
 	struct ndr_token_list switch_list;
 
+	struct ndr_compression_state *cstate;
+
 	TALLOC_CTX *current_mem_ctx;
 
 	/* this is used to ensure we generate unique reference IDs
@@ -97,6 +101,8 @@ struct ndr_push {
 	struct ndr_token_list dns_string_list;
 	struct ndr_token_list full_ptr_list;
 
+	struct ndr_compression_state *cstate;
+
 	/* this is used to ensure we generate unique reference IDs */
 	uint32_t ptr_count;
 };
@@ -256,6 +262,7 @@ enum ndr_err_code {
 } while (0)
 
 enum ndr_compression_alg {
+	NDR_COMPRESSION_MSZIP_CAB = 1,
 	NDR_COMPRESSION_MSZIP	= 2,
 	NDR_COMPRESSION_XPRESS	= 3
 };
diff --git a/librpc/ndr/ndr_cab.c b/librpc/ndr/ndr_cab.c
index ae95bf4..837ed25 100644
--- a/librpc/ndr/ndr_cab.c
+++ b/librpc/ndr/ndr_cab.c
@@ -21,6 +21,9 @@
 
 #include "includes.h"
 #include "librpc/gen_ndr/ndr_cab.h"
+#include "librpc/ndr/ndr_compression.h"
+
+#define OFFSET_OF_FOLDER_COFFCABSTART(folder) (36 /* cfheader size */ + (size_t)(folder)*8)
 
 _PUBLIC_ void ndr_print_cf_time(struct ndr_print *ndr, const char *name, const struct cf_time *r)
 {
@@ -79,7 +82,7 @@ static uint32_t ndr_cab_compute_checksum(uint8_t *data, uint32_t length, uint32_
 	pb = data;
 
 	while (num_ulong-- > 0) {
-		ul = *pb++;
+		ul = (uint32_t)(*pb++);
 		ul |= (((uint32_t)(*pb++)) <<  8);
 		ul |= (((uint32_t)(*pb++)) << 16);
 		ul |= (((uint32_t)(*pb++)) << 24);
@@ -95,7 +98,7 @@ static uint32_t ndr_cab_compute_checksum(uint8_t *data, uint32_t length, uint32_
 	case 2:
 		ul |= (((uint32_t)(*pb++)) <<  8);
 	case 1:
-		ul |= *pb++;
+		ul |= (uint32_t)(*pb++);
 	default:
 		break;
 	}
@@ -109,97 +112,182 @@ uint32_t ndr_cab_generate_checksum(const struct CFDATA *r)
 {
 	uint32_t csumPartial;
 
-	csumPartial = ndr_cab_compute_checksum(&r->ab[0], r->cbData, 0);
+	csumPartial = ndr_cab_compute_checksum(&r->ab.data[0], r->cbData, 0);
 
 	return ndr_cab_compute_checksum((uint8_t *)discard_const(&r->cbData),
 					sizeof(r->cbData) + sizeof(r->cbUncomp),
 					csumPartial);
 }
 
-static bool ndr_size_cab_file(const struct cab_file *r, uint32_t *psize)
+/* Push all CFDATA of a folder.
+ *
+ * This works on a folder level because compression type is set per
+ * folder, and a compression state can be shared between CFDATA of the
+ * same folder.
+ *
+ * This is not a regular NDR func as we pass the compression type and
+ * the number of CFDATA as extra arguments
+ */
+static enum ndr_err_code ndr_push_folder_cfdata(struct ndr_push *ndr,
+						const struct CFDATA *r,
+						enum cf_compress_type cab_ctype,
+						size_t num_cfdata)
 {
-	uint32_t size = 0;
-	int i;
+	size_t i;
+	enum ndr_compression_alg ndr_ctype = 0;
 
-	/* header */
-	size += 36;
+	ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX|LIBNDR_FLAG_LITTLE_ENDIAN|LIBNDR_FLAG_NOALIGN);
 
-	/* folder */
-	for (i = 0; i < r->cfheader.cFolders; i++) {
-		if (size + 8 < size) {
-			/* Integer wrap. */
-			return false;
-		}
-		size += 8;
+	if (cab_ctype == CF_COMPRESS_MSZIP) {
+		ndr_ctype = NDR_COMPRESSION_MSZIP_CAB;
+		NDR_CHECK(ndr_push_compression_state_init(ndr, ndr_ctype, &ndr->cstate));
 	}
 
-	/* files */
-	for (i = 0; i < r->cfheader.cFiles; i++) {
-		uint32_t cfsize = ndr_size_CFFILE(&r->cffiles[i], 0);
-		if (size + cfsize < size) {
-			/* Integer wrap. */
-			return false;
-		}
-		size += cfsize;
-	}
+	for (i = 0; i < num_cfdata; i++, r++) {
+		uint32_t compressed_length = 0;
+		uint32_t csum, csumPartial;
+		size_t compressed_offset, csum_offset, data_offset;
 
-	/* data */
-	for (i = 0; i < ndr_count_cfdata(r); i++) {
-		if (size + 8 < size) {
-			/* Integer wrap. */
-			return false;
+		if (!r->ab.data) {
+			return ndr_push_error(ndr, NDR_ERR_LENGTH,
+					      "NULL uncompressed data blob");
 		}
-		size += 8;
-		if (size + r->cfdata[i].cbData < size) {
-			/* Integer wrap. */
-			return false;
+		if (r->ab.length != r->cbUncomp) {
+			return ndr_push_error(ndr, NDR_ERR_LENGTH,
+					      "Uncompressed data blob size != uncompressed data size field");
 		}
-		size += r->cfdata[i].cbData;
-	}
 
-	*psize = size;
-	return true;
-}
+		/*
+		 * checksum is a function of the size fields
+		 * and the potentially compressed data bytes,
+		 * which haven't been compressed yet so
+		 * remember offset, write zeroes, fill out
+		 * later
+		 */
+		csum_offset = ndr->offset;
+		NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+
+		/*
+		 * similarly, we don't know the compressed
+		 * size yet, remember offset, write zeros,
+		 * fill out later
+		 */
+		compressed_offset = ndr->offset;
+		NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 0));
+		NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->cbUncomp));
+
+		data_offset = ndr->offset;
+
+		switch (cab_ctype) {
+		case CF_COMPRESS_NONE:
+			/* just copy the data */
+			NDR_PUSH_NEED_BYTES(ndr, r->ab.length);
+			NDR_CHECK(ndr_push_bytes(ndr, r->ab.data, r->ab.length));
+			compressed_length = r->ab.length;
+			break;
+		case CF_COMPRESS_LZX:
+			/*
+			 * we have not yet worked out the details of LZX
+			 * compression
+			 */
+			return NDR_ERR_COMPRESSION;
+
+		case CF_COMPRESS_MSZIP: {
+			struct ndr_push *push_sub, *push_compress;
+
+			/* compress via subcontext */
+			NDR_CHECK(ndr_push_subcontext_start(ndr, &push_sub, 0, -1));
+			push_sub->cstate = ndr->cstate;
+			NDR_CHECK(ndr_push_compression_start(push_sub, &push_compress, ndr_ctype, -1));
+			ndr_set_flags(&push_compress->flags, LIBNDR_FLAG_REMAINING);
+			NDR_CHECK(ndr_push_DATA_BLOB(push_compress, NDR_SCALARS, r->ab));
+			NDR_CHECK(ndr_push_compression_end(push_sub, push_compress, ndr_ctype, -1));
+			NDR_CHECK(ndr_push_subcontext_end(ndr, push_sub, 0, -1));
+			compressed_length = push_sub->offset;
+
+			break;
+			}
+		default:
+			return NDR_ERR_BAD_SWITCH;
+		}
 
-enum cf_compress_type ndr_cab_get_compression(const struct cab_file *r)
-{
-	if (r->cfheader.cFolders == 0) {
-		return CF_COMPRESS_NONE;
+		/* we can now write the compressed size and the checksum */
+		SSVAL(ndr->data, compressed_offset, compressed_length);
+
+		/*
+		 * Create checksum over compressed data.
+		 *
+		 * The 8 bytes are the header size.
+		 *
+		 * We have already have written the checksum and set it to zero,
+		 * earlier. So we know that after the checksum end the value
+		 * for the compressed length comes the blob data.
+		 *
+		 * NDR already did all the checks for integer wraps.
+		 */
+		csumPartial = ndr_cab_compute_checksum(&ndr->data[data_offset],
+						       compressed_length, 0);
+
+		/*
+		 * Checksum over header (compressed and uncompressed length).
+		 *
+		 * The first 4 bytes are the checksum size.
+		 * The second 4 bytes are the size of the compressed and
+		 * uncompressed length fields.
+		 *
+		 * NDR already did all the checks for integer wraps.
+		 */
+		csum = ndr_cab_compute_checksum(&ndr->data[compressed_offset],
+						data_offset - compressed_offset,
+						csumPartial);
+
+		SIVAL(ndr->data, csum_offset, csum);
 	}
 
-	return r->cffolders[0].typeCompress;
+	ndr_push_compression_state_free(ndr->cstate);
+	ndr->cstate = NULL;
+
+	return NDR_ERR_SUCCESS;
 }
 
 _PUBLIC_ enum ndr_err_code ndr_push_cab_file(struct ndr_push *ndr, int ndr_flags, const struct cab_file *r)
 {
 	uint32_t cntr_cffolders_0;
 	uint32_t cntr_cffiles_0;
-	uint32_t cntr_cfdata_0;
-	uint32_t cab_size = 0;
+	size_t processed_cfdata = 0;
 	{
 		uint32_t _flags_save_STRUCT = ndr->flags;
 		ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX|LIBNDR_FLAG_LITTLE_ENDIAN|LIBNDR_FLAG_NOALIGN);
 		NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+
 		if (ndr_flags & NDR_SCALARS) {
-			uint32_t next_offset = 0;
+			uint32_t i;
 			NDR_CHECK(ndr_push_align(ndr, 4));
 			NDR_CHECK(ndr_push_CFHEADER(ndr, NDR_SCALARS, &r->cfheader));
 			for (cntr_cffolders_0 = 0; cntr_cffolders_0 < (r->cfheader.cFolders); cntr_cffolders_0++) {
 				NDR_CHECK(ndr_push_CFFOLDER(ndr, NDR_SCALARS, &r->cffolders[cntr_cffolders_0]));
 			}
 			for (cntr_cffiles_0 = 0; cntr_cffiles_0 < (r->cfheader.cFiles); cntr_cffiles_0++) {
-				uint32_t offset = ndr->offset + 4;
 				NDR_CHECK(ndr_push_CFFILE(ndr, NDR_SCALARS, &r->cffiles[cntr_cffiles_0]));
-				if (cntr_cffiles_0 > 0) {
-					next_offset += r->cffiles[cntr_cffiles_0 - 1].cbFile;
-				}
-				SIVAL(ndr->data, offset, next_offset);
 			}
 #if 0
 			NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_count_cfdata(r)));
 #endif
-			for (cntr_cfdata_0 = 0; cntr_cfdata_0 < (ndr_count_cfdata(r)); cntr_cfdata_0++) {
-				NDR_CHECK(ndr_push_CFDATA(ndr, NDR_SCALARS, &r->cfdata[cntr_cfdata_0]));
+
+			/* write in the folder header the offset of its first data block */
+			for (i = 0; i < r->cfheader.cFolders; i++) {
+				size_t off = OFFSET_OF_FOLDER_COFFCABSTART(i);
+				/* check that the offset we want to
+				 * write to is always inside our
+				 * current push buffer
+				 */
+				if (off >= ndr->offset) {
+					return ndr_push_error(ndr, NDR_ERR_OFFSET,
+							      "trying to write past current push buffer size");
+				}
+				SIVAL(ndr->data, off, ndr->offset);
+				NDR_CHECK(ndr_push_folder_cfdata(ndr, r->cfdata + processed_cfdata, r->cffolders[i].typeCompress, r->cffolders[i].cCFData));
+				processed_cfdata += r->cffolders[i].cCFData;
 			}
 			NDR_CHECK(ndr_push_trailer_align(ndr, 4));
 		}
@@ -208,10 +296,90 @@ _PUBLIC_ enum ndr_err_code ndr_push_cab_file(struct ndr_push *ndr, int ndr_flags
 		ndr->flags = _flags_save_STRUCT;
 	}
 
-	if (ndr_size_cab_file(r, &cab_size) == false) {
-		return NDR_ERR_VALIDATE;
+
+	/* write total file size in header */
+	SIVAL(ndr->data, 8, ndr->offset);
+
+	return NDR_ERR_SUCCESS;
+}
+
+
+/* Pull all CFDATA of a folder.
+ *
+ * This works on a folder level because compression type is set per
+ * folder, and a compression state can be shared between CFDATA of the
+ * same folder.
+ *
+ * This is not a regular NDR func as we pass the compression type and
+ * the number of CFDATA as extra arguments
+ */
+static enum ndr_err_code ndr_pull_folder_cfdata(struct ndr_pull *ndr,
+						struct CFDATA *r,
+						enum cf_compress_type cab_ctype,
+						size_t num_cfdata)
+{
+	size_t i;
+	enum ndr_compression_alg ndr_ctype = 0;
+
+	if (cab_ctype == CF_COMPRESS_MSZIP) {
+		ndr_ctype = NDR_COMPRESSION_MSZIP_CAB;
+		NDR_CHECK(ndr_pull_compression_state_init(ndr, NDR_COMPRESSION_MSZIP_CAB, &ndr->cstate));
+	}
+
+	for (i = 0; i < num_cfdata; i++, r++) {
+		NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->csum));
+		NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->cbData));
+		NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->cbUncomp));
+
+		switch (cab_ctype) {
+		case CF_COMPRESS_NONE:
+			/* just copy the data */
+			NDR_PULL_NEED_BYTES(ndr, r->cbUncomp);
+			r->ab = data_blob_talloc(ndr->current_mem_ctx,
+						 ndr->data+ndr->offset,
+						 r->cbUncomp);
+			if (r->ab.data == NULL) {
+				return ndr_pull_error(ndr, NDR_ERR_ALLOC,
+						      "failed to allocate buffer for uncompressed CFDATA block");
+			}
+			ndr->offset += r->cbUncomp;
+			break;
+
+		case CF_COMPRESS_LZX:
+			/* just copy the data (LZX decompression not implemented yet) */
+			NDR_PULL_NEED_BYTES(ndr, r->cbData);
+			r->ab = data_blob_talloc(ndr->current_mem_ctx,
+						 ndr->data+ndr->offset,
+						 r->cbData);
+			if (r->ab.data == NULL) {
+				return ndr_pull_error(ndr, NDR_ERR_ALLOC,
+						      "failed to allocate buffer for LZX-compressed CFDATA block");
+			}
+			ndr->offset += r->cbData;
+			break;
+
+		case CF_COMPRESS_MSZIP: {
+			struct ndr_pull *pull_sub, *pull_compress;
+			NDR_PULL_NEED_BYTES(ndr, r->cbData);
+			/* decompress via subcontext */
+			NDR_CHECK(ndr_pull_subcontext_start(ndr, &pull_sub, 0, r->cbData));
+			pull_sub->cstate = ndr->cstate;
+			NDR_CHECK(ndr_pull_compression_start(pull_sub, &pull_compress,
+							     ndr_ctype, r->cbUncomp, r->cbData));
+			ndr_set_flags(&pull_compress->flags, LIBNDR_FLAG_REMAINING);
+			NDR_CHECK(ndr_pull_DATA_BLOB(pull_compress, NDR_SCALARS, &r->ab));
+			NDR_CHECK(ndr_pull_compression_end(pull_sub, pull_compress, ndr_ctype, r->cbUncomp));
+			NDR_CHECK(ndr_pull_subcontext_end(ndr, pull_sub, 0, r->cbData));
+
+			break;
+		}
+		default:
+			return NDR_ERR_BAD_SWITCH;
+		}
 	}
-	SIVAL(ndr->data, 8, cab_size);
+
+	ndr_pull_compression_state_free(ndr->cstate);
+	ndr->cstate = NULL;
 
 	return NDR_ERR_SUCCESS;
 }
@@ -225,7 +393,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_cab_file(struct ndr_pull *ndr, int ndr_flags
 	uint32_t cntr_cffiles_0;
 	TALLOC_CTX *_mem_save_cffiles_0 = NULL;
 	uint32_t size_cfdata_0 = 0;
-	uint32_t cntr_cfdata_0;
+	size_t processed_cfdata = 0;
 	TALLOC_CTX *_mem_save_cfdata_0 = NULL;
 	{
 		uint32_t _flags_save_STRUCT = ndr->flags;
@@ -259,8 +427,12 @@ _PUBLIC_ enum ndr_err_code ndr_pull_cab_file(struct ndr_pull *ndr, int ndr_flags
 			NDR_PULL_ALLOC_N(ndr, r->cfdata, size_cfdata_0);
 			_mem_save_cfdata_0 = NDR_PULL_GET_MEM_CTX(ndr);
 			NDR_PULL_SET_MEM_CTX(ndr, r->cfdata, 0);
-			for (cntr_cfdata_0 = 0; cntr_cfdata_0 < (size_cfdata_0); cntr_cfdata_0++) {
-				NDR_CHECK(ndr_pull_CFDATA(ndr, NDR_SCALARS, &r->cfdata[cntr_cfdata_0]));
+			for (cntr_cffolders_0 = 0; cntr_cffolders_0 < (size_cffolders_0); cntr_cffolders_0++) {
+				NDR_CHECK(ndr_pull_folder_cfdata(ndr,
+								 r->cfdata + processed_cfdata,
+								 r->cffolders[cntr_cffolders_0].typeCompress,
+								 r->cffolders[cntr_cffolders_0].cCFData));
+				processed_cfdata += r->cffolders[cntr_cffolders_0].cCFData;
 			}
 			NDR_PULL_SET_MEM_CTX(ndr, _mem_save_cfdata_0, 0);
 			NDR_CHECK(ndr_pull_trailer_align(ndr, 4));
diff --git a/librpc/ndr/ndr_cab.h b/librpc/ndr/ndr_cab.h
index 7987153..59dbc99 100644
--- a/librpc/ndr/ndr_cab.h
+++ b/librpc/ndr/ndr_cab.h
@@ -21,4 +21,3 @@
 
 uint32_t ndr_count_cfdata(const struct cab_file *r);
 uint32_t ndr_cab_generate_checksum(const struct CFDATA *r);
-enum cf_compress_type ndr_cab_get_compression(const struct cab_file *r);
diff --git a/librpc/ndr/ndr_compression.c b/librpc/ndr/ndr_compression.c
index d291df5..bdce431 100644
--- a/librpc/ndr/ndr_compression.c
+++ b/librpc/ndr/ndr_compression.c
@@ -1,21 +1,21 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
 
    libndr compression support
 
    Copyright (C) Stefan Metzmacher 2005
    Copyright (C) Matthieu Suiche 2008
-   
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -26,6 +26,17 @@
 #include "../librpc/ndr/ndr_compression.h"
 #include <zlib.h>
 
+struct ndr_compression_state {
+	enum ndr_compression_alg type;
+	union {
+		struct {
+			struct z_stream_s *z;
+			uint8_t *dict;
+			size_t dict_size;
+		} mszip;
+	};
+};
+
 static voidpf ndr_zlib_alloc(voidpf opaque, uInt items, uInt size)
 {
 	return talloc_zero_size(opaque, items * size);
@@ -36,6 +47,261 @@ static void  ndr_zlib_free(voidpf opaque, voidpf address)
 	talloc_free(address);
 }
 
+static enum ndr_err_code ndr_pull_compression_mszip_cab_chunk(struct ndr_pull *ndrpull,
+							      struct ndr_push *ndrpush,
+							      struct ndr_compression_state *state,


-- 
Samba Shared Repository



More information about the samba-cvs mailing list