diff options
author | Andrew Bartlett <abartlet@samba.org> | 2023-03-28 18:26:13 +1300 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2023-03-31 01:48:30 +0000 |
commit | 327c84cf8701437324410068ab8e9a6efba24345 (patch) | |
tree | 787bfe9ae930a85a1dbaf6258c7015cc625c66ba /librpc | |
parent | c85cadf195208adb9bc204fdbc15f665cdb3d65d (diff) | |
download | samba-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.h | 25 | ||||
-rw-r--r-- | librpc/ndr/ndr_compression.c | 130 |
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); |