summaryrefslogtreecommitdiff
path: root/librpc
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2023-03-28 18:26:13 +1300
committerAndrew Bartlett <abartlet@samba.org>2023-03-31 01:48:30 +0000
commit327c84cf8701437324410068ab8e9a6efba24345 (patch)
tree787bfe9ae930a85a1dbaf6258c7015cc625c66ba /librpc
parentc85cadf195208adb9bc204fdbc15f665cdb3d65d (diff)
downloadsamba-327c84cf8701437324410068ab8e9a6efba24345.tar.gz
librpc/ndr: Implement lzxpress_huffman() compression in libndr for Kerberos Claims
Rather than just pick the next value we re-arrange compression values in libndr to be memnonic to values in MS Windows ntifs.h This helps avoid confusing developers who compare these algorithms with local the MS Windows interface. Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Diffstat (limited to 'librpc')
-rw-r--r--librpc/ndr/libndr.h25
-rw-r--r--librpc/ndr/ndr_compression.c130
2 files changed, 149 insertions, 6 deletions
diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h
index 811623c463c..556d17f68c7 100644
--- a/librpc/ndr/libndr.h
+++ b/librpc/ndr/libndr.h
@@ -289,13 +289,26 @@ enum ndr_err_code {
} \
} while (0)
+/*
+ * Values here are chosen to be distinct from but recognisable as the
+ * values in ntifs.h and claims.idl
+ */
enum ndr_compression_alg {
- NDR_COMPRESSION_NONE = 0,
- NDR_COMPRESSION_MSZIP_CAB = 1,
- NDR_COMPRESSION_MSZIP = 2,
- NDR_COMPRESSION_XPRESS = 3,
- NDR_COMPRESSION_WIN2K3_LZ77_DIRECT2 = 4, /* Unimplemented */
- NDR_COMPRESSION_INVALID = 255,
+ NDR_COMPRESSION_NONE = 0, /* 0x00 in ntifs.h */
+ NDR_COMPRESSION_XPRESS_LZNT1 = 102, /* MS-XCA 0x02 in ntifs.h
+ * (Unimplemented)
+ */
+ NDR_COMPRESSION_XPRESS_RAW = 103, /* MS-XCA 0x03 in ntifs.h
+ * (implemented in
+ * lib/compression but
+ * not connected to libndr)
+ */
+ NDR_COMPRESSION_XPRESS_HUFF_RAW = 104, /* MS-XCA 0x04 in ntifs.h */
+ NDR_COMPRESSION_MSZIP_CAB = 201,
+ NDR_COMPRESSION_MSZIP = 202,
+ NDR_COMPRESSION_XPRESS = 203,
+ NDR_COMPRESSION_WIN2K3_LZ77_DIRECT2 = 204, /* Unimplemented */
+ NDR_COMPRESSION_INVALID = 255,
};
/*
diff --git a/librpc/ndr/ndr_compression.c b/librpc/ndr/ndr_compression.c
index a8efb6a27f4..5374cdfbb1f 100644
--- a/librpc/ndr/ndr_compression.c
+++ b/librpc/ndr/ndr_compression.c
@@ -22,6 +22,7 @@
#include "includes.h"
#include "../lib/compression/lzxpress.h"
+#include "../lib/compression/lzxpress_huffman.h"
#include "librpc/ndr/libndr.h"
#include "../librpc/ndr/ndr_compression.h"
#include <zlib.h>
@@ -34,6 +35,9 @@ struct ndr_compression_state {
uint8_t *dict;
size_t dict_size;
} mszip;
+ struct {
+ struct lzxhuff_compressor_mem *mem;
+ } lzxpress_huffman;
} alg;
};
@@ -702,6 +706,109 @@ static enum ndr_err_code ndr_push_compression_none(struct ndr_push *ndrpush,
return NDR_ERR_SUCCESS;
}
+static enum ndr_err_code ndr_pull_compression_xpress_huff_raw_chunk(struct ndr_pull *ndrpull,
+ struct ndr_push *ndrpush,
+ ssize_t decompressed_len,
+ ssize_t compressed_len)
+{
+ DATA_BLOB comp_chunk;
+ uint32_t comp_chunk_offset;
+ uint32_t comp_chunk_size;
+ DATA_BLOB plain_chunk;
+ uint32_t plain_chunk_offset;
+ uint32_t plain_chunk_size;
+ ssize_t ret;
+
+ plain_chunk_size = decompressed_len;
+ comp_chunk_size = compressed_len;
+
+ DEBUG(9,("XPRESS_HUFF plain_chunk_size: %08X (%u) comp_chunk_size: %08X (%u)\n",
+ plain_chunk_size, plain_chunk_size, comp_chunk_size, comp_chunk_size));
+
+ comp_chunk_offset = ndrpull->offset;
+ NDR_CHECK(ndr_pull_advance(ndrpull, comp_chunk_size));
+ comp_chunk.length = comp_chunk_size;
+ comp_chunk.data = ndrpull->data + comp_chunk_offset;
+
+ plain_chunk_offset = ndrpush->offset;
+ NDR_CHECK(ndr_push_zero(ndrpush, plain_chunk_size));
+ plain_chunk.length = plain_chunk_size;
+ plain_chunk.data = ndrpush->data + plain_chunk_offset;
+
+ /* Decompressing the buffer using LZ Xpress w/ Huffman algorithm */
+ ret = lzxpress_huffman_decompress(comp_chunk.data,
+ comp_chunk.length,
+ plain_chunk.data,
+ plain_chunk.length);
+ if (ret < 0) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "XPRESS HUFF lzxpress_huffman_decompress() returned %d\n",
+ (int)ret);
+ }
+
+ if (plain_chunk.length != ret) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "XPRESS HUFF lzxpress_huffman_decompress() output is not as expected (%zd != %zu) (PULL)",
+ ret, plain_chunk.length);
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_push_compression_xpress_huff_raw_chunk(struct ndr_push *ndrpush,
+ struct ndr_pull *ndrpull,
+ struct ndr_compression_state *state)
+{
+ DATA_BLOB comp_chunk;
+ DATA_BLOB plain_chunk;
+ uint32_t plain_chunk_size;
+ uint32_t plain_chunk_offset;
+ ssize_t ret;
+
+ struct lzxhuff_compressor_mem *mem = state->alg.lzxpress_huffman.mem;
+
+ if (ndrpull->data_size <= ndrpull->offset) {
+ return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION,
+ "strange NDR pull size and offset (integer overflow?)");
+
+ }
+
+ plain_chunk_size = ndrpull->data_size - ndrpull->offset;
+ plain_chunk_offset = ndrpull->offset;
+ NDR_CHECK(ndr_pull_advance(ndrpull, plain_chunk_size));
+
+ plain_chunk.data = ndrpull->data + plain_chunk_offset;
+ plain_chunk.length = plain_chunk_size;
+
+ comp_chunk.length = lzxpress_huffman_max_compressed_size(plain_chunk_size);
+ NDR_CHECK(ndr_push_expand(ndrpush, comp_chunk.length));
+
+ comp_chunk.data = ndrpush->data + ndrpush->offset;
+
+
+ /* Compressing the buffer using LZ Xpress w/ Huffman algorithm */
+ ret = lzxpress_huffman_compress(mem,
+ plain_chunk.data,
+ plain_chunk.length,
+ comp_chunk.data,
+ comp_chunk.length);
+ if (ret < 0) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "XPRESS HUFF lzxpress_huffman_compress() returned %d\n",
+ (int)ret);
+ }
+
+ if (ret > comp_chunk.length) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "XPRESS HUFF lzxpress_huffman_compress() output is not as expected (%zd > %zu) (PULL)",
+ ret, comp_chunk.length);
+ }
+
+ ndrpush->offset += ret;
+ return NDR_ERR_SUCCESS;
+}
+
+
/*
handle compressed subcontext buffers, which in midl land are user-marshalled, but
we use magic in pidl to make them easier to cope with
@@ -746,6 +853,12 @@ enum ndr_err_code ndr_pull_compression_start(struct ndr_pull *subndr,
}
break;
+ case NDR_COMPRESSION_XPRESS_HUFF_RAW:
+ NDR_CHECK(ndr_pull_compression_xpress_huff_raw_chunk(subndr, ndrpush,
+ decompressed_len,
+ compressed_len));
+ break;
+
default:
return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad compression algorithm %d (PULL)",
compression_alg);
@@ -795,6 +908,7 @@ enum ndr_err_code ndr_push_compression_start(struct ndr_push *subndr,
case NDR_COMPRESSION_MSZIP_CAB:
case NDR_COMPRESSION_MSZIP:
case NDR_COMPRESSION_XPRESS:
+ case NDR_COMPRESSION_XPRESS_HUFF_RAW:
break;
default:
return ndr_push_error(subndr, NDR_ERR_COMPRESSION,
@@ -850,6 +964,10 @@ enum ndr_err_code ndr_push_compression_end(struct ndr_push *subndr,
}
break;
+ case NDR_COMPRESSION_XPRESS_HUFF_RAW:
+ NDR_CHECK(ndr_push_compression_xpress_huff_raw_chunk(subndr, ndrpull, subndr->cstate));
+ break;
+
default:
return ndr_push_error(subndr, NDR_ERR_COMPRESSION, "Bad compression algorithm %d (PUSH)",
compression_alg);
@@ -904,6 +1022,7 @@ enum ndr_err_code ndr_pull_compression_state_init(struct ndr_pull *ndr,
case NDR_COMPRESSION_NONE:
case NDR_COMPRESSION_MSZIP:
case NDR_COMPRESSION_XPRESS:
+ case NDR_COMPRESSION_XPRESS_HUFF_RAW:
break;
case NDR_COMPRESSION_MSZIP_CAB:
NDR_CHECK(generic_mszip_init(ndr, s));
@@ -936,6 +1055,7 @@ void ndr_pull_compression_state_free(struct ndr_compression_state *state)
case NDR_COMPRESSION_NONE:
case NDR_COMPRESSION_MSZIP:
case NDR_COMPRESSION_XPRESS:
+ case NDR_COMPRESSION_XPRESS_HUFF_RAW:
break;
case NDR_COMPRESSION_MSZIP_CAB:
generic_mszip_free(state);
@@ -960,6 +1080,15 @@ enum ndr_err_code ndr_push_compression_state_init(struct ndr_push *ndr,
switch (compression_alg) {
case NDR_COMPRESSION_NONE:
case NDR_COMPRESSION_XPRESS:
+ break;
+
+ case NDR_COMPRESSION_XPRESS_HUFF_RAW:
+ s->alg.lzxpress_huffman.mem = talloc(s, struct lzxhuff_compressor_mem);
+ if (s->alg.lzxpress_huffman.mem == NULL) {
+ return NDR_ERR_ALLOC;
+ }
+ break;
+
case NDR_COMPRESSION_MSZIP:
break;
case NDR_COMPRESSION_MSZIP_CAB:
@@ -998,6 +1127,7 @@ void ndr_push_compression_state_free(struct ndr_compression_state *state)
case NDR_COMPRESSION_NONE:
case NDR_COMPRESSION_MSZIP:
case NDR_COMPRESSION_XPRESS:
+ case NDR_COMPRESSION_XPRESS_HUFF_RAW:
break;
case NDR_COMPRESSION_MSZIP_CAB:
generic_mszip_free(state);