1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-28 01:58:17 +03:00

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>
This commit is contained in:
Andrew Bartlett 2023-03-28 18:26:13 +13:00
parent c85cadf195
commit 327c84cf87
3 changed files with 150 additions and 7 deletions

View File

@ -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,
};
/*

View File

@ -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);

View File

@ -525,7 +525,7 @@ dump OK
self.assertEqual(actual, expected)
def test_ndrdump_fuzzed_ndr_compression(self):
expected = 'ndr_pull_compression_start: ndr_pull_error\(Compression Error\): Bad compression algorithm 4 \(PULL\)'
expected = r'ndr_pull_compression_start: ndr_pull_error\(Compression Error\): Bad compression algorithm 204 \(PULL\)'
command = (
"ndrdump --debug-stdout drsuapi 3 out --base64-input "
"--input BwAAAAcAAAAGAAAAAwAgICAgICAJAAAAICAgIAkAAAAgIAAA//////8=")