uuid("bba9cb76-eb0c-462c-aa1b-5d8c34415701"),
version(1.0),
pointer_default(unique),
- helpstring("Active Directory Claims")
+ helpstring("Active Directory Claims"),
+ helper("../librpc/ndr/ndr_claims.h")
]
interface claims
{
#define wchar_t uint16
#define CLAIM_ID [string, charset(UTF16)] wchar_t *
+ const int CLAIM_MINIMUM_BYTES_TO_COMPRESS = 384;
+
typedef enum {
CLAIM_TYPE_INT64 = 1,
CLAIM_TYPE_UINT64 = 2,
[size_is(reserved_field_size)] uint8 *reserved_field;
} CLAIMS_SET;
- typedef [public] struct {
+ typedef [public, gensize] struct {
[subcontext(0xFFFFFC01)] CLAIMS_SET_CTR claims;
} CLAIMS_SET_NDR;
} CLAIMS_SET_METADATA_NDR;
typedef [public] struct {
- uint32 claims_set_size;
- [size_is(claims_set_size)] uint8 *claims_set;
- CLAIMS_COMPRESSION_FORMAT compression_format;
- uint32 uncompressed_claims_set_size;
+ [value(ndr_claims_compressed_size(claims_set,
+ r->compression_format,
+ ndr->flags))] uint32 claims_set_size;
+ [subcontext(4),
+ compression(ndr_claims_compression_alg(compression_format),
+ claims_set_size,
+ uncompressed_claims_set_size)
+ ] CLAIMS_SET_NDR *claims_set;
+ /*
+ * The second argument to
+ * ndr_claims_actual_wire_compression_alg() in the
+ * value() below should be
+ * uncompressed_claims_set_size but the value()
+ * handling isn't recursive (enough) so we have to
+ * specify that manually otherwise the
+ * compression_format in the above includes the struct
+ * member, not the value()
+ *
+ * The caller should set compression_format to
+ * CLAIMS_COMPRESSION_FORMAT_XPRESS_HUFF and this will
+ * be reset to CLAIMS_COMPRESSION_FORMAT_NONE if the
+ * buffer is not large enough to compress.
+ *
+ * Otherwise setting CLAIMS_COMPRESSION_FORMAT_NONE
+ * disabled compression entirely.
+ */
+ [value(ndr_claims_actual_wire_compression_alg(r->compression_format,
+ ndr_size_CLAIMS_SET_NDR(claims_set,
+ ndr->flags)))] CLAIMS_COMPRESSION_FORMAT compression_format;
+ [value(ndr_size_CLAIMS_SET_NDR(claims_set,
+ ndr->flags))] uint32 uncompressed_claims_set_size;
uint16 reserved_type;
uint32 reserved_field_size;
[size_is(reserved_field_size)] uint8 *reserved_field;
--- /dev/null
+#include "includes.h"
+#include "bin/default/librpc/gen_ndr/ndr_claims.h"
+#include "librpc/ndr/ndr_claims.h"
+
+#include "librpc/ndr/ndr_compression.h"
+#include "lib/compression/lzxpress_huffman.h"
+
+enum ndr_compression_alg ndr_claims_compression_alg(enum CLAIMS_COMPRESSION_FORMAT wire_alg)
+{
+ switch (wire_alg) {
+ case CLAIMS_COMPRESSION_FORMAT_NONE:
+ return NDR_COMPRESSION_NONE;
+
+ case CLAIMS_COMPRESSION_FORMAT_LZNT1:
+ return NDR_COMPRESSION_INVALID;
+
+ case CLAIMS_COMPRESSION_FORMAT_XPRESS:
+ return NDR_COMPRESSION_INVALID;
+
+ case CLAIMS_COMPRESSION_FORMAT_XPRESS_HUFF:
+ return NDR_COMPRESSION_XPRESS_HUFF_RAW;
+ }
+ return NDR_COMPRESSION_INVALID;
+}
+
+
+enum CLAIMS_COMPRESSION_FORMAT ndr_claims_actual_wire_compression_alg(enum CLAIMS_COMPRESSION_FORMAT specified_compression,
+ size_t uncompressed_claims_size) {
+ if (uncompressed_claims_size < CLAIM_MINIMUM_BYTES_TO_COMPRESS) {
+ return CLAIMS_COMPRESSION_FORMAT_NONE;
+ }
+
+ return specified_compression;
+}
+
+size_t ndr_claims_compressed_size(struct CLAIMS_SET_NDR *claims_set,
+ enum CLAIMS_COMPRESSION_FORMAT wire_alg,
+ int flags)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ DATA_BLOB tmp_blob;
+ uint8_t * tmp_compressed;
+ ssize_t compressed_size;
+ enum ndr_err_code ndr_err;
+ enum CLAIMS_COMPRESSION_FORMAT actual_wire_alg;
+
+ ndr_err = ndr_push_struct_blob(&tmp_blob,
+ frame,
+ claims_set,
+ (ndr_push_flags_fn_t)ndr_push_CLAIMS_SET_NDR);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DBG_ERR("Failed to push claims while determining compressed size");
+ TALLOC_FREE(frame);
+ return 0;
+ }
+
+ actual_wire_alg = ndr_claims_actual_wire_compression_alg(wire_alg,
+ tmp_blob.length);
+
+ switch (actual_wire_alg) {
+ case CLAIMS_COMPRESSION_FORMAT_NONE:
+ TALLOC_FREE(frame);
+ return tmp_blob.length;
+
+ case CLAIMS_COMPRESSION_FORMAT_XPRESS_HUFF:
+ compressed_size = lzxpress_huffman_compress_talloc(frame,
+ tmp_blob.data,
+ tmp_blob.length,
+ &tmp_compressed);
+
+ TALLOC_FREE(frame);
+
+ if (compressed_size < 0) {
+ DBG_ERR("Failed to compress claims (for determining compressed size)");
+ return 0;
+ }
+ return compressed_size;
+
+ default:
+ TALLOC_FREE(frame);
+ DBG_ERR("Invalid chosen compression algorithm while determining compressed claim size");
+ return 0;
+ }
+}
--- /dev/null
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for helping the compression in claims
+
+ Copyright (C) Andrew Bartlett 2023
+
+ 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/>.
+*/
+
+#ifndef _LIBRPC_NDR_NDR_CLAIMS_H
+#define _LIBRPC_NDR_NDR_CLAIMS_H
+
+enum ndr_compression_alg ndr_claims_compression_alg(enum CLAIMS_COMPRESSION_FORMAT wire_alg);
+enum CLAIMS_COMPRESSION_FORMAT ndr_claims_actual_wire_compression_alg(enum CLAIMS_COMPRESSION_FORMAT specified_compression,
+ size_t uncompressed_claims_size);
+
+size_t ndr_claims_compressed_size(struct CLAIMS_SET_NDR *claims_set,
+ enum CLAIMS_COMPRESSION_FORMAT wire_alg,
+ int flags);
+
+
+#endif /* _LIBRPC_NDR_NDR_CLAIMS_H */
)
bld.SAMBA_SUBSYSTEM('NDR_CLAIMS',
- source='gen_ndr/ndr_claims.c',
- deps='ndr')
+ source='gen_ndr/ndr_claims.c ndr/ndr_claims.c',
+ deps='ndr NDR_COMPRESSION LZXPRESS')
bld.SAMBA_LIBRARY('ndr-standard',
source='',
f'got empty CLAIMS_SET_METADATA_NDR '
f'inner structure {empty_msg}')
- claims_data = bytes(client_claims.claims_set)
- self.assertIsNotNone(claims_data,
+ self.assertIsNotNone(client_claims.claims_set,
f'got empty CLAIMS_SET_METADATA '
f'structure {empty_msg}')
- self.assertGreater(len(claims_data), 0,
- f'got empty encoded claims data '
- f'{empty_msg}')
- self.assertEqual(len(claims_data),
- client_claims.claims_set_size,
- f'encoded {claims_type} data size mismatch')
uncompressed_size = client_claims.uncompressed_claims_set_size
compression_format = client_claims.compression_format
- if uncompressed_size < 384:
+ if uncompressed_size < claims.CLAIM_MINIMUM_BYTES_TO_COMPRESS:
self.assertEqual(claims.CLAIMS_COMPRESSION_FORMAT_NONE,
compression_format,
f'{claims_type} unexpectedly '
f'{claims_type} unexpectedly not compressed '
f'({uncompressed_size} bytes uncompressed)')
- claims_data = huffman_decompress(claims_data,
- uncompressed_size)
-
- claims_set = ndr_unpack(claims.CLAIMS_SET_NDR,
- claims_data)
- claims_set = claims_set.claims.claims
+ claims_set = client_claims.claims_set.claims.claims
self.assertIsNotNone(claims_set,
f'got empty CLAIMS_SET_NDR inner '
f'structure {empty_msg}')