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:
parent
c85cadf195
commit
327c84cf87
@ -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,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
@ -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=")
|
||||
|
Loading…
x
Reference in New Issue
Block a user