summaryrefslogtreecommitdiffstats
path: root/librpc/ndr
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--librpc/ndr.pc.in11
-rw-r--r--librpc/ndr/libndr.h857
-rw-r--r--librpc/ndr/ndr.c2005
-rw-r--r--librpc/ndr/ndr_ODJ.c65
-rw-r--r--librpc/ndr/ndr_ODJ.h22
-rw-r--r--librpc/ndr/ndr_auth.c44
-rw-r--r--librpc/ndr/ndr_auth.h32
-rw-r--r--librpc/ndr/ndr_backupkey.c222
-rw-r--r--librpc/ndr/ndr_backupkey.h23
-rw-r--r--librpc/ndr/ndr_basic.c1538
-rw-r--r--librpc/ndr/ndr_bkupblobs.c82
-rw-r--r--librpc/ndr/ndr_cab.c437
-rw-r--r--librpc/ndr/ndr_cab.h22
-rw-r--r--librpc/ndr/ndr_compression.c941
-rw-r--r--librpc/ndr/ndr_compression.h68
-rw-r--r--librpc/ndr/ndr_dcerpc.c316
-rw-r--r--librpc/ndr/ndr_dcerpc.h29
-rw-r--r--librpc/ndr/ndr_dns.c327
-rw-r--r--librpc/ndr/ndr_dns.h40
-rw-r--r--librpc/ndr/ndr_dns_utils.c134
-rw-r--r--librpc/ndr/ndr_dns_utils.h6
-rw-r--r--librpc/ndr/ndr_dnsp.c263
-rw-r--r--librpc/ndr/ndr_dnsp.h33
-rw-r--r--librpc/ndr/ndr_dnsserver.c100
-rw-r--r--librpc/ndr/ndr_dnsserver.h25
-rw-r--r--librpc/ndr/ndr_drsblobs.c220
-rw-r--r--librpc/ndr/ndr_drsblobs.h23
-rw-r--r--librpc/ndr/ndr_drsuapi.c569
-rw-r--r--librpc/ndr/ndr_drsuapi.h34
-rw-r--r--librpc/ndr/ndr_frsrpc.c92
-rw-r--r--librpc/ndr/ndr_frsrpc.h34
-rw-r--r--librpc/ndr/ndr_ioctl.c40
-rw-r--r--librpc/ndr/ndr_krb5pac.c130
-rw-r--r--librpc/ndr/ndr_krb5pac.h26
-rw-r--r--librpc/ndr/ndr_misc.c77
-rw-r--r--librpc/ndr/ndr_nbt.c406
-rw-r--r--librpc/ndr/ndr_nbt.h42
-rw-r--r--librpc/ndr/ndr_negoex.c521
-rw-r--r--librpc/ndr/ndr_negoex.h37
-rw-r--r--librpc/ndr/ndr_netlogon.c65
-rw-r--r--librpc/ndr/ndr_netlogon.h28
-rw-r--r--librpc/ndr/ndr_ntlmssp.c195
-rw-r--r--librpc/ndr/ndr_ntlmssp.h35
-rw-r--r--librpc/ndr/ndr_ntprinting.c87
-rw-r--r--librpc/ndr/ndr_ntprinting.h27
-rw-r--r--librpc/ndr/ndr_orpc.c163
-rw-r--r--librpc/ndr/ndr_preg.c69
-rw-r--r--librpc/ndr/ndr_preg.h23
-rw-r--r--librpc/ndr/ndr_private.h32
-rw-r--r--librpc/ndr/ndr_rap.c28
-rw-r--r--librpc/ndr/ndr_rap.h22
-rw-r--r--librpc/ndr/ndr_schannel.c107
-rw-r--r--librpc/ndr/ndr_schannel.h25
-rw-r--r--librpc/ndr/ndr_sec_helper.c338
-rw-r--r--librpc/ndr/ndr_spoolss_buf.c1615
-rw-r--r--librpc/ndr/ndr_spoolss_buf.h85
-rw-r--r--librpc/ndr/ndr_string.c815
-rw-r--r--librpc/ndr/ndr_svcctl.c52
-rw-r--r--librpc/ndr/ndr_svcctl.h24
-rw-r--r--librpc/ndr/ndr_table.c182
-rw-r--r--librpc/ndr/ndr_table.h37
-rw-r--r--librpc/ndr/ndr_witness.c110
-rw-r--r--librpc/ndr/ndr_witness.h23
-rw-r--r--librpc/ndr/ndr_wmi.c60
-rw-r--r--librpc/ndr/ndr_wmi.h24
-rw-r--r--librpc/ndr/ndr_xattr.c148
-rw-r--r--librpc/ndr/ndr_xattr.h37
-rw-r--r--librpc/ndr/util.c36
-rw-r--r--librpc/ndr/uuid.c258
-rw-r--r--librpc/ndr_krb5pac.pc.in11
-rw-r--r--librpc/ndr_nbt.pc.in11
-rw-r--r--librpc/ndr_standard.pc.in11
72 files changed, 14676 insertions, 0 deletions
diff --git a/librpc/ndr.pc.in b/librpc/ndr.pc.in
new file mode 100644
index 0000000..6828ac0
--- /dev/null
+++ b/librpc/ndr.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ndr
+Description: Network Data Representation Core Library
+Requires: samba-util talloc
+Version: @PACKAGE_VERSION@
+Libs: @LIB_RPATH@ -L${libdir} -lndr
+Cflags: -I${includedir} -DHAVE_IMMEDIATE_STRUCTURES=1 -D_GNU_SOURCE=1
diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h
new file mode 100644
index 0000000..98f8ff8
--- /dev/null
+++ b/librpc/ndr/libndr.h
@@ -0,0 +1,857 @@
+/*
+ Unix SMB/CIFS implementation.
+ rpc interface definitions
+
+ Copyright (C) Andrew Tridgell 2003
+
+ 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/>.
+*/
+
+/* This is a public header file that is installed as part of Samba.
+ * If you remove any functions or change their signature, update
+ * the so version number. */
+
+#ifndef __LIBNDR_H__
+#define __LIBNDR_H__
+
+#include <talloc.h>
+#include "../lib/util/discard.h" /* for discard_const */
+#include "../lib/util/data_blob.h"
+#include "../lib/util/time.h"
+#include "../lib/util/charset/charset.h"
+
+/*
+ this provides definitions for the libcli/rpc/ MSRPC library
+*/
+
+
+/*
+ We store the token mapping in an array that is resized as necessary.
+*/
+struct ndr_token;
+
+struct ndr_token_list {
+ struct ndr_token *tokens;
+ uint32_t count;
+};
+
+struct ndr_compression_state;
+
+/* this is the base structure passed to routines that
+ parse MSRPC formatted data
+
+ note that in Samba4 we use separate routines and structures for
+ MSRPC marshalling and unmarshalling. Also note that these routines
+ are being kept deliberately very simple, and are not tied to a
+ particular transport
+*/
+struct ndr_pull {
+ uint32_t flags; /* LIBNDR_FLAG_* */
+ uint8_t *data;
+ uint32_t data_size;
+ uint32_t offset;
+
+ uint32_t relative_highest_offset;
+ uint32_t relative_base_offset;
+ uint32_t relative_rap_convert;
+ struct ndr_token_list relative_base_list;
+
+ struct ndr_token_list relative_list;
+ struct ndr_token_list array_size_list;
+ struct ndr_token_list array_length_list;
+ struct ndr_token_list switch_list;
+
+ struct ndr_compression_state *cstate;
+
+ TALLOC_CTX *current_mem_ctx;
+
+ /* this is used to ensure we generate unique reference IDs
+ between request and reply */
+ uint32_t ptr_count;
+ uint32_t recursion_depth;
+ /*
+ * The global maximum depth for recursion. When set it overrides the
+ * value supplied by the max_recursion idl attribute. This is needed
+ * for fuzzing as ASAN uses a low threshold for stack depth to check
+ * for stack overflow.
+ */
+ uint32_t global_max_recursion;
+};
+
+/* structure passed to functions that generate NDR formatted data */
+struct ndr_push {
+ uint32_t flags; /* LIBNDR_FLAG_* */
+ uint8_t *data;
+ uint32_t alloc_size;
+ uint32_t offset;
+ bool fixed_buf_size;
+
+ uint32_t relative_base_offset;
+ uint32_t relative_end_offset;
+ struct ndr_token_list relative_base_list;
+
+ struct ndr_token_list switch_list;
+ struct ndr_token_list relative_list;
+ struct ndr_token_list relative_begin_list;
+ struct ndr_token_list nbt_string_list;
+ struct ndr_token_list dns_string_list;
+ struct ndr_token_list full_ptr_list;
+
+ struct ndr_compression_state *cstate;
+
+ /* this is used to ensure we generate unique reference IDs */
+ uint32_t ptr_count;
+};
+
+/* structure passed to functions that print IDL structures */
+struct ndr_print {
+ uint32_t flags; /* LIBNDR_FLAG_* */
+ uint32_t depth;
+ struct ndr_token_list switch_list;
+ void (*print)(struct ndr_print *, const char *, ...) PRINTF_ATTRIBUTE(2,3);
+ void *private_data;
+ bool no_newline;
+ bool print_secrets;
+};
+
+#define LIBNDR_FLAG_BIGENDIAN (1U<<0)
+#define LIBNDR_FLAG_NOALIGN (1U<<1)
+
+#define LIBNDR_FLAG_STR_ASCII (1U<<2)
+#define LIBNDR_FLAG_STR_LEN4 (1U<<3)
+#define LIBNDR_FLAG_STR_SIZE4 (1U<<4)
+#define LIBNDR_FLAG_STR_NOTERM (1U<<5)
+#define LIBNDR_FLAG_STR_NULLTERM (1U<<6)
+#define LIBNDR_FLAG_STR_SIZE2 (1U<<7)
+#define LIBNDR_FLAG_STR_BYTESIZE (1U<<8)
+#define LIBNDR_FLAG_STR_CONFORMANT (1U<<10)
+#define LIBNDR_FLAG_STR_CHARLEN (1U<<11)
+#define LIBNDR_FLAG_STR_UTF8 (1U<<12)
+#define LIBNDR_FLAG_STR_RAW8 (1U<<13)
+#define LIBNDR_STRING_FLAGS (0U | \
+ LIBNDR_FLAG_STR_ASCII | \
+ LIBNDR_FLAG_STR_LEN4 | \
+ LIBNDR_FLAG_STR_SIZE4 | \
+ LIBNDR_FLAG_STR_NOTERM | \
+ LIBNDR_FLAG_STR_NULLTERM | \
+ LIBNDR_FLAG_STR_SIZE2 | \
+ LIBNDR_FLAG_STR_BYTESIZE | \
+ LIBNDR_FLAG_STR_CONFORMANT | \
+ LIBNDR_FLAG_STR_CHARLEN | \
+ LIBNDR_FLAG_STR_UTF8 | \
+ LIBNDR_FLAG_STR_RAW8 | \
+ 0)
+
+/*
+ * Mark an element as SECRET, it won't be printed by
+ * via ndr_print* unless NDR_PRINT_SECRETS is specified.
+ */
+#define LIBNDR_FLAG_IS_SECRET (1U<<14)
+
+/* Disable string token compression */
+#define LIBNDR_FLAG_NO_COMPRESSION (1U<<15)
+
+/*
+ * don't debug NDR_ERR_BUFSIZE failures,
+ * as the available buffer might be incomplete.
+ *
+ * return NDR_ERR_INCOMPLETE_BUFFER instead.
+ */
+#define LIBNDR_FLAG_INCOMPLETE_BUFFER (1U<<16)
+
+/*
+ * This lets ndr_pull_subcontext_end() return
+ * NDR_ERR_UNREAD_BYTES.
+ */
+#define LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES (1U<<17)
+
+/* set if relative pointers should *not* be marshalled in reverse order */
+#define LIBNDR_FLAG_NO_RELATIVE_REVERSE (1U<<18)
+
+/* set if relative pointers are marshalled in reverse order */
+#define LIBNDR_FLAG_RELATIVE_REVERSE (1U<<19)
+
+#define LIBNDR_FLAG_REF_ALLOC (1U<<20)
+#define LIBNDR_FLAG_REMAINING (1U<<21)
+#define LIBNDR_FLAG_ALIGN2 (1U<<22)
+#define LIBNDR_FLAG_ALIGN4 (1U<<23)
+#define LIBNDR_FLAG_ALIGN8 (1U<<24)
+
+#define LIBNDR_ALIGN_FLAGS ( 0 | \
+ LIBNDR_FLAG_NOALIGN | \
+ LIBNDR_FLAG_REMAINING | \
+ LIBNDR_FLAG_ALIGN2 | \
+ LIBNDR_FLAG_ALIGN4 | \
+ LIBNDR_FLAG_ALIGN8 | \
+ 0)
+
+#define LIBNDR_PRINT_ARRAY_HEX (1U<<25)
+#define LIBNDR_PRINT_SET_VALUES (1U<<26)
+
+/* used to force a section of IDL to be little-endian */
+#define LIBNDR_FLAG_LITTLE_ENDIAN (1U<<27)
+
+/* used to check if alignment padding is zero */
+#define LIBNDR_FLAG_PAD_CHECK (1U<<28)
+
+#define LIBNDR_FLAG_NDR64 (1U<<29)
+
+/* set if an object uuid will be present */
+#define LIBNDR_FLAG_OBJECT_PRESENT (1U<<30)
+
+/* set to avoid recursion in ndr_size_*() calculation */
+#define LIBNDR_FLAG_NO_NDR_SIZE (1U<<31)
+
+/* useful macro for debugging */
+#define NDR_PRINT_DEBUG(type, p) (void)ndr_print_debug(1, (ndr_print_fn_t)ndr_print_ ##type, #p, p, __location__, __func__)
+#define NDR_PRINT_DEBUGC(dbgc_class, type, p) ndr_print_debugc(dbgc_class, (ndr_print_fn_t)ndr_print_ ##type, #p, p)
+#define NDR_PRINT_UNION_DEBUG(type, level, p) ndr_print_union_debug((ndr_print_fn_t)ndr_print_ ##type, #p, level, p)
+#define NDR_PRINT_FUNCTION_DEBUG(type, flags, p) ndr_print_function_debug((ndr_print_function_t)ndr_print_ ##type, #type, flags, p)
+#define NDR_PRINT_BOTH_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_BOTH, p)
+#define NDR_PRINT_OUT_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_OUT, p)
+#define NDR_PRINT_IN_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_IN | NDR_SET_VALUES, p)
+
+/**
+ * @brief Prints NDR structure.
+ *
+ * Like NDR_PRINT_DEBUG, but takes a debug level parameter.
+ *
+ * @param[in] l The debug level.
+ * @param[in] type ndr_print_#type is the function that will be called.
+ * @param[in] p Pointer to the struct.
+ *
+ * @code
+ * NDR_PRINT_DEBUG_LEVEL(DBGLVL_DEBUG, wbint_userinfo, state->info);
+ * @endcode
+ *
+ * @return void.
+ */
+#define NDR_PRINT_DEBUG_LEVEL(l, type, p) \
+ (void) ( CHECK_DEBUGLVL(l) \
+ && ndr_print_debug(l, (ndr_print_fn_t)ndr_print_ ##type, #p, p, __location__, __func__) )
+
+/* useful macro for debugging in strings */
+#define NDR_PRINT_STRUCT_STRING(ctx, type, p) ndr_print_struct_string(ctx, (ndr_print_fn_t)ndr_print_ ##type, #p, p)
+#define NDR_PRINT_UNION_STRING(ctx, type, level, p) ndr_print_union_string(ctx, (ndr_print_fn_t)ndr_print_ ##type, #p, level, p)
+#define NDR_PRINT_FUNCTION_STRING(ctx, type, flags, p) ndr_print_function_string(ctx, (ndr_print_function_t)ndr_print_ ##type, #type, flags, p)
+#define NDR_PRINT_BOTH_STRING(ctx, type, p) NDR_PRINT_FUNCTION_STRING(ctx, type, NDR_BOTH, p)
+#define NDR_PRINT_OUT_STRING(ctx, type, p) NDR_PRINT_FUNCTION_STRING(ctx, type, NDR_OUT, p)
+#define NDR_PRINT_IN_STRING(ctx, type, p) NDR_PRINT_FUNCTION_STRING(ctx, type, NDR_IN | NDR_SET_VALUES, p)
+
+#define NDR_HIDE_SECRET(ndr) \
+ (unlikely(((ndr)->flags & LIBNDR_FLAG_IS_SECRET) && !(ndr)->print_secrets))
+
+#define NDR_BE(ndr) (unlikely(((ndr)->flags & (LIBNDR_FLAG_BIGENDIAN|LIBNDR_FLAG_LITTLE_ENDIAN)) == LIBNDR_FLAG_BIGENDIAN))
+
+enum ndr_err_code {
+ NDR_ERR_SUCCESS = 0,
+ NDR_ERR_ARRAY_SIZE,
+ NDR_ERR_BAD_SWITCH,
+ NDR_ERR_OFFSET,
+ NDR_ERR_RELATIVE,
+ NDR_ERR_CHARCNV,
+ NDR_ERR_LENGTH,
+ NDR_ERR_SUBCONTEXT,
+ NDR_ERR_COMPRESSION,
+ NDR_ERR_STRING,
+ NDR_ERR_VALIDATE,
+ NDR_ERR_BUFSIZE,
+ NDR_ERR_ALLOC,
+ NDR_ERR_RANGE,
+ NDR_ERR_TOKEN,
+ NDR_ERR_IPV4ADDRESS,
+ NDR_ERR_IPV6ADDRESS,
+ NDR_ERR_INVALID_POINTER,
+ NDR_ERR_UNREAD_BYTES,
+ NDR_ERR_NDR64,
+ NDR_ERR_FLAGS,
+ NDR_ERR_INCOMPLETE_BUFFER,
+ NDR_ERR_MAX_RECURSION_EXCEEDED,
+ NDR_ERR_UNDERFLOW
+};
+
+#define NDR_ERR_CODE_IS_SUCCESS(x) (x == NDR_ERR_SUCCESS)
+
+#define NDR_ERR_HAVE_NO_MEMORY(x) do { \
+ if (NULL == (x)) { \
+ return NDR_ERR_ALLOC; \
+ } \
+} while (0)
+
+enum ndr_compression_alg {
+ NDR_COMPRESSION_MSZIP_CAB = 1,
+ NDR_COMPRESSION_MSZIP = 2,
+ NDR_COMPRESSION_XPRESS = 3
+};
+
+/*
+ flags passed to control parse flow
+ These are deliberately in a different range to the NDR_IN/NDR_OUT
+ flags to catch mixups
+*/
+#define NDR_SCALARS 0x100
+#define NDR_BUFFERS 0x200
+
+/*
+ flags passed to ndr_print_*() and ndr pull/push for functions
+ These are deliberately in a different range to the NDR_SCALARS/NDR_BUFFERS
+ flags to catch mixups
+*/
+#define NDR_IN 0x10
+#define NDR_OUT 0x20
+#define NDR_BOTH 0x30
+#define NDR_SET_VALUES 0x40
+
+
+#define NDR_PULL_CHECK_FLAGS(ndr, ndr_flags) do { \
+ if ((ndr_flags) & ~(NDR_SCALARS|NDR_BUFFERS)) { \
+ return ndr_pull_error(ndr, NDR_ERR_FLAGS, "Invalid pull struct ndr_flags 0x%x", ndr_flags); \
+ } \
+} while (0)
+
+#define NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags) do { \
+ if ((ndr_flags) & ~(NDR_SCALARS|NDR_BUFFERS)) \
+ return ndr_push_error(ndr, NDR_ERR_FLAGS, "Invalid push struct ndr_flags 0x%x", ndr_flags); \
+} while (0)
+
+#define NDR_PULL_CHECK_FN_FLAGS(ndr, flags) do { \
+ if ((flags) & ~(NDR_BOTH|NDR_SET_VALUES)) { \
+ return ndr_pull_error(ndr, NDR_ERR_FLAGS, "Invalid fn pull flags 0x%x", flags); \
+ } \
+} while (0)
+
+#define NDR_PUSH_CHECK_FN_FLAGS(ndr, flags) do { \
+ if ((flags) & ~(NDR_BOTH|NDR_SET_VALUES)) \
+ return ndr_push_error(ndr, NDR_ERR_FLAGS, "Invalid fn push flags 0x%x", flags); \
+} while (0)
+
+#define NDR_PULL_NEED_BYTES(ndr, n) do { \
+ if (unlikely(\
+ (n) > ndr->data_size || \
+ ndr->offset + (n) > ndr->data_size || \
+ ndr->offset + (n) < ndr->offset)) { \
+ if (ndr->flags & LIBNDR_FLAG_INCOMPLETE_BUFFER) { \
+ uint32_t _available = ndr->data_size - ndr->offset; \
+ uint32_t _missing = n - _available; \
+ ndr->relative_highest_offset = _missing; \
+ } \
+ return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "Pull bytes %u (%s)", (unsigned)n, __location__); \
+ } \
+} while(0)
+
+#define NDR_ALIGN(ndr, n) ndr_align_size(ndr->offset, n)
+
+#define NDR_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
+
+#define NDR_PULL_ALIGN(ndr, n) do { \
+ if (unlikely(!(ndr->flags & LIBNDR_FLAG_NOALIGN))) { \
+ if (unlikely(ndr->flags & LIBNDR_FLAG_PAD_CHECK)) { \
+ ndr_check_padding(ndr, n); \
+ } \
+ if(unlikely( \
+ ((ndr->offset + (n-1)) & (~(n-1))) < ndr->offset)) {\
+ return ndr_pull_error( \
+ ndr, \
+ NDR_ERR_BUFSIZE, \
+ "Pull align (overflow) %u", (unsigned)n); \
+ } \
+ ndr->offset = (ndr->offset + (n-1)) & ~(n-1); \
+ } \
+ if (unlikely(ndr->offset > ndr->data_size)) { \
+ if (ndr->flags & LIBNDR_FLAG_INCOMPLETE_BUFFER) { \
+ uint32_t _missing = ndr->offset - ndr->data_size; \
+ ndr->relative_highest_offset = _missing; \
+ } \
+ return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "Pull align %u", (unsigned)n); \
+ } \
+} while(0)
+
+#define NDR_PUSH_NEED_BYTES(ndr, n) NDR_CHECK(ndr_push_expand(ndr, n))
+
+#define NDR_PUSH_ALIGN(ndr, n) do { \
+ if (likely(!(ndr->flags & LIBNDR_FLAG_NOALIGN))) { \
+ uint32_t _pad = ((ndr->offset + (n-1)) & ~(n-1)) - ndr->offset; \
+ while (_pad--) NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, 0)); \
+ } \
+} while(0)
+
+#define NDR_RECURSION_CHECK(ndr, d) do { \
+ uint32_t _ndr_min_ = (d); \
+ if (ndr->global_max_recursion && ndr->global_max_recursion < (d)) { \
+ _ndr_min_ = ndr->global_max_recursion; \
+ } \
+ ndr->recursion_depth++; \
+ if (unlikely(ndr->recursion_depth > _ndr_min_)) { \
+ return ndr_pull_error( \
+ ndr, \
+ NDR_ERR_MAX_RECURSION_EXCEEDED, \
+ "Depth of recursion exceeds (%u)", \
+ (unsigned) d); \
+ } \
+} while (0)
+
+#define NDR_RECURSION_UNWIND(ndr) do { \
+ if (unlikely(ndr->recursion_depth == 0)) { \
+ return ndr_pull_error( \
+ ndr, \
+ NDR_ERR_UNDERFLOW, \
+ "ndr_pull.recursion_depth is 0"); \
+ } \
+ ndr->recursion_depth--; \
+} while (0)
+
+/* these are used to make the error checking on each element in libndr
+ less tedious, hopefully making the code more readable */
+#define NDR_CHECK(call) do { \
+ enum ndr_err_code _status; \
+ _status = call; \
+ if (unlikely(!NDR_ERR_CODE_IS_SUCCESS(_status))) { \
+ return _status; \
+ } \
+} while (0)
+
+/* if the call fails then free the ndr pointer */
+#define NDR_CHECK_FREE(call) do { \
+ enum ndr_err_code _status; \
+ _status = call; \
+ if (unlikely(!NDR_ERR_CODE_IS_SUCCESS(_status))) { \
+ talloc_free(ndr); \
+ return _status; \
+ } \
+} while (0)
+
+#define NDR_PULL_GET_MEM_CTX(ndr) (ndr->current_mem_ctx)
+
+#define NDR_PULL_SET_MEM_CTX(ndr, mem_ctx, flgs) do {\
+ if ( (flgs == 0) || (ndr->flags & flgs) ) {\
+ if (!(mem_ctx)) {\
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "NDR_PULL_SET_MEM_CTX(NULL): %s\n", __location__); \
+ }\
+ ndr->current_mem_ctx = discard_const(mem_ctx);\
+ }\
+} while(0)
+
+#define _NDR_PULL_FIX_CURRENT_MEM_CTX(ndr) do {\
+ if (!ndr->current_mem_ctx) {\
+ ndr->current_mem_ctx = talloc_new(ndr);\
+ if (!ndr->current_mem_ctx) {\
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "_NDR_PULL_FIX_CURRENT_MEM_CTX() failed: %s\n", __location__); \
+ }\
+ }\
+} while(0)
+
+#define NDR_PULL_ALLOC(ndr, s) do { \
+ _NDR_PULL_FIX_CURRENT_MEM_CTX(ndr);\
+ (s) = talloc_ptrtype(ndr->current_mem_ctx, (s)); \
+ if (unlikely(!(s))) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Alloc %s failed: %s\n", # s, __location__); \
+} while (0)
+
+#define NDR_PULL_ALLOC_N(ndr, s, n) do { \
+ _NDR_PULL_FIX_CURRENT_MEM_CTX(ndr);\
+ (s) = talloc_array_ptrtype(ndr->current_mem_ctx, (s), n); \
+ if (unlikely(!(s))) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Alloc %u * %s failed: %s\n", (unsigned)n, # s, __location__); \
+} while (0)
+
+
+#define NDR_PUSH_ALLOC_SIZE(ndr, s, size) do { \
+ (s) = talloc_array(ndr, uint8_t, size); \
+ if (unlikely(!(s))) return ndr_push_error(ndr, NDR_ERR_ALLOC, "push alloc %u failed: %s\n", (unsigned)size, __location__); \
+} while (0)
+
+#define NDR_PUSH_ALLOC(ndr, s) do { \
+ (s) = talloc_ptrtype(ndr, (s)); \
+ if (unlikely(!(s))) return ndr_push_error(ndr, NDR_ERR_ALLOC, "push alloc %s failed: %s\n", # s, __location__); \
+} while (0)
+
+#define NDR_ZERO_STRUCT(x) ndr_zero_memory(&(x), sizeof(x))
+#define NDR_ZERO_STRUCTP(x) do { \
+ if ((x) != NULL) { \
+ ndr_zero_memory((x), sizeof(*(x))); \
+ } \
+} while(0)
+
+/* these are used when generic fn pointers are needed for ndr push/pull fns */
+typedef enum ndr_err_code (*ndr_push_flags_fn_t)(struct ndr_push *, int ndr_flags, const void *);
+typedef enum ndr_err_code (*ndr_pull_flags_fn_t)(struct ndr_pull *, int ndr_flags, void *);
+typedef void (*ndr_print_fn_t)(struct ndr_print *, const char *, const void *);
+typedef void (*ndr_print_function_t)(struct ndr_print *, const char *, int, const void *);
+
+#include "../libcli/util/error.h"
+#include "librpc/gen_ndr/misc.h"
+
+extern const struct ndr_syntax_id ndr_transfer_syntax_ndr;
+extern const struct ndr_syntax_id ndr_transfer_syntax_ndr64;
+extern const struct ndr_syntax_id ndr_syntax_id_null;
+
+struct ndr_interface_call_pipe {
+ const char *name;
+ const char *chunk_struct_name;
+ size_t chunk_struct_size;
+ ndr_push_flags_fn_t ndr_push;
+ ndr_pull_flags_fn_t ndr_pull;
+ ndr_print_fn_t ndr_print;
+};
+
+struct ndr_interface_call_pipes {
+ uint32_t num_pipes;
+ const struct ndr_interface_call_pipe *pipes;
+};
+
+struct ndr_interface_call {
+ const char *name;
+ size_t struct_size;
+ ndr_push_flags_fn_t ndr_push;
+ ndr_pull_flags_fn_t ndr_pull;
+ ndr_print_function_t ndr_print;
+ struct ndr_interface_call_pipes in_pipes;
+ struct ndr_interface_call_pipes out_pipes;
+};
+
+struct ndr_interface_public_struct {
+ const char *name;
+ size_t struct_size;
+ ndr_push_flags_fn_t ndr_push;
+ ndr_pull_flags_fn_t ndr_pull;
+ ndr_print_function_t ndr_print;
+};
+
+struct ndr_interface_string_array {
+ uint32_t count;
+ const char * const *names;
+};
+
+struct ndr_interface_table {
+ const char *name;
+ struct ndr_syntax_id syntax_id;
+ const char *helpstring;
+ uint32_t num_calls;
+ const struct ndr_interface_call *calls;
+ uint32_t num_public_structs;
+ const struct ndr_interface_public_struct *public_structs;
+ const struct ndr_interface_string_array *endpoints;
+ const struct ndr_interface_string_array *authservices;
+};
+
+struct ndr_interface_list {
+ struct ndr_interface_list *prev, *next;
+ const struct ndr_interface_table *table;
+};
+
+struct sockaddr_storage;
+
+/*********************************************************************
+ Map an NT error code from a NDR error code.
+*********************************************************************/
+NTSTATUS ndr_map_error2ntstatus(enum ndr_err_code ndr_err);
+int ndr_map_error2errno(enum ndr_err_code ndr_err);
+const char *ndr_map_error2string(enum ndr_err_code ndr_err);
+#define ndr_errstr ndr_map_error2string
+
+/* FIXME: Use represent_as instead */
+struct dom_sid;
+enum ndr_err_code ndr_push_dom_sid2(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid);
+enum ndr_err_code ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid);
+void ndr_print_dom_sid2(struct ndr_print *ndr, const char *name, const struct dom_sid *sid);
+enum ndr_err_code ndr_push_dom_sid28(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid);
+enum ndr_err_code ndr_pull_dom_sid28(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid);
+void ndr_print_dom_sid28(struct ndr_print *ndr, const char *name, const struct dom_sid *sid);
+size_t ndr_size_dom_sid28(const struct dom_sid *sid, int flags);
+enum ndr_err_code ndr_push_dom_sid0(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid);
+enum ndr_err_code ndr_pull_dom_sid0(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid);
+void ndr_print_dom_sid0(struct ndr_print *ndr, const char *name, const struct dom_sid *sid);
+size_t ndr_size_dom_sid0(const struct dom_sid *sid, int flags);
+void ndr_print_GUID(struct ndr_print *ndr, const char *name, const struct GUID *guid);
+void ndr_print_sockaddr_storage(struct ndr_print *ndr, const char *name, const struct sockaddr_storage *ss);
+void ndr_zero_memory(void *ptr, size_t len);
+bool ndr_syntax_id_equal(const struct ndr_syntax_id *i1, const struct ndr_syntax_id *i2);
+
+struct ndr_syntax_id_buf { char buf[39 /*GUID*/ + 3 /* "/0x" */ + 8]; };
+char *ndr_syntax_id_buf_string(
+ const struct ndr_syntax_id *id, struct ndr_syntax_id_buf *buf);
+char *ndr_syntax_id_to_string(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *id);
+
+bool ndr_syntax_id_from_string(const char *s, struct ndr_syntax_id *id);
+enum ndr_err_code ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, const void *p, ndr_push_flags_fn_t fn);
+enum ndr_err_code ndr_push_struct_into_fixed_blob(DATA_BLOB *blob,
+ const void *p,
+ ndr_push_flags_fn_t fn);
+enum ndr_err_code ndr_push_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, uint32_t level, ndr_push_flags_fn_t fn);
+size_t ndr_size_struct(const void *p, int flags, ndr_push_flags_fn_t push);
+size_t ndr_size_union(const void *p, int flags, uint32_t level, ndr_push_flags_fn_t push);
+uint32_t ndr_push_get_relative_base_offset(struct ndr_push *ndr);
+void ndr_push_restore_relative_base_offset(struct ndr_push *ndr, uint32_t offset);
+enum ndr_err_code ndr_push_setup_relative_base_offset1(struct ndr_push *ndr, const void *p, uint32_t offset);
+enum ndr_err_code ndr_push_setup_relative_base_offset2(struct ndr_push *ndr, const void *p);
+enum ndr_err_code ndr_push_relative_ptr1(struct ndr_push *ndr, const void *p);
+enum ndr_err_code ndr_push_short_relative_ptr1(struct ndr_push *ndr, const void *p);
+enum ndr_err_code ndr_push_relative_ptr2_start(struct ndr_push *ndr, const void *p);
+enum ndr_err_code ndr_push_relative_ptr2_end(struct ndr_push *ndr, const void *p);
+enum ndr_err_code ndr_push_short_relative_ptr2(struct ndr_push *ndr, const void *p);
+uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull *ndr);
+void ndr_pull_restore_relative_base_offset(struct ndr_pull *ndr, uint32_t offset);
+enum ndr_err_code ndr_pull_setup_relative_base_offset1(struct ndr_pull *ndr, const void *p, uint32_t offset);
+enum ndr_err_code ndr_pull_setup_relative_base_offset2(struct ndr_pull *ndr, const void *p);
+enum ndr_err_code ndr_pull_relative_ptr1(struct ndr_pull *ndr, const void *p, uint32_t rel_offset);
+enum ndr_err_code ndr_pull_relative_ptr2(struct ndr_pull *ndr, const void *p);
+enum ndr_err_code ndr_pull_relative_ptr_short(struct ndr_pull *ndr, uint16_t *v);
+size_t ndr_align_size(uint32_t offset, size_t n);
+struct ndr_pull *ndr_pull_init_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx);
+enum ndr_err_code ndr_pull_append(struct ndr_pull *ndr, DATA_BLOB *blob);
+enum ndr_err_code ndr_pull_pop(struct ndr_pull *ndr);
+enum ndr_err_code ndr_pull_advance(struct ndr_pull *ndr, uint32_t size);
+struct ndr_push *ndr_push_init_ctx(TALLOC_CTX *mem_ctx);
+DATA_BLOB ndr_push_blob(struct ndr_push *ndr);
+enum ndr_err_code ndr_push_expand(struct ndr_push *ndr, uint32_t extra_size);
+void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...) PRINTF_ATTRIBUTE(2,3);
+void ndr_print_debugc_helper(struct ndr_print *ndr, const char *format, ...) PRINTF_ATTRIBUTE(2,3);
+void ndr_print_printf_helper(struct ndr_print *ndr, const char *format, ...) PRINTF_ATTRIBUTE(2,3);
+void ndr_print_string_helper(struct ndr_print *ndr, const char *format, ...) PRINTF_ATTRIBUTE(2,3);
+bool ndr_print_debug(int level, ndr_print_fn_t fn, const char *name, void *ptr, const char *location, const char *function);
+void ndr_print_debugc(int dbgc_class, ndr_print_fn_t fn, const char *name, void *ptr);
+void ndr_print_union_debug(ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr);
+void ndr_print_function_debug(ndr_print_function_t fn, const char *name, int flags, void *ptr);
+char *ndr_print_struct_string(TALLOC_CTX *mem_ctx, ndr_print_fn_t fn, const char *name, void *ptr);
+char *ndr_print_union_string(TALLOC_CTX *mem_ctx, ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr);
+char *ndr_print_function_string(TALLOC_CTX *mem_ctx,
+ ndr_print_function_t fn, const char *name,
+ int flags, void *ptr);
+void ndr_set_flags(uint32_t *pflags, uint32_t new_flags);
+enum ndr_err_code _ndr_pull_error(struct ndr_pull *ndr,
+ enum ndr_err_code ndr_err,
+ const char *function,
+ const char *location,
+ const char *format, ...) PRINTF_ATTRIBUTE(5,6);
+#define ndr_pull_error(ndr, ndr_err, ...) \
+ _ndr_pull_error(ndr, \
+ ndr_err, \
+ __FUNCTION__, \
+ __location__, \
+ __VA_ARGS__)
+enum ndr_err_code _ndr_push_error(struct ndr_push *ndr,
+ enum ndr_err_code ndr_err,
+ const char *function,
+ const char *location,
+ const char *format, ...) PRINTF_ATTRIBUTE(5,6);
+#define ndr_push_error(ndr, ndr_err, ...) \
+ _ndr_push_error(ndr, \
+ ndr_err, \
+ __FUNCTION__, \
+ __location__, \
+ __VA_ARGS__)
+enum ndr_err_code ndr_pull_subcontext_start(struct ndr_pull *ndr,
+ struct ndr_pull **_subndr,
+ size_t header_size,
+ ssize_t size_is);
+enum ndr_err_code ndr_pull_subcontext_end(struct ndr_pull *ndr,
+ struct ndr_pull *subndr,
+ size_t header_size,
+ ssize_t size_is);
+enum ndr_err_code ndr_push_subcontext_start(struct ndr_push *ndr,
+ struct ndr_push **_subndr,
+ size_t header_size,
+ ssize_t size_is);
+enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr,
+ struct ndr_push *subndr,
+ size_t header_size,
+ ssize_t size_is);
+enum ndr_err_code ndr_token_store(TALLOC_CTX *mem_ctx,
+ struct ndr_token_list *list,
+ const void *key,
+ uint32_t value);
+enum ndr_err_code ndr_token_retrieve_cmp_fn(struct ndr_token_list *list, const void *key, uint32_t *v,
+ int(*_cmp_fn)(const void*,const void*), bool erase);
+enum ndr_err_code ndr_token_retrieve(struct ndr_token_list *list, const void *key, uint32_t *v);
+enum ndr_err_code ndr_token_peek(struct ndr_token_list *list, const void *key, uint32_t *v);
+enum ndr_err_code ndr_pull_array_size(struct ndr_pull *ndr, const void *p);
+enum ndr_err_code ndr_get_array_size(struct ndr_pull *ndr, const void *p, uint32_t *size);
+enum ndr_err_code ndr_steal_array_size(struct ndr_pull *ndr, const void *p, uint32_t *size);
+enum ndr_err_code ndr_check_array_size(struct ndr_pull *ndr, const void *p, uint32_t size);
+enum ndr_err_code ndr_check_steal_array_size(struct ndr_pull *ndr, const void *p, uint32_t size);
+enum ndr_err_code ndr_pull_array_length(struct ndr_pull *ndr, const void *p);
+enum ndr_err_code ndr_get_array_length(struct ndr_pull *ndr, const void *p, uint32_t *length);
+enum ndr_err_code ndr_steal_array_length(struct ndr_pull *ndr, const void *p, uint32_t *length);
+enum ndr_err_code ndr_check_array_length(struct ndr_pull *ndr, const void *p, uint32_t length);
+enum ndr_err_code ndr_check_steal_array_length(struct ndr_pull *ndr, const void *p, uint32_t length);
+enum ndr_err_code ndr_push_pipe_chunk_trailer(struct ndr_push *ndr, int ndr_flags, uint32_t count);
+enum ndr_err_code ndr_check_pipe_chunk_trailer(struct ndr_pull *ndr, int ndr_flags, uint32_t count);
+enum ndr_err_code ndr_push_set_switch_value(struct ndr_push *ndr, const void *p, uint32_t val);
+enum ndr_err_code ndr_pull_set_switch_value(struct ndr_pull *ndr, const void *p, uint32_t val);
+enum ndr_err_code ndr_print_set_switch_value(struct ndr_print *ndr, const void *p, uint32_t val);
+/* retrieve a switch value (for push) and remove it from the list */
+enum ndr_err_code ndr_push_steal_switch_value(struct ndr_push *ndr,
+ const void *p,
+ uint32_t *v);
+/* retrieve a switch value and remove it from the list */
+uint32_t ndr_print_steal_switch_value(struct ndr_print *ndr, const void *p);
+/* retrieve a switch value and remove it from the list */
+enum ndr_err_code ndr_pull_steal_switch_value(struct ndr_pull *ndr,
+ const void *p,
+ uint32_t *v);
+enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, ndr_pull_flags_fn_t fn);
+enum ndr_err_code ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, ndr_pull_flags_fn_t fn);
+enum ndr_err_code ndr_pull_struct_blob_all_noalloc(const DATA_BLOB *blob,
+ void *p, ndr_pull_flags_fn_t fn);
+enum ndr_err_code ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, uint32_t level, ndr_pull_flags_fn_t fn);
+enum ndr_err_code ndr_pull_union_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, uint32_t level, ndr_pull_flags_fn_t fn);
+
+/* from libndr_basic.h */
+#define NDR_SCALAR_PROTO(name, type) \
+enum ndr_err_code ndr_push_ ## name(struct ndr_push *ndr, int ndr_flags, type v); \
+enum ndr_err_code ndr_pull_ ## name(struct ndr_pull *ndr, int ndr_flags, type *v); \
+void ndr_print_ ## name(struct ndr_print *ndr, const char *var_name, type v);
+
+#define NDR_SCALAR_PTR_PROTO(name, type) \
+enum ndr_err_code ndr_push_ ## name(struct ndr_push *ndr, int ndr_flags, const type *v); \
+enum ndr_err_code ndr_pull_ ## name(struct ndr_pull *ndr, int ndr_flags, type **v); \
+void ndr_print_ ## name(struct ndr_print *ndr, const char *var_name, const type *v);
+
+#define NDR_BUFFER_PROTO(name, type) \
+enum ndr_err_code ndr_push_ ## name(struct ndr_push *ndr, int ndr_flags, const type *v); \
+enum ndr_err_code ndr_pull_ ## name(struct ndr_pull *ndr, int ndr_flags, type *v); \
+void ndr_print_ ## name(struct ndr_print *ndr, const char *var_name, const type *v);
+
+NDR_SCALAR_PROTO(uint8, uint8_t)
+NDR_SCALAR_PROTO(int8, int8_t)
+NDR_SCALAR_PROTO(uint16, uint16_t)
+NDR_SCALAR_PROTO(int16, int16_t)
+NDR_SCALAR_PROTO(uint1632, uint16_t)
+NDR_SCALAR_PROTO(uint32, uint32_t)
+NDR_SCALAR_PROTO(uint3264, uint32_t)
+NDR_SCALAR_PROTO(int32, int32_t)
+NDR_SCALAR_PROTO(int3264, int32_t)
+NDR_SCALAR_PROTO(udlong, uint64_t)
+NDR_SCALAR_PROTO(udlongr, uint64_t)
+NDR_SCALAR_PROTO(dlong, int64_t)
+NDR_SCALAR_PROTO(hyper, uint64_t)
+NDR_SCALAR_PROTO(pointer, void *)
+NDR_SCALAR_PROTO(time_t, time_t)
+NDR_SCALAR_PROTO(uid_t, uid_t)
+NDR_SCALAR_PROTO(gid_t, gid_t)
+NDR_SCALAR_PROTO(NTSTATUS, NTSTATUS)
+NDR_SCALAR_PROTO(WERROR, WERROR)
+NDR_SCALAR_PROTO(HRESULT, HRESULT)
+NDR_SCALAR_PROTO(NTTIME, NTTIME)
+NDR_SCALAR_PROTO(NTTIME_1sec, NTTIME)
+NDR_SCALAR_PROTO(NTTIME_hyper, NTTIME)
+NDR_SCALAR_PROTO(DATA_BLOB, DATA_BLOB)
+NDR_SCALAR_PROTO(ipv4address, const char *)
+NDR_SCALAR_PROTO(ipv6address, const char *)
+NDR_SCALAR_PROTO(string, const char *)
+NDR_SCALAR_PROTO(double, double)
+
+enum ndr_err_code ndr_pull_policy_handle(struct ndr_pull *ndr, int ndr_flags, struct policy_handle *r);
+enum ndr_err_code ndr_push_policy_handle(struct ndr_push *ndr, int ndr_flags, const struct policy_handle *r);
+void ndr_print_policy_handle(struct ndr_print *ndr, const char *name, const struct policy_handle *r);
+bool ndr_policy_handle_empty(const struct policy_handle *h);
+#define is_valid_policy_hnd(hnd) (!ndr_policy_handle_empty(hnd))
+bool ndr_policy_handle_equal(const struct policy_handle *hnd1,
+ const struct policy_handle *hnd2);
+
+void ndr_check_padding(struct ndr_pull *ndr, size_t n);
+enum ndr_err_code ndr_pull_generic_ptr(struct ndr_pull *ndr, uint32_t *v);
+enum ndr_err_code ndr_pull_ref_ptr(struct ndr_pull *ndr, uint32_t *v);
+enum ndr_err_code ndr_pull_bytes(struct ndr_pull *ndr, uint8_t *data, uint32_t n);
+enum ndr_err_code ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *data, uint32_t n);
+enum ndr_err_code ndr_push_align(struct ndr_push *ndr, size_t size);
+enum ndr_err_code ndr_pull_align(struct ndr_pull *ndr, size_t size);
+enum ndr_err_code ndr_push_union_align(struct ndr_push *ndr, size_t size);
+enum ndr_err_code ndr_pull_union_align(struct ndr_pull *ndr, size_t size);
+enum ndr_err_code ndr_push_trailer_align(struct ndr_push *ndr, size_t size);
+enum ndr_err_code ndr_pull_trailer_align(struct ndr_pull *ndr, size_t size);
+enum ndr_err_code ndr_push_bytes(struct ndr_push *ndr, const uint8_t *data, uint32_t n);
+enum ndr_err_code ndr_push_zero(struct ndr_push *ndr, uint32_t n);
+enum ndr_err_code ndr_push_array_uint8(struct ndr_push *ndr, int ndr_flags, const uint8_t *data, uint32_t n);
+enum ndr_err_code ndr_push_unique_ptr(struct ndr_push *ndr, const void *p);
+enum ndr_err_code ndr_push_full_ptr(struct ndr_push *ndr, const void *p);
+enum ndr_err_code ndr_push_ref_ptr(struct ndr_push *ndr);
+void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type);
+void ndr_print_null(struct ndr_print *ndr);
+void ndr_print_enum(struct ndr_print *ndr, const char *name, const char *type, const char *val, uint32_t value);
+void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const char *flag_name, uint32_t flag, uint32_t value);
+void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const char *flag_name, uint32_t flag, uint32_t value);
+void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p);
+void ndr_print_union(struct ndr_print *ndr, const char *name, int level, const char *type);
+void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16_t level);
+void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, const uint8_t *data, uint32_t count);
+uint32_t ndr_size_DATA_BLOB(int ret, const DATA_BLOB *data, int flags);
+
+/* strings */
+uint32_t ndr_charset_length(const void *var, charset_t chset);
+size_t ndr_string_array_size(struct ndr_push *ndr, const char *s);
+uint32_t ndr_size_string(int ret, const char * const* string, int flags);
+enum ndr_err_code ndr_pull_string_array(struct ndr_pull *ndr, int ndr_flags, const char ***_a);
+enum ndr_err_code ndr_push_string_array(struct ndr_push *ndr, int ndr_flags, const char **a);
+void ndr_print_string_array(struct ndr_print *ndr, const char *name, const char **a);
+size_t ndr_size_string_array(const char **a, uint32_t count, int flags);
+uint32_t ndr_string_length(const void *_var, uint32_t element_size);
+enum ndr_err_code ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size);
+enum ndr_err_code ndr_pull_charset(struct ndr_pull *ndr, int ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset);
+enum ndr_err_code ndr_pull_charset_to_null(struct ndr_pull *ndr, int ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset);
+enum ndr_err_code ndr_push_charset(struct ndr_push *ndr, int ndr_flags, const char *var, uint32_t length, uint8_t byte_mul, charset_t chset);
+enum ndr_err_code ndr_push_charset_to_null(struct ndr_push *ndr, int ndr_flags, const char *var, uint32_t length, uint8_t byte_mul, charset_t chset);
+
+/* GUIDs */
+bool GUID_equal(const struct GUID *u1, const struct GUID *u2);
+struct GUID_ndr_buf { uint8_t buf[16]; };
+NTSTATUS GUID_to_ndr_buf(const struct GUID *guid, struct GUID_ndr_buf *buf);
+NTSTATUS GUID_to_ndr_blob(const struct GUID *guid, TALLOC_CTX *mem_ctx, DATA_BLOB *b);
+NTSTATUS GUID_from_ndr_blob(const DATA_BLOB *b, struct GUID *guid);
+NTSTATUS GUID_from_data_blob(const DATA_BLOB *s, struct GUID *guid);
+NTSTATUS GUID_from_string(const char *s, struct GUID *guid);
+struct GUID GUID_zero(void);
+bool GUID_all_zero(const struct GUID *u);
+int GUID_compare(const struct GUID *u1, const struct GUID *u2);
+char *GUID_string(TALLOC_CTX *mem_ctx, const struct GUID *guid);
+char *GUID_string2(TALLOC_CTX *mem_ctx, const struct GUID *guid);
+char *GUID_hexstring(TALLOC_CTX *mem_ctx, const struct GUID *guid);
+struct GUID GUID_random(void);
+
+/* Format is "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" */
+ /* 32 chars + 4 ' ' + \0 + 2 for adding {} */
+struct GUID_txt_buf { char buf[39]; };
+_PUBLIC_ char* GUID_buf_string(const struct GUID *guid,
+ struct GUID_txt_buf *dst);
+
+_PUBLIC_ enum ndr_err_code ndr_pull_enum_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *v);
+_PUBLIC_ enum ndr_err_code ndr_pull_enum_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v);
+_PUBLIC_ enum ndr_err_code ndr_pull_enum_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v);
+_PUBLIC_ enum ndr_err_code ndr_pull_enum_uint1632(struct ndr_pull *ndr, int ndr_flags, uint16_t *v);
+_PUBLIC_ enum ndr_err_code ndr_push_enum_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v);
+_PUBLIC_ enum ndr_err_code ndr_push_enum_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v);
+_PUBLIC_ enum ndr_err_code ndr_push_enum_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v);
+_PUBLIC_ enum ndr_err_code ndr_push_enum_uint1632(struct ndr_push *ndr, int ndr_flags, uint16_t v);
+
+_PUBLIC_ void ndr_print_bool(struct ndr_print *ndr, const char *name, const bool b);
+
+_PUBLIC_ enum ndr_err_code ndr_push_timespec(struct ndr_push *ndr,
+ int ndr_flags,
+ const struct timespec *t);
+_PUBLIC_ enum ndr_err_code ndr_pull_timespec(struct ndr_pull *ndr,
+ int ndr_flags,
+ struct timespec *t);
+_PUBLIC_ void ndr_print_timespec(struct ndr_print *ndr, const char *name,
+ const struct timespec *t);
+
+_PUBLIC_ enum ndr_err_code ndr_push_timeval(struct ndr_push *ndr,
+ int ndr_flags,
+ const struct timeval *t);
+_PUBLIC_ enum ndr_err_code ndr_pull_timeval(struct ndr_pull *ndr,
+ int ndr_flags,
+ struct timeval *t);
+_PUBLIC_ void ndr_print_timeval(struct ndr_print *ndr, const char *name,
+ const struct timeval *t);
+
+
+
+#endif /* __LIBNDR_H__ */
diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c
new file mode 100644
index 0000000..2576588
--- /dev/null
+++ b/librpc/ndr/ndr.c
@@ -0,0 +1,2005 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ libndr interface
+
+ Copyright (C) Andrew Tridgell 2003
+ Copyright (C) Jelmer Vernooij 2005-2008
+
+ 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/>.
+*/
+
+/*
+ this provides the core routines for NDR parsing functions
+
+ see http://www.opengroup.org/onlinepubs/9629399/chap14.htm for details
+ of NDR encoding rules
+*/
+
+#include "includes.h"
+#include "librpc/ndr/libndr.h"
+#include "librpc/ndr/ndr_private.h"
+#include "../lib/util/dlinklist.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_PARSE
+
+#define NDR_BASE_MARSHALL_SIZE 1024
+
+/*
+ * This value is arbitrary, but designed to reduce the memory a client
+ * can allocate and the work the client can force in processing a
+ * malicious packet.
+ *
+ * In an ideal world this would be controlled by range() restrictions
+ * on array sizes and careful IDL construction to avoid arbitary
+ * linked lists, but this is a backstop for now.
+ */
+#define NDR_TOKEN_MAX_LIST_SIZE 65535
+
+size_t ndr_token_max_list_size(void) {
+ return NDR_TOKEN_MAX_LIST_SIZE;
+};
+
+/* this guid indicates NDR encoding in a protocol tower */
+const struct ndr_syntax_id ndr_transfer_syntax_ndr = {
+ { 0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8}, {0x08,0x00,0x2b,0x10,0x48,0x60} },
+ 2
+};
+
+const struct ndr_syntax_id ndr_transfer_syntax_ndr64 = {
+ { 0x71710533, 0xbeba, 0x4937, {0x83, 0x19}, {0xb5,0xdb,0xef,0x9c,0xcc,0x36} },
+ 1
+};
+
+const struct ndr_syntax_id ndr_syntax_id_null = {
+ { 0, 0, 0, { 0, 0 }, { 0, 0, 0, 0, 0, 0 } },
+ 0
+};
+
+/*
+ work out the number of bytes needed to align on a n byte boundary
+*/
+_PUBLIC_ size_t ndr_align_size(uint32_t offset, size_t n)
+{
+ if ((offset & (n-1)) == 0) return 0;
+ return n - (offset & (n-1));
+}
+
+/*
+ initialise a ndr parse structure from a data blob
+*/
+_PUBLIC_ struct ndr_pull *ndr_pull_init_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
+{
+ struct ndr_pull *ndr;
+
+ ndr = talloc_zero(mem_ctx, struct ndr_pull);
+ if (!ndr) return NULL;
+ ndr->current_mem_ctx = mem_ctx;
+
+ ndr->data = blob->data;
+ ndr->data_size = blob->length;
+
+ return ndr;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_append(struct ndr_pull *ndr, DATA_BLOB *blob)
+{
+ enum ndr_err_code ndr_err;
+ DATA_BLOB b;
+ uint32_t append = 0;
+ bool ok;
+
+ if (blob->length == 0) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ ndr_err = ndr_token_retrieve(&ndr->array_size_list, ndr, &append);
+ if (ndr_err == NDR_ERR_TOKEN) {
+ append = 0;
+ ndr_err = NDR_ERR_SUCCESS;
+ }
+ NDR_CHECK(ndr_err);
+
+ if (ndr->data_size == 0) {
+ ndr->data = NULL;
+ append = UINT32_MAX;
+ }
+
+ if (append == UINT32_MAX) {
+ /*
+ * append == UINT32_MAX means that
+ * ndr->data is either NULL or a valid
+ * talloc child of ndr, which means
+ * we can use data_blob_append() without
+ * data_blob_talloc() of the existing callers data
+ */
+ b = data_blob_const(ndr->data, ndr->data_size);
+ } else {
+ b = data_blob_talloc(ndr, ndr->data, ndr->data_size);
+ if (b.data == NULL) {
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "%s", __location__);
+ }
+ }
+
+ ok = data_blob_append(ndr, &b, blob->data, blob->length);
+ if (!ok) {
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "%s", __location__);
+ }
+
+ ndr->data = b.data;
+ ndr->data_size = b.length;
+
+ return ndr_token_store(ndr, &ndr->array_size_list, ndr, UINT32_MAX);
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_pop(struct ndr_pull *ndr)
+{
+ uint32_t skip = 0;
+ uint32_t append = 0;
+ enum ndr_err_code ndr_err;
+
+ if (ndr->relative_base_offset != 0) {
+ return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
+ "%s", __location__);
+ }
+ if (ndr->relative_highest_offset != 0) {
+ return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
+ "%s", __location__);
+ }
+ if (ndr->relative_list.count != 0) {
+ return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
+ "%s", __location__);
+ }
+ if (ndr->relative_base_list.count != 0) {
+ return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
+ "%s", __location__);
+ }
+
+ /*
+ * we need to keep up to 7 bytes
+ * in order to get the aligment right.
+ */
+ skip = ndr->offset & 0xFFFFFFF8;
+
+ if (skip == 0) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ ndr->offset -= skip;
+ ndr->data_size -= skip;
+
+ ndr_err = ndr_token_peek(&ndr->array_size_list, ndr, &append);
+ if (ndr_err == NDR_ERR_TOKEN) {
+ /*
+ * here we assume, that ndr->data is not a
+ * talloc child of ndr.
+ */
+ ndr->data += skip;
+ return NDR_ERR_SUCCESS;
+ }
+
+ memmove(ndr->data, ndr->data + skip, ndr->data_size);
+
+ ndr->data = talloc_realloc(ndr, ndr->data, uint8_t, ndr->data_size);
+ if (ndr->data_size != 0 && ndr->data == NULL) {
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "%s", __location__);
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ advance by 'size' bytes
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_advance(struct ndr_pull *ndr, uint32_t size)
+{
+ NDR_PULL_NEED_BYTES(ndr, size);
+ ndr->offset += size;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ set the parse offset to 'ofs'
+*/
+static enum ndr_err_code ndr_pull_set_offset(struct ndr_pull *ndr, uint32_t ofs)
+{
+ ndr->offset = ofs;
+ if (ndr->offset > ndr->data_size) {
+ return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
+ "ndr_pull_set_offset %u failed",
+ ofs);
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+/* create a ndr_push structure, ready for some marshalling */
+_PUBLIC_ struct ndr_push *ndr_push_init_ctx(TALLOC_CTX *mem_ctx)
+{
+ struct ndr_push *ndr;
+
+ ndr = talloc_zero(mem_ctx, struct ndr_push);
+ if (!ndr) {
+ return NULL;
+ }
+
+ ndr->flags = 0;
+ ndr->alloc_size = NDR_BASE_MARSHALL_SIZE;
+ ndr->data = talloc_array(ndr, uint8_t, ndr->alloc_size);
+ if (!ndr->data) {
+ talloc_free(ndr);
+ return NULL;
+ }
+
+ return ndr;
+}
+
+/* return a DATA_BLOB structure for the current ndr_push marshalled data */
+_PUBLIC_ DATA_BLOB ndr_push_blob(struct ndr_push *ndr)
+{
+ DATA_BLOB blob;
+ blob = data_blob_const(ndr->data, ndr->offset);
+ if (ndr->alloc_size > ndr->offset) {
+ ndr->data[ndr->offset] = 0;
+ }
+ return blob;
+}
+
+
+/*
+ expand the available space in the buffer to ndr->offset + extra_size
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_expand(struct ndr_push *ndr, uint32_t extra_size)
+{
+ uint32_t size = extra_size + ndr->offset;
+
+ if (size < ndr->offset) {
+ /* extra_size overflowed the offset */
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE, "Overflow in push_expand to %u",
+ size);
+ }
+
+ if (ndr->fixed_buf_size) {
+ if (ndr->alloc_size >= size) {
+ return NDR_ERR_SUCCESS;
+ }
+ return ndr_push_error(ndr,
+ NDR_ERR_BUFSIZE,
+ "Overflow of fixed buffer in "
+ "push_expand to %u",
+ size);
+ }
+
+ if (ndr->alloc_size > size) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ ndr->alloc_size += NDR_BASE_MARSHALL_SIZE;
+ if (size+1 > ndr->alloc_size) {
+ ndr->alloc_size = size+1;
+ }
+ ndr->data = talloc_realloc(ndr, ndr->data, uint8_t, ndr->alloc_size);
+ if (!ndr->data) {
+ return ndr_push_error(ndr, NDR_ERR_ALLOC, "Failed to push_expand to %u",
+ ndr->alloc_size);
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_debugc_helper(struct ndr_print *ndr, const char *format, ...)
+{
+ va_list ap;
+ char *s = NULL;
+ uint32_t i;
+ int ret;
+ int dbgc_class;
+
+ va_start(ap, format);
+ ret = vasprintf(&s, format, ap);
+ va_end(ap);
+
+ if (ret == -1) {
+ return;
+ }
+
+ dbgc_class = *(int *)ndr->private_data;
+
+ if (ndr->no_newline) {
+ DEBUGADDC(dbgc_class, 1,("%s", s));
+ free(s);
+ return;
+ }
+
+ for (i=0;i<ndr->depth;i++) {
+ DEBUGADDC(dbgc_class, 1,(" "));
+ }
+
+ DEBUGADDC(dbgc_class, 1,("%s\n", s));
+ free(s);
+}
+
+_PUBLIC_ void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...)
+{
+ va_list ap;
+ char *s = NULL;
+ uint32_t i;
+ int ret;
+
+ va_start(ap, format);
+ ret = vasprintf(&s, format, ap);
+ va_end(ap);
+
+ if (ret == -1) {
+ return;
+ }
+
+ if (ndr->no_newline) {
+ DEBUGADD(1,("%s", s));
+ free(s);
+ return;
+ }
+
+ for (i=0;i<ndr->depth;i++) {
+ DEBUGADD(1,(" "));
+ }
+
+ DEBUGADD(1,("%s\n", s));
+ free(s);
+}
+
+_PUBLIC_ void ndr_print_printf_helper(struct ndr_print *ndr, const char *format, ...)
+{
+ va_list ap;
+ uint32_t i;
+
+ if (!ndr->no_newline) {
+ for (i=0;i<ndr->depth;i++) {
+ printf(" ");
+ }
+ }
+
+ va_start(ap, format);
+ vprintf(format, ap);
+ va_end(ap);
+ if (!ndr->no_newline) {
+ printf("\n");
+ }
+}
+
+_PUBLIC_ void ndr_print_string_helper(struct ndr_print *ndr, const char *format, ...)
+{
+ va_list ap;
+ uint32_t i;
+
+ if (!ndr->no_newline) {
+ for (i=0;i<ndr->depth;i++) {
+ ndr->private_data = talloc_asprintf_append_buffer(
+ (char *)ndr->private_data, " ");
+ }
+ }
+
+ va_start(ap, format);
+ ndr->private_data = talloc_vasprintf_append_buffer((char *)ndr->private_data,
+ format, ap);
+ va_end(ap);
+ if (!ndr->no_newline) {
+ ndr->private_data = talloc_asprintf_append_buffer((char *)ndr->private_data,
+ "\n");
+ }
+}
+
+/*
+ a useful helper function for printing idl structures via DEBUGC()
+*/
+_PUBLIC_ void ndr_print_debugc(int dbgc_class, ndr_print_fn_t fn, const char *name, void *ptr)
+{
+ struct ndr_print *ndr;
+
+ DEBUGC(dbgc_class, 1,(" "));
+
+ ndr = talloc_zero(NULL, struct ndr_print);
+ if (!ndr) return;
+ ndr->private_data = &dbgc_class;
+ ndr->print = ndr_print_debugc_helper;
+ ndr->depth = 1;
+ ndr->flags = 0;
+#ifdef DEBUG_PASSWORD
+ if (CHECK_DEBUGLVL(100)) {
+ ndr->print_secrets = true;
+ }
+#endif
+
+ fn(ndr, name, ptr);
+ talloc_free(ndr);
+}
+
+/*
+ a useful helper function for printing idl structures via DEBUG()
+*/
+_PUBLIC_ bool ndr_print_debug(int level,
+ ndr_print_fn_t fn,
+ const char *name,
+ void *ptr,
+ const char *location,
+ const char *function)
+{
+ struct ndr_print *ndr;
+
+ DEBUGLF(level, (" "), location, function);
+
+ ndr = talloc_zero(NULL, struct ndr_print);
+ if (!ndr) return false;
+ ndr->print = ndr_print_debug_helper;
+ ndr->depth = 1;
+ ndr->flags = 0;
+#ifdef DEBUG_PASSWORD
+ if (CHECK_DEBUGLVL(100)) {
+ ndr->print_secrets = true;
+ }
+#endif
+
+ fn(ndr, name, ptr);
+ talloc_free(ndr);
+ return true;
+}
+
+/*
+ a useful helper function for printing idl unions via DEBUG()
+*/
+_PUBLIC_ void ndr_print_union_debug(ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr)
+{
+ struct ndr_print *ndr;
+
+ DEBUG(1,(" "));
+
+ ndr = talloc_zero(NULL, struct ndr_print);
+ if (!ndr) return;
+ ndr->print = ndr_print_debug_helper;
+ ndr->depth = 1;
+ ndr->flags = 0;
+#ifdef DEBUG_PASSWORD
+ if (CHECK_DEBUGLVL(100)) {
+ ndr->print_secrets = true;
+ }
+#endif
+
+ ndr_print_set_switch_value(ndr, ptr, level);
+ fn(ndr, name, ptr);
+ talloc_free(ndr);
+}
+
+/*
+ a useful helper function for printing idl function calls via DEBUG()
+*/
+_PUBLIC_ void ndr_print_function_debug(ndr_print_function_t fn, const char *name, int flags, void *ptr)
+{
+ struct ndr_print *ndr;
+
+ DEBUG(1,(" "));
+
+ ndr = talloc_zero(NULL, struct ndr_print);
+ if (!ndr) return;
+ ndr->print = ndr_print_debug_helper;
+ ndr->depth = 1;
+ ndr->flags = 0;
+#ifdef DEBUG_PASSWORD
+ if (CHECK_DEBUGLVL(100)) {
+ ndr->print_secrets = true;
+ }
+#endif
+
+ fn(ndr, name, flags, ptr);
+ talloc_free(ndr);
+}
+
+/*
+ a useful helper function for printing idl structures to a string
+*/
+_PUBLIC_ char *ndr_print_struct_string(TALLOC_CTX *mem_ctx, ndr_print_fn_t fn, const char *name, void *ptr)
+{
+ struct ndr_print *ndr;
+ char *ret = NULL;
+
+ ndr = talloc_zero(mem_ctx, struct ndr_print);
+ if (!ndr) return NULL;
+ ndr->private_data = talloc_strdup(ndr, "");
+ if (!ndr->private_data) {
+ goto failed;
+ }
+ ndr->print = ndr_print_string_helper;
+ ndr->depth = 1;
+ ndr->flags = 0;
+
+ fn(ndr, name, ptr);
+ ret = talloc_steal(mem_ctx, (char *)ndr->private_data);
+failed:
+ talloc_free(ndr);
+ return ret;
+}
+
+/*
+ a useful helper function for printing idl unions to a string
+*/
+_PUBLIC_ char *ndr_print_union_string(TALLOC_CTX *mem_ctx, ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr)
+{
+ struct ndr_print *ndr;
+ char *ret = NULL;
+
+ ndr = talloc_zero(mem_ctx, struct ndr_print);
+ if (!ndr) return NULL;
+ ndr->private_data = talloc_strdup(ndr, "");
+ if (!ndr->private_data) {
+ goto failed;
+ }
+ ndr->print = ndr_print_string_helper;
+ ndr->depth = 1;
+ ndr->flags = 0;
+ ndr_print_set_switch_value(ndr, ptr, level);
+ fn(ndr, name, ptr);
+ ret = talloc_steal(mem_ctx, (char *)ndr->private_data);
+failed:
+ talloc_free(ndr);
+ return ret;
+}
+
+/*
+ a useful helper function for printing idl function calls to a string
+*/
+_PUBLIC_ char *ndr_print_function_string(TALLOC_CTX *mem_ctx,
+ ndr_print_function_t fn, const char *name,
+ int flags, void *ptr)
+{
+ struct ndr_print *ndr;
+ char *ret = NULL;
+
+ ndr = talloc_zero(mem_ctx, struct ndr_print);
+ if (!ndr) return NULL;
+ ndr->private_data = talloc_strdup(ndr, "");
+ if (!ndr->private_data) {
+ goto failed;
+ }
+ ndr->print = ndr_print_string_helper;
+ ndr->depth = 1;
+ ndr->flags = 0;
+ fn(ndr, name, flags, ptr);
+ ret = talloc_steal(mem_ctx, (char *)ndr->private_data);
+failed:
+ talloc_free(ndr);
+ return ret;
+}
+
+_PUBLIC_ void ndr_set_flags(uint32_t *pflags, uint32_t new_flags)
+{
+ /* the big/little endian flags are inter-dependent */
+ if (new_flags & LIBNDR_FLAG_LITTLE_ENDIAN) {
+ (*pflags) &= ~LIBNDR_FLAG_BIGENDIAN;
+ (*pflags) &= ~LIBNDR_FLAG_NDR64;
+ }
+ if (new_flags & LIBNDR_FLAG_BIGENDIAN) {
+ (*pflags) &= ~LIBNDR_FLAG_LITTLE_ENDIAN;
+ (*pflags) &= ~LIBNDR_FLAG_NDR64;
+ }
+ if (new_flags & LIBNDR_ALIGN_FLAGS) {
+ /* Ensure we only have the passed-in
+ align flag set in the new_flags,
+ remove any old align flag. */
+ (*pflags) &= ~LIBNDR_ALIGN_FLAGS;
+ }
+ if (new_flags & LIBNDR_FLAG_NO_RELATIVE_REVERSE) {
+ (*pflags) &= ~LIBNDR_FLAG_RELATIVE_REVERSE;
+ }
+ (*pflags) |= new_flags;
+}
+
+/*
+ return and possibly log an NDR error
+*/
+_PUBLIC_ enum ndr_err_code _ndr_pull_error(struct ndr_pull *ndr,
+ enum ndr_err_code ndr_err,
+ const char *function,
+ const char *location,
+ const char *format, ...)
+{
+ char *s=NULL;
+ va_list ap;
+ int ret;
+
+ if (ndr->flags & LIBNDR_FLAG_INCOMPLETE_BUFFER) {
+ switch (ndr_err) {
+ case NDR_ERR_BUFSIZE:
+ return NDR_ERR_INCOMPLETE_BUFFER;
+ default:
+ break;
+ }
+ }
+
+ va_start(ap, format);
+ ret = vasprintf(&s, format, ap);
+ va_end(ap);
+
+ if (ret == -1) {
+ return NDR_ERR_ALLOC;
+ }
+
+ D_WARNING("%s: ndr_pull_error(%s): %s at %s\n",
+ function,
+ ndr_map_error2string(ndr_err),
+ s,
+ location);
+
+ free(s);
+
+ return ndr_err;
+}
+
+/*
+ return and possibly log an NDR error
+*/
+_PUBLIC_ enum ndr_err_code _ndr_push_error(struct ndr_push *ndr,
+ enum ndr_err_code ndr_err,
+ const char *function,
+ const char *location,
+ const char *format, ...)
+{
+ char *s=NULL;
+ va_list ap;
+ int ret;
+
+ va_start(ap, format);
+ ret = vasprintf(&s, format, ap);
+ va_end(ap);
+
+ if (ret == -1) {
+ return NDR_ERR_ALLOC;
+ }
+
+ D_WARNING("%s: ndr_push_error(%s): %s at %s\n",
+ function,
+ ndr_map_error2string(ndr_err),
+ s,
+ location);
+
+ free(s);
+
+ return ndr_err;
+}
+
+/*
+ handle subcontext buffers, which in midl land are user-marshalled, but
+ we use magic in pidl to make them easier to cope with
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start(struct ndr_pull *ndr,
+ struct ndr_pull **_subndr,
+ size_t header_size,
+ ssize_t size_is)
+{
+ struct ndr_pull *subndr;
+ uint32_t r_content_size;
+ bool force_le = false;
+ bool force_be = false;
+
+ switch (header_size) {
+ case 0: {
+ uint32_t content_size = ndr->data_size - ndr->offset;
+ if (size_is >= 0) {
+ content_size = size_is;
+ }
+ r_content_size = content_size;
+ break;
+ }
+
+ case 2: {
+ uint16_t content_size;
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &content_size));
+ if (size_is >= 0 && size_is != content_size) {
+ return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) (0x%04x) mismatch content_size %d (0x%04x)",
+ (int)size_is, (int)size_is,
+ (int)content_size,
+ (int)content_size);
+ }
+ r_content_size = content_size;
+ break;
+ }
+
+ case 4: {
+ uint32_t content_size;
+ NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &content_size));
+ if (size_is >= 0 && size_is != content_size) {
+ return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) (0x%08x) mismatch content_size %d (0x%08x)",
+ (int)size_is, (int)size_is,
+ (int)content_size,
+ (int)content_size);
+ }
+ r_content_size = content_size;
+ break;
+ }
+ case 0xFFFFFC01: {
+ /*
+ * Common Type Header for the Serialization Stream
+ * See [MS-RPCE] 2.2.6 Type Serialization Version 1
+ */
+ uint8_t version;
+ uint8_t drep;
+ uint16_t hdrlen;
+ uint32_t filler;
+ uint32_t content_size;
+ uint32_t reserved;
+
+ /* version */
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &version));
+
+ if (version != 1) {
+ return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
+ "Bad subcontext (PULL) Common Type Header version %d != 1",
+ (int)version);
+ }
+
+ /*
+ * 0x10 little endian
+ * 0x00 big endian
+ */
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &drep));
+ if (drep == 0x10) {
+ force_le = true;
+ } else if (drep == 0x00) {
+ force_be = true;
+ } else {
+ return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
+ "Bad subcontext (PULL) Common Type Header invalid drep 0x%02X",
+ (unsigned int)drep);
+ }
+
+ /* length of the "Private Header for Constructed Type" */
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &hdrlen));
+ if (hdrlen != 8) {
+ return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
+ "Bad subcontext (PULL) Common Type Header length %d != 8",
+ (int)hdrlen);
+ }
+
+ /* filler should be ignored */
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &filler));
+
+ /*
+ * Private Header for Constructed Type
+ */
+ /* length - will be updated latter */
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &content_size));
+ if (size_is >= 0 && size_is != content_size) {
+ return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
+ (int)size_is, (int)content_size);
+ }
+ /* the content size must be a multiple of 8 */
+ if ((content_size % 8) != 0) {
+ return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
+ "Bad subcontext (PULL) size_is(%d) not padded to 8 content_size %d",
+ (int)size_is, (int)content_size);
+ }
+ r_content_size = content_size;
+
+ /* reserved */
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &reserved));
+ break;
+ }
+ case 0xFFFFFFFF:
+ /*
+ * a shallow copy like subcontext
+ * useful for DCERPC pipe chunks.
+ */
+ subndr = talloc_zero(ndr, struct ndr_pull);
+ NDR_ERR_HAVE_NO_MEMORY(subndr);
+
+ subndr->flags = ndr->flags;
+ subndr->current_mem_ctx = ndr->current_mem_ctx;
+ subndr->data = ndr->data;
+ subndr->offset = ndr->offset;
+ subndr->data_size = ndr->data_size;
+
+ *_subndr = subndr;
+ return NDR_ERR_SUCCESS;
+
+ default:
+ return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) header_size %d",
+ (int)header_size);
+ }
+
+ NDR_PULL_NEED_BYTES(ndr, r_content_size);
+
+ subndr = talloc_zero(ndr, struct ndr_pull);
+ NDR_ERR_HAVE_NO_MEMORY(subndr);
+ subndr->flags = ndr->flags & ~LIBNDR_FLAG_NDR64;
+ subndr->current_mem_ctx = ndr->current_mem_ctx;
+
+ subndr->data = ndr->data + ndr->offset;
+ subndr->offset = 0;
+ subndr->data_size = r_content_size;
+
+ if (force_le) {
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN);
+ } else if (force_be) {
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_BIGENDIAN);
+ }
+
+ *_subndr = subndr;
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_subcontext_end(struct ndr_pull *ndr,
+ struct ndr_pull *subndr,
+ size_t header_size,
+ ssize_t size_is)
+{
+ uint32_t advance;
+ uint32_t highest_ofs;
+
+ if (header_size == 0xFFFFFFFF) {
+ advance = subndr->offset - ndr->offset;
+ } else if (size_is >= 0) {
+ advance = size_is;
+ } else if (header_size > 0) {
+ advance = subndr->data_size;
+ } else {
+ advance = subndr->offset;
+ }
+
+ if (subndr->offset > ndr->relative_highest_offset) {
+ highest_ofs = subndr->offset;
+ } else {
+ highest_ofs = subndr->relative_highest_offset;
+ }
+ if (!(subndr->flags & LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES)) {
+ /*
+ * avoid an error unless SUBCONTEXT_NO_UNREAD_BYTES is specified
+ */
+ highest_ofs = advance;
+ }
+ if (highest_ofs < advance) {
+ return ndr_pull_error(subndr, NDR_ERR_UNREAD_BYTES,
+ "not all bytes consumed ofs[%u] advance[%u]",
+ highest_ofs, advance);
+ }
+
+ NDR_CHECK(ndr_pull_advance(ndr, advance));
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_subcontext_start(struct ndr_push *ndr,
+ struct ndr_push **_subndr,
+ size_t header_size,
+ ssize_t size_is)
+{
+ struct ndr_push *subndr;
+
+ subndr = ndr_push_init_ctx(ndr);
+ NDR_ERR_HAVE_NO_MEMORY(subndr);
+ subndr->flags = ndr->flags & ~LIBNDR_FLAG_NDR64;
+
+ if (size_is > 0) {
+ NDR_CHECK(ndr_push_zero(subndr, size_is));
+ subndr->offset = 0;
+ subndr->relative_end_offset = size_is;
+ }
+
+ *_subndr = subndr;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a subcontext header
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr,
+ struct ndr_push *subndr,
+ size_t header_size,
+ ssize_t size_is)
+{
+ ssize_t padding_len;
+
+ if (size_is >= 0) {
+ padding_len = size_is - subndr->offset;
+ if (padding_len < 0) {
+ return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)",
+ (int)subndr->offset, (int)size_is);
+ }
+ subndr->offset = size_is;
+ }
+
+ switch (header_size) {
+ case 0:
+ break;
+
+ case 2:
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, subndr->offset));
+ break;
+
+ case 4:
+ NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, subndr->offset));
+ break;
+
+ case 0xFFFFFC01:
+ /*
+ * Common Type Header for the Serialization Stream
+ * See [MS-RPCE] 2.2.6 Type Serialization Version 1
+ */
+ padding_len = NDR_ROUND(subndr->offset, 8) - subndr->offset;
+ if (padding_len > 0) {
+ NDR_CHECK(ndr_push_zero(subndr, padding_len));
+ }
+
+ /* version */
+ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, 1));
+
+ /*
+ * 0x10 little endian
+ * 0x00 big endian
+ */
+ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, NDR_BE(ndr)?0x00:0x10));
+
+ /* length of the "Private Header for Constructed Type" */
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 8));
+
+ /* filler */
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0xCCCCCCCC));
+
+ /*
+ * Private Header for Constructed Type
+ */
+ /* length - will be updated latter */
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, subndr->offset));
+
+ /* reserved */
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ break;
+
+ default:
+ return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext header size %d",
+ (int)header_size);
+ }
+
+ NDR_CHECK(ndr_push_bytes(ndr, subndr->data, subndr->offset));
+ return NDR_ERR_SUCCESS;
+}
+
+
+struct ndr_token {
+ const void *key;
+ uint32_t value;
+};
+
+/*
+ store a token in the ndr context, for later retrieval
+*/
+_PUBLIC_ enum ndr_err_code ndr_token_store(TALLOC_CTX *mem_ctx,
+ struct ndr_token_list *list,
+ const void *key,
+ uint32_t value)
+{
+ if (list->tokens == NULL) {
+ list->tokens = talloc_array(mem_ctx, struct ndr_token, 10);
+ if (list->tokens == NULL) {
+ NDR_ERR_HAVE_NO_MEMORY(list->tokens);
+ }
+ } else {
+ struct ndr_token *new_tokens = NULL;
+ uint32_t alloc_count = talloc_array_length(list->tokens);
+
+ /*
+ * Check every time we have not allocated too many
+ * tokens. This ensures developer sanity when
+ * debugging the boundary condition
+ */
+ if (list->count >= NDR_TOKEN_MAX_LIST_SIZE) {
+ return NDR_ERR_RANGE;
+ }
+ if (list->count == alloc_count) {
+ unsigned new_alloc;
+ /*
+ * Double the list, until we start in chunks
+ * of 1000
+ */
+ unsigned increment = MIN(list->count, 1000);
+ new_alloc = alloc_count + increment;
+ if (new_alloc < alloc_count) {
+ return NDR_ERR_RANGE;
+ }
+ new_tokens = talloc_realloc(mem_ctx, list->tokens,
+ struct ndr_token, new_alloc);
+ NDR_ERR_HAVE_NO_MEMORY(new_tokens);
+ list->tokens = new_tokens;
+ }
+ }
+ list->tokens[list->count].key = key;
+ list->tokens[list->count].value = value;
+ list->count++;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ retrieve a token from a ndr context, using cmp_fn to match the tokens
+*/
+_PUBLIC_ enum ndr_err_code ndr_token_retrieve_cmp_fn(struct ndr_token_list *list,
+ const void *key, uint32_t *v,
+ comparison_fn_t _cmp_fn,
+ bool erase)
+{
+ struct ndr_token *tokens = list->tokens;
+ unsigned i;
+ if (_cmp_fn) {
+ for (i = list->count - 1; i < list->count; i--) {
+ if (_cmp_fn(tokens[i].key, key) == 0) {
+ goto found;
+ }
+ }
+ } else {
+ for (i = list->count - 1; i < list->count; i--) {
+ if (tokens[i].key == key) {
+ goto found;
+ }
+ }
+ }
+ return NDR_ERR_TOKEN;
+found:
+ *v = tokens[i].value;
+ if (erase) {
+ if (i != list->count - 1) {
+ tokens[i] = tokens[list->count - 1];
+ }
+ list->count--;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ retrieve a token from a ndr context
+*/
+_PUBLIC_ enum ndr_err_code ndr_token_retrieve(struct ndr_token_list *list,
+ const void *key, uint32_t *v)
+{
+ return ndr_token_retrieve_cmp_fn(list, key, v, NULL, true);
+}
+
+/*
+ peek at but don't removed a token from a ndr context
+*/
+_PUBLIC_ enum ndr_err_code ndr_token_peek(struct ndr_token_list *list,
+ const void *key, uint32_t *v)
+{
+ return ndr_token_retrieve_cmp_fn(list, key, v, NULL, false);
+}
+
+/*
+ pull an array size field and add it to the array_size_list token list
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_array_size(struct ndr_pull *ndr, const void *p)
+{
+ enum ndr_err_code ret;
+ uint32_t size;
+ NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &size));
+ ret = ndr_token_store(ndr, &ndr->array_size_list, p, size);
+ if (ret == NDR_ERR_RANGE) {
+ return ndr_pull_error(ndr, ret,
+ "More than %d NDR tokens stored for array_size",
+ NDR_TOKEN_MAX_LIST_SIZE);
+ }
+ return ret;
+}
+
+/*
+ get the stored array size field
+*/
+_PUBLIC_ enum ndr_err_code ndr_get_array_size(struct ndr_pull *ndr, const void *p, uint32_t *size)
+{
+ return ndr_token_peek(&ndr->array_size_list, p, size);
+}
+
+/*
+ get and remove from the stored list the stored array size field
+*/
+_PUBLIC_ enum ndr_err_code ndr_steal_array_size(struct ndr_pull *ndr, const void *p, uint32_t *size)
+{
+ return ndr_token_retrieve(&ndr->array_size_list, p, size);
+}
+
+/*
+ * check the stored array size field and remove from the stored list
+ * (the array_size NDR token list). We try to remove when possible to
+ * avoid the list growing towards the bounds check
+ */
+_PUBLIC_ enum ndr_err_code ndr_check_steal_array_size(struct ndr_pull *ndr, const void *p, uint32_t size)
+{
+ uint32_t stored;
+ NDR_CHECK(ndr_steal_array_size(ndr, p, &stored));
+ if (stored != size) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
+ "Bad array size - got %u expected %u\n",
+ stored, size);
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ * check the stored array size field (leaving it on the array_size
+ * token list)
+ */
+_PUBLIC_ enum ndr_err_code ndr_check_array_size(struct ndr_pull *ndr, const void *p, uint32_t size)
+{
+ uint32_t stored;
+ NDR_CHECK(ndr_get_array_size(ndr, p, &stored));
+ if (stored != size) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
+ "Bad array size - got %u expected %u\n",
+ stored, size);
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ pull an array length field and add it to the array_length_list token list
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_array_length(struct ndr_pull *ndr, const void *p)
+{
+ enum ndr_err_code ret;
+ uint32_t length, offset;
+ NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &offset));
+ if (offset != 0) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
+ "non-zero array offset %u\n", offset);
+ }
+ NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &length));
+ ret = ndr_token_store(ndr, &ndr->array_length_list, p, length);
+ if (ret == NDR_ERR_RANGE) {
+ return ndr_pull_error(ndr, ret,
+ "More than %d NDR tokens stored for array_length_list",
+ NDR_TOKEN_MAX_LIST_SIZE);
+ }
+ return ret;
+}
+
+/*
+ get the stored array length field
+*/
+_PUBLIC_ enum ndr_err_code ndr_get_array_length(struct ndr_pull *ndr, const void *p, uint32_t *length)
+{
+ return ndr_token_peek(&ndr->array_length_list, p, length);
+}
+
+/*
+ * check the stored array length field and remove from the stored list
+ * (the array_size NDR token list). We try to remove when possible to
+ * avoid the list growing towards the bounds check
+ */
+_PUBLIC_ enum ndr_err_code ndr_steal_array_length(struct ndr_pull *ndr, const void *p, uint32_t *length)
+{
+ return ndr_token_retrieve(&ndr->array_length_list, p, length);
+}
+/*
+ check the stored array length field, removing it from the list
+*/
+_PUBLIC_ enum ndr_err_code ndr_check_steal_array_length(struct ndr_pull *ndr, const void *p, uint32_t length)
+{
+ uint32_t stored;
+ NDR_CHECK(ndr_steal_array_length(ndr, p, &stored));
+ if (stored != length) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
+ "Bad array length - got %u expected %u\n",
+ stored, length);
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_pipe_chunk_trailer(struct ndr_push *ndr, int ndr_flags, uint32_t count)
+{
+ if (ndr->flags & LIBNDR_FLAG_NDR64) {
+ int64_t tmp = 0 - (int64_t)count;
+ uint64_t ncount = tmp;
+
+ NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, ncount));
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_check_pipe_chunk_trailer(struct ndr_pull *ndr, int ndr_flags, uint32_t count)
+{
+ if (ndr->flags & LIBNDR_FLAG_NDR64) {
+ int64_t tmp = 0 - (int64_t)count;
+ uint64_t ncount1 = tmp;
+ uint64_t ncount2;
+
+ NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &ncount2));
+ if (ncount1 == ncount2) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
+ "Bad pipe trailer[%lld should be %lld] size was %lu\"",
+ (unsigned long long)ncount2,
+ (unsigned long long)ncount1,
+ (unsigned long)count);
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ store a switch value
+ */
+_PUBLIC_ enum ndr_err_code ndr_push_set_switch_value(struct ndr_push *ndr, const void *p, uint32_t val)
+{
+ enum ndr_err_code ret =
+ ndr_token_store(ndr, &ndr->switch_list, p, val);
+ if (ret == NDR_ERR_RANGE) {
+ return ndr_push_error(ndr, ret,
+ "More than %d NDR tokens stored for switch_list",
+ NDR_TOKEN_MAX_LIST_SIZE);
+ }
+ return ret;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_set_switch_value(struct ndr_pull *ndr, const void *p, uint32_t val)
+{
+
+ enum ndr_err_code ret =
+ ndr_token_store(ndr, &ndr->switch_list, p, val);
+ if (ret == NDR_ERR_RANGE) {
+ return ndr_pull_error(ndr, ret,
+ "More than %d NDR tokens stored for switch_list",
+ NDR_TOKEN_MAX_LIST_SIZE);
+ }
+ return ret;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_print_set_switch_value(struct ndr_print *ndr, const void *p, uint32_t val)
+{
+ return ndr_token_store(ndr, &ndr->switch_list, p, val);
+}
+
+/* retrieve a switch value (for push) and remove it from the list */
+_PUBLIC_ enum ndr_err_code ndr_push_steal_switch_value(struct ndr_push *ndr,
+ const void *p,
+ uint32_t *v)
+{
+ return ndr_token_retrieve(&ndr->switch_list, p, v);
+}
+
+/* retrieve a switch value and remove it from the list */
+_PUBLIC_ uint32_t ndr_print_steal_switch_value(struct ndr_print *ndr, const void *p)
+{
+ enum ndr_err_code status;
+ uint32_t v;
+
+ status = ndr_token_retrieve(&ndr->switch_list, p, &v);
+ if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
+ return 0;
+ }
+
+ return v;
+}
+
+/* retrieve a switch value and remove it from the list */
+_PUBLIC_ enum ndr_err_code ndr_pull_steal_switch_value(struct ndr_pull *ndr,
+ const void *p,
+ uint32_t *v)
+{
+ return ndr_token_retrieve(&ndr->switch_list, p, v);
+}
+
+/*
+ pull a struct from a blob using NDR
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
+ ndr_pull_flags_fn_t fn)
+{
+ struct ndr_pull *ndr;
+ ndr = ndr_pull_init_blob(blob, mem_ctx);
+ NDR_ERR_HAVE_NO_MEMORY(ndr);
+ NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
+ talloc_free(ndr);
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ pull a struct from a blob using NDR - failing if all bytes are not consumed
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
+ void *p, ndr_pull_flags_fn_t fn)
+{
+ struct ndr_pull *ndr;
+ uint32_t highest_ofs;
+ ndr = ndr_pull_init_blob(blob, mem_ctx);
+ NDR_ERR_HAVE_NO_MEMORY(ndr);
+ NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
+ if (ndr->offset > ndr->relative_highest_offset) {
+ highest_ofs = ndr->offset;
+ } else {
+ highest_ofs = ndr->relative_highest_offset;
+ }
+ if (highest_ofs < ndr->data_size) {
+ enum ndr_err_code ret;
+ ret = ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
+ "not all bytes consumed ofs[%u] size[%u]",
+ highest_ofs, ndr->data_size);
+ talloc_free(ndr);
+ return ret;
+ }
+ talloc_free(ndr);
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ pull a struct from a blob using NDR - failing if all bytes are not consumed
+
+ This only works for structures with NO allocated memory, like
+ objectSID and GUID. This helps because we parse these a lot.
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all_noalloc(const DATA_BLOB *blob,
+ void *p, ndr_pull_flags_fn_t fn)
+{
+ /*
+ * We init this structure on the stack here, to avoid a
+ * talloc() as otherwise this call to the fn() is assured not
+ * to be doing any allocation, eg SIDs and GUIDs.
+ *
+ * This allows us to keep the safety of the PIDL-generated
+ * code without the talloc() overhead.
+ */
+ struct ndr_pull ndr = {
+ .data = blob->data,
+ .data_size = blob->length,
+ .current_mem_ctx = (void *)-1
+ };
+ uint32_t highest_ofs;
+ NDR_CHECK(fn(&ndr, NDR_SCALARS|NDR_BUFFERS, p));
+ highest_ofs = MAX(ndr.offset, ndr.relative_highest_offset);
+ if (highest_ofs < ndr.data_size) {
+ enum ndr_err_code ret;
+ ret = ndr_pull_error(
+ &ndr,
+ NDR_ERR_UNREAD_BYTES,
+ "not all bytes consumed ofs[%"PRIu32"] "
+ "size[%"PRIu32"]",
+ highest_ofs,
+ ndr.data_size);
+ return ret;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ pull a union from a blob using NDR, given the union discriminator
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
+ void *p,
+ uint32_t level, ndr_pull_flags_fn_t fn)
+{
+ struct ndr_pull *ndr;
+ ndr = ndr_pull_init_blob(blob, mem_ctx);
+ NDR_ERR_HAVE_NO_MEMORY(ndr);
+ NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr, p, level));
+ NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
+ talloc_free(ndr);
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ pull a union from a blob using NDR, given the union discriminator,
+ failing if all bytes are not consumed
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_union_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
+ void *p,
+ uint32_t level, ndr_pull_flags_fn_t fn)
+{
+ struct ndr_pull *ndr;
+ uint32_t highest_ofs;
+ ndr = ndr_pull_init_blob(blob, mem_ctx);
+ NDR_ERR_HAVE_NO_MEMORY(ndr);
+ NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr, p, level));
+ NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
+ if (ndr->offset > ndr->relative_highest_offset) {
+ highest_ofs = ndr->offset;
+ } else {
+ highest_ofs = ndr->relative_highest_offset;
+ }
+ if (highest_ofs < ndr->data_size) {
+ enum ndr_err_code ret;
+ ret = ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
+ "not all bytes consumed ofs[%u] size[%u]",
+ highest_ofs, ndr->data_size);
+ talloc_free(ndr);
+ return ret;
+ }
+ talloc_free(ndr);
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a struct to a blob using NDR
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, const void *p, ndr_push_flags_fn_t fn)
+{
+ struct ndr_push *ndr;
+ ndr = ndr_push_init_ctx(mem_ctx);
+ NDR_ERR_HAVE_NO_MEMORY(ndr);
+
+ NDR_CHECK(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
+
+ *blob = ndr_push_blob(ndr);
+ talloc_steal(mem_ctx, blob->data);
+ talloc_free(ndr);
+
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a struct into a provided blob using NDR.
+
+ We error because we want to have the performance issue (extra
+ talloc() calls) show up as an error, not just slower code. This is
+ used for things like GUIDs, which we expect to be a fixed size, and
+ SIDs that we can pre-calculate the size for.
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_struct_into_fixed_blob(
+ DATA_BLOB *blob, const void *p, ndr_push_flags_fn_t fn)
+{
+ struct ndr_push ndr = {
+ .data = blob->data,
+ .alloc_size = blob->length,
+ .fixed_buf_size = true
+ };
+
+ NDR_CHECK(fn(&ndr, NDR_SCALARS|NDR_BUFFERS, p));
+
+ if (ndr.offset != blob->length) {
+ return ndr_push_error(&ndr, NDR_ERR_BUFSIZE,
+ "buffer was either to large or small "
+ "ofs[%u] size[%zu]",
+ ndr.offset, blob->length);
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a union to a blob using NDR
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
+ uint32_t level, ndr_push_flags_fn_t fn)
+{
+ struct ndr_push *ndr;
+ ndr = ndr_push_init_ctx(mem_ctx);
+ NDR_ERR_HAVE_NO_MEMORY(ndr);
+
+ NDR_CHECK(ndr_push_set_switch_value(ndr, p, level));
+ NDR_CHECK(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
+
+ *blob = ndr_push_blob(ndr);
+ talloc_steal(mem_ctx, blob->data);
+ talloc_free(ndr);
+
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ generic ndr_size_*() handler for structures
+*/
+_PUBLIC_ size_t ndr_size_struct(const void *p, int flags, ndr_push_flags_fn_t push)
+{
+ struct ndr_push *ndr;
+ enum ndr_err_code status;
+ size_t ret;
+
+ /* avoid recursion */
+ if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
+
+ /* Avoid following a NULL pointer */
+ if (p == NULL) {
+ return 0;
+ }
+
+ ndr = ndr_push_init_ctx(NULL);
+ if (!ndr) return 0;
+ ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
+ status = push(ndr, NDR_SCALARS|NDR_BUFFERS, discard_const(p));
+ if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
+ talloc_free(ndr);
+ return 0;
+ }
+ ret = ndr->offset;
+ talloc_free(ndr);
+ return ret;
+}
+
+/*
+ generic ndr_size_*() handler for unions
+*/
+_PUBLIC_ size_t ndr_size_union(const void *p, int flags, uint32_t level, ndr_push_flags_fn_t push)
+{
+ struct ndr_push *ndr;
+ enum ndr_err_code status;
+ size_t ret;
+
+ /* avoid recursion */
+ if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
+
+ /* Avoid following a NULL pointer */
+ if (p == NULL) {
+ return 0;
+ }
+
+ ndr = ndr_push_init_ctx(NULL);
+ if (!ndr) return 0;
+ ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
+
+ status = ndr_push_set_switch_value(ndr, p, level);
+ if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
+ talloc_free(ndr);
+ return 0;
+ }
+ status = push(ndr, NDR_SCALARS|NDR_BUFFERS, p);
+ if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
+ talloc_free(ndr);
+ return 0;
+ }
+ ret = ndr->offset;
+ talloc_free(ndr);
+ return ret;
+}
+
+/*
+ get the current base for relative pointers for the push
+*/
+_PUBLIC_ uint32_t ndr_push_get_relative_base_offset(struct ndr_push *ndr)
+{
+ return ndr->relative_base_offset;
+}
+
+/*
+ restore the old base for relative pointers for the push
+*/
+_PUBLIC_ void ndr_push_restore_relative_base_offset(struct ndr_push *ndr, uint32_t offset)
+{
+ ndr->relative_base_offset = offset;
+}
+
+/*
+ setup the current base for relative pointers for the push
+ called in the NDR_SCALAR stage
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_setup_relative_base_offset1(struct ndr_push *ndr, const void *p, uint32_t offset)
+{
+ enum ndr_err_code ret;
+ ndr->relative_base_offset = offset;
+ ret = ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
+ if (ret == NDR_ERR_RANGE) {
+ return ndr_push_error(ndr, ret,
+ "More than %d NDR tokens stored for relative_base_list",
+ NDR_TOKEN_MAX_LIST_SIZE);
+ }
+ return ret;
+}
+
+/*
+ setup the current base for relative pointers for the push
+ called in the NDR_BUFFERS stage
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_setup_relative_base_offset2(struct ndr_push *ndr, const void *p)
+{
+ return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
+}
+
+/*
+ push a relative object - stage1
+ this is called during SCALARS processing
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_relative_ptr1(struct ndr_push *ndr, const void *p)
+{
+ enum ndr_err_code ret;
+ if (p == NULL) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ return NDR_ERR_SUCCESS;
+ }
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ ret = ndr_token_store(ndr, &ndr->relative_list, p, ndr->offset);
+ if (ret == NDR_ERR_RANGE) {
+ return ndr_push_error(ndr, ret,
+ "More than %d NDR tokens stored for relative_list",
+ NDR_TOKEN_MAX_LIST_SIZE);
+ }
+ NDR_CHECK(ret);
+ return ndr_push_uint32(ndr, NDR_SCALARS, 0xFFFFFFFF);
+}
+
+/*
+ push a short relative object - stage1
+ this is called during SCALARS processing
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr1(struct ndr_push *ndr, const void *p)
+{
+ enum ndr_err_code ret;
+ if (p == NULL) {
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 0));
+ return NDR_ERR_SUCCESS;
+ }
+ NDR_CHECK(ndr_push_align(ndr, 2));
+ ret = ndr_token_store(ndr, &ndr->relative_list, p, ndr->offset);
+ if (ret == NDR_ERR_RANGE) {
+ return ndr_push_error(ndr, ret,
+ "More than %d NDR tokens stored for relative_list",
+ NDR_TOKEN_MAX_LIST_SIZE);
+ }
+ NDR_CHECK(ret);
+ return ndr_push_uint16(ndr, NDR_SCALARS, 0xFFFF);
+}
+/*
+ push a relative object - stage2
+ this is called during buffers processing
+*/
+static enum ndr_err_code ndr_push_relative_ptr2(struct ndr_push *ndr, const void *p)
+{
+ uint32_t save_offset;
+ uint32_t ptr_offset = 0xFFFFFFFF;
+ if (p == NULL) {
+ return NDR_ERR_SUCCESS;
+ }
+ save_offset = ndr->offset;
+ NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset));
+ if (ptr_offset > ndr->offset) {
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
+ "ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
+ ptr_offset, ndr->offset);
+ }
+ ndr->offset = ptr_offset;
+ if (save_offset < ndr->relative_base_offset) {
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
+ "ndr_push_relative_ptr2 save_offset(%u) < ndr->relative_base_offset(%u)",
+ save_offset, ndr->relative_base_offset);
+ }
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, save_offset - ndr->relative_base_offset));
+ ndr->offset = save_offset;
+ return NDR_ERR_SUCCESS;
+}
+/*
+ push a short relative object - stage2
+ this is called during buffers processing
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr2(struct ndr_push *ndr, const void *p)
+{
+ uint32_t save_offset;
+ uint32_t ptr_offset = 0xFFFF;
+ uint32_t relative_offset;
+ size_t pad;
+ size_t align = 1;
+
+ if (p == NULL) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ if (ndr->offset < ndr->relative_base_offset) {
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
+ "ndr_push_relative_ptr2 ndr->offset(%u) < ndr->relative_base_offset(%u)",
+ ndr->offset, ndr->relative_base_offset);
+ }
+
+ relative_offset = ndr->offset - ndr->relative_base_offset;
+
+ if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
+ align = 1;
+ } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
+ align = 2;
+ } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
+ align = 4;
+ } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
+ align = 8;
+ }
+
+ pad = ndr_align_size(relative_offset, align);
+ if (pad != 0) {
+ NDR_CHECK(ndr_push_zero(ndr, pad));
+ }
+
+ relative_offset = ndr->offset - ndr->relative_base_offset;
+ if (relative_offset > UINT16_MAX) {
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
+ "ndr_push_relative_ptr2 relative_offset(%u) > UINT16_MAX",
+ relative_offset);
+ }
+
+ save_offset = ndr->offset;
+ NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset));
+ if (ptr_offset > ndr->offset) {
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
+ "ndr_push_short_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
+ ptr_offset, ndr->offset);
+ }
+ ndr->offset = ptr_offset;
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, relative_offset));
+ ndr->offset = save_offset;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a relative object - stage2 start
+ this is called during buffers processing
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_start(struct ndr_push *ndr, const void *p)
+{
+ enum ndr_err_code ret;
+ if (p == NULL) {
+ return NDR_ERR_SUCCESS;
+ }
+ if (!(ndr->flags & LIBNDR_FLAG_RELATIVE_REVERSE)) {
+ uint32_t relative_offset;
+ size_t pad;
+ size_t align = 1;
+
+ if (ndr->offset < ndr->relative_base_offset) {
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
+ "ndr_push_relative_ptr2_start ndr->offset(%u) < ndr->relative_base_offset(%u)",
+ ndr->offset, ndr->relative_base_offset);
+ }
+
+ relative_offset = ndr->offset - ndr->relative_base_offset;
+
+ if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
+ align = 1;
+ } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
+ align = 2;
+ } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
+ align = 4;
+ } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
+ align = 8;
+ }
+
+ pad = ndr_align_size(relative_offset, align);
+ if (pad) {
+ NDR_CHECK(ndr_push_zero(ndr, pad));
+ }
+
+ return ndr_push_relative_ptr2(ndr, p);
+ }
+ if (ndr->relative_end_offset == -1) {
+ return ndr_push_error(ndr, NDR_ERR_RELATIVE,
+ "ndr_push_relative_ptr2_start RELATIVE_REVERSE flag set and relative_end_offset %d",
+ ndr->relative_end_offset);
+ }
+ ret = ndr_token_store(ndr,
+ &ndr->relative_begin_list,
+ p,
+ ndr->offset);
+ if (ret == NDR_ERR_RANGE) {
+ return ndr_push_error(ndr, ret,
+ "More than %d NDR tokens stored for array_size",
+ NDR_TOKEN_MAX_LIST_SIZE);
+ }
+ return ret;
+}
+
+/*
+ push a relative object - stage2 end
+ this is called during buffers processing
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_end(struct ndr_push *ndr, const void *p)
+{
+ uint32_t begin_offset = 0xFFFFFFFF;
+ ssize_t len;
+ uint32_t correct_offset = 0;
+ uint32_t align = 1;
+ uint32_t pad = 0;
+
+ if (p == NULL) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ if (!(ndr->flags & LIBNDR_FLAG_RELATIVE_REVERSE)) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ if (ndr->flags & LIBNDR_FLAG_NO_NDR_SIZE) {
+ /* better say more than calculation a too small buffer */
+ NDR_PUSH_ALIGN(ndr, 8);
+ return NDR_ERR_SUCCESS;
+ }
+
+ if (ndr->relative_end_offset < ndr->offset) {
+ return ndr_push_error(ndr, NDR_ERR_RELATIVE,
+ "ndr_push_relative_ptr2_end:"
+ "relative_end_offset %u < offset %u",
+ ndr->relative_end_offset, ndr->offset);
+ }
+
+ NDR_CHECK(ndr_token_retrieve(&ndr->relative_begin_list, p, &begin_offset));
+
+ /* we have marshalled a buffer, see how long it was */
+ len = ndr->offset - begin_offset;
+
+ if (len < 0) {
+ return ndr_push_error(ndr, NDR_ERR_RELATIVE,
+ "ndr_push_relative_ptr2_end:"
+ "offset %u - begin_offset %u < 0",
+ ndr->offset, begin_offset);
+ }
+
+ if (ndr->relative_end_offset < len) {
+ return ndr_push_error(ndr, NDR_ERR_RELATIVE,
+ "ndr_push_relative_ptr2_end:"
+ "relative_end_offset %u < len %lld",
+ ndr->offset, (long long)len);
+ }
+
+ /* the reversed offset is at the end of the main buffer */
+ correct_offset = ndr->relative_end_offset - len;
+
+ if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
+ align = 1;
+ } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
+ align = 2;
+ } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
+ align = 4;
+ } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
+ align = 8;
+ }
+
+ pad = ndr_align_size(correct_offset, align);
+ if (pad) {
+ correct_offset += pad;
+ correct_offset -= align;
+ }
+
+ if (correct_offset < begin_offset) {
+ return ndr_push_error(ndr, NDR_ERR_RELATIVE,
+ "ndr_push_relative_ptr2_end: "
+ "correct_offset %u < begin_offset %u",
+ correct_offset, begin_offset);
+ }
+
+ if (len > 0) {
+ uint32_t clear_size = correct_offset - begin_offset;
+
+ clear_size = MIN(clear_size, len);
+
+ /* now move the marshalled buffer to the end of the main buffer */
+ memmove(ndr->data + correct_offset, ndr->data + begin_offset, len);
+
+ if (clear_size) {
+ /* and wipe out old buffer within the main buffer */
+ memset(ndr->data + begin_offset, '\0', clear_size);
+ }
+ }
+
+ /* and set the end offset for the next buffer */
+ ndr->relative_end_offset = correct_offset;
+
+ /* finally write the offset to the main buffer */
+ ndr->offset = correct_offset;
+ NDR_CHECK(ndr_push_relative_ptr2(ndr, p));
+
+ /* restore to where we were in the main buffer */
+ ndr->offset = begin_offset;
+
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ get the current base for relative pointers for the pull
+*/
+_PUBLIC_ uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull *ndr)
+{
+ return ndr->relative_base_offset;
+}
+
+/*
+ restore the old base for relative pointers for the pull
+*/
+_PUBLIC_ void ndr_pull_restore_relative_base_offset(struct ndr_pull *ndr, uint32_t offset)
+{
+ ndr->relative_base_offset = offset;
+}
+
+/*
+ setup the current base for relative pointers for the pull
+ called in the NDR_SCALAR stage
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_setup_relative_base_offset1(struct ndr_pull *ndr, const void *p, uint32_t offset)
+{
+ enum ndr_err_code ret;
+ ndr->relative_base_offset = offset;
+ ret = ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
+ if (ret == NDR_ERR_RANGE) {
+ return ndr_pull_error(ndr, ret,
+ "More than %d NDR tokens stored for relative_base_list",
+ NDR_TOKEN_MAX_LIST_SIZE);
+ }
+ return ret;
+}
+
+/*
+ setup the current base for relative pointers for the pull
+ called in the NDR_BUFFERS stage
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_setup_relative_base_offset2(struct ndr_pull *ndr, const void *p)
+{
+ return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
+}
+
+/*
+ pull a relative object - stage1
+ called during SCALARS processing
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr1(struct ndr_pull *ndr, const void *p, uint32_t rel_offset)
+{
+ enum ndr_err_code ret;
+ rel_offset += ndr->relative_base_offset;
+ if (rel_offset > ndr->data_size) {
+ return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
+ "ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u)",
+ rel_offset, ndr->data_size);
+ }
+ ret = ndr_token_store(ndr, &ndr->relative_list, p, rel_offset);
+ if (ret == NDR_ERR_RANGE) {
+ return ndr_pull_error(ndr, ret,
+ "More than %d NDR tokens stored for relative_list",
+ NDR_TOKEN_MAX_LIST_SIZE);
+ }
+ return ret;
+}
+
+/*
+ pull a relative object - stage2
+ called during BUFFERS processing
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr2(struct ndr_pull *ndr, const void *p)
+{
+ uint32_t rel_offset;
+ NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &rel_offset));
+ return ndr_pull_set_offset(ndr, rel_offset);
+}
+
+static const struct {
+ enum ndr_err_code err;
+ const char *string;
+} ndr_err_code_strings[] = {
+ { NDR_ERR_SUCCESS, "Success" },
+ { NDR_ERR_ARRAY_SIZE, "Bad Array Size" },
+ { NDR_ERR_BAD_SWITCH, "Bad Switch" },
+ { NDR_ERR_OFFSET, "Offset Error" },
+ { NDR_ERR_RELATIVE, "Relative Pointer Error" },
+ { NDR_ERR_CHARCNV, "Character Conversion Error" },
+ { NDR_ERR_LENGTH, "Length Error" },
+ { NDR_ERR_SUBCONTEXT, "Subcontext Error" },
+ { NDR_ERR_COMPRESSION, "Compression Error" },
+ { NDR_ERR_STRING, "String Error" },
+ { NDR_ERR_VALIDATE, "Validate Error" },
+ { NDR_ERR_BUFSIZE, "Buffer Size Error" },
+ { NDR_ERR_ALLOC, "Allocation Error" },
+ { NDR_ERR_RANGE, "Range Error" },
+ { NDR_ERR_TOKEN, "Token Error" },
+ { NDR_ERR_IPV4ADDRESS, "IPv4 Address Error" },
+ { NDR_ERR_INVALID_POINTER, "Invalid Pointer" },
+ { NDR_ERR_UNREAD_BYTES, "Unread Bytes" },
+ { NDR_ERR_NDR64, "NDR64 assertion error" },
+ { NDR_ERR_INCOMPLETE_BUFFER, "Incomplete Buffer" },
+ { NDR_ERR_MAX_RECURSION_EXCEEDED, "Maximum Recursion Exceeded" },
+ { NDR_ERR_UNDERFLOW, "Underflow" },
+ { 0, NULL }
+};
+
+_PUBLIC_ const char *ndr_map_error2string(enum ndr_err_code ndr_err)
+{
+ int i;
+ for (i = 0; ndr_err_code_strings[i].string != NULL; i++) {
+ if (ndr_err_code_strings[i].err == ndr_err)
+ return ndr_err_code_strings[i].string;
+ }
+ return "Unknown error";
+}
diff --git a/librpc/ndr/ndr_ODJ.c b/librpc/ndr/ndr_ODJ.c
new file mode 100644
index 0000000..86630b8
--- /dev/null
+++ b/librpc/ndr/ndr_ODJ.c
@@ -0,0 +1,65 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling special ODJ structures
+
+ Copyright (C) Guenther Deschner 2021
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "../librpc/gen_ndr/ndr_ODJ.h"
+#include "../librpc/ndr/ndr_ODJ.h"
+
+uint32_t odj_switch_level_from_guid(const struct GUID *r)
+{
+ struct {
+ uint16_t level;
+ const char *guid;
+ } levels[] = {
+ {
+ .level = 1,
+ .guid = ODJ_GUID_JOIN_PROVIDER
+ },{
+ .level = 2,
+ .guid = ODJ_GUID_JOIN_PROVIDER2
+ },{
+ .level = 3,
+ .guid = ODJ_GUID_JOIN_PROVIDER3
+ },{
+ .level = 4,
+ .guid = ODJ_GUID_CERT_PROVIDER
+ },{
+ .level = 5,
+ .guid = ODJ_GUID_POLICY_PROVIDER
+ }
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(levels); i++) {
+ struct GUID guid;
+ NTSTATUS status;
+
+ status = GUID_from_string(levels[i].guid, &guid);
+ if (!NT_STATUS_IS_OK(status)) {
+ return 0;
+ }
+ if (GUID_equal(&guid, r)) {
+ return levels[i].level;
+ }
+ }
+
+ return 0;
+}
diff --git a/librpc/ndr/ndr_ODJ.h b/librpc/ndr/ndr_ODJ.h
new file mode 100644
index 0000000..f57f2d7
--- /dev/null
+++ b/librpc/ndr/ndr_ODJ.h
@@ -0,0 +1,22 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling special ODJ structures
+
+ Copyright (C) Guenther Deschner 2021
+
+ 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/>.
+*/
+
+uint32_t odj_switch_level_from_guid(const struct GUID *r);
diff --git a/librpc/ndr/ndr_auth.c b/librpc/ndr/ndr_auth.c
new file mode 100644
index 0000000..5252d80
--- /dev/null
+++ b/librpc/ndr/ndr_auth.c
@@ -0,0 +1,44 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Helper routines for marshalling the internal 'auth.idl'
+
+ Copyright (C) Andrew Bartlett 2011
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/ndr/ndr_auth.h"
+#include "librpc/ndr/libndr.h"
+
+_PUBLIC_ void ndr_print_cli_credentials(struct ndr_print *ndr, const char *name, struct cli_credentials *v)
+{
+ ndr->print(ndr, "%-25s: NULL", name);
+}
+
+/*
+ cli_credentials does not have a network representation, just pull/push a NULL pointer
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_cli_credentials(struct ndr_pull *ndr, int ndr_flags, struct cli_credentials *v)
+{
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_cli_credentials(struct ndr_push *ndr, int ndr_flags, struct cli_credentials *v)
+{
+ return ndr_push_pointer(ndr, ndr_flags, NULL);
+}
+
+
diff --git a/librpc/ndr/ndr_auth.h b/librpc/ndr/ndr_auth.h
new file mode 100644
index 0000000..57f6535
--- /dev/null
+++ b/librpc/ndr/ndr_auth.h
@@ -0,0 +1,32 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Helper routines for marshalling the internal 'auth.idl'
+
+ Copyright (C) Andrew Bartlett 2011
+
+ 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/>.
+*/
+
+/*
+ cli_credentials does not have a network representation, just pull/push a NULL pointer
+*/
+
+#include "librpc/gen_ndr/ndr_auth.h"
+
+struct cli_credentials;
+_PUBLIC_ enum ndr_err_code ndr_pull_cli_credentials(struct ndr_pull *ndr, int ndr_flags, struct cli_credentials *v);
+_PUBLIC_ enum ndr_err_code ndr_push_cli_credentials(struct ndr_push *ndr, int ndr_flags, struct cli_credentials *v);
+
+_PUBLIC_ void ndr_print_cli_credentials(struct ndr_print *ndr, const char *name, struct cli_credentials *v);
diff --git a/librpc/ndr/ndr_backupkey.c b/librpc/ndr/ndr_backupkey.c
new file mode 100644
index 0000000..adb6e39
--- /dev/null
+++ b/librpc/ndr/ndr_backupkey.c
@@ -0,0 +1,222 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for top backup key protocol marshalling/unmarshalling
+
+ Copyright (C) Matthieu Patou 2010
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_misc.h"
+#include "librpc/gen_ndr/ndr_backupkey.h"
+#include "librpc/gen_ndr/ndr_security.h"
+
+static uint32_t backupkeyguid_to_uint(const struct GUID *guid)
+{
+ struct GUID tmp;
+ NTSTATUS status;
+ bool match;
+
+ status = GUID_from_string(BACKUPKEY_RESTORE_GUID, &tmp);
+ if (NT_STATUS_IS_OK(status)) {
+ match = GUID_equal(guid, &tmp);
+ if (match) {
+ return BACKUPKEY_RESTORE_GUID_INTEGER;
+ }
+ }
+
+ status = GUID_from_string(BACKUPKEY_RETRIEVE_BACKUP_KEY_GUID, &tmp);
+ if (NT_STATUS_IS_OK(status)) {
+ match = GUID_equal(guid, &tmp);
+ if (match) {
+ return BACKUPKEY_RETRIEVE_BACKUP_KEY_GUID_INTEGER;
+ }
+ }
+
+ return BACKUPKEY_INVALID_GUID_INTEGER;
+}
+
+_PUBLIC_ void ndr_print_bkrp_BackupKey(struct ndr_print *ndr, const char *name, int flags, const struct bkrp_BackupKey *r)
+{
+ ndr_print_struct(ndr, name, "bkrp_BackupKey");
+ if (r == NULL) { ndr_print_null(ndr); return; }
+ ndr->depth++;
+ if (flags & NDR_SET_VALUES) {
+ ndr->flags |= LIBNDR_PRINT_SET_VALUES;
+ }
+ if (flags & NDR_IN) {
+ union bkrp_data_in_blob inblob = {
+ .empty._empty_ = '\0',
+ };
+ DATA_BLOB blob;
+ uint32_t level;
+ enum ndr_err_code ndr_err;
+
+ ndr_print_struct(ndr, "in", "bkrp_BackupKey");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "guidActionAgent", r->in.guidActionAgent);
+ ndr->depth++;
+ ndr_print_GUID(ndr, "guidActionAgent", r->in.guidActionAgent);
+ ndr->depth--;
+
+ level = backupkeyguid_to_uint(r->in.guidActionAgent);
+ ndr_err = ndr_print_set_switch_value(ndr, &inblob, level);
+ if (unlikely(!NDR_ERR_CODE_IS_SUCCESS(ndr_err))) { \
+ DEBUG(0,("ERROR: ndr_print_bkrp_BackupKey ndr_print_set_switch_value failed: %d\n", ndr_err));
+ return;
+ }
+ blob.data = r->in.data_in;
+ blob.length = r->in.data_in_len;
+ ndr_err = ndr_pull_union_blob(&blob, ndr, &inblob, level,
+ (ndr_pull_flags_fn_t)ndr_pull_bkrp_data_in_blob);
+
+ ndr_print_ptr(ndr, "data_in", r->in.data_in);
+ ndr->depth++;
+ if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ ndr_print_bkrp_data_in_blob(ndr, "data_in", &inblob);
+ } else {
+ ndr_print_array_uint8(ndr, "data_in", r->in.data_in, r->in.data_in_len);
+ }
+ ndr->depth--;
+
+ ndr_print_uint32(ndr, "data_in_len", r->in.data_in_len);
+ ndr_print_uint32(ndr, "param", r->in.param);
+ ndr->depth--;
+ }
+ if (flags & NDR_OUT) {
+ ndr_print_struct(ndr, "out", "bkrp_BackupKey");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "data_out", r->out.data_out);
+ ndr->depth++;
+ ndr_print_ptr(ndr, "data_out", *r->out.data_out);
+ ndr->depth++;
+
+ if (*r->out.data_out) {
+ ndr_print_array_uint8(ndr, "data_out", *r->out.data_out, *r->out.data_out_len);
+ }
+ ndr->depth--;
+ ndr->depth--;
+ ndr_print_ptr(ndr, "data_out_len", r->out.data_out_len);
+ ndr->depth++;
+ ndr_print_uint32(ndr, "data_out_len", *r->out.data_out_len);
+ ndr->depth--;
+ ndr_print_WERROR(ndr, "result", r->out.result);
+ ndr->depth--;
+ }
+ ndr->depth--;
+}
+
+/* We have manual push/pull because we didn't manage to do the alignment
+ * purely in PIDL as the padding is sized so that the whole access_check_v3
+ * struct size is a multiple of 8 (as specified in 2.2.2.3 of ms-bkrp.pdf)
+ */
+_PUBLIC_ enum ndr_err_code ndr_push_bkrp_access_check_v2(struct ndr_push *ndr, int ndr_flags, const struct bkrp_access_check_v2 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ size_t ofs;
+ size_t pad;
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0x00000001));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->nonce_len));
+ NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->nonce, r->nonce_len));
+ NDR_CHECK(ndr_push_dom_sid(ndr, NDR_SCALARS, &r->sid));
+ /* We articially increment the offset of 20 bytes (size of hash
+ * comming after the pad) so that ndr_align can determine easily
+ * the correct pad size to make the whole struct 8 bytes aligned
+ */
+ ofs = ndr->offset + 20;
+ pad = ndr_align_size(ofs, 8);
+ NDR_CHECK(ndr_push_zero(ndr, pad));
+ NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->hash, 20));
+ NDR_CHECK(ndr_push_trailer_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_bkrp_access_check_v2(struct ndr_pull *ndr, int ndr_flags, struct bkrp_access_check_v2 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ size_t ofs;
+ size_t pad;
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->magic));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->nonce_len));
+ NDR_PULL_ALLOC_N(ndr, r->nonce, r->nonce_len);
+ NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->nonce, r->nonce_len));
+ NDR_CHECK(ndr_pull_dom_sid(ndr, NDR_SCALARS, &r->sid));
+ ofs = ndr->offset + 20;
+ pad = ndr_align_size(ofs, 8);
+ NDR_CHECK(ndr_pull_advance(ndr, pad));
+ NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->hash, 20));
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+/* We have manual push/pull because we didn't manage to do the alignment
+ * purely in PIDL as the padding is sized so that the whole access_check_v3
+ * struct size is a multiple of 16 (as specified in 2.2.2.4 of ms-bkrp.pdf)
+ */
+_PUBLIC_ enum ndr_err_code ndr_push_bkrp_access_check_v3(struct ndr_push *ndr, int ndr_flags, const struct bkrp_access_check_v3 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ size_t ofs;
+ size_t pad;
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0x00000001));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->nonce_len));
+ NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->nonce, r->nonce_len));
+ NDR_CHECK(ndr_push_dom_sid(ndr, NDR_SCALARS, &r->sid));
+ /* We articially increment the offset of 64 bytes (size of hash
+ * comming after the pad) so that ndr_align can determine easily
+ * the correct pad size to make the whole struct 16 bytes aligned
+ */
+ ofs = ndr->offset + 64;
+ pad = ndr_align_size(ofs, 16);
+ NDR_CHECK(ndr_push_zero(ndr, pad));
+ NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->hash, 64));
+ NDR_CHECK(ndr_push_trailer_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_bkrp_access_check_v3(struct ndr_pull *ndr, int ndr_flags, struct bkrp_access_check_v3 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ size_t ofs;
+ size_t pad;
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->magic));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->nonce_len));
+ NDR_PULL_ALLOC_N(ndr, r->nonce, r->nonce_len);
+ NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->nonce, r->nonce_len));
+ NDR_CHECK(ndr_pull_dom_sid(ndr, NDR_SCALARS, &r->sid));
+ ofs = ndr->offset + 64;
+ pad = ndr_align_size(ofs, 16);
+ NDR_CHECK(ndr_pull_advance(ndr, pad));
+ NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->hash, 64));
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_backupkey.h b/librpc/ndr/ndr_backupkey.h
new file mode 100644
index 0000000..4e82f62
--- /dev/null
+++ b/librpc/ndr/ndr_backupkey.h
@@ -0,0 +1,23 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for top backup key protocol marshalling/unmarshalling
+
+ Copyright (C) Matthieu Patou 2010
+
+ 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/>.
+*/
+
+_PUBLIC_ enum ndr_err_code ndr_push_bkrp_access_check_v2(struct ndr_push *ndr, int ndr_flags, const struct bkrp_access_check_v2 *r);
+_PUBLIC_ enum ndr_err_code ndr_pull_bkrp_access_check_v2(struct ndr_pull *ndr, int ndr_flags, struct bkrp_access_check_v2 *r);
diff --git a/librpc/ndr/ndr_basic.c b/librpc/ndr/ndr_basic.c
new file mode 100644
index 0000000..e239cfb
--- /dev/null
+++ b/librpc/ndr/ndr_basic.c
@@ -0,0 +1,1538 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling basic types
+
+ Copyright (C) Andrew Tridgell 2003
+
+ 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/>.
+*/
+
+#include "replace.h"
+#include "system/network.h"
+#include "librpc/ndr/libndr.h"
+#include "lib/util/util_net.h"
+#include "lib/util/debug.h"
+#include "lib/util/util.h"
+#include "lib/util/bytearray.h"
+
+#define NDR_PULL_U16(ndr, ofs) \
+ (NDR_BE(ndr) ? PULL_BE_U16(ndr->data,ofs) : PULL_LE_U16(ndr->data,ofs))
+
+#define NDR_PULL_U32(ndr, ofs) \
+ (NDR_BE(ndr) ? PULL_BE_U32(ndr->data,ofs) : PULL_LE_U32(ndr->data,ofs))
+
+#define NDR_PULL_I32(ndr, ofs) \
+ (int32_t)(NDR_BE(ndr) ? PULL_BE_U32(ndr->data,ofs) : PULL_LE_U32(ndr->data,ofs))
+
+#define NDR_PUSH_U16(ndr, ofs, v) \
+ do { \
+ if (NDR_BE(ndr)) { \
+ PUSH_BE_U16(ndr->data, ofs, v); \
+ } else { \
+ PUSH_LE_U16(ndr->data, ofs, v); \
+ } \
+ } while (0)
+
+#define NDR_PUSH_U32(ndr, ofs, v) \
+ do { \
+ if (NDR_BE(ndr)) { \
+ PUSH_BE_U32(ndr->data, ofs, v); \
+ } else { \
+ PUSH_LE_U32(ndr->data, ofs, v); \
+ } \
+ } while (0)
+
+#define NDR_PUSH_I32(ndr, ofs, v) \
+ do { \
+ if (NDR_BE(ndr)) { \
+ PUSH_BE_U32(ndr->data, ofs, v); \
+ } else { \
+ PUSH_LE_U32(ndr->data, ofs, v); \
+ } \
+ } while (0)
+
+static void ndr_dump_data(struct ndr_print *ndr, const uint8_t *buf, int len);
+
+/*
+ check for data leaks from the server by looking for non-zero pad bytes
+ these could also indicate that real structure elements have been
+ mistaken for padding in the IDL
+*/
+_PUBLIC_ void ndr_check_padding(struct ndr_pull *ndr, size_t n)
+{
+ size_t ofs2 = (ndr->offset + (n-1)) & ~(n-1);
+ size_t i;
+ for (i=ndr->offset;i<ofs2;i++) {
+ if (ndr->data[i] != 0) {
+ break;
+ }
+ }
+ if (i<ofs2) {
+ DEBUG(0,("WARNING: Non-zero padding to %d: ", (int)n));
+ for (i=ndr->offset;i<ofs2;i++) {
+ DEBUG(0,("%02x ", ndr->data[i]));
+ }
+ DEBUG(0,("\n"));
+ }
+
+}
+
+/*
+ parse a int8_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_int8(struct ndr_pull *ndr, int ndr_flags, int8_t *v)
+{
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PULL_NEED_BYTES(ndr, 1);
+ *v = (int8_t)PULL_BE_U8(ndr->data, ndr->offset);
+ ndr->offset += 1;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ parse a uint8_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *v)
+{
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PULL_NEED_BYTES(ndr, 1);
+ *v = PULL_BE_U8(ndr->data, ndr->offset);
+ ndr->offset += 1;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ parse a int16_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_int16(struct ndr_pull *ndr, int ndr_flags, int16_t *v)
+{
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PULL_ALIGN(ndr, 2);
+ NDR_PULL_NEED_BYTES(ndr, 2);
+ *v = (uint16_t)NDR_PULL_U16(ndr, ndr->offset);
+ ndr->offset += 2;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ parse a uint16_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
+{
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PULL_ALIGN(ndr, 2);
+ NDR_PULL_NEED_BYTES(ndr, 2);
+ *v = NDR_PULL_U16(ndr, ndr->offset);
+ ndr->offset += 2;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ parse a uint1632_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_uint1632(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
+{
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
+ uint32_t v32 = 0;
+ enum ndr_err_code err = ndr_pull_uint32(ndr, ndr_flags, &v32);
+ *v = v32;
+ if (unlikely(v32 != *v)) {
+ DEBUG(0,(__location__ ": non-zero upper 16 bits 0x%08x\n", (unsigned)v32));
+ return NDR_ERR_NDR64;
+ }
+ return err;
+ }
+ return ndr_pull_uint16(ndr, ndr_flags, v);
+}
+
+/*
+ parse a int32_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_int32(struct ndr_pull *ndr, int ndr_flags, int32_t *v)
+{
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PULL_ALIGN(ndr, 4);
+ NDR_PULL_NEED_BYTES(ndr, 4);
+ *v = NDR_PULL_I32(ndr, ndr->offset);
+ ndr->offset += 4;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ parse a uint32_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
+{
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PULL_ALIGN(ndr, 4);
+ NDR_PULL_NEED_BYTES(ndr, 4);
+ *v = NDR_PULL_U32(ndr, ndr->offset);
+ ndr->offset += 4;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ parse a arch dependent uint32/uint64
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_uint3264(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
+{
+ uint64_t v64 = 0;
+ enum ndr_err_code err;
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (likely(!(ndr->flags & LIBNDR_FLAG_NDR64))) {
+ return ndr_pull_uint32(ndr, ndr_flags, v);
+ }
+ err = ndr_pull_hyper(ndr, ndr_flags, &v64);
+ if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
+ return err;
+ }
+ *v = (uint32_t)v64;
+ if (unlikely(v64 != *v)) {
+ DEBUG(0,(__location__ ": non-zero upper 32 bits 0x%016llx\n",
+ (unsigned long long)v64));
+ return ndr_pull_error(ndr, NDR_ERR_NDR64, __location__ ": non-zero upper 32 bits 0x%016llx\n",
+ (unsigned long long)v64);
+ }
+ return err;
+}
+
+/*
+ parse a double
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_double(struct ndr_pull *ndr, int ndr_flags, double *v)
+{
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PULL_ALIGN(ndr, 8);
+ NDR_PULL_NEED_BYTES(ndr, 8);
+ memcpy(v, ndr->data+ndr->offset, 8);
+ ndr->offset += 8;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ parse a pointer referent identifier stored in 2 bytes
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr_short(struct ndr_pull *ndr, uint16_t *v)
+{
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, v));
+ if (*v != 0) {
+ ndr->ptr_count++;
+ }
+ *(v) -= ndr->relative_rap_convert;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ parse a pointer referent identifier
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_generic_ptr(struct ndr_pull *ndr, uint32_t *v)
+{
+ NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, v));
+ if (*v != 0) {
+ ndr->ptr_count++;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ parse a ref pointer referent identifier
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_ref_ptr(struct ndr_pull *ndr, uint32_t *v)
+{
+ NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, v));
+ /* ref pointers always point to data */
+ *v = 1;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ parse a udlong
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_udlong(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
+{
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PULL_ALIGN(ndr, 4);
+ NDR_PULL_NEED_BYTES(ndr, 8);
+ *v = NDR_PULL_U32(ndr, ndr->offset);
+ *v |= (uint64_t)(NDR_PULL_U32(ndr, ndr->offset+4)) << 32;
+ ndr->offset += 8;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ parse a udlongr
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_udlongr(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
+{
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PULL_ALIGN(ndr, 4);
+ NDR_PULL_NEED_BYTES(ndr, 8);
+ *v = ((uint64_t)NDR_PULL_U32(ndr, ndr->offset)) << 32;
+ *v |= NDR_PULL_U32(ndr, ndr->offset+4);
+ ndr->offset += 8;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ parse a dlong
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_dlong(struct ndr_pull *ndr, int ndr_flags, int64_t *v)
+{
+ return ndr_pull_udlong(ndr, ndr_flags, (uint64_t *)v);
+}
+
+/*
+ parse a hyper
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_hyper(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
+{
+ NDR_PULL_ALIGN(ndr, 8);
+ if (NDR_BE(ndr)) {
+ return ndr_pull_udlongr(ndr, ndr_flags, v);
+ }
+ return ndr_pull_udlong(ndr, ndr_flags, v);
+}
+
+/*
+ parse a pointer
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_pointer(struct ndr_pull *ndr, int ndr_flags, void* *v)
+{
+ uintptr_t h;
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PULL_ALIGN(ndr, sizeof(h));
+ NDR_PULL_NEED_BYTES(ndr, sizeof(h));
+ memcpy(&h, ndr->data+ndr->offset, sizeof(h));
+ ndr->offset += sizeof(h);
+ *v = (void *)h;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ pull a NTSTATUS
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_NTSTATUS(struct ndr_pull *ndr, int ndr_flags, NTSTATUS *status)
+{
+ uint32_t v;
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+ *status = NT_STATUS(v);
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a NTSTATUS
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_NTSTATUS(struct ndr_push *ndr, int ndr_flags, NTSTATUS status)
+{
+ return ndr_push_uint32(ndr, ndr_flags, NT_STATUS_V(status));
+}
+
+_PUBLIC_ void ndr_print_NTSTATUS(struct ndr_print *ndr, const char *name, NTSTATUS r)
+{
+ ndr->print(ndr, "%-25s: %s", name, nt_errstr(r));
+}
+
+/*
+ pull a WERROR
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_WERROR(struct ndr_pull *ndr, int ndr_flags, WERROR *status)
+{
+ uint32_t v;
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+ *status = W_ERROR(v);
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ pull a HRESULT
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_HRESULT(struct ndr_pull *ndr, int ndr_flags, HRESULT *status)
+{
+ uint32_t v;
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+ *status = HRES_ERROR(v);
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ parse a uint8_t enum
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_enum_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *v)
+{
+ return ndr_pull_uint8(ndr, ndr_flags, v);
+}
+
+/*
+ parse a uint16_t enum
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_enum_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
+{
+ return ndr_pull_uint16(ndr, ndr_flags, v);
+}
+
+/*
+ parse a uint1632_t enum (uint32_t on NDR64)
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_enum_uint1632(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
+{
+ if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
+ uint32_t v32;
+ NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &v32));
+ *v = v32;
+ if (v32 != *v) {
+ DEBUG(0,(__location__ ": non-zero upper 16 bits 0x%08x\n", (unsigned)v32));
+ return NDR_ERR_NDR64;
+ }
+ return NDR_ERR_SUCCESS;
+ }
+ return ndr_pull_uint16(ndr, ndr_flags, v);
+}
+
+/*
+ parse a uint32_t enum
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_enum_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
+{
+ return ndr_pull_uint32(ndr, ndr_flags, v);
+}
+
+/*
+ push a uint8_t enum
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_enum_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v)
+{
+ return ndr_push_uint8(ndr, ndr_flags, v);
+}
+
+/*
+ push a uint16_t enum
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_enum_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v)
+{
+ return ndr_push_uint16(ndr, ndr_flags, v);
+}
+
+/*
+ push a uint32_t enum
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_enum_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v)
+{
+ return ndr_push_uint32(ndr, ndr_flags, v);
+}
+
+/*
+ push a uint1632_t enum
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_enum_uint1632(struct ndr_push *ndr, int ndr_flags, uint16_t v)
+{
+ if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
+ return ndr_push_uint32(ndr, ndr_flags, v);
+ }
+ return ndr_push_uint16(ndr, ndr_flags, v);
+}
+
+/*
+ push a WERROR
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_WERROR(struct ndr_push *ndr, int ndr_flags, WERROR status)
+{
+ return ndr_push_uint32(ndr, NDR_SCALARS, W_ERROR_V(status));
+}
+
+_PUBLIC_ void ndr_print_WERROR(struct ndr_print *ndr, const char *name, WERROR r)
+{
+ ndr->print(ndr, "%-25s: %s", name, win_errstr(r));
+}
+
+/*
+ push a HRESULT
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_HRESULT(struct ndr_push *ndr, int ndr_flags, HRESULT status)
+{
+ return ndr_push_uint32(ndr, NDR_SCALARS, HRES_ERROR_V(status));
+}
+
+_PUBLIC_ void ndr_print_HRESULT(struct ndr_print *ndr, const char *name, HRESULT r)
+{
+ ndr->print(ndr, "%-25s: %s", name, hresult_errstr(r));
+}
+
+
+/*
+ parse a set of bytes
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_bytes(struct ndr_pull *ndr, uint8_t *data, uint32_t n)
+{
+ NDR_PULL_NEED_BYTES(ndr, n);
+ memcpy(data, ndr->data + ndr->offset, n);
+ ndr->offset += n;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ pull an array of uint8
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *data, uint32_t n)
+{
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+ return ndr_pull_bytes(ndr, data, n);
+}
+
+/*
+ push a int8_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_int8(struct ndr_push *ndr, int ndr_flags, int8_t v)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PUSH_NEED_BYTES(ndr, 1);
+ PUSH_BE_U8(ndr->data, ndr->offset, (uint8_t)v);
+ ndr->offset += 1;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a uint8_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PUSH_NEED_BYTES(ndr, 1);
+ PUSH_BE_U8(ndr->data, ndr->offset, v);
+ ndr->offset += 1;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a int16_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_int16(struct ndr_push *ndr, int ndr_flags, int16_t v)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PUSH_ALIGN(ndr, 2);
+ NDR_PUSH_NEED_BYTES(ndr, 2);
+ NDR_PUSH_U16(ndr, ndr->offset, (uint16_t)v);
+ ndr->offset += 2;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a uint16_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PUSH_ALIGN(ndr, 2);
+ NDR_PUSH_NEED_BYTES(ndr, 2);
+ NDR_PUSH_U16(ndr, ndr->offset, v);
+ ndr->offset += 2;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a uint1632
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_uint1632(struct ndr_push *ndr, int ndr_flags, uint16_t v)
+{
+ if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
+ return ndr_push_uint32(ndr, ndr_flags, v);
+ }
+ return ndr_push_uint16(ndr, ndr_flags, v);
+}
+
+/*
+ push a int32_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_int32(struct ndr_push *ndr, int ndr_flags, int32_t v)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PUSH_ALIGN(ndr, 4);
+ NDR_PUSH_NEED_BYTES(ndr, 4);
+ NDR_PUSH_I32(ndr, ndr->offset, v);
+ ndr->offset += 4;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a uint32_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PUSH_ALIGN(ndr, 4);
+ NDR_PUSH_NEED_BYTES(ndr, 4);
+ NDR_PUSH_U32(ndr, ndr->offset, v);
+ ndr->offset += 4;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a uint3264
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_uint3264(struct ndr_push *ndr, int ndr_flags, uint32_t v)
+{
+ if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
+ return ndr_push_hyper(ndr, ndr_flags, v);
+ }
+ return ndr_push_uint32(ndr, ndr_flags, v);
+}
+
+/*
+ push a udlong
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_udlong(struct ndr_push *ndr, int ndr_flags, uint64_t v)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PUSH_ALIGN(ndr, 4);
+ NDR_PUSH_NEED_BYTES(ndr, 8);
+ NDR_PUSH_U32(ndr, ndr->offset, (v & 0xFFFFFFFF));
+ NDR_PUSH_U32(ndr, ndr->offset+4, (v>>32));
+ ndr->offset += 8;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a udlongr
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_udlongr(struct ndr_push *ndr, int ndr_flags, uint64_t v)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PUSH_ALIGN(ndr, 4);
+ NDR_PUSH_NEED_BYTES(ndr, 8);
+ NDR_PUSH_U32(ndr, ndr->offset, (v>>32));
+ NDR_PUSH_U32(ndr, ndr->offset+4, (v & 0xFFFFFFFF));
+ ndr->offset += 8;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a dlong
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_dlong(struct ndr_push *ndr, int ndr_flags, int64_t v)
+{
+ return ndr_push_udlong(ndr, NDR_SCALARS, (uint64_t)v);
+}
+
+/*
+ push a hyper
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_hyper(struct ndr_push *ndr, int ndr_flags, uint64_t v)
+{
+ NDR_PUSH_ALIGN(ndr, 8);
+ if (NDR_BE(ndr)) {
+ return ndr_push_udlongr(ndr, NDR_SCALARS, v);
+ }
+ return ndr_push_udlong(ndr, NDR_SCALARS, v);
+}
+
+/*
+ push a double
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_double(struct ndr_push *ndr, int ndr_flags, double v)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PUSH_ALIGN(ndr, 8);
+ NDR_PUSH_NEED_BYTES(ndr, 8);
+ memcpy(ndr->data+ndr->offset, &v, 8);
+ ndr->offset += 8;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a pointer
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_pointer(struct ndr_push *ndr, int ndr_flags, void* v)
+{
+ uintptr_t h = (intptr_t)v;
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_PUSH_ALIGN(ndr, sizeof(h));
+ NDR_PUSH_NEED_BYTES(ndr, sizeof(h));
+ memcpy(ndr->data+ndr->offset, &h, sizeof(h));
+ ndr->offset += sizeof(h);
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_align(struct ndr_push *ndr, size_t size)
+{
+ /* this is a nasty hack to make pidl work with NDR64 */
+ if (size == 5) {
+ if (ndr->flags & LIBNDR_FLAG_NDR64) {
+ size = 8;
+ } else {
+ size = 4;
+ }
+ } else if (size == 3) {
+ if (ndr->flags & LIBNDR_FLAG_NDR64) {
+ size = 4;
+ } else {
+ size = 2;
+ }
+ }
+ NDR_PUSH_ALIGN(ndr, size);
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_align(struct ndr_pull *ndr, size_t size)
+{
+ /* this is a nasty hack to make pidl work with NDR64 */
+ if (size == 5) {
+ if (ndr->flags & LIBNDR_FLAG_NDR64) {
+ size = 8;
+ } else {
+ size = 4;
+ }
+ } else if (size == 3) {
+ if (ndr->flags & LIBNDR_FLAG_NDR64) {
+ size = 4;
+ } else {
+ size = 2;
+ }
+ }
+ NDR_PULL_ALIGN(ndr, size);
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_union_align(struct ndr_push *ndr, size_t size)
+{
+ /* MS-RPCE section 2.2.5.3.4.4 */
+ if (ndr->flags & LIBNDR_FLAG_NDR64) {
+ return ndr_push_align(ndr, size);
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_union_align(struct ndr_pull *ndr, size_t size)
+{
+ /* MS-RPCE section 2.2.5.3.4.4 */
+ if (ndr->flags & LIBNDR_FLAG_NDR64) {
+ return ndr_pull_align(ndr, size);
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_trailer_align(struct ndr_push *ndr, size_t size)
+{
+ /* MS-RPCE section 2.2.5.3.4.1 */
+ if (ndr->flags & LIBNDR_FLAG_NDR64) {
+ return ndr_push_align(ndr, size);
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_trailer_align(struct ndr_pull *ndr, size_t size)
+{
+ /* MS-RPCE section 2.2.5.3.4.1 */
+ if (ndr->flags & LIBNDR_FLAG_NDR64) {
+ return ndr_pull_align(ndr, size);
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push some bytes
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_bytes(struct ndr_push *ndr, const uint8_t *data, uint32_t n)
+{
+ if (unlikely(n == 0)) {
+ return NDR_ERR_SUCCESS;
+ }
+ if (unlikely(data == NULL)) {
+ return NDR_ERR_INVALID_POINTER;
+ }
+ NDR_PUSH_NEED_BYTES(ndr, n);
+ memcpy(ndr->data + ndr->offset, data, n);
+ ndr->offset += n;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push some zero bytes
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_zero(struct ndr_push *ndr, uint32_t n)
+{
+ NDR_PUSH_NEED_BYTES(ndr, n);
+ memset(ndr->data + ndr->offset, 0, n);
+ ndr->offset += n;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push an array of uint8
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_array_uint8(struct ndr_push *ndr, int ndr_flags, const uint8_t *data, uint32_t n)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+ return ndr_push_bytes(ndr, data, n);
+}
+
+/*
+ push a unique non-zero value if a pointer is non-NULL, otherwise 0
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_unique_ptr(struct ndr_push *ndr, const void *p)
+{
+ uint32_t ptr = 0;
+ if (p) {
+ ptr = ndr->ptr_count * 4;
+ ptr |= 0x00020000;
+ ndr->ptr_count++;
+ }
+ return ndr_push_uint3264(ndr, NDR_SCALARS, ptr);
+}
+
+/*
+ push a 'simple' full non-zero value if a pointer is non-NULL, otherwise 0
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_full_ptr(struct ndr_push *ndr, const void *p)
+{
+ enum ndr_err_code ret = NDR_ERR_SUCCESS;
+ uint32_t ptr = 0;
+ if (p) {
+ /* Check if the pointer already exists and has an id */
+ ret = ndr_token_peek(&ndr->full_ptr_list, p, &ptr);
+ if (ret == NDR_ERR_TOKEN) {
+ ndr->ptr_count++;
+ ptr = ndr->ptr_count;
+ ret = ndr_token_store(ndr, &ndr->full_ptr_list, p, ptr);
+ if (ret != NDR_ERR_SUCCESS) {
+ return ret;
+ }
+ } else if (ret != NDR_ERR_SUCCESS) {
+ return ret;
+ }
+ }
+ return ndr_push_uint3264(ndr, NDR_SCALARS, ptr);
+}
+
+/*
+ push always a 0, if a pointer is NULL it's a fatal error
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_ref_ptr(struct ndr_push *ndr)
+{
+ return ndr_push_uint3264(ndr, NDR_SCALARS, 0xAEF1AEF1);
+}
+
+
+/*
+ push a NTTIME
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_NTTIME(struct ndr_push *ndr, int ndr_flags, NTTIME t)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_CHECK(ndr_push_udlong(ndr, ndr_flags, t));
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ pull a NTTIME
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_NTTIME(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
+{
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_CHECK(ndr_pull_udlong(ndr, ndr_flags, t));
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a NTTIME_1sec
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_NTTIME_1sec(struct ndr_push *ndr, int ndr_flags, NTTIME t)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ t /= 10000000;
+ NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ pull a NTTIME_1sec
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
+{
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
+ (*t) *= 10000000;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ pull a NTTIME_hyper
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_NTTIME_hyper(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
+{
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a NTTIME_hyper
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_NTTIME_hyper(struct ndr_push *ndr, int ndr_flags, NTTIME t)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a time_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_time_t(struct ndr_push *ndr, int ndr_flags, time_t t)
+{
+ return ndr_push_uint32(ndr, ndr_flags, t);
+}
+
+/*
+ pull a time_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_time_t(struct ndr_pull *ndr, int ndr_flags, time_t *t)
+{
+ uint32_t tt;
+ NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &tt));
+ *t = tt;
+ return NDR_ERR_SUCCESS;
+}
+
+
+/*
+ push a uid_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_uid_t(struct ndr_push *ndr, int ndr_flags, uid_t u)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ return ndr_push_hyper(ndr, NDR_SCALARS, (uint64_t)u);
+}
+
+/*
+ pull a uid_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_uid_t(struct ndr_pull *ndr, int ndr_flags, uid_t *u)
+{
+ uint64_t uu = 0;
+ NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &uu));
+ *u = (uid_t)uu;
+ if (unlikely(uu != *u)) {
+ DEBUG(0,(__location__ ": uid_t pull doesn't fit 0x%016llx\n",
+ (unsigned long long)uu));
+ return NDR_ERR_NDR64;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+
+/*
+ push a gid_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_gid_t(struct ndr_push *ndr, int ndr_flags, gid_t g)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ return ndr_push_hyper(ndr, NDR_SCALARS, (uint64_t)g);
+}
+
+/*
+ pull a gid_t
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_gid_t(struct ndr_pull *ndr, int ndr_flags, gid_t *g)
+{
+ uint64_t gg = 0;
+ NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &gg));
+ *g = (gid_t)gg;
+ if (unlikely(gg != *g)) {
+ DEBUG(0,(__location__ ": gid_t pull doesn't fit 0x%016llx\n",
+ (unsigned long long)gg));
+ return NDR_ERR_NDR64;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+
+/*
+ pull a ipv4address
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_ipv4address(struct ndr_pull *ndr, int ndr_flags, const char **address)
+{
+ uint32_t addr;
+ struct in_addr in;
+ NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &addr));
+ in.s_addr = htonl(addr);
+ *address = talloc_strdup(ndr->current_mem_ctx, inet_ntoa(in));
+ NDR_ERR_HAVE_NO_MEMORY(*address);
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a ipv4address
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_ipv4address(struct ndr_push *ndr, int ndr_flags, const char *address)
+{
+ uint32_t addr;
+ if (!is_ipaddress(address)) {
+ return ndr_push_error(ndr, NDR_ERR_IPV4ADDRESS,
+ "Invalid IPv4 address: '%s'",
+ address);
+ }
+ addr = inet_addr(address);
+ NDR_CHECK(ndr_push_uint32(ndr, ndr_flags, htonl(addr)));
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ print a ipv4address
+*/
+_PUBLIC_ void ndr_print_ipv4address(struct ndr_print *ndr, const char *name,
+ const char *address)
+{
+ ndr->print(ndr, "%-25s: %s", name, address);
+}
+
+/*
+ pull a ipv6address
+*/
+#define IPV6_BYTES 16
+#define IPV6_ADDR_STR_LEN 39
+_PUBLIC_ enum ndr_err_code ndr_pull_ipv6address(struct ndr_pull *ndr, int ndr_flags, const char **address)
+{
+ uint8_t addr[IPV6_BYTES];
+ char *addr_str = talloc_strdup(ndr->current_mem_ctx, "");
+ int i;
+ NDR_CHECK(ndr_pull_array_uint8(ndr, ndr_flags, addr, IPV6_BYTES));
+ for (i = 0; i < IPV6_BYTES; ++i) {
+ addr_str = talloc_asprintf_append(addr_str, "%02x", addr[i]);
+ /* We need a ':' every second byte but the last one */
+ if (i%2 == 1 && i != (IPV6_BYTES - 1)) {
+ addr_str = talloc_strdup_append(addr_str, ":");
+ }
+ }
+ *address = addr_str;
+ NDR_ERR_HAVE_NO_MEMORY(*address);
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a ipv6address
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_ipv6address(struct ndr_push *ndr, int ndr_flags, const char *address)
+{
+#ifdef AF_INET6
+ uint8_t addr[IPV6_BYTES];
+ int ret;
+
+ if (!is_ipaddress(address)) {
+ return ndr_push_error(ndr, NDR_ERR_IPV6ADDRESS,
+ "Invalid IPv6 address: '%s'",
+ address);
+ }
+ ret = inet_pton(AF_INET6, address, addr);
+ if (ret <= 0) {
+ return NDR_ERR_IPV6ADDRESS;
+ }
+
+ NDR_CHECK(ndr_push_array_uint8(ndr, ndr_flags, addr, IPV6_BYTES));
+
+ return NDR_ERR_SUCCESS;
+#else
+ return NDR_ERR_IPV6ADDRESS;
+#endif
+}
+
+/*
+ print a ipv6address
+*/
+_PUBLIC_ void ndr_print_ipv6address(struct ndr_print *ndr, const char *name,
+ const char *address)
+{
+ ndr->print(ndr, "%-25s: %s", name, address);
+}
+#undef IPV6_BYTES
+
+_PUBLIC_ void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type)
+{
+ ndr->print(ndr, "%s: struct %s", name, type);
+}
+
+_PUBLIC_ void ndr_print_null(struct ndr_print *ndr)
+{
+ ndr->print(ndr, "UNEXPECTED NULL POINTER");
+}
+
+_PUBLIC_ void ndr_print_enum(struct ndr_print *ndr, const char *name, const char *type,
+ const char *val, uint32_t value)
+{
+ if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
+ ndr->print(ndr, "%-25s: %s (0x%X)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
+ } else {
+ ndr->print(ndr, "%-25s: %s (%d)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
+ }
+}
+
+_PUBLIC_ void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const char *flag_name, uint32_t flag, uint32_t value)
+{
+ if (flag == 0) {
+ return;
+ }
+
+ /* this is an attempt to support multi-bit bitmap masks */
+ value &= flag;
+
+ while (!(flag & 1)) {
+ flag >>= 1;
+ value >>= 1;
+ }
+ if (flag == 1) {
+ ndr->print(ndr, " %d: %-25s", value, flag_name);
+ } else {
+ ndr->print(ndr, "0x%02x: %-25s (%d)", value, flag_name, value);
+ }
+}
+
+_PUBLIC_ void ndr_print_int8(struct ndr_print *ndr, const char *name, int8_t v)
+{
+ if (NDR_HIDE_SECRET(ndr)) {
+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name);
+ return;
+ }
+ ndr->print(ndr, "%-25s: %d", name, v);
+}
+
+_PUBLIC_ void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8_t v)
+{
+ if (NDR_HIDE_SECRET(ndr)) {
+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name);
+ return;
+ }
+ ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v);
+}
+
+_PUBLIC_ void ndr_print_int16(struct ndr_print *ndr, const char *name, int16_t v)
+{
+ if (NDR_HIDE_SECRET(ndr)) {
+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name);
+ return;
+ }
+ ndr->print(ndr, "%-25s: %d", name, v);
+}
+
+_PUBLIC_ void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16_t v)
+{
+ if (NDR_HIDE_SECRET(ndr)) {
+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name);
+ return;
+ }
+ ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v);
+}
+
+_PUBLIC_ void ndr_print_int32(struct ndr_print *ndr, const char *name, int32_t v)
+{
+ if (NDR_HIDE_SECRET(ndr)) {
+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name);
+ return;
+ }
+ ndr->print(ndr, "%-25s: %d", name, v);
+}
+
+_PUBLIC_ void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32_t v)
+{
+ if (NDR_HIDE_SECRET(ndr)) {
+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name);
+ return;
+ }
+ ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
+}
+
+_PUBLIC_ void ndr_print_int3264(struct ndr_print *ndr, const char *name, int32_t v)
+{
+ if (NDR_HIDE_SECRET(ndr)) {
+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name);
+ return;
+ }
+ ndr->print(ndr, "%-25s: %d", name, v);
+}
+
+_PUBLIC_ void ndr_print_uint3264(struct ndr_print *ndr, const char *name, uint32_t v)
+{
+ if (NDR_HIDE_SECRET(ndr)) {
+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name);
+ return;
+ }
+ ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
+}
+
+_PUBLIC_ void ndr_print_udlong(struct ndr_print *ndr, const char *name, uint64_t v)
+{
+ ndr->print(ndr, "%-25s: 0x%016llx (%llu)", name, (unsigned long long)v, (unsigned long long)v);
+}
+
+_PUBLIC_ void ndr_print_udlongr(struct ndr_print *ndr, const char *name, uint64_t v)
+{
+ ndr_print_udlong(ndr, name, v);
+}
+
+_PUBLIC_ void ndr_print_dlong(struct ndr_print *ndr, const char *name, int64_t v)
+{
+ if (NDR_HIDE_SECRET(ndr)) {
+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name);
+ return;
+ }
+ ndr->print(ndr, "%-25s: 0x%016llx (%lld)", name, (unsigned long long)v, (long long)v);
+}
+
+_PUBLIC_ void ndr_print_double(struct ndr_print *ndr, const char *name, double v)
+{
+ ndr->print(ndr, "%-25s: %f", name, v);
+}
+
+_PUBLIC_ void ndr_print_hyper(struct ndr_print *ndr, const char *name, uint64_t v)
+{
+ ndr_print_dlong(ndr, name, v);
+}
+
+_PUBLIC_ void ndr_print_pointer(struct ndr_print *ndr, const char *name, void *v)
+{
+ ndr->print(ndr, "%-25s: %p", name, v);
+}
+
+_PUBLIC_ void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p)
+{
+ if (p) {
+ ndr->print(ndr, "%-25s: *", name);
+ } else {
+ ndr->print(ndr, "%-25s: NULL", name);
+ }
+}
+
+_PUBLIC_ void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t)
+{
+ ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr, t));
+}
+
+_PUBLIC_ void ndr_print_NTTIME_1sec(struct ndr_print *ndr, const char *name, NTTIME t)
+{
+ /* this is a standard NTTIME here
+ * as it's already converted in the pull/push code
+ */
+ ndr_print_NTTIME(ndr, name, t);
+}
+
+_PUBLIC_ void ndr_print_NTTIME_hyper(struct ndr_print *ndr, const char *name, NTTIME t)
+{
+ ndr_print_NTTIME(ndr, name, t);
+}
+
+_PUBLIC_ void ndr_print_time_t(struct ndr_print *ndr, const char *name, time_t t)
+{
+ if (t == (time_t)-1 || t == 0) {
+ ndr->print(ndr, "%-25s: (time_t)%d", name, (int)t);
+ } else {
+ ndr->print(ndr, "%-25s: %s", name, timestring(ndr, t));
+ }
+}
+
+_PUBLIC_ void ndr_print_uid_t(struct ndr_print *ndr, const char *name, uid_t u)
+{
+ ndr_print_dlong(ndr, name, u);
+}
+
+_PUBLIC_ void ndr_print_gid_t(struct ndr_print *ndr, const char *name, gid_t g)
+{
+ ndr_print_dlong(ndr, name, g);
+}
+
+_PUBLIC_ void ndr_print_union(struct ndr_print *ndr, const char *name, int level, const char *type)
+{
+ if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
+ ndr->print(ndr, "%-25s: union %s(case 0x%X)", name, type, level);
+ } else {
+ ndr->print(ndr, "%-25s: union %s(case %d)", name, type, level);
+ }
+}
+
+_PUBLIC_ void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16_t level)
+{
+ ndr->print(ndr, "UNKNOWN LEVEL %u", level);
+}
+
+_PUBLIC_ void ndr_print_array_uint8(struct ndr_print *ndr, const char *name,
+ const uint8_t *data, uint32_t count)
+{
+ int i;
+#define _ONELINE_LIMIT 32
+
+ if (data == NULL) {
+ ndr->print(ndr, "%s: ARRAY(%d) : NULL", name, count);
+ return;
+ }
+
+ if (NDR_HIDE_SECRET(ndr)) {
+ ndr->print(ndr, "%s: ARRAY(%d): <REDACTED SECRET VALUES>", name, count);
+ return;
+ }
+
+ if (count <= _ONELINE_LIMIT && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
+ char s[(_ONELINE_LIMIT + 1) * 2];
+ for (i=0;i<count;i++) {
+ snprintf(&s[i*2], 3, "%02x", data[i]);
+ }
+ s[i*2] = 0;
+ ndr->print(ndr, "%-25s: %s", name, s);
+ return;
+ }
+
+ ndr->print(ndr, "%s: ARRAY(%d)", name, count);
+ if (count > _ONELINE_LIMIT && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
+ ndr_dump_data(ndr, data, count);
+ return;
+ }
+
+ ndr->depth++;
+ for (i=0;i<count;i++) {
+ char *idx=NULL;
+ if (asprintf(&idx, "[%d]", i) != -1) {
+ ndr_print_uint8(ndr, idx, data[i]);
+ free(idx);
+ }
+ }
+ ndr->depth--;
+#undef _ONELINE_LIMIT
+}
+
+static void ndr_print_dump_data_cb(const char *buf, void *private_data)
+{
+ struct ndr_print *ndr = (struct ndr_print *)private_data;
+
+ ndr->print(ndr, "%s", buf);
+}
+
+/*
+ ndr_print version of dump_data()
+ */
+static void ndr_dump_data(struct ndr_print *ndr, const uint8_t *buf, int len)
+{
+ if (NDR_HIDE_SECRET(ndr)) {
+ return;
+ }
+ ndr->no_newline = true;
+ dump_data_cb(buf, len, true, ndr_print_dump_data_cb, ndr);
+ ndr->no_newline = false;
+}
+
+
+_PUBLIC_ void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r)
+{
+ ndr->print(ndr, "%-25s: DATA_BLOB length=%u", name, (unsigned)r.length);
+ if (r.length) {
+ ndr_dump_data(ndr, r.data, r.length);
+ }
+}
+
+
+/*
+ * Push a DATA_BLOB onto the wire.
+ * 1) When called with LIBNDR_FLAG_ALIGN* alignment flags set, push padding
+ * bytes _only_. The length is determined by the alignment required and the
+ * current ndr offset.
+ * 2) When called with the LIBNDR_FLAG_REMAINING flag, push the byte array to
+ * the ndr buffer.
+ * 3) Otherwise, push a uint3264 length _and_ a corresponding byte array to the
+ * ndr buffer.
+ */
+_PUBLIC_ enum ndr_err_code ndr_push_DATA_BLOB(struct ndr_push *ndr, int ndr_flags, DATA_BLOB blob)
+{
+ if (ndr->flags & LIBNDR_FLAG_REMAINING) {
+ /* nothing to do */
+ } else if (ndr->flags & (LIBNDR_ALIGN_FLAGS & ~LIBNDR_FLAG_NOALIGN)) {
+ if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
+ blob.length = NDR_ALIGN(ndr, 2);
+ } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
+ blob.length = NDR_ALIGN(ndr, 4);
+ } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
+ blob.length = NDR_ALIGN(ndr, 8);
+ }
+ NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length);
+ data_blob_clear(&blob);
+ } else {
+ NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, blob.length));
+ }
+ NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length));
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ * Pull a DATA_BLOB from the wire.
+ * 1) when called with LIBNDR_FLAG_ALIGN* alignment flags set, pull padding
+ * bytes _only_. The length is determined by the alignment required and the
+ * current ndr offset.
+ * 2) When called with the LIBNDR_FLAG_REMAINING flag, pull all remaining bytes
+ * from the ndr buffer.
+ * 3) Otherwise, pull a uint3264 length _and_ a corresponding byte array from the
+ * ndr buffer.
+ */
+_PUBLIC_ enum ndr_err_code ndr_pull_DATA_BLOB(struct ndr_pull *ndr, int ndr_flags, DATA_BLOB *blob)
+{
+ uint32_t length = 0;
+
+ if (ndr->flags & LIBNDR_FLAG_REMAINING) {
+ length = ndr->data_size - ndr->offset;
+ } else if (ndr->flags & (LIBNDR_ALIGN_FLAGS & ~LIBNDR_FLAG_NOALIGN)) {
+ if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
+ length = NDR_ALIGN(ndr, 2);
+ } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
+ length = NDR_ALIGN(ndr, 4);
+ } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
+ length = NDR_ALIGN(ndr, 8);
+ }
+ if (ndr->data_size - ndr->offset < length) {
+ length = ndr->data_size - ndr->offset;
+ }
+ } else {
+ NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &length));
+ }
+ NDR_PULL_NEED_BYTES(ndr, length);
+ *blob = data_blob_talloc(ndr->current_mem_ctx, ndr->data+ndr->offset, length);
+ ndr->offset += length;
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ uint32_t ndr_size_DATA_BLOB(int ret, const DATA_BLOB *data, int flags)
+{
+ if (!data) return ret;
+ return ret + data->length;
+}
+
+_PUBLIC_ void ndr_print_bool(struct ndr_print *ndr, const char *name, const bool b)
+{
+ ndr->print(ndr, "%-25s: %s", name, b?"true":"false");
+}
+
+_PUBLIC_ NTSTATUS ndr_map_error2ntstatus(enum ndr_err_code ndr_err)
+{
+ switch (ndr_err) {
+ case NDR_ERR_SUCCESS:
+ return NT_STATUS_OK;
+ case NDR_ERR_BUFSIZE:
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ case NDR_ERR_TOKEN:
+ return NT_STATUS_INTERNAL_ERROR;
+ case NDR_ERR_ALLOC:
+ return NT_STATUS_NO_MEMORY;
+ case NDR_ERR_ARRAY_SIZE:
+ return NT_STATUS_ARRAY_BOUNDS_EXCEEDED;
+ case NDR_ERR_INVALID_POINTER:
+ return NT_STATUS_INVALID_PARAMETER_MIX;
+ case NDR_ERR_UNREAD_BYTES:
+ return NT_STATUS_PORT_MESSAGE_TOO_LONG;
+ default:
+ break;
+ }
+
+ /* we should map all error codes to different status codes */
+ return NT_STATUS_INVALID_PARAMETER;
+}
+
+_PUBLIC_ int ndr_map_error2errno(enum ndr_err_code ndr_err)
+{
+ switch (ndr_err) {
+ case NDR_ERR_SUCCESS:
+ return 0;
+ case NDR_ERR_BUFSIZE:
+ return ENOSPC;
+ case NDR_ERR_TOKEN:
+ return EINVAL;
+ case NDR_ERR_ALLOC:
+ return ENOMEM;
+ case NDR_ERR_ARRAY_SIZE:
+ return EMSGSIZE;
+ case NDR_ERR_INVALID_POINTER:
+ return EINVAL;
+ case NDR_ERR_UNREAD_BYTES:
+ return EOVERFLOW;
+ default:
+ break;
+ }
+
+ /* we should map all error codes to different status codes */
+ return EINVAL;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_timespec(struct ndr_push *ndr,
+ int ndr_flags,
+ const struct timespec *t)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t->tv_sec));
+ NDR_CHECK(ndr_push_uint32(ndr, ndr_flags, t->tv_nsec));
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_timespec(struct ndr_pull *ndr,
+ int ndr_flags,
+ struct timespec *t)
+{
+ uint64_t secs = 0;
+ uint32_t nsecs = 0;
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &secs));
+ NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &nsecs));
+ t->tv_sec = secs;
+ t->tv_nsec = nsecs;
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_timespec(struct ndr_print *ndr, const char *name,
+ const struct timespec *t)
+{
+ char *str = timestring(ndr, t->tv_sec);
+ ndr->print(ndr, "%-25s: %s.%ld", name, str, t->tv_nsec);
+ TALLOC_FREE(str);
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_timeval(struct ndr_push *ndr,
+ int ndr_flags,
+ const struct timeval *t)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t->tv_sec));
+ NDR_CHECK(ndr_push_uint32(ndr, ndr_flags, t->tv_usec));
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_timeval(struct ndr_pull *ndr,
+ int ndr_flags,
+ struct timeval *t)
+{
+ uint64_t secs = 0;
+ uint32_t usecs = 0;
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &secs));
+ NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &usecs));
+ t->tv_sec = secs;
+ t->tv_usec = usecs;
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_timeval(struct ndr_print *ndr, const char *name,
+ const struct timeval *t)
+{
+ ndr->print(ndr, "%-25s: %s.%ld", name, timestring(ndr, t->tv_sec),
+ (long)t->tv_usec);
+}
diff --git a/librpc/ndr/ndr_bkupblobs.c b/librpc/ndr/ndr_bkupblobs.c
new file mode 100644
index 0000000..9335664
--- /dev/null
+++ b/librpc/ndr/ndr_bkupblobs.c
@@ -0,0 +1,82 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ helper routines for BKUP Blobs marshalling
+
+ Copyright (C) Matthieu Patou <mat@matws.net> 2011
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_bkupblobs.h"
+
+
+_PUBLIC_ enum ndr_err_code ndr_push_bkup_NTBackupFile(struct ndr_push *ndr, int ndr_flags, const struct bkup_NTBackupFile *r)
+{
+ uint32_t cntr_streams_0;
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 2));
+ for (cntr_streams_0 = 0; cntr_streams_0 < r->num_stream; cntr_streams_0++) {
+ NDR_CHECK(ndr_push_bkup_Win32StreamId(ndr, NDR_SCALARS, &r->streams[cntr_streams_0]));
+ }
+ NDR_CHECK(ndr_push_trailer_align(ndr, 8));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+#define _TMP_PULL_REALLOC_N(ndr, s, t, n) do { \
+ _NDR_PULL_FIX_CURRENT_MEM_CTX(ndr);\
+ (s) = talloc_realloc(ndr->current_mem_ctx, (s), t, n); \
+ if (!(s)) { \
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, \
+ "Alloc %u * %s failed: %s\n", \
+ (unsigned)n, # s, __location__); \
+ } \
+} while (0)
+
+_PUBLIC_ enum ndr_err_code ndr_pull_bkup_NTBackupFile(struct ndr_pull *ndr, int ndr_flags, struct bkup_NTBackupFile *r)
+{
+ uint32_t cntr_streams_0;
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ if (ndr_flags & NDR_SCALARS) {
+ uint32_t remaining = ndr->data_size - ndr->offset;
+ r->num_stream = 0;
+ r->streams = NULL;
+ for (cntr_streams_0 = 0; remaining > 0; cntr_streams_0++) {
+ r->num_stream += 1;
+ _TMP_PULL_REALLOC_N(ndr, r->streams,
+ struct bkup_Win32StreamId,
+ r->num_stream);
+ NDR_CHECK(ndr_pull_bkup_Win32StreamId(ndr,
+ NDR_SCALARS,
+ &r->streams[cntr_streams_0]));
+ remaining = ndr->data_size - ndr->offset;
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_cab.c b/librpc/ndr/ndr_cab.c
new file mode 100644
index 0000000..476e21c
--- /dev/null
+++ b/librpc/ndr/ndr_cab.c
@@ -0,0 +1,437 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling cab structures
+
+ Copyright (C) Guenther Deschner 2016
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_cab.h"
+#include "librpc/ndr/ndr_compression.h"
+
+#define OFFSET_OF_FOLDER_COFFCABSTART(folder) (36 /* cfheader size */ + (size_t)(folder)*8)
+
+_PUBLIC_ void ndr_print_cf_time(struct ndr_print *ndr, const char *name, const struct cf_time *r)
+{
+ uint8_t hour = 0, minute = 0, seconds = 0;
+ char *s;
+ if (r == NULL) { ndr_print_null(ndr); return; }
+ hour = r->time >> 11;
+ minute = (r->time >> 5) & 0x3f;
+ seconds = (r->time << 1) & 0x3e;
+ s = talloc_asprintf(ndr, "%02d:%02d:%02d", hour, minute, seconds);
+ if (s == NULL) { return; }
+ ndr_print_string(ndr, "time", s);
+ talloc_free(s);
+}
+
+_PUBLIC_ void ndr_print_cf_date(struct ndr_print *ndr, const char *name, const struct cf_date *r)
+{
+ uint16_t year = 0;
+ uint8_t month = 0, day = 0;
+ char *s;
+ if (r == NULL) { ndr_print_null(ndr); return; }
+ year = (r->date >> 9);
+ year += 1980;
+ month = (r->date >> 5 & 0xf);
+ day = (r->date & 0x1f);
+ s = talloc_asprintf(ndr, "%02d/%02d/%04d", day, month, year);
+ if (s == NULL) { return; }
+ ndr_print_string(ndr, "date", s);
+ talloc_free(s);
+}
+
+uint32_t ndr_count_cfdata(const struct cab_file *r)
+{
+ uint32_t count = 0, i;
+
+ for (i = 0; i < r->cfheader.cFolders; i++) {
+ if (count + r->cffolders[i].cCFData < count) {
+ /* Integer wrap. */
+ return 0;
+ }
+ count += r->cffolders[i].cCFData;
+ }
+
+ return count;
+}
+
+static uint32_t ndr_cab_compute_checksum(uint8_t *data, uint32_t length, uint32_t seed)
+{
+ int num_ulong;
+ uint32_t checksum;
+ uint8_t *pb;
+ uint32_t ul;
+
+ num_ulong = length / 4;
+ checksum = seed;
+ pb = data;
+
+ while (num_ulong-- > 0) {
+ ul = (uint32_t)(*pb++);
+ ul |= (((uint32_t)(*pb++)) << 8);
+ ul |= (((uint32_t)(*pb++)) << 16);
+ ul |= (((uint32_t)(*pb++)) << 24);
+
+ checksum ^= ul;
+ }
+
+ ul = 0;
+
+ switch (length % 4) {
+ case 3:
+ ul |= (((uint32_t)(*pb++)) << 16);
+ FALL_THROUGH;
+ case 2:
+ ul |= (((uint32_t)(*pb++)) << 8);
+ FALL_THROUGH;
+ case 1:
+ ul |= (uint32_t)(*pb++);
+ FALL_THROUGH;
+ default:
+ break;
+ }
+
+ checksum ^= ul;
+
+ return checksum;
+}
+
+/* Push all CFDATA of a folder.
+ *
+ * This works on a folder level because compression type is set per
+ * folder, and a compression state can be shared between CFDATA of the
+ * same folder.
+ *
+ * This is not a regular NDR func as we pass the compression type and
+ * the number of CFDATA as extra arguments
+ */
+static enum ndr_err_code ndr_push_folder_cfdata(struct ndr_push *ndr,
+ const struct CFDATA *r,
+ enum cf_compress_type cab_ctype,
+ size_t num_cfdata)
+{
+ size_t i;
+ enum ndr_compression_alg ndr_ctype = 0;
+
+ ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX|LIBNDR_FLAG_LITTLE_ENDIAN|LIBNDR_FLAG_NOALIGN);
+
+ if (cab_ctype == CF_COMPRESS_MSZIP) {
+ ndr_ctype = NDR_COMPRESSION_MSZIP_CAB;
+ NDR_CHECK(ndr_push_compression_state_init(ndr, ndr_ctype, &ndr->cstate));
+ }
+
+ for (i = 0; i < num_cfdata; i++, r++) {
+ uint32_t compressed_length = 0;
+ uint32_t csum, csumPartial;
+ size_t compressed_offset, csum_offset, data_offset;
+
+ if (!r->ab.data) {
+ return ndr_push_error(ndr, NDR_ERR_LENGTH,
+ "NULL uncompressed data blob");
+ }
+ if (r->ab.length != r->cbUncomp) {
+ return ndr_push_error(ndr, NDR_ERR_LENGTH,
+ "Uncompressed data blob size != uncompressed data size field");
+ }
+
+ /*
+ * checksum is a function of the size fields
+ * and the potentially compressed data bytes,
+ * which haven't been compressed yet so
+ * remember offset, write zeroes, fill out
+ * later
+ */
+ csum_offset = ndr->offset;
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+
+ /*
+ * similarly, we don't know the compressed
+ * size yet, remember offset, write zeros,
+ * fill out later
+ */
+ compressed_offset = ndr->offset;
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->cbUncomp));
+
+ data_offset = ndr->offset;
+
+ switch (cab_ctype) {
+ case CF_COMPRESS_NONE:
+ /* just copy the data */
+ NDR_PUSH_NEED_BYTES(ndr, r->ab.length);
+ NDR_CHECK(ndr_push_bytes(ndr, r->ab.data, r->ab.length));
+ compressed_length = r->ab.length;
+ break;
+ case CF_COMPRESS_LZX:
+ /*
+ * we have not yet worked out the details of LZX
+ * compression
+ */
+ return NDR_ERR_COMPRESSION;
+
+ case CF_COMPRESS_MSZIP: {
+ struct ndr_push *push_sub, *push_compress;
+
+ /* compress via subcontext */
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &push_sub, 0, -1));
+ push_sub->cstate = ndr->cstate;
+ NDR_CHECK(ndr_push_compression_start(push_sub, &push_compress, ndr_ctype, -1));
+ ndr_set_flags(&push_compress->flags, LIBNDR_FLAG_REMAINING);
+ NDR_CHECK(ndr_push_DATA_BLOB(push_compress, NDR_SCALARS, r->ab));
+ NDR_CHECK(ndr_push_compression_end(push_sub, push_compress, ndr_ctype, -1));
+ NDR_CHECK(ndr_push_subcontext_end(ndr, push_sub, 0, -1));
+ compressed_length = push_sub->offset;
+
+ break;
+ }
+ default:
+ return NDR_ERR_BAD_SWITCH;
+ }
+
+ /* we can now write the compressed size and the checksum */
+ SSVAL(ndr->data, compressed_offset, compressed_length);
+
+ /*
+ * Create checksum over compressed data.
+ *
+ * The 8 bytes are the header size.
+ *
+ * We have already have written the checksum and set it to zero,
+ * earlier. So we know that after the checksum end the value
+ * for the compressed length comes the blob data.
+ *
+ * NDR already did all the checks for integer wraps.
+ */
+ csumPartial = ndr_cab_compute_checksum(&ndr->data[data_offset],
+ compressed_length, 0);
+
+ /*
+ * Checksum over header (compressed and uncompressed length).
+ *
+ * The first 4 bytes are the checksum size.
+ * The second 4 bytes are the size of the compressed and
+ * uncompressed length fields.
+ *
+ * NDR already did all the checks for integer wraps.
+ */
+ csum = ndr_cab_compute_checksum(&ndr->data[compressed_offset],
+ data_offset - compressed_offset,
+ csumPartial);
+
+ SIVAL(ndr->data, csum_offset, csum);
+ }
+
+ ndr_push_compression_state_free(ndr->cstate);
+ ndr->cstate = NULL;
+
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_cab_file(struct ndr_push *ndr, int ndr_flags, const struct cab_file *r)
+{
+ uint32_t cntr_cffolders_0;
+ uint32_t cntr_cffiles_0;
+ size_t processed_cfdata = 0;
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX|LIBNDR_FLAG_LITTLE_ENDIAN|LIBNDR_FLAG_NOALIGN);
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+
+ if (ndr_flags & NDR_SCALARS) {
+ uint32_t i;
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_CFHEADER(ndr, NDR_SCALARS, &r->cfheader));
+ for (cntr_cffolders_0 = 0; cntr_cffolders_0 < (r->cfheader.cFolders); cntr_cffolders_0++) {
+ NDR_CHECK(ndr_push_CFFOLDER(ndr, NDR_SCALARS, &r->cffolders[cntr_cffolders_0]));
+ }
+ for (cntr_cffiles_0 = 0; cntr_cffiles_0 < (r->cfheader.cFiles); cntr_cffiles_0++) {
+ NDR_CHECK(ndr_push_CFFILE(ndr, NDR_SCALARS, &r->cffiles[cntr_cffiles_0]));
+ }
+#if 0
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_count_cfdata(r)));
+#endif
+
+ /* write in the folder header the offset of its first data block */
+ for (i = 0; i < r->cfheader.cFolders; i++) {
+ size_t off = OFFSET_OF_FOLDER_COFFCABSTART(i);
+ /* check that the offset we want to
+ * write to is always inside our
+ * current push buffer
+ */
+ if (off >= ndr->offset) {
+ return ndr_push_error(ndr, NDR_ERR_OFFSET,
+ "trying to write past current push buffer size");
+ }
+ SIVAL(ndr->data, off, ndr->offset);
+ NDR_CHECK(ndr_push_folder_cfdata(ndr, r->cfdata + processed_cfdata, r->cffolders[i].typeCompress, r->cffolders[i].cCFData));
+ processed_cfdata += r->cffolders[i].cCFData;
+ }
+ NDR_CHECK(ndr_push_trailer_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+
+
+ /* write total file size in header */
+ SIVAL(ndr->data, 8, ndr->offset);
+
+ return NDR_ERR_SUCCESS;
+}
+
+
+/* Pull all CFDATA of a folder.
+ *
+ * This works on a folder level because compression type is set per
+ * folder, and a compression state can be shared between CFDATA of the
+ * same folder.
+ *
+ * This is not a regular NDR func as we pass the compression type and
+ * the number of CFDATA as extra arguments
+ */
+static enum ndr_err_code ndr_pull_folder_cfdata(struct ndr_pull *ndr,
+ struct CFDATA *r,
+ enum cf_compress_type cab_ctype,
+ size_t num_cfdata)
+{
+ size_t i;
+ enum ndr_compression_alg ndr_ctype = 0;
+
+ if (cab_ctype == CF_COMPRESS_MSZIP) {
+ ndr_ctype = NDR_COMPRESSION_MSZIP_CAB;
+ NDR_CHECK(ndr_pull_compression_state_init(ndr, NDR_COMPRESSION_MSZIP_CAB, &ndr->cstate));
+ }
+
+ for (i = 0; i < num_cfdata; i++, r++) {
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->csum));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->cbData));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->cbUncomp));
+
+ switch (cab_ctype) {
+ case CF_COMPRESS_NONE:
+ /* just copy the data */
+ NDR_PULL_NEED_BYTES(ndr, r->cbUncomp);
+ r->ab = data_blob_talloc(ndr->current_mem_ctx,
+ ndr->data+ndr->offset,
+ r->cbUncomp);
+ if (r->ab.data == NULL) {
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC,
+ "failed to allocate buffer for uncompressed CFDATA block");
+ }
+ ndr->offset += r->cbUncomp;
+ break;
+
+ case CF_COMPRESS_LZX:
+ /* just copy the data (LZX decompression not implemented yet) */
+ NDR_PULL_NEED_BYTES(ndr, r->cbData);
+ r->ab = data_blob_talloc(ndr->current_mem_ctx,
+ ndr->data+ndr->offset,
+ r->cbData);
+ if (r->ab.data == NULL) {
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC,
+ "failed to allocate buffer for LZX-compressed CFDATA block");
+ }
+ ndr->offset += r->cbData;
+ break;
+
+ case CF_COMPRESS_MSZIP: {
+ struct ndr_pull *pull_sub, *pull_compress;
+ NDR_PULL_NEED_BYTES(ndr, r->cbData);
+ /* decompress via subcontext */
+ NDR_CHECK(ndr_pull_subcontext_start(ndr, &pull_sub, 0, r->cbData));
+ pull_sub->cstate = ndr->cstate;
+ NDR_CHECK(ndr_pull_compression_start(pull_sub, &pull_compress,
+ ndr_ctype, r->cbUncomp, r->cbData));
+ ndr_set_flags(&pull_compress->flags, LIBNDR_FLAG_REMAINING);
+ NDR_CHECK(ndr_pull_DATA_BLOB(pull_compress, NDR_SCALARS, &r->ab));
+ NDR_CHECK(ndr_pull_compression_end(pull_sub, pull_compress, ndr_ctype, r->cbUncomp));
+ NDR_CHECK(ndr_pull_subcontext_end(ndr, pull_sub, 0, r->cbData));
+
+ break;
+ }
+ default:
+ return NDR_ERR_BAD_SWITCH;
+ }
+ }
+
+ ndr_pull_compression_state_free(ndr->cstate);
+ ndr->cstate = NULL;
+
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_cab_file(struct ndr_pull *ndr, int ndr_flags, struct cab_file *r)
+{
+ uint32_t size_cffolders_0 = 0;
+ uint32_t cntr_cffolders_0;
+ TALLOC_CTX *_mem_save_cffolders_0 = NULL;
+ uint32_t size_cffiles_0 = 0;
+ uint32_t cntr_cffiles_0;
+ TALLOC_CTX *_mem_save_cffiles_0 = NULL;
+ uint32_t size_cfdata_0 = 0;
+ size_t processed_cfdata = 0;
+ TALLOC_CTX *_mem_save_cfdata_0 = NULL;
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX|LIBNDR_FLAG_LITTLE_ENDIAN|LIBNDR_FLAG_NOALIGN);
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_CFHEADER(ndr, NDR_SCALARS, &r->cfheader));
+ size_cffolders_0 = r->cfheader.cFolders;
+ NDR_PULL_ALLOC_N(ndr, r->cffolders, size_cffolders_0);
+ _mem_save_cffolders_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->cffolders, 0);
+ for (cntr_cffolders_0 = 0; cntr_cffolders_0 < (size_cffolders_0); cntr_cffolders_0++) {
+ NDR_CHECK(ndr_pull_CFFOLDER(ndr, NDR_SCALARS, &r->cffolders[cntr_cffolders_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_cffolders_0, 0);
+ size_cffiles_0 = r->cfheader.cFiles;
+ NDR_PULL_ALLOC_N(ndr, r->cffiles, size_cffiles_0);
+ _mem_save_cffiles_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->cffiles, 0);
+ for (cntr_cffiles_0 = 0; cntr_cffiles_0 < (size_cffiles_0); cntr_cffiles_0++) {
+ NDR_CHECK(ndr_pull_CFFILE(ndr, NDR_SCALARS, &r->cffiles[cntr_cffiles_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_cffiles_0, 0);
+#if 0
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->cfdata_count));
+#else
+ r->cfdata_count = ndr_count_cfdata(r);
+#endif
+ size_cfdata_0 = r->cfdata_count;
+ NDR_PULL_ALLOC_N(ndr, r->cfdata, size_cfdata_0);
+ _mem_save_cfdata_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->cfdata, 0);
+ for (cntr_cffolders_0 = 0; cntr_cffolders_0 < (size_cffolders_0); cntr_cffolders_0++) {
+ NDR_CHECK(ndr_pull_folder_cfdata(ndr,
+ r->cfdata + processed_cfdata,
+ r->cffolders[cntr_cffolders_0].typeCompress,
+ r->cffolders[cntr_cffolders_0].cCFData));
+ processed_cfdata += r->cffolders[cntr_cffolders_0].cCFData;
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_cfdata_0, 0);
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_cab.h b/librpc/ndr/ndr_cab.h
new file mode 100644
index 0000000..39b6bc9
--- /dev/null
+++ b/librpc/ndr/ndr_cab.h
@@ -0,0 +1,22 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling cab structures
+
+ Copyright (C) Guenther Deschner 2016
+
+ 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/>.
+*/
+
+uint32_t ndr_count_cfdata(const struct cab_file *r);
diff --git a/librpc/ndr/ndr_compression.c b/librpc/ndr/ndr_compression.c
new file mode 100644
index 0000000..8838c2f
--- /dev/null
+++ b/librpc/ndr/ndr_compression.c
@@ -0,0 +1,941 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ libndr compression support
+
+ Copyright (C) Stefan Metzmacher 2005
+ Copyright (C) Matthieu Suiche 2008
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "../lib/compression/lzxpress.h"
+#include "librpc/ndr/libndr.h"
+#include "../librpc/ndr/ndr_compression.h"
+#include <zlib.h>
+
+struct ndr_compression_state {
+ enum ndr_compression_alg type;
+ union {
+ struct {
+ struct z_stream_s *z;
+ uint8_t *dict;
+ size_t dict_size;
+ } mszip;
+ } alg;
+};
+
+static voidpf ndr_zlib_alloc(voidpf opaque, uInt items, uInt size)
+{
+ return talloc_zero_size(opaque, items * size);
+}
+
+static void ndr_zlib_free(voidpf opaque, voidpf address)
+{
+ talloc_free(address);
+}
+
+static enum ndr_err_code ndr_pull_compression_mszip_cab_chunk(struct ndr_pull *ndrpull,
+ struct ndr_push *ndrpush,
+ struct ndr_compression_state *state,
+ 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;
+ z_stream *z = state->alg.mszip.z;
+ int z_ret;
+
+ plain_chunk_size = decompressed_len;
+
+ if (plain_chunk_size > 0x00008000) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "Bad MSZIP CAB plain chunk size %08X > 0x00008000 (PULL)",
+ plain_chunk_size);
+ }
+
+
+ comp_chunk_size = compressed_len;
+
+ DEBUG(9,("MSZIP CAB 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;
+
+ if (comp_chunk.length < 2) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "Bad MSZIP CAB comp chunk size %u < 2 (PULL)",
+ (unsigned int)comp_chunk.length);
+ }
+ /* CK = Chris Kirmse, official Microsoft purloiner */
+ if (comp_chunk.data[0] != 'C' ||
+ comp_chunk.data[1] != 'K') {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "Bad MSZIP CAB invalid prefix [%c%c] != [CK]",
+ comp_chunk.data[0], comp_chunk.data[1]);
+ }
+
+ /*
+ * This is a MSZIP block. It is actually using the deflate
+ * algorithm which can be decompressed by zlib. zlib will try
+ * to decompress as much as it can in each run. If we provide
+ * all the input and enough room for the uncompressed output,
+ * one call is enough. It will loop over all the sub-blocks
+ * that make up a deflate block.
+ *
+ * See corresponding push function for more info.
+ */
+
+ z->next_in = comp_chunk.data + 2;
+ z->avail_in = comp_chunk.length - 2;
+ z->next_out = plain_chunk.data;
+ z->avail_out = plain_chunk.length;
+
+ /*
+ * Each MSZIP CDATA contains a complete deflate stream
+ * i.e. the stream starts and ends in the CFDATA but the
+ * _dictionary_ is shared between all CFDATA of a CFFOLDER.
+ *
+ * When decompressing, the initial dictionary of the first
+ * CDATA is empty. All other CFDATA use the previous CFDATA
+ * uncompressed output as dictionary.
+ */
+
+ if (state->alg.mszip.dict_size) {
+ z_ret = inflateSetDictionary(z, state->alg.mszip.dict, state->alg.mszip.dict_size);
+ if (z_ret != Z_OK) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "zlib inflateSetDictionary error %s (%d) %s (PULL)",
+ zError(z_ret), z_ret, z->msg);
+ }
+ }
+
+ z_ret = inflate(z, Z_FINISH);
+ if (z_ret == Z_OK) {
+ /*
+ * Z_OK here means there was no error but the stream
+ * hasn't been fully decompressed because there was
+ * not enough room for the output, which should not
+ * happen
+ */
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "zlib inflate error not enough space for output (PULL)");
+ }
+ if (z_ret != Z_STREAM_END) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "zlib inflate error %s (%d) %s (PULL)", zError(z_ret), z_ret, z->msg);
+ }
+
+ if (z->total_out < plain_chunk.length) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "zlib uncompressed output is smaller than expected (%lu < %zu) (PULL)",
+ z->total_out, plain_chunk.length);
+ }
+
+ /*
+ * Keep a copy of the output to set as dictionary for the
+ * next decompression call.
+ *
+ * The input pointer seems to be still valid between calls, so
+ * we can just store that instead of copying the memory over
+ * the dict temp buffer.
+ */
+ state->alg.mszip.dict = plain_chunk.data;
+ state->alg.mszip.dict_size = plain_chunk.length;
+
+ z_ret = inflateReset(z);
+ if (z_ret != Z_OK) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "zlib inflateReset error %s (%d) %s (PULL)",
+ zError(z_ret), z_ret, z->msg);
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_push_compression_mszip_cab_chunk(struct ndr_push *ndrpush,
+ struct ndr_pull *ndrpull,
+ struct ndr_compression_state *state)
+{
+ DATA_BLOB comp_chunk;
+ uint32_t comp_chunk_size;
+ DATA_BLOB plain_chunk;
+ uint32_t plain_chunk_size;
+ uint32_t plain_chunk_offset;
+ uint32_t max_plain_size = 0x00008000;
+ /*
+ * The maximum compressed size of each MSZIP block is 32k + 12 bytes
+ * header size.
+ */
+ uint32_t max_comp_size = 0x00008000 + 12;
+ int z_ret;
+ z_stream *z;
+
+ 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 = MIN(max_plain_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;
+
+ NDR_CHECK(ndr_push_expand(ndrpush, max_comp_size));
+
+ comp_chunk.data = ndrpush->data + ndrpush->offset;
+ comp_chunk.length = max_comp_size;
+
+ /* CK = Chris Kirmse, official Microsoft purloiner */
+ comp_chunk.data[0] = 'C';
+ comp_chunk.data[1] = 'K';
+
+ z = state->alg.mszip.z;
+ z->next_in = plain_chunk.data;
+ z->avail_in = plain_chunk.length;
+ z->total_in = 0;
+
+ z->next_out = comp_chunk.data + 2;
+ z->avail_out = comp_chunk.length;
+ z->total_out = 0;
+
+ /*
+ * See pull function for explanations of the MSZIP format.
+ *
+ * The CFDATA block contains a full deflate stream. Each stream
+ * uses the uncompressed input of the previous CFDATA in the
+ * same CFFOLDER as a dictionary for the compression.
+ */
+
+ if (state->alg.mszip.dict_size) {
+ z_ret = deflateSetDictionary(z, state->alg.mszip.dict, state->alg.mszip.dict_size);
+ if (z_ret != Z_OK) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "zlib deflateSetDictionary error %s (%d) %s (PUSH)",
+ zError(z_ret), z_ret, z->msg);
+ }
+ }
+
+ /*
+ * Z_FINISH should make deflate process all of the input in
+ * one call. If the stream is not finished there was an error
+ * e.g. not enough room to store the compressed output.
+ */
+ z_ret = deflate(z, Z_FINISH);
+ if (z_ret != Z_STREAM_END) {
+ return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION,
+ "zlib deflate error %s (%d) %s (PUSH)",
+ zError(z_ret), z_ret, z->msg);
+ }
+
+ if (z->avail_in) {
+ return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION,
+ "MSZIP not all avail_in[%u] bytes consumed (PUSH)",
+ z->avail_in);
+ }
+
+ comp_chunk_size = 2 + z->total_out;
+ if (comp_chunk_size < z->total_out) {
+ return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION,
+ "strange NDR push compressed size (integer overflow?)");
+ }
+
+ z_ret = deflateReset(z);
+ if (z_ret != Z_OK) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "zlib deflateReset error %s (%d) %s (PUSH)",
+ zError(z_ret), z_ret, z->msg);
+ }
+
+ if (plain_chunk.length > talloc_array_length(state->alg.mszip.dict)) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "zlib dict buffer is too big (PUSH)");
+ }
+
+ /*
+ * Keep a copy of the input to set as dictionary for the next
+ * compression call.
+ *
+ * Ideally we would just store the input pointer and length
+ * without copying but the memory gets invalidated between the
+ * calls, so we just copy to a dedicated buffer we now is
+ * still going to been valid for the lifetime of the
+ * compressions state object.
+ */
+ memcpy(state->alg.mszip.dict, plain_chunk.data, plain_chunk.length);
+ state->alg.mszip.dict_size = plain_chunk.length;
+
+ DEBUG(9,("MSZIP comp plain_chunk_size: %08X (%u) comp_chunk_size: %08X (%u)\n",
+ (unsigned int)plain_chunk.length,
+ (unsigned int)plain_chunk.length,
+ comp_chunk_size, comp_chunk_size));
+
+ ndrpush->offset += comp_chunk_size;
+ return NDR_ERR_SUCCESS;
+}
+
+
+static enum ndr_err_code ndr_pull_compression_mszip_chunk(struct ndr_pull *ndrpull,
+ struct ndr_push *ndrpush,
+ z_stream *z,
+ bool *last)
+{
+ 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;
+ int z_ret;
+
+ NDR_CHECK(ndr_pull_uint32(ndrpull, NDR_SCALARS, &plain_chunk_size));
+ if (plain_chunk_size > 0x00008000) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, "Bad MSZIP plain chunk size %08X > 0x00008000 (PULL)",
+ plain_chunk_size);
+ }
+
+ NDR_CHECK(ndr_pull_uint32(ndrpull, NDR_SCALARS, &comp_chunk_size));
+
+ DEBUG(9,("MSZIP 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;
+
+ if (comp_chunk.length < 2) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "Bad MSZIP comp chunk size %u < 2 (PULL)",
+ (unsigned int)comp_chunk.length);
+ }
+ /* CK = Chris Kirmse, official Microsoft purloiner */
+ if (comp_chunk.data[0] != 'C' ||
+ comp_chunk.data[1] != 'K') {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "Bad MSZIP invalid prefix [%c%c] != [CK]",
+ comp_chunk.data[0], comp_chunk.data[1]);
+ }
+
+ z->next_in = comp_chunk.data + 2;
+ z->avail_in = comp_chunk.length -2;
+ z->total_in = 0;
+
+ z->next_out = plain_chunk.data;
+ z->avail_out = plain_chunk.length;
+ z->total_out = 0;
+
+ if (!z->opaque) {
+ /* the first time we need to intialize completely */
+ z->zalloc = ndr_zlib_alloc;
+ z->zfree = ndr_zlib_free;
+ z->opaque = ndrpull;
+
+ z_ret = inflateInit2(z, -MAX_WBITS);
+ if (z_ret != Z_OK) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "Bad inflateInit2 error %s(%d) (PULL)",
+ zError(z_ret), z_ret);
+
+ }
+ }
+
+ /* call inflate untill we get Z_STREAM_END or an error */
+ while (true) {
+ z_ret = inflate(z, Z_BLOCK);
+ if (z_ret != Z_OK) break;
+ }
+
+ if (z_ret != Z_STREAM_END) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "Bad inflate(Z_BLOCK) error %s(%d) (PULL)",
+ zError(z_ret), z_ret);
+ }
+
+ if (z->avail_in) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "MSZIP not all avail_in[%u] bytes consumed (PULL)",
+ z->avail_in);
+ }
+
+ if (z->avail_out) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "MSZIP not all avail_out[%u] bytes consumed (PULL)",
+ z->avail_out);
+ }
+
+ if ((plain_chunk_size < 0x00008000) || (ndrpull->offset+4 >= ndrpull->data_size)) {
+ /* this is the last chunk */
+ *last = true;
+ }
+
+ z_ret = inflateReset(z);
+ if (z_ret != Z_OK) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "Bad inflateReset error %s(%d) (PULL)",
+ zError(z_ret), z_ret);
+ }
+
+ z_ret = inflateSetDictionary(z, plain_chunk.data, plain_chunk.length);
+ if (z_ret != Z_OK) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "Bad inflateSetDictionary error %s(%d) (PULL)",
+ zError(z_ret), z_ret);
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_push_compression_mszip_chunk(struct ndr_push *ndrpush,
+ struct ndr_pull *ndrpull,
+ z_stream *z,
+ bool *last)
+{
+ DATA_BLOB comp_chunk;
+ uint32_t comp_chunk_size;
+ uint32_t comp_chunk_size_offset;
+ DATA_BLOB plain_chunk;
+ uint32_t plain_chunk_size;
+ uint32_t plain_chunk_offset;
+ uint32_t max_plain_size = 0x00008000;
+ /*
+ * The maximum compressed size of each MSZIP block is 32k + 12 bytes
+ * header size.
+ */
+ uint32_t max_comp_size = 0x00008000 + 12;
+ uint32_t tmp_offset;
+ int z_ret;
+
+ plain_chunk_size = MIN(max_plain_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;
+
+ if (plain_chunk_size < max_plain_size) {
+ *last = true;
+ }
+
+ NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, plain_chunk_size));
+ comp_chunk_size_offset = ndrpush->offset;
+ NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, 0xFEFEFEFE));
+
+ NDR_CHECK(ndr_push_expand(ndrpush, max_comp_size));
+
+ comp_chunk.data = ndrpush->data + ndrpush->offset;
+ comp_chunk.length = max_comp_size;
+
+ /* CK = Chris Kirmse, official Microsoft purloiner */
+ comp_chunk.data[0] = 'C';
+ comp_chunk.data[1] = 'K';
+
+ z->next_in = plain_chunk.data;
+ z->avail_in = plain_chunk.length;
+ z->total_in = 0;
+
+ z->next_out = comp_chunk.data + 2;
+ z->avail_out = comp_chunk.length;
+ z->total_out = 0;
+
+ if (!z->opaque) {
+ /* the first time we need to intialize completely */
+ z->zalloc = ndr_zlib_alloc;
+ z->zfree = ndr_zlib_free;
+ z->opaque = ndrpull;
+
+ /* TODO: find how to trigger the same parameters windows uses */
+ z_ret = deflateInit2(z,
+ Z_DEFAULT_COMPRESSION,
+ Z_DEFLATED,
+ -MAX_WBITS,
+ 8, /* memLevel */
+ Z_DEFAULT_STRATEGY);
+ if (z_ret != Z_OK) {
+ return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION,
+ "Bad deflateInit2 error %s(%d) (PUSH)",
+ zError(z_ret), z_ret);
+
+ }
+ }
+
+ /* call deflate untill we get Z_STREAM_END or an error */
+ while (true) {
+ z_ret = deflate(z, Z_FINISH);
+ if (z_ret != Z_OK) break;
+ }
+ if (z_ret != Z_STREAM_END) {
+ return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION,
+ "Bad delate(Z_BLOCK) error %s(%d) (PUSH)",
+ zError(z_ret), z_ret);
+ }
+
+ if (z->avail_in) {
+ return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION,
+ "MSZIP not all avail_in[%u] bytes consumed (PUSH)",
+ z->avail_in);
+ }
+
+ comp_chunk_size = 2 + z->total_out;
+
+ z_ret = deflateReset(z);
+ if (z_ret != Z_OK) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "Bad deflateReset error %s(%d) (PULL)",
+ zError(z_ret), z_ret);
+ }
+
+ z_ret = deflateSetDictionary(z, plain_chunk.data, plain_chunk.length);
+ if (z_ret != Z_OK) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "Bad deflateSetDictionary error %s(%d) (PULL)",
+ zError(z_ret), z_ret);
+ }
+
+ tmp_offset = ndrpush->offset;
+ ndrpush->offset = comp_chunk_size_offset;
+ NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, comp_chunk_size));
+ ndrpush->offset = tmp_offset;
+
+ DEBUG(9,("MSZIP comp plain_chunk_size: %08X (%u) comp_chunk_size: %08X (%u)\n",
+ (unsigned int)plain_chunk.length,
+ (unsigned int)plain_chunk.length,
+ comp_chunk_size, comp_chunk_size));
+
+ ndrpush->offset += comp_chunk_size;
+ return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_compression_xpress_chunk(struct ndr_pull *ndrpull,
+ struct ndr_push *ndrpush,
+ bool *last)
+{
+ DATA_BLOB comp_chunk;
+ DATA_BLOB plain_chunk;
+ uint32_t comp_chunk_offset;
+ uint32_t plain_chunk_offset;
+ uint32_t comp_chunk_size;
+ uint32_t plain_chunk_size;
+ ssize_t ret;
+
+ NDR_CHECK(ndr_pull_uint32(ndrpull, NDR_SCALARS, &plain_chunk_size));
+ if (plain_chunk_size > 0x00010000) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, "Bad XPRESS plain chunk size %08X > 0x00010000 (PULL)",
+ plain_chunk_size);
+ }
+
+ NDR_CHECK(ndr_pull_uint32(ndrpull, NDR_SCALARS, &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;
+
+ DEBUG(9,("XPRESS plain_chunk_size: %08X (%u) comp_chunk_size: %08X (%u)\n",
+ plain_chunk_size, plain_chunk_size, comp_chunk_size, comp_chunk_size));
+
+ /* Uncompressing the buffer using LZ Xpress algorithm */
+ ret = lzxpress_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 lzxpress_decompress() returned %d\n",
+ (int)ret);
+ }
+ plain_chunk.length = ret;
+
+ if ((plain_chunk_size < 0x00010000) || (ndrpull->offset+4 >= ndrpull->data_size)) {
+ /* this is the last chunk */
+ *last = true;
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_push_compression_xpress_chunk(struct ndr_push *ndrpush,
+ struct ndr_pull *ndrpull,
+ bool *last)
+{
+ DATA_BLOB comp_chunk;
+ uint32_t comp_chunk_size_offset;
+ DATA_BLOB plain_chunk;
+ uint32_t plain_chunk_size;
+ uint32_t plain_chunk_offset;
+ uint32_t max_plain_size = 0x00010000;
+ uint32_t max_comp_size = 0x00020000 + 2; /* TODO: use the correct value here */
+ uint32_t tmp_offset;
+ ssize_t ret;
+
+ plain_chunk_size = MIN(max_plain_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;
+
+ if (plain_chunk_size < max_plain_size) {
+ *last = true;
+ }
+
+ NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, plain_chunk_size));
+ comp_chunk_size_offset = ndrpush->offset;
+ NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, 0xFEFEFEFE));
+
+ NDR_CHECK(ndr_push_expand(ndrpush, max_comp_size));
+
+ comp_chunk.data = ndrpush->data + ndrpush->offset;
+ comp_chunk.length = max_comp_size;
+
+ /* Compressing the buffer using LZ Xpress algorithm */
+ ret = lzxpress_compress(plain_chunk.data,
+ plain_chunk.length,
+ comp_chunk.data,
+ comp_chunk.length);
+ if (ret < 0) {
+ return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+ "XPRESS lzxpress_compress() returned %d\n",
+ (int)ret);
+ }
+ comp_chunk.length = ret;
+
+ tmp_offset = ndrpush->offset;
+ ndrpush->offset = comp_chunk_size_offset;
+ NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, comp_chunk.length));
+ ndrpush->offset = tmp_offset;
+
+ ndrpush->offset += comp_chunk.length;
+ 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
+*/
+enum ndr_err_code ndr_pull_compression_start(struct ndr_pull *subndr,
+ struct ndr_pull **_comndr,
+ enum ndr_compression_alg compression_alg,
+ ssize_t decompressed_len,
+ ssize_t compressed_len)
+{
+ struct ndr_push *ndrpush;
+ struct ndr_pull *comndr;
+ DATA_BLOB uncompressed;
+ bool last = false;
+ z_stream z;
+
+ ndrpush = ndr_push_init_ctx(subndr);
+ NDR_ERR_HAVE_NO_MEMORY(ndrpush);
+
+ switch (compression_alg) {
+ case NDR_COMPRESSION_MSZIP_CAB:
+ NDR_CHECK(ndr_pull_compression_mszip_cab_chunk(subndr, ndrpush,
+ subndr->cstate,
+ decompressed_len,
+ compressed_len));
+ break;
+ case NDR_COMPRESSION_MSZIP:
+ ZERO_STRUCT(z);
+ while (!last) {
+ NDR_CHECK(ndr_pull_compression_mszip_chunk(subndr, ndrpush, &z, &last));
+ }
+ break;
+
+ case NDR_COMPRESSION_XPRESS:
+ while (!last) {
+ NDR_CHECK(ndr_pull_compression_xpress_chunk(subndr, ndrpush, &last));
+ }
+ break;
+
+ default:
+ return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad compression algorithm %d (PULL)",
+ compression_alg);
+ }
+
+ uncompressed = ndr_push_blob(ndrpush);
+ if (uncompressed.length != decompressed_len) {
+ return ndr_pull_error(subndr, NDR_ERR_COMPRESSION,
+ "Bad uncompressed_len [%u] != [%u](0x%08X) (PULL)",
+ (int)uncompressed.length,
+ (int)decompressed_len,
+ (int)decompressed_len);
+ }
+
+ comndr = talloc_zero(subndr, struct ndr_pull);
+ NDR_ERR_HAVE_NO_MEMORY(comndr);
+ comndr->flags = subndr->flags;
+ comndr->current_mem_ctx = subndr->current_mem_ctx;
+
+ comndr->data = uncompressed.data;
+ comndr->data_size = uncompressed.length;
+ comndr->offset = 0;
+
+ *_comndr = comndr;
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_compression_end(struct ndr_pull *subndr,
+ struct ndr_pull *comndr,
+ enum ndr_compression_alg compression_alg,
+ ssize_t decompressed_len)
+{
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a compressed subcontext
+*/
+enum ndr_err_code ndr_push_compression_start(struct ndr_push *subndr,
+ struct ndr_push **_uncomndr,
+ enum ndr_compression_alg compression_alg,
+ ssize_t decompressed_len)
+{
+ struct ndr_push *uncomndr;
+
+ switch (compression_alg) {
+ case NDR_COMPRESSION_MSZIP_CAB:
+ case NDR_COMPRESSION_MSZIP:
+ case NDR_COMPRESSION_XPRESS:
+ break;
+ default:
+ return ndr_push_error(subndr, NDR_ERR_COMPRESSION,
+ "Bad compression algorithm %d (PUSH)",
+ compression_alg);
+ }
+
+ uncomndr = ndr_push_init_ctx(subndr);
+ NDR_ERR_HAVE_NO_MEMORY(uncomndr);
+ uncomndr->flags = subndr->flags;
+
+ *_uncomndr = uncomndr;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a compressed subcontext
+*/
+enum ndr_err_code ndr_push_compression_end(struct ndr_push *subndr,
+ struct ndr_push *uncomndr,
+ enum ndr_compression_alg compression_alg,
+ ssize_t decompressed_len)
+{
+ struct ndr_pull *ndrpull;
+ bool last = false;
+ z_stream z;
+
+ ndrpull = talloc_zero(uncomndr, struct ndr_pull);
+ NDR_ERR_HAVE_NO_MEMORY(ndrpull);
+ ndrpull->flags = uncomndr->flags;
+ ndrpull->data = uncomndr->data;
+ ndrpull->data_size = uncomndr->offset;
+ ndrpull->offset = 0;
+
+ switch (compression_alg) {
+ case NDR_COMPRESSION_MSZIP_CAB:
+ NDR_CHECK(ndr_push_compression_mszip_cab_chunk(subndr, ndrpull, subndr->cstate));
+ break;
+
+ case NDR_COMPRESSION_MSZIP:
+ ZERO_STRUCT(z);
+ while (!last) {
+ NDR_CHECK(ndr_push_compression_mszip_chunk(subndr, ndrpull, &z, &last));
+ }
+ break;
+
+ case NDR_COMPRESSION_XPRESS:
+ while (!last) {
+ NDR_CHECK(ndr_push_compression_xpress_chunk(subndr, ndrpull, &last));
+ }
+ break;
+
+ default:
+ return ndr_push_error(subndr, NDR_ERR_COMPRESSION, "Bad compression algorithm %d (PUSH)",
+ compression_alg);
+ }
+
+ talloc_free(uncomndr);
+ return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code generic_mszip_init(TALLOC_CTX *mem_ctx,
+ struct ndr_compression_state *state)
+{
+ z_stream *z = talloc_zero(mem_ctx, z_stream);
+ NDR_ERR_HAVE_NO_MEMORY(z);
+
+ z->zalloc = ndr_zlib_alloc;
+ z->zfree = ndr_zlib_free;
+ z->opaque = mem_ctx;
+
+ state->alg.mszip.z = z;
+ state->alg.mszip.dict_size = 0;
+ /* pre-alloc dictionary */
+ state->alg.mszip.dict = talloc_array(mem_ctx, uint8_t, 0x8000);
+ NDR_ERR_HAVE_NO_MEMORY(state->alg.mszip.dict);
+
+ return NDR_ERR_SUCCESS;
+}
+
+static void generic_mszip_free(struct ndr_compression_state *state)
+{
+ if (state == NULL) {
+ return;
+ }
+
+ TALLOC_FREE(state->alg.mszip.z);
+ TALLOC_FREE(state->alg.mszip.dict);
+}
+
+
+enum ndr_err_code ndr_pull_compression_state_init(struct ndr_pull *ndr,
+ enum ndr_compression_alg compression_alg,
+ struct ndr_compression_state **state)
+{
+ struct ndr_compression_state *s;
+ int z_ret;
+
+ s = talloc_zero(ndr, struct ndr_compression_state);
+ NDR_ERR_HAVE_NO_MEMORY(s);
+ s->type = compression_alg;
+
+ switch (compression_alg) {
+ case NDR_COMPRESSION_MSZIP:
+ case NDR_COMPRESSION_XPRESS:
+ break;
+ case NDR_COMPRESSION_MSZIP_CAB:
+ NDR_CHECK(generic_mszip_init(ndr, s));
+ z_ret = inflateInit2(s->alg.mszip.z, -MAX_WBITS);
+ if (z_ret != Z_OK) {
+ return ndr_pull_error(ndr, NDR_ERR_COMPRESSION,
+ "zlib inflateinit2 error %s (%d) %s (PULL)",
+ zError(z_ret), z_ret, s->alg.mszip.z->msg);
+ }
+ break;
+ default:
+ return ndr_pull_error(ndr, NDR_ERR_COMPRESSION,
+ "Bad compression algorithm %d (PULL)",
+ compression_alg);
+ break;
+ }
+
+ *state = s;
+
+ return NDR_ERR_SUCCESS;
+}
+
+void ndr_pull_compression_state_free(struct ndr_compression_state *state)
+{
+ if (state == NULL) {
+ return;
+ }
+
+ switch (state->type) {
+ case NDR_COMPRESSION_MSZIP:
+ case NDR_COMPRESSION_XPRESS:
+ break;
+ case NDR_COMPRESSION_MSZIP_CAB:
+ generic_mszip_free(state);
+ break;
+ default:
+ break;
+ }
+ TALLOC_FREE(state);
+}
+
+enum ndr_err_code ndr_push_compression_state_init(struct ndr_push *ndr,
+ enum ndr_compression_alg compression_alg,
+ struct ndr_compression_state **state)
+{
+ struct ndr_compression_state *s;
+ int z_ret;
+
+ s = talloc_zero(ndr, struct ndr_compression_state);
+ NDR_ERR_HAVE_NO_MEMORY(s);
+ s->type = compression_alg;
+
+ switch (compression_alg) {
+ case NDR_COMPRESSION_XPRESS:
+ case NDR_COMPRESSION_MSZIP:
+ break;
+ case NDR_COMPRESSION_MSZIP_CAB:
+ NDR_CHECK(generic_mszip_init(ndr, s));
+ z_ret = deflateInit2(s->alg.mszip.z,
+ Z_DEFAULT_COMPRESSION,
+ Z_DEFLATED,
+ -MAX_WBITS,
+ 8, /* memLevel */
+ Z_DEFAULT_STRATEGY);
+ if (z_ret != Z_OK) {
+ return ndr_push_error(ndr, NDR_ERR_COMPRESSION,
+ "zlib inflateinit2 error %s (%d) %s (PUSH)",
+ zError(z_ret), z_ret, s->alg.mszip.z->msg);
+ }
+ break;
+ default:
+ return ndr_push_error(ndr, NDR_ERR_COMPRESSION,
+ "Bad compression algorithm %d (PUSH)",
+ compression_alg);
+ break;
+ }
+
+ *state = s;
+
+ return NDR_ERR_SUCCESS;
+}
+
+void ndr_push_compression_state_free(struct ndr_compression_state *state)
+{
+ if (state == NULL) {
+ return;
+ }
+
+ switch (state->type) {
+ case NDR_COMPRESSION_MSZIP:
+ case NDR_COMPRESSION_XPRESS:
+ break;
+ case NDR_COMPRESSION_MSZIP_CAB:
+ generic_mszip_free(state);
+ break;
+ default:
+ break;
+ }
+ TALLOC_FREE(state);
+}
diff --git a/librpc/ndr/ndr_compression.h b/librpc/ndr/ndr_compression.h
new file mode 100644
index 0000000..a67a73e
--- /dev/null
+++ b/librpc/ndr/ndr_compression.h
@@ -0,0 +1,68 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ libndr compression support
+
+ Copyright (C) Stefan Metzmacher 2005
+ Copyright (C) Matthieu Suiche 2008
+
+ 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_COMPRESSION_H__
+#define __LIBRPC_NDR_NDR_COMPRESSION_H__
+
+#undef _PRINTF_ATTRIBUTE
+#define _PRINTF_ATTRIBUTE(a1, a2) PRINTF_ATTRIBUTE(a1, a2)
+/* This file was automatically generated by mkproto.pl. DO NOT EDIT */
+
+/* this file contains prototypes for functions that are private
+ * to this subsystem or library. These functions should not be
+ * used outside this particular subsystem! */
+
+
+/* The following definitions come from librpc/ndr/ndr_compression.c */
+
+enum ndr_err_code ndr_pull_compression_start(struct ndr_pull *subndr,
+ struct ndr_pull **_comndr,
+ enum ndr_compression_alg compression_alg,
+ ssize_t decompressed_len,
+ ssize_t compressed_len);
+enum ndr_err_code ndr_pull_compression_end(struct ndr_pull *subndr,
+ struct ndr_pull *comndr,
+ enum ndr_compression_alg compression_alg,
+ ssize_t decompressed_len);
+enum ndr_err_code ndr_push_compression_start(struct ndr_push *subndr,
+ struct ndr_push **_uncomndr,
+ enum ndr_compression_alg compression_alg,
+ ssize_t decompressed_len);
+enum ndr_err_code ndr_push_compression_end(struct ndr_push *subndr,
+ struct ndr_push *uncomndr,
+ enum ndr_compression_alg compression_alg,
+ ssize_t decompressed_len);
+
+enum ndr_err_code ndr_pull_compression_state_init(struct ndr_pull *ndr,
+ enum ndr_compression_alg compression_alg,
+ struct ndr_compression_state **state);
+void ndr_pull_compression_state_free(struct ndr_compression_state *state);
+enum ndr_err_code ndr_push_compression_state_init(struct ndr_push *ndr,
+ enum ndr_compression_alg compression_alg,
+ struct ndr_compression_state **state);
+void ndr_push_compression_state_free(struct ndr_compression_state *state);
+
+#undef _PRINTF_ATTRIBUTE
+#define _PRINTF_ATTRIBUTE(a1, a2)
+
+#endif /* __LIBRPC_NDR_NDR_COMPRESSION_H__ */
+
diff --git a/librpc/ndr/ndr_dcerpc.c b/librpc/ndr/ndr_dcerpc.c
new file mode 100644
index 0000000..ccb3af5
--- /dev/null
+++ b/librpc/ndr/ndr_dcerpc.c
@@ -0,0 +1,316 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Manually parsed structures found in the DCERPC protocol
+
+ Copyright (C) Stefan Metzmacher 2014
+ Copyright (C) Gregor Beck 2014
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_dcerpc.h"
+#include "librpc/gen_ndr/ndr_misc.h"
+
+_PUBLIC_ enum ndr_err_code ndr_push_ncacn_packet(struct ndr_push *ndr, int ndr_flags, const struct ncacn_packet *r)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->rpc_vers));
+ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->rpc_vers_minor));
+ NDR_CHECK(ndr_push_dcerpc_pkt_type(ndr, NDR_SCALARS, r->ptype));
+ NDR_CHECK(ndr_push_dcerpc_pfc_flags(ndr, NDR_SCALARS, r->pfc_flags));
+ NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->drep, 4));
+ if (r->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
+ ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
+ }
+ if (!(r->drep[0] & DCERPC_DREP_LE)) {
+ ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
+ }
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->frag_length));
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->auth_length));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->call_id));
+ NDR_CHECK(ndr_push_set_switch_value(ndr, &r->u, r->ptype));
+ NDR_CHECK(ndr_push_dcerpc_payload(ndr, NDR_SCALARS, &r->u));
+ NDR_CHECK(ndr_push_trailer_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_ncacn_packet(struct ndr_pull *ndr, int ndr_flags, struct ncacn_packet *r)
+{
+ uint32_t size_drep_0 = 0;
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->rpc_vers));
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->rpc_vers_minor));
+ NDR_CHECK(ndr_pull_dcerpc_pkt_type(ndr, NDR_SCALARS, &r->ptype));
+ NDR_CHECK(ndr_pull_dcerpc_pfc_flags(ndr, NDR_SCALARS, &r->pfc_flags));
+ size_drep_0 = 4;
+ NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->drep, size_drep_0));
+ if (r->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
+ ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
+ }
+ if (!(r->drep[0] & DCERPC_DREP_LE)) {
+ ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
+ }
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->frag_length));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->auth_length));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->call_id));
+ NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->u, r->ptype));
+ NDR_CHECK(ndr_pull_dcerpc_payload(ndr, NDR_SCALARS, &r->u));
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_ncacn_packet(struct ndr_print *ndr, const char *name, const struct ncacn_packet *r)
+{
+ ndr_print_struct(ndr, name, "ncacn_packet");
+ if (r == NULL) { ndr_print_null(ndr); return; }
+ ndr->depth++;
+ ndr_print_uint8(ndr, "rpc_vers", r->rpc_vers);
+ ndr_print_uint8(ndr, "rpc_vers_minor", r->rpc_vers_minor);
+ ndr_print_dcerpc_pkt_type(ndr, "ptype", r->ptype);
+ ndr_print_dcerpc_pfc_flags(ndr, "pfc_flags", r->pfc_flags);
+ ndr_print_array_uint8(ndr, "drep", r->drep, 4);
+ if (r->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
+ ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
+ }
+ if (!(r->drep[0] & DCERPC_DREP_LE)) {
+ ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
+ }
+ ndr_print_uint16(ndr, "frag_length", r->frag_length);
+ ndr_print_uint16(ndr, "auth_length", r->auth_length);
+ ndr_print_uint32(ndr, "call_id", r->call_id);
+ ndr_print_set_switch_value(ndr, &r->u, r->ptype);
+ ndr_print_dcerpc_payload(ndr, "u", &r->u);
+ ndr->depth--;
+}
+
+/*
+ * This function was generated by pidl and
+ * has been extended by the (_available == 0) check.
+ *
+ * That's why we ignore the 80 char per line limit.
+ */
+enum ndr_err_code ndr_pull_dcerpc_bind_nak(struct ndr_pull *ndr, int ndr_flags, struct dcerpc_bind_nak *r)
+{
+ uint32_t size_versions_0 = 0;
+ uint32_t cntr_versions_0;
+ TALLOC_CTX *_mem_save_versions_0 = NULL;
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ uint32_t _available;
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_dcerpc_bind_nak_reason(ndr, NDR_SCALARS, &r->reject_reason));
+ _available = ndr->data_size - ndr->offset;
+ if (_available == 0) {
+ /*
+ * This works around a bug in older
+ * Samba (<= 4.1) releases.
+ *
+ * See bug #11327.
+ */
+ r->num_versions = 0;
+ } else {
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->num_versions));
+ }
+ size_versions_0 = r->num_versions;
+ NDR_PULL_ALLOC_N(ndr, r->versions, size_versions_0);
+ _mem_save_versions_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->versions, 0);
+ for (cntr_versions_0 = 0; cntr_versions_0 < (size_versions_0); cntr_versions_0++) {
+ NDR_CHECK(ndr_pull_dcerpc_bind_nak_version(ndr, NDR_SCALARS, &r->versions[cntr_versions_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_versions_0, 0);
+ {
+ uint32_t _flags_save_DATA_BLOB = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
+ NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS, &r->_pad));
+ ndr->flags = _flags_save_DATA_BLOB;
+ }
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+const uint8_t DCERPC_SEC_VT_MAGIC[] = {0x8a,0xe3,0x13,0x71,0x02,0xf4,0x36,0x71};
+
+_PUBLIC_ enum ndr_err_code ndr_push_dcerpc_sec_vt_count(struct ndr_push *ndr, int ndr_flags, const struct dcerpc_sec_vt_count *r)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ /* nothing */
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_dcerpc_sec_vt_count(struct ndr_pull *ndr, int ndr_flags, struct dcerpc_sec_vt_count *r)
+{
+ uint32_t _saved_ofs = ndr->offset;
+
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ r->count = 0;
+
+ while (true) {
+ uint16_t command;
+ uint16_t length;
+
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &command));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &length));
+ NDR_CHECK(ndr_pull_advance(ndr, length));
+
+ r->count += 1;
+
+ if (command & DCERPC_SEC_VT_COMMAND_END) {
+ break;
+ }
+ }
+
+ ndr->offset = _saved_ofs;
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pop_dcerpc_sec_verification_trailer(
+ struct ndr_pull *ndr, TALLOC_CTX *mem_ctx,
+ struct dcerpc_sec_verification_trailer **_r)
+{
+ enum ndr_err_code ndr_err;
+ uint32_t ofs;
+ uint32_t min_ofs = 0;
+ struct dcerpc_sec_verification_trailer *r;
+ DATA_BLOB sub_blob = data_blob_null;
+ struct ndr_pull *sub_ndr = NULL;
+ uint32_t remaining;
+
+ *_r = NULL;
+
+ r = talloc_zero(mem_ctx, struct dcerpc_sec_verification_trailer);
+ if (r == NULL) {
+ return NDR_ERR_ALLOC;
+ }
+
+ if (ndr->data_size < sizeof(DCERPC_SEC_VT_MAGIC)) {
+ /*
+ * we return with r->count = 0
+ */
+ *_r = r;
+ return NDR_ERR_SUCCESS;
+ }
+
+ ofs = ndr->data_size - sizeof(DCERPC_SEC_VT_MAGIC);
+ /* the magic is 4 byte aligned */
+ ofs &= ~3;
+
+ if (ofs > DCERPC_SEC_VT_MAX_SIZE) {
+ /*
+ * We just scan the last 1024 bytes.
+ */
+ min_ofs = ofs - DCERPC_SEC_VT_MAX_SIZE;
+ } else {
+ min_ofs = 0;
+ }
+
+ while (true) {
+ int ret;
+
+ ret = memcmp(&ndr->data[ofs],
+ DCERPC_SEC_VT_MAGIC,
+ sizeof(DCERPC_SEC_VT_MAGIC));
+ if (ret == 0) {
+ sub_blob = data_blob_const(&ndr->data[ofs],
+ ndr->data_size - ofs);
+ break;
+ }
+
+ if (ofs <= min_ofs) {
+ break;
+ }
+
+ ofs -= 4;
+ }
+
+ if (sub_blob.length == 0) {
+ /*
+ * we return with r->count = 0
+ */
+ *_r = r;
+ return NDR_ERR_SUCCESS;
+ }
+
+ sub_ndr = ndr_pull_init_blob(&sub_blob, r);
+ if (sub_ndr == NULL) {
+ TALLOC_FREE(r);
+ return NDR_ERR_ALLOC;
+ }
+
+ ndr_err = ndr_pull_dcerpc_sec_verification_trailer(sub_ndr,
+ NDR_SCALARS | NDR_BUFFERS,
+ r);
+ if (ndr_err == NDR_ERR_ALLOC) {
+ TALLOC_FREE(r);
+ return NDR_ERR_ALLOC;
+ }
+
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ goto ignore_error;
+ }
+
+ remaining = sub_ndr->data_size - sub_ndr->offset;
+ if (remaining > 16) {
+ /*
+ * we expect not more than 16 byte of additional
+ * padding after the verification trailer.
+ */
+ goto ignore_error;
+ }
+
+ /*
+ * We assume that we got a real verification trailer.
+ *
+ * We remove it from the available stub data.
+ */
+ ndr->data_size = ofs;
+
+ TALLOC_FREE(sub_ndr);
+
+ *_r = r;
+ return NDR_ERR_SUCCESS;
+
+ignore_error:
+ TALLOC_FREE(sub_ndr);
+ /*
+ * just ignore the error, it's likely
+ * that the magic we found belongs to
+ * the stub data.
+ *
+ * we return with r->count = 0
+ */
+ ZERO_STRUCTP(r);
+ *_r = r;
+ return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_dcerpc.h b/librpc/ndr/ndr_dcerpc.h
new file mode 100644
index 0000000..1a7c3bd
--- /dev/null
+++ b/librpc/ndr/ndr_dcerpc.h
@@ -0,0 +1,29 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Manually parsed structures found in the DCERPC protocol
+
+ Copyright (C) Stefan Metzmacher 2014
+ Copyright (C) Gregor Beck 2014
+
+ 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/>.
+*/
+
+enum ndr_err_code ndr_pop_dcerpc_sec_verification_trailer(
+ struct ndr_pull *ndr, TALLOC_CTX *mem_ctx,
+ struct dcerpc_sec_verification_trailer **_r);
+
+#ifndef NDR_DCERPC_REQUEST_OBJECT_PRESENT
+#define NDR_DCERPC_REQUEST_OBJECT_PRESENT (ndr->flags & LIBNDR_FLAG_OBJECT_PRESENT)
+#endif /* NDR_DCERPC_REQUEST_OBJECT_PRESENT */
diff --git a/librpc/ndr/ndr_dns.c b/librpc/ndr/ndr_dns.c
new file mode 100644
index 0000000..966e0b5
--- /dev/null
+++ b/librpc/ndr/ndr_dns.c
@@ -0,0 +1,327 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ manipulate dns name structures
+
+ Copyright (C) 2010 Kai Blin <kai@samba.org>
+
+ Heavily based on nbtname.c which is:
+
+ Copyright (C) Andrew Tridgell 2005
+
+ 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/>.
+*/
+
+/*
+ see rfc1002 for the detailed format of compressed names
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_dns.h"
+#include "librpc/gen_ndr/ndr_misc.h"
+#include "librpc/gen_ndr/ndr_dnsp.h"
+#include "system/locale.h"
+#include "lib/util/util_net.h"
+#include "ndr_dns_utils.h"
+
+/* don't allow an unlimited number of name components */
+#define MAX_COMPONENTS 128
+
+/**
+ print a dns string
+*/
+_PUBLIC_ void ndr_print_dns_string(struct ndr_print *ndr,
+ const char *name,
+ const char *s)
+{
+ ndr_print_string(ndr, name, s);
+}
+
+/*
+ pull one component of a dns_string
+*/
+static enum ndr_err_code ndr_pull_component(struct ndr_pull *ndr,
+ uint8_t **component,
+ uint32_t *offset,
+ uint32_t *max_offset)
+{
+ uint8_t len;
+ unsigned int loops = 0;
+ while (loops < 5) {
+ if (*offset >= ndr->data_size) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING,
+ "BAD DNS NAME component, bad offset");
+ }
+ len = ndr->data[*offset];
+ if (len == 0) {
+ *offset += 1;
+ *max_offset = MAX(*max_offset, *offset);
+ *component = NULL;
+ return NDR_ERR_SUCCESS;
+ }
+ if ((len & 0xC0) == 0xC0) {
+ /* its a label pointer */
+ if (1 + *offset >= ndr->data_size) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING,
+ "BAD DNS NAME component, " \
+ "bad label offset");
+ }
+ *max_offset = MAX(*max_offset, *offset + 2);
+ *offset = ((len&0x3F)<<8) | ndr->data[1 + *offset];
+ *max_offset = MAX(*max_offset, *offset);
+ loops++;
+ continue;
+ }
+ if ((len & 0xC0) != 0) {
+ /* its a reserved length field */
+ return ndr_pull_error(ndr, NDR_ERR_STRING,
+ "BAD DNS NAME component, " \
+ "reserved length field: 0x%02x",
+ (len &0xC));
+ }
+ if (*offset + len + 1 > ndr->data_size) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING,
+ "BAD DNS NAME component, "\
+ "length too long");
+ }
+ *component = (uint8_t*)talloc_strndup(ndr,
+ (const char *)&ndr->data[1 + *offset], len);
+ NDR_ERR_HAVE_NO_MEMORY(*component);
+ *offset += len + 1;
+ *max_offset = MAX(*max_offset, *offset);
+ return NDR_ERR_SUCCESS;
+ }
+
+ /* too many pointers */
+ return ndr_pull_error(ndr, NDR_ERR_STRING,
+ "BAD DNS NAME component, too many pointers");
+}
+
+/**
+ pull a dns_string from the wire
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_dns_string(struct ndr_pull *ndr,
+ int ndr_flags,
+ const char **s)
+{
+ uint32_t offset = ndr->offset;
+ uint32_t max_offset = offset;
+ unsigned num_components;
+ char *name;
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ name = talloc_strdup(ndr->current_mem_ctx, "");
+
+ /* break up name into a list of components */
+ for (num_components=0; num_components<MAX_COMPONENTS;
+ num_components++) {
+ uint8_t *component = NULL;
+ NDR_CHECK(ndr_pull_component(ndr, &component, &offset,
+ &max_offset));
+ if (component == NULL) break;
+ if (num_components > 0) {
+ name = talloc_asprintf_append_buffer(name, ".%s",
+ component);
+ } else {
+ name = talloc_asprintf_append_buffer(name, "%s",
+ component);
+ }
+ NDR_ERR_HAVE_NO_MEMORY(name);
+ }
+ if (num_components == MAX_COMPONENTS) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING,
+ "BAD DNS NAME too many components");
+ }
+
+ (*s) = name;
+ ndr->offset = max_offset;
+
+ return NDR_ERR_SUCCESS;
+}
+
+/**
+ push a dns string to the wire
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_dns_string(struct ndr_push *ndr,
+ int ndr_flags,
+ const char *s)
+{
+ return ndr_push_dns_string_list(ndr,
+ &ndr->dns_string_list,
+ ndr_flags,
+ s,
+ false);
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_dns_txt_record(struct ndr_pull *ndr, int ndr_flags, struct dns_txt_record *r)
+{
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ enum ndr_err_code ndr_err;
+ uint32_t data_size = ndr->data_size;
+ uint32_t record_size = 0;
+ ndr_err = ndr_token_retrieve(&ndr->array_size_list, r,
+ &record_size);
+ if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NDR_PULL_NEED_BYTES(ndr, record_size);
+ ndr->data_size = ndr->offset + record_size;
+ }
+ NDR_CHECK(ndr_pull_align(ndr, 1));
+ NDR_CHECK(ndr_pull_dnsp_string_list(ndr, NDR_SCALARS, &r->txt));
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 1));
+ ndr->data_size = data_size;
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_dns_res_rec(struct ndr_push *ndr,
+ int ndr_flags,
+ const struct dns_res_rec *r)
+{
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ uint32_t _saved_offset1, _saved_offset2;
+ uint16_t length;
+ ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX |
+ LIBNDR_FLAG_NOALIGN);
+ if (ndr_flags & NDR_SCALARS) {
+ uint32_t _flags_save_name = ndr->flags;
+
+ NDR_CHECK(ndr_push_align(ndr, 4));
+
+ switch (r->rr_type) {
+ case DNS_QTYPE_TKEY:
+ case DNS_QTYPE_TSIG:
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NO_COMPRESSION);
+ break;
+ default:
+ break;
+ }
+ NDR_CHECK(ndr_push_dns_string(ndr, NDR_SCALARS, r->name));
+ ndr->flags = _flags_save_name;
+
+ NDR_CHECK(ndr_push_dns_qtype(ndr, NDR_SCALARS, r->rr_type));
+ NDR_CHECK(ndr_push_dns_qclass(ndr, NDR_SCALARS, r->rr_class));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->ttl));
+ _saved_offset1 = ndr->offset;
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 0));
+ if (r->length > 0) {
+ uint32_t _saved_offset3;
+
+ NDR_CHECK(ndr_push_set_switch_value(ndr, &r->rdata,
+ r->rr_type));
+ _saved_offset3 = ndr->offset;
+ NDR_CHECK(ndr_push_dns_rdata(ndr, NDR_SCALARS,
+ &r->rdata));
+ if ((ndr->offset != _saved_offset3) &&
+ (r->unexpected.length > 0)) {
+ /*
+ * ndr_push_dns_rdata pushed a known
+ * record, but we have something
+ * unexpected. That's invalid.
+ */
+ return ndr_push_error(ndr,
+ NDR_ERR_LENGTH,
+ "Invalid...Unexpected " \
+ "blob length is too " \
+ "large");
+ }
+ }
+ if (r->unexpected.length > UINT16_MAX) {
+ return ndr_push_error(ndr, NDR_ERR_LENGTH,
+ "Unexpected blob length "\
+ "is too large");
+ }
+
+ NDR_CHECK(ndr_push_bytes(ndr, r->unexpected.data,
+ r->unexpected.length));
+ NDR_CHECK(ndr_push_trailer_align(ndr, 4));
+ length = ndr->offset - (_saved_offset1 + 2);
+ _saved_offset2 = ndr->offset;
+ ndr->offset = _saved_offset1;
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, length));
+ ndr->offset = _saved_offset2;
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ NDR_CHECK(ndr_push_dns_rdata(ndr, NDR_BUFFERS,
+ &r->rdata));
+ }
+ ndr->flags = _flags_save_STRUCT;
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_dns_res_rec(struct ndr_pull *ndr,
+ int ndr_flags,
+ struct dns_res_rec *r)
+{
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ uint32_t _saved_offset1;
+ uint32_t pad, length;
+
+ ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX |
+ LIBNDR_FLAG_NOALIGN);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_dns_string(ndr, NDR_SCALARS, &r->name));
+ NDR_CHECK(ndr_pull_dns_qtype(ndr, NDR_SCALARS, &r->rr_type));
+ NDR_CHECK(ndr_pull_dns_qclass(ndr, NDR_SCALARS, &r->rr_class));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->ttl));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->length));
+ _saved_offset1 = ndr->offset;
+ if (r->length > 0) {
+ NDR_CHECK(ndr_token_store(ndr, &ndr->array_size_list,
+ &r->rdata,
+ r->length));
+ NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->rdata,
+ r->rr_type));
+ NDR_CHECK(ndr_pull_dns_rdata(ndr, NDR_SCALARS,
+ &r->rdata));
+ } else {
+ ZERO_STRUCT(r->rdata);
+ }
+ length = ndr->offset - _saved_offset1;
+ if (length > r->length) {
+ return ndr_pull_error(ndr, NDR_ERR_LENGTH, "TODO");
+ }
+
+ r->unexpected = data_blob_null;
+ pad = r->length - length;
+ if (pad > 0) {
+ NDR_PULL_NEED_BYTES(ndr, pad);
+ r->unexpected = data_blob_talloc(ndr->current_mem_ctx,
+ ndr->data +
+ ndr->offset,
+ pad);
+ if (r->unexpected.data == NULL) {
+ return ndr_pull_error(ndr,
+ NDR_ERR_ALLOC,
+ "Failed to allocate a " \
+ "data blob");
+ }
+ ndr->offset += pad;
+ }
+
+
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ NDR_CHECK(ndr_pull_dns_rdata(ndr, NDR_BUFFERS, &r->rdata));
+ }
+ ndr->flags = _flags_save_STRUCT;
+ return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_dns.h b/librpc/ndr/ndr_dns.h
new file mode 100644
index 0000000..16bf11b
--- /dev/null
+++ b/librpc/ndr/ndr_dns.h
@@ -0,0 +1,40 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ manipulate dns name structures
+
+ Copyright (C) 2010 Kai Blin <kai@samba.org>
+
+ Heavily based on nbtname.c which is:
+
+ Copyright (C) Andrew Tridgell 2005
+
+ 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/>.
+*/
+
+void ndr_print_dns_string(struct ndr_print *ndr,
+ const char *name,
+ const char *s);
+enum ndr_err_code ndr_pull_dns_string(struct ndr_pull *ndr,
+ int ndr_flags,
+ const char **s);
+enum ndr_err_code ndr_push_dns_string(struct ndr_push *ndr,
+ int ndr_flags,
+ const char *s);
+enum ndr_err_code ndr_push_dns_res_rec(struct ndr_push *ndr,
+ int ndr_flags,
+ const struct dns_res_rec *r);
+enum ndr_err_code ndr_pull_dns_res_rec(struct ndr_pull *ndr,
+ int ndr_flags,
+ struct dns_res_rec *r);
diff --git a/librpc/ndr/ndr_dns_utils.c b/librpc/ndr/ndr_dns_utils.c
new file mode 100644
index 0000000..325d9c6
--- /dev/null
+++ b/librpc/ndr/ndr_dns_utils.c
@@ -0,0 +1,134 @@
+#include "includes.h"
+#include "../librpc/ndr/libndr.h"
+#include "ndr_dns_utils.h"
+
+
+/**
+ push a dns/nbt string list to the wire
+*/
+enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr,
+ struct ndr_token_list *string_list,
+ int ndr_flags,
+ const char *s,
+ bool is_nbt)
+{
+ const char *start = s;
+ bool use_compression;
+ size_t max_length;
+ if (is_nbt) {
+ use_compression = true;
+ /*
+ * Max length is longer in NBT/Wins, because Windows counts
+ * the semi-decompressed size of the netbios name (16 bytes)
+ * rather than the wire size of 32, which is what you'd expect
+ * if it followed RFC1002 (it uses the short form in
+ * [MS-WINSRA]). In other words the maximum size of the
+ * "scope" is 237, not 221.
+ *
+ * We make the size limit slightly larger than 255 + 16,
+ * because the 237 scope limit is already enforced in the
+ * winsserver code with a specific return value; bailing out
+ * here would muck with that.
+ */
+ max_length = 274;
+ } else {
+ use_compression = !(ndr->flags & LIBNDR_FLAG_NO_COMPRESSION);
+ max_length = 255;
+ }
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ while (s && *s) {
+ enum ndr_err_code ndr_err;
+ char *compname;
+ size_t complen;
+ uint32_t offset;
+
+ if (use_compression) {
+ /* see if we have pushed the remaining string already,
+ * if so we use a label pointer to this string
+ */
+ ndr_err = ndr_token_retrieve_cmp_fn(string_list, s,
+ &offset,
+ (comparison_fn_t)strcmp,
+ false);
+ if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ uint8_t b[2];
+
+ if (offset > 0x3FFF) {
+ return ndr_push_error(ndr, NDR_ERR_STRING,
+ "offset for dns string " \
+ "label pointer " \
+ "%u[%08X] > 0x00003FFF",
+ offset, offset);
+ }
+
+ b[0] = 0xC0 | (offset>>8);
+ b[1] = (offset & 0xFF);
+
+ return ndr_push_bytes(ndr, b, 2);
+ }
+ }
+
+ complen = strcspn(s, ".");
+
+ /* the length must fit into 6 bits (i.e. <= 63) */
+ if (complen > 0x3F) {
+ return ndr_push_error(ndr, NDR_ERR_STRING,
+ "component length %u[%08X] > " \
+ "0x0000003F",
+ (unsigned)complen,
+ (unsigned)complen);
+ }
+
+ if (complen == 0 && s[complen] == '.') {
+ return ndr_push_error(ndr, NDR_ERR_STRING,
+ "component length is 0 "
+ "(consecutive dots)");
+ }
+
+ if (is_nbt && s[complen] == '.' && s[complen + 1] == '\0') {
+ /* nbt names are sometimes usernames, and we need to
+ * keep a trailing dot to ensure it is byte-identical,
+ * (not just semantically identical given DNS
+ * semantics). */
+ complen++;
+ }
+
+ compname = talloc_asprintf(ndr, "%c%*.*s",
+ (unsigned char)complen,
+ (unsigned char)complen,
+ (unsigned char)complen, s);
+ NDR_ERR_HAVE_NO_MEMORY(compname);
+
+ /* remember the current component + the rest of the string
+ * so it can be reused later
+ */
+ if (use_compression) {
+ NDR_CHECK(ndr_token_store(ndr, string_list, s,
+ ndr->offset));
+ }
+
+ /* push just this component into the blob */
+ NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)compname,
+ complen+1));
+ talloc_free(compname);
+
+ s += complen;
+ if (*s == '.') {
+ s++;
+ }
+ if (s - start > max_length) {
+ return ndr_push_error(ndr, NDR_ERR_STRING,
+ "name > %zu character long",
+ max_length);
+ }
+ }
+
+ /* if we reach the end of the string and have pushed the last component
+ * without using a label pointer, we need to terminate the string
+ */
+ return ndr_push_bytes(ndr, (const uint8_t *)"", 1);
+}
diff --git a/librpc/ndr/ndr_dns_utils.h b/librpc/ndr/ndr_dns_utils.h
new file mode 100644
index 0000000..71a6543
--- /dev/null
+++ b/librpc/ndr/ndr_dns_utils.h
@@ -0,0 +1,6 @@
+
+enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr,
+ struct ndr_token_list *string_list,
+ int ndr_flags,
+ const char *s,
+ bool is_nbt);
diff --git a/librpc/ndr/ndr_dnsp.c b/librpc/ndr/ndr_dnsp.c
new file mode 100644
index 0000000..d75c58f
--- /dev/null
+++ b/librpc/ndr/ndr_dnsp.c
@@ -0,0 +1,263 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Manually parsed structures found in DNSP
+
+ Copyright (C) Andrew Tridgell 2010
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_dnsp.h"
+
+/*
+ print a dnsp_name
+*/
+_PUBLIC_ void ndr_print_dnsp_name(struct ndr_print *ndr, const char *name,
+ const char *dns_name)
+{
+ ndr->print(ndr, "%-25s: %s", name, dns_name);
+}
+
+/*
+ pull a dnsp_name
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_dnsp_name(struct ndr_pull *ndr, int ndr_flags, const char **name)
+{
+ uint8_t len, count, termination;
+ int i;
+ uint32_t total_len, raw_offset;
+ char *ret;
+
+ NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &len));
+ NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &count));
+
+ raw_offset = ndr->offset;
+
+ ret = talloc_strdup(ndr->current_mem_ctx, "");
+ if (!ret) {
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name");
+ }
+ total_len = 1;
+
+ for (i=0; i<count; i++) {
+ uint8_t sublen, newlen;
+ NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &sublen));
+ newlen = total_len + sublen;
+ if (newlen < total_len) {
+ return ndr_pull_error(ndr, NDR_ERR_RANGE,
+ "Failed to pull dnsp_name");
+ }
+ if (i != count-1) {
+ if (newlen == UINT8_MAX) {
+ return ndr_pull_error(
+ ndr, NDR_ERR_RANGE,
+ "Failed to pull dnsp_name");
+ }
+ newlen++; /* for the '.' */
+ }
+ ret = talloc_realloc(ndr->current_mem_ctx, ret, char, newlen);
+ if (!ret) {
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name");
+ }
+ NDR_CHECK(ndr_pull_bytes(ndr, (uint8_t *)&ret[total_len-1], sublen));
+ if (i != count-1) {
+ ret[newlen-2] = '.';
+ }
+ ret[newlen-1] = 0;
+ total_len = newlen;
+ }
+ NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &termination));
+ if (termination != 0) {
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name - not NUL terminated");
+ }
+ if (ndr->offset > raw_offset + len) {
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_name - overrun by %u bytes",
+ ndr->offset - (raw_offset + len));
+ }
+ /* there could be additional pad bytes */
+ while (ndr->offset < raw_offset + len) {
+ uint8_t pad;
+ NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &pad));
+ }
+ (*name) = ret;
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_push_dnsp_name(struct ndr_push *ndr, int ndr_flags, const char *name)
+{
+ int count, total_len, i;
+
+ /* count the dots */
+ for (count=i=0; name[i]; i++) {
+ if (name[i] == '.') count++;
+ }
+ total_len = strlen(name) + 1;
+
+ /*
+ * cope with names ending in '.'
+ */
+ if (name[0] == '\0') {
+ /*
+ * Don't access name[-1] for the "" input, which has
+ * the same meaning as a lone '.'.
+ *
+ * This allows a round-trip of a dnsRecord from
+ * Windows of a MX record of '.'
+ */
+ } else if (name[strlen(name)-1] != '.') {
+ total_len++;
+ count++;
+ }
+ if (total_len > 255 || count > 255) {
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
+ "dns_name of length %d larger than 255", total_len);
+ }
+ NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)total_len));
+ NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)count));
+ for (i=0; i<count; i++) {
+ const char *p = strchr(name, '.');
+ size_t sublen = p?(p-name):strlen(name);
+ NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)sublen));
+ NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)name, sublen));
+ name += sublen + 1;
+ }
+ NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, 0));
+
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ print a dnsp_string
+*/
+_PUBLIC_ void ndr_print_dnsp_string(struct ndr_print *ndr, const char *name,
+ const char *dns_string)
+{
+ ndr->print(ndr, "%-25s: %s", name, dns_string);
+}
+
+/*
+ pull a dnsp_string
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_dnsp_string(struct ndr_pull *ndr, int ndr_flags, const char **string)
+{
+ uint8_t len;
+ char *ret;
+
+ NDR_CHECK(ndr_pull_uint8(ndr, ndr_flags, &len));
+
+ ret = talloc_zero_array(ndr->current_mem_ctx, char, len + 1);
+ if (!ret) {
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_string");
+ }
+ NDR_CHECK(ndr_pull_bytes(ndr, (uint8_t *)ret, len));
+
+ (*string) = ret;
+ NDR_PULL_ALIGN(ndr, 1);
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_push_dnsp_string(struct ndr_push *ndr, int ndr_flags, const char *string)
+{
+ int total_len;
+ total_len = strlen(string);
+ if (total_len > 255) {
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
+ "dns_name of length %d larger than 255", total_len);
+ }
+ NDR_CHECK(ndr_push_uint8(ndr, ndr_flags, (uint8_t)total_len));
+ NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)string, total_len));
+
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ * print a dnsp_string_list
+ */
+_PUBLIC_ void ndr_print_dnsp_string_list(struct ndr_print *ndr, const char *name,
+ const struct dnsp_string_list *list)
+{
+ uint32_t i;
+
+ ndr->no_newline = true;
+ for (i=0; i<ndr->depth; i++) {
+ ndr->print(ndr, " ");
+ }
+ ndr->print(ndr, "%-25s:", name);
+ for (i=0; i<list->count; i++) {
+ ndr->print(ndr, " \"%s\"", list->str[i]);
+ }
+ ndr->print(ndr, "\n");
+ ndr->no_newline = false;
+}
+
+/*
+ * pull a dnsp_string_list
+ */
+_PUBLIC_ enum ndr_err_code ndr_pull_dnsp_string_list(struct ndr_pull *ndr, int ndr_flags, struct dnsp_string_list *list)
+{
+ list->count = 0;
+ list->str = talloc_array(ndr->current_mem_ctx, const char *,
+ list->count);
+ if (! list->str) {
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_string_list");
+ }
+
+ while (ndr->offset < ndr->data_size) {
+ list->str = talloc_realloc(ndr->current_mem_ctx, list->str,
+ const char *, list->count+1);
+ if (! list->str) {
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull dnsp_string_list");
+ }
+ NDR_CHECK(ndr_pull_dnsp_string(ndr, ndr_flags, &list->str[list->count]));
+ list->count++;
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_push_dnsp_string_list(struct ndr_push *ndr, int ndr_flags, const struct dnsp_string_list *list)
+{
+ uint8_t i;
+
+ for (i=0; i<list->count; i++) {
+ NDR_CHECK(ndr_push_dnsp_string(ndr, ndr_flags, list->str[i]));
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_dnsp_string_list_copy(TALLOC_CTX *mem_ctx,
+ const struct dnsp_string_list *src,
+ struct dnsp_string_list *dst)
+{
+ size_t i;
+
+ dst->count = 0;
+ dst->str = talloc_zero_array(mem_ctx, const char *, src->count);
+ if (dst->str == NULL) {
+ return NDR_ERR_ALLOC;
+ }
+
+ for (i = 0; i < src->count; i++) {
+ dst->str[i] = talloc_strdup(dst->str, src->str[i]);
+ if (dst->str[i] == NULL) {
+ TALLOC_FREE(dst->str);
+ return NDR_ERR_ALLOC;
+ }
+ }
+
+ dst->count = src->count;
+ return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_dnsp.h b/librpc/ndr/ndr_dnsp.h
new file mode 100644
index 0000000..0d56633
--- /dev/null
+++ b/librpc/ndr/ndr_dnsp.h
@@ -0,0 +1,33 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Manually parsed structures found in the DNSP IDL
+
+ Copyright (C) Andrew Tridgell 2010
+
+ 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/>.
+*/
+
+void ndr_print_dnsp_name(struct ndr_print *ndr, const char *name,
+ const char *dns_name);
+enum ndr_err_code ndr_pull_dnsp_name(struct ndr_pull *ndr, int ndr_flags, const char **name);
+enum ndr_err_code ndr_push_dnsp_name(struct ndr_push *ndr, int ndr_flags, const char *name);
+void ndr_print_dnsp_string(struct ndr_print *ndr, const char *name,
+ const char *dns_string);
+enum ndr_err_code ndr_pull_dnsp_string(struct ndr_pull *ndr, int ndr_flags, const char **string);
+enum ndr_err_code ndr_push_dnsp_string(struct ndr_push *ndr, int ndr_flags, const char *string);
+
+enum ndr_err_code ndr_dnsp_string_list_copy(TALLOC_CTX *mem_ctx,
+ const struct dnsp_string_list *src,
+ struct dnsp_string_list *dst);
diff --git a/librpc/ndr/ndr_dnsserver.c b/librpc/ndr/ndr_dnsserver.c
new file mode 100644
index 0000000..3201f04
--- /dev/null
+++ b/librpc/ndr/ndr_dnsserver.c
@@ -0,0 +1,100 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Manually parsed structures for DNSSERVER
+
+ Copyright (C) Amitay Isaacs 2011
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_dnsp.h"
+#include "librpc/gen_ndr/ndr_dnsserver.h"
+
+/*
+ * parsing DNS_RPC_RECORDS_ARRAY
+ */
+
+enum ndr_err_code ndr_pull_DNS_RPC_RECORDS_ARRAY(struct ndr_pull *ndr,
+ int ndr_flags, struct DNS_RPC_RECORDS_ARRAY *rec)
+{
+ rec->count = 0;
+ rec->rec = talloc_array(ndr->current_mem_ctx, struct DNS_RPC_RECORDS, rec->count);
+ if (! rec->rec) {
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull DNS_RPC_RECORDS_ARRAY");
+ }
+
+ while (ndr->offset < ndr->data_size) {
+ rec->rec = talloc_realloc(ndr->current_mem_ctx, rec->rec, struct DNS_RPC_RECORDS, rec->count+1);
+ if (! rec->rec) {
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull DNS_RPC_RECORDS_ARRAY");
+ }
+ NDR_CHECK(ndr_pull_DNS_RPC_RECORDS(ndr, ndr_flags, &rec->rec[rec->count]));
+ NDR_PULL_ALIGN(ndr, 4);
+ rec->count++;
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_push_DNS_RPC_RECORDS_ARRAY(struct ndr_push *ndr,
+ int ndr_flags, const struct DNS_RPC_RECORDS_ARRAY *rec)
+{
+ int i;
+
+ for (i=0; i<rec->count; i++) {
+ NDR_CHECK(ndr_push_DNS_RPC_RECORDS(ndr, ndr_flags, &rec->rec[i]));
+ NDR_PUSH_ALIGN(ndr, 4);
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ * Parsing of DNS_RPC_RECORD_STRING
+ */
+
+enum ndr_err_code ndr_pull_DNS_RPC_RECORD_STRING(struct ndr_pull *ndr,
+ int ndr_flags, struct DNS_RPC_RECORD_STRING *rec)
+{
+ rec->count = 0;
+ rec->str = talloc_array(ndr->current_mem_ctx, struct DNS_RPC_NAME, rec->count);
+ if (! rec->str) {
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull DNS_RPC_RECORD_STRING");
+ }
+
+ while (ndr->offset < ndr->data_size) {
+ rec->str = talloc_realloc(ndr->current_mem_ctx, rec->str, struct DNS_RPC_NAME, rec->count+1);
+ if (! rec->str) {
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Failed to pull DNS_RPC_RECORD_STRING");
+ }
+ NDR_CHECK(ndr_pull_DNS_RPC_NAME(ndr, ndr_flags, &rec->str[rec->count]));
+ rec->count++;
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_push_DNS_RPC_RECORD_STRING(struct ndr_push *ndr,
+ int ndr_flags, const struct DNS_RPC_RECORD_STRING *rec)
+{
+ int i;
+
+ for (i=0; i<rec->count; i++) {
+ NDR_CHECK(ndr_push_DNS_RPC_NAME(ndr, ndr_flags, &rec->str[i]));
+ }
+
+ return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_dnsserver.h b/librpc/ndr/ndr_dnsserver.h
new file mode 100644
index 0000000..68eb863
--- /dev/null
+++ b/librpc/ndr/ndr_dnsserver.h
@@ -0,0 +1,25 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Manually parsed structures for DNSSERVER
+
+ Copyright (C) Amitay Isaacs 2011
+
+ 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/>.
+*/
+
+enum ndr_err_code ndr_pull_DNS_RPC_RECORDS_ARRAY(struct ndr_pull *ndr,
+ int ndr_flags, struct DNS_RPC_RECORDS_ARRAY *rec);
+enum ndr_err_code ndr_push_DNS_RPC_RECORDS_ARRAY(struct ndr_push *ndr,
+ int ndr_flags, const struct DNS_RPC_RECORDS_ARRAY *rec);
diff --git a/librpc/ndr/ndr_drsblobs.c b/librpc/ndr/ndr_drsblobs.c
new file mode 100644
index 0000000..b0d3f50
--- /dev/null
+++ b/librpc/ndr/ndr_drsblobs.c
@@ -0,0 +1,220 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Manually parsed structures found in the DRS protocol
+
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
+ Copyright (C) Guenther Deschner <gd@samba.org> 2010
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_drsblobs.h"
+#include "../lib/util/asn1.h"
+
+_PUBLIC_ enum ndr_err_code ndr_push_AuthenticationInformationArray(struct ndr_push *ndr, int ndr_flags, const struct AuthenticationInformationArray *r)
+{
+ uint32_t cntr_array_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ for (cntr_array_0 = 0; cntr_array_0 < r->count; cntr_array_0++) {
+ NDR_CHECK(ndr_push_AuthenticationInformation(ndr, NDR_SCALARS, &r->array[cntr_array_0]));
+ }
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_AuthenticationInformationArray(struct ndr_pull *ndr, int ndr_flags, struct AuthenticationInformationArray *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ r->count = 0;
+ NDR_PULL_ALLOC_N(ndr, r->array, r->count);
+ /* entry is at least 16 bytes large */
+ while (ndr->offset + 16 <= ndr->data_size) {
+ r->array = talloc_realloc(ndr, r->array, struct AuthenticationInformation, r->count + 1);
+ NDR_ERR_HAVE_NO_MEMORY(r->array);
+ NDR_CHECK(ndr_pull_AuthenticationInformation(ndr, NDR_SCALARS, &r->array[r->count]));
+ r->count++;
+ }
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_trustAuthInOutBlob(struct ndr_push *ndr, int ndr_flags, const struct trustAuthInOutBlob *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->count));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, (r->count > 0)?12:0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, (r->count > 0)?12 + ndr_size_AuthenticationInformationArray(&r->current, 0):0));
+ {
+ struct ndr_push *_ndr_current;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_current, 0, ((r->count > 0)?12 + ndr_size_AuthenticationInformationArray(&r->current, 0):0) - ((r->count > 0)?12:0)));
+ NDR_CHECK(ndr_push_AuthenticationInformationArray(_ndr_current, NDR_SCALARS, &r->current));
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_current, 0, ((r->count > 0)?12 + ndr_size_AuthenticationInformationArray(&r->current, 0):0) - ((r->count > 0)?12:0)));
+ }
+ {
+ uint32_t _flags_save_AuthenticationInformationArray = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
+ {
+ struct ndr_push *_ndr_previous;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_previous, 0, -1));
+ NDR_CHECK(ndr_push_AuthenticationInformationArray(_ndr_previous, NDR_SCALARS, &r->previous));
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_previous, 0, -1));
+ }
+ ndr->flags = _flags_save_AuthenticationInformationArray;
+ }
+ NDR_CHECK(ndr_push_trailer_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+
+_PUBLIC_ enum ndr_err_code ndr_pull_trustDomainPasswords(struct ndr_pull *ndr, int ndr_flags, struct trustDomainPasswords *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ uint32_t offset;
+ NDR_PULL_ALIGN(ndr, 4);
+ NDR_PULL_NEED_BYTES(ndr, 8);
+
+ offset = ndr->offset;
+ ndr->offset = ndr->data_size - 8;
+
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->outgoing_size));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->incoming_size));
+
+ ndr->offset = offset;
+ NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->confounder, 512));
+ {
+ struct ndr_pull *_ndr_outgoing;
+ NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_outgoing, 0, r->outgoing_size));
+ NDR_CHECK(ndr_pull_trustAuthInOutBlob(_ndr_outgoing, NDR_SCALARS|NDR_BUFFERS, &r->outgoing));
+ NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_outgoing, 0, r->outgoing_size));
+ }
+ {
+ struct ndr_pull *_ndr_incoming;
+ NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_incoming, 0, r->incoming_size));
+ NDR_CHECK(ndr_pull_trustAuthInOutBlob(_ndr_incoming, NDR_SCALARS|NDR_BUFFERS, &r->incoming));
+ NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_incoming, 0, r->incoming_size));
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->outgoing_size));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->incoming_size));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_drsuapi_MSPrefixMap_Entry(struct ndr_print *ndr, const char *name, const struct drsuapi_MSPrefixMap_Entry *r)
+{
+ ndr_print_struct(ndr, name, "drsuapi_MSPrefixMap_Entry");
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ ndr->depth++;
+ ndr_print_uint16(ndr, "entryID", r->entryID);
+ ndr->print(ndr, "%-25s: length=%u", "oid", r->length);
+ if (r->binary_oid) {
+ char *partial_oid = NULL;
+ DATA_BLOB oid_blob = data_blob_const(r->binary_oid, r->length);
+ char *hex_str = data_blob_hex_string_upper(ndr, &oid_blob);
+ ber_read_partial_OID_String(ndr, oid_blob, &partial_oid);
+ ndr->depth++;
+ ndr->print(ndr, "%-25s: 0x%s (%s)", "binary_oid", hex_str, partial_oid);
+ ndr->depth--;
+ talloc_free(hex_str);
+ talloc_free(partial_oid);
+ }
+ ndr->depth--;
+ ndr->flags = _flags_save_STRUCT;
+ }
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_supplementalCredentialsSubBlob(struct ndr_push *ndr, int ndr_flags, const struct supplementalCredentialsSubBlob *r)
+{
+ uint32_t cntr_packages_0;
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ if ((r->signature != SUPPLEMENTAL_CREDENTIALS_SIGNATURE)
+ && (r->num_packages == 0)) {
+ return NDR_ERR_SUCCESS;
+ }
+ NDR_CHECK(ndr_push_align(ndr, 3));
+ NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, SUPPLEMENTAL_CREDENTIALS_PREFIX, 0x30, sizeof(uint16_t), CH_UTF16));
+ NDR_CHECK(ndr_push_supplementalCredentialsSignature(ndr, NDR_SCALARS, SUPPLEMENTAL_CREDENTIALS_SIGNATURE));
+ if (r->num_packages > 0) {
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->num_packages));
+ }
+ for (cntr_packages_0 = 0; cntr_packages_0 < (r->num_packages); cntr_packages_0++) {
+ NDR_CHECK(ndr_push_supplementalCredentialsPackage(ndr, NDR_SCALARS, &r->packages[cntr_packages_0]));
+ }
+ NDR_CHECK(ndr_push_trailer_align(ndr, 3));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_supplementalCredentialsSubBlob(struct ndr_pull *ndr, int ndr_flags, struct supplementalCredentialsSubBlob *r)
+{
+ uint32_t size_prefix_0 = 0;
+ uint32_t size_packages_0 = 0;
+ uint32_t cntr_packages_0;
+ TALLOC_CTX *_mem_save_packages_0 = NULL;
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ uint32_t remaining = 0;
+ NDR_CHECK(ndr_pull_align(ndr, 3));
+ size_prefix_0 = 0x30;
+ remaining = ndr->data_size - ndr->offset;
+ if (remaining >= size_prefix_0) {
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->prefix, size_prefix_0, sizeof(uint16_t), CH_UTF16));
+ } else {
+ r->prefix = NULL;
+ }
+ remaining = ndr->data_size - ndr->offset;
+ if (remaining >= 2) {
+ NDR_CHECK(ndr_pull_supplementalCredentialsSignature(ndr, NDR_SCALARS, &r->signature));
+ } else {
+ r->signature = 0;
+ }
+ remaining = ndr->data_size - ndr->offset;
+ if (remaining > 0) {
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->num_packages));
+ } else {
+ r->num_packages = 0;
+ }
+ size_packages_0 = r->num_packages;
+ NDR_PULL_ALLOC_N(ndr, r->packages, size_packages_0);
+ _mem_save_packages_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->packages, 0);
+ for (cntr_packages_0 = 0; cntr_packages_0 < (size_packages_0); cntr_packages_0++) {
+ NDR_CHECK(ndr_pull_supplementalCredentialsPackage(ndr, NDR_SCALARS, &r->packages[cntr_packages_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_packages_0, 0);
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 3));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_drsblobs.h b/librpc/ndr/ndr_drsblobs.h
new file mode 100644
index 0000000..eb7993c
--- /dev/null
+++ b/librpc/ndr/ndr_drsblobs.h
@@ -0,0 +1,23 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Manually parsed structures found in the DRS protocol
+
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
+
+ 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/>.
+*/
+
+_PUBLIC_ enum ndr_err_code ndr_pull_trustDomainPasswords(struct ndr_pull *ndr, int ndr_flags, struct trustDomainPasswords *r);
+_PUBLIC_ void ndr_print_drsuapi_MSPrefixMap_Entry(struct ndr_print *ndr, const char *name, const struct drsuapi_MSPrefixMap_Entry *r);
diff --git a/librpc/ndr/ndr_drsuapi.c b/librpc/ndr/ndr_drsuapi.c
new file mode 100644
index 0000000..cda2e2c
--- /dev/null
+++ b/librpc/ndr/ndr_drsuapi.c
@@ -0,0 +1,569 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for printing some linked list structs in DRSUAPI
+
+ Copyright (C) Stefan (metze) Metzmacher 2005
+ Copyright (C) Matthieu Patou 2013
+
+ 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/>.
+*/
+
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_drsuapi.h"
+#include "librpc/gen_ndr/ndr_misc.h"
+#include "../lib/util/asn1.h"
+#include "librpc/ndr/ndr_compression.h"
+/* We don't need multibyte if we're just comparing to 'ff' */
+#undef strncasecmp
+
+void ndr_print_drsuapi_DsReplicaObjectListItem(struct ndr_print *ndr, const char *name,
+ const struct drsuapi_DsReplicaObjectListItem *r)
+{
+ ndr_print_struct(ndr, name, "drsuapi_DsReplicaObjectListItem");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "next_object", r->next_object);
+ ndr_print_drsuapi_DsReplicaObject(ndr, "object", &r->object);
+ ndr->depth--;
+ if (r->next_object) {
+ ndr_print_drsuapi_DsReplicaObjectListItem(ndr, "next_object", r->next_object);
+ }
+}
+
+void ndr_print_drsuapi_DsReplicaObjectListItemEx(struct ndr_print *ndr, const char *name, const struct drsuapi_DsReplicaObjectListItemEx *r)
+{
+ ndr_print_struct(ndr, name, "drsuapi_DsReplicaObjectListItemEx");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "next_object", r->next_object);
+ ndr_print_drsuapi_DsReplicaObject(ndr, "object", &r->object);
+ ndr_print_uint32(ndr, "is_nc_prefix", r->is_nc_prefix);
+ ndr_print_ptr(ndr, "parent_object_guid", r->parent_object_guid);
+ ndr->depth++;
+ if (r->parent_object_guid) {
+ ndr_print_GUID(ndr, "parent_object_guid", r->parent_object_guid);
+ }
+ ndr->depth--;
+ ndr_print_ptr(ndr, "meta_data_ctr", r->meta_data_ctr);
+ ndr->depth++;
+ if (r->meta_data_ctr) {
+ ndr_print_drsuapi_DsReplicaMetaDataCtr(ndr, "meta_data_ctr", r->meta_data_ctr);
+ }
+ ndr->depth--;
+ ndr->depth--;
+ if (r->next_object) {
+ ndr_print_drsuapi_DsReplicaObjectListItemEx(ndr, "next_object", r->next_object);
+ }
+}
+
+_PUBLIC_ void ndr_print_drsuapi_DsReplicaOID(struct ndr_print *ndr, const char *name, const struct drsuapi_DsReplicaOID *r)
+{
+ ndr_print_struct(ndr, name, "drsuapi_DsReplicaOID");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "length", r->length);
+ ndr->print(ndr, "%-25s: length=%u", "oid", r->length);
+ if (r->binary_oid) {
+ char *partial_oid = NULL;
+ DATA_BLOB oid_blob = data_blob_const(r->binary_oid, r->length);
+ char *hex_str = data_blob_hex_string_upper(ndr, &oid_blob);
+ ber_read_partial_OID_String(ndr, oid_blob, &partial_oid);
+ ndr->depth++;
+ ndr->print(ndr, "%-25s: 0x%s (%s)", "binary_oid", hex_str, partial_oid);
+ ndr->depth--;
+ talloc_free(hex_str);
+ talloc_free(partial_oid);
+ }
+ ndr->depth--;
+}
+
+static void _print_drsuapi_DsAttributeValue_attid(struct ndr_print *ndr, const char *name,
+ const struct drsuapi_DsAttributeValue *r)
+{
+ uint32_t v;
+
+ ndr_print_struct(ndr, name, "drsuapi_DsAttributeValue");
+ ndr->depth++;
+ if (r->blob == NULL || r->blob->data == NULL) {
+ ndr_print_string(ndr, "attid", "NULL");
+ } else if (r->blob->length < 4) {
+ ndr_print_DATA_BLOB(ndr, "attid", *r->blob);
+ } else {
+ v = IVAL(r->blob->data, 0);
+ ndr_print_uint32(ndr, "attid", v);
+ }
+ ndr->depth--;
+}
+
+static void _print_drsuapi_DsAttributeValue_str(struct ndr_print *ndr, const char *name,
+ const struct drsuapi_DsAttributeValue *r)
+{
+ void *p;
+ size_t converted_size = 0;
+
+ ndr_print_struct(ndr, name, "drsuapi_DsAttributeValue");
+ ndr->depth++;
+ if (r->blob == NULL || r->blob->data == NULL) {
+ ndr_print_string(ndr, "string", "NULL");
+ } else if (!convert_string_talloc(ndr,
+ CH_UTF16, CH_UNIX,
+ r->blob->data,
+ r->blob->length,
+ &p, &converted_size)) {
+ ndr_print_DATA_BLOB(ndr, "string (INVALID CONVERSION)",
+ *r->blob);
+ } else {
+ char *str = (char *)p;
+ ndr_print_string(ndr, "string", str);
+ talloc_free(str);
+ }
+ ndr->depth--;
+}
+
+static void _print_drsuapi_DsAttributeValueCtr(struct ndr_print *ndr,
+ const char *name,
+ const struct drsuapi_DsAttributeValueCtr *r,
+ void (*print_val_fn)(struct ndr_print *ndr, const char *name, const struct drsuapi_DsAttributeValue *r))
+{
+ uint32_t cntr_values_1;
+ ndr_print_struct(ndr, name, "drsuapi_DsAttributeValueCtr");
+ ndr->depth++;
+ ndr_print_uint32(ndr, "num_values", r->num_values);
+ ndr_print_ptr(ndr, "values", r->values);
+ ndr->depth++;
+ if (r->values) {
+ ndr->print(ndr, "%s: ARRAY(%d)", "values", (int)r->num_values);
+ ndr->depth++;
+ for (cntr_values_1=0;cntr_values_1<r->num_values;cntr_values_1++) {
+ char *idx_1=NULL;
+ if (asprintf(&idx_1, "[%d]", cntr_values_1) != -1) {
+ //ndr_print_drsuapi_DsAttributeValue(ndr, "values", &r->values[cntr_values_1]);
+ print_val_fn(ndr, "values", &r->values[cntr_values_1]);
+ free(idx_1);
+ }
+ }
+ ndr->depth--;
+ }
+ ndr->depth--;
+ ndr->depth--;
+}
+
+_PUBLIC_ void ndr_print_drsuapi_DsReplicaAttribute(struct ndr_print *ndr,
+ const char *name,
+ const struct drsuapi_DsReplicaAttribute *r)
+{
+ ndr_print_struct(ndr, name, "drsuapi_DsReplicaAttribute");
+ ndr->depth++;
+ ndr_print_drsuapi_DsAttributeId(ndr, "attid", r->attid);
+ switch (r->attid) {
+ case DRSUAPI_ATTID_objectClass:
+ case DRSUAPI_ATTID_possSuperiors:
+ case DRSUAPI_ATTID_subClassOf:
+ case DRSUAPI_ATTID_governsID:
+ case DRSUAPI_ATTID_mustContain:
+ case DRSUAPI_ATTID_mayContain:
+ case DRSUAPI_ATTID_rDNAttId:
+ case DRSUAPI_ATTID_attributeID:
+ case DRSUAPI_ATTID_attributeSyntax:
+ case DRSUAPI_ATTID_auxiliaryClass:
+ case DRSUAPI_ATTID_systemPossSuperiors:
+ case DRSUAPI_ATTID_systemMayContain:
+ case DRSUAPI_ATTID_systemMustContain:
+ case DRSUAPI_ATTID_systemAuxiliaryClass:
+ case DRSUAPI_ATTID_transportAddressAttribute:
+ /* ATTIDs for classSchema and attributeSchema */
+ _print_drsuapi_DsAttributeValueCtr(ndr, "value_ctr", &r->value_ctr,
+ _print_drsuapi_DsAttributeValue_attid);
+ break;
+ case DRSUAPI_ATTID_cn:
+ case DRSUAPI_ATTID_ou:
+ case DRSUAPI_ATTID_description:
+ case DRSUAPI_ATTID_displayName:
+ case DRSUAPI_ATTID_dMDLocation:
+ case DRSUAPI_ATTID_adminDisplayName:
+ case DRSUAPI_ATTID_adminDescription:
+ case DRSUAPI_ATTID_lDAPDisplayName:
+ case DRSUAPI_ATTID_name:
+ _print_drsuapi_DsAttributeValueCtr(ndr, "value_ctr", &r->value_ctr,
+ _print_drsuapi_DsAttributeValue_str);
+ break;
+ default:
+ _print_drsuapi_DsAttributeValueCtr(ndr, "value_ctr", &r->value_ctr,
+ ndr_print_drsuapi_DsAttributeValue);
+ break;
+ }
+ ndr->depth--;
+}
+
+enum ndr_err_code ndr_push_drsuapi_DsGetNCChangesMSZIPCtr1(struct ndr_push *ndr, int ndr_flags, const struct drsuapi_DsGetNCChangesMSZIPCtr1 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ uint32_t decompressed_length = 0;
+ uint32_t compressed_length = 0;
+ if (r->ts) {
+ {
+ struct ndr_push *_ndr_ts;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1));
+ {
+ struct ndr_push *_ndr_ts_compressed;
+ NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1));
+ NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr1TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts));
+ decompressed_length = _ndr_ts_compressed->offset;
+ NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1));
+ }
+ compressed_length = _ndr_ts->offset;
+ talloc_free(_ndr_ts);
+ }
+ }
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, decompressed_length));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, compressed_length));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->ts));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->ts) {
+ {
+ struct ndr_push *_ndr_ts;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1));
+ {
+ struct ndr_push *_ndr_ts_compressed;
+ NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1));
+ NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr1TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts));
+ NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1));
+ }
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_ts, 4, -1));
+ }
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_push_drsuapi_DsGetNCChangesMSZIPCtr6(struct ndr_push *ndr, int ndr_flags, const struct drsuapi_DsGetNCChangesMSZIPCtr6 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ uint32_t decompressed_length = 0;
+ uint32_t compressed_length = 0;
+ if (r->ts) {
+ {
+ struct ndr_push *_ndr_ts;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1));
+ {
+ struct ndr_push *_ndr_ts_compressed;
+ NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1));
+ NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr6TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts));
+ decompressed_length = _ndr_ts_compressed->offset;
+ NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1));
+ }
+ compressed_length = _ndr_ts->offset;
+ talloc_free(_ndr_ts);
+ }
+ }
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, decompressed_length));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, compressed_length));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->ts));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->ts) {
+ {
+ struct ndr_push *_ndr_ts;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1));
+ {
+ struct ndr_push *_ndr_ts_compressed;
+ NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1));
+ NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr6TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts));
+ NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_MSZIP, -1));
+ }
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_ts, 4, -1));
+ }
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_push_drsuapi_DsGetNCChangesXPRESSCtr1(struct ndr_push *ndr, int ndr_flags, const struct drsuapi_DsGetNCChangesXPRESSCtr1 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ uint32_t decompressed_length = 0;
+ uint32_t compressed_length = 0;
+ if (r->ts) {
+ {
+ struct ndr_push *_ndr_ts;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1));
+ {
+ struct ndr_push *_ndr_ts_compressed;
+ NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1));
+ NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr1TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts));
+ decompressed_length = _ndr_ts_compressed->offset;
+ NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1));
+ }
+ compressed_length = _ndr_ts->offset;
+ talloc_free(_ndr_ts);
+ }
+ }
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, decompressed_length));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, compressed_length));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->ts));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->ts) {
+ {
+ struct ndr_push *_ndr_ts;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1));
+ {
+ struct ndr_push *_ndr_ts_compressed;
+ NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1));
+ NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr1TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts));
+ NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1));
+ }
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_ts, 4, -1));
+ }
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_push_drsuapi_DsGetNCChangesXPRESSCtr6(struct ndr_push *ndr, int ndr_flags, const struct drsuapi_DsGetNCChangesXPRESSCtr6 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ uint32_t decompressed_length = 0;
+ uint32_t compressed_length = 0;
+ if (r->ts) {
+ {
+ struct ndr_push *_ndr_ts;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1));
+ {
+ struct ndr_push *_ndr_ts_compressed;
+ NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1));
+ NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr6TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts));
+ decompressed_length = _ndr_ts_compressed->offset;
+ NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1));
+ }
+ compressed_length = _ndr_ts->offset;
+ talloc_free(_ndr_ts);
+ }
+ }
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, decompressed_length));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, compressed_length));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->ts));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->ts) {
+ {
+ struct ndr_push *_ndr_ts;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_ts, 4, -1));
+ {
+ struct ndr_push *_ndr_ts_compressed;
+ NDR_CHECK(ndr_push_compression_start(_ndr_ts, &_ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1));
+ NDR_CHECK(ndr_push_drsuapi_DsGetNCChangesCtr6TS(_ndr_ts_compressed, NDR_SCALARS|NDR_BUFFERS, r->ts));
+ NDR_CHECK(ndr_push_compression_end(_ndr_ts, _ndr_ts_compressed, NDR_COMPRESSION_XPRESS, -1));
+ }
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_ts, 4, -1));
+ }
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ size_t ndr_size_drsuapi_DsReplicaObjectIdentifier3Binary_without_Binary(const struct drsuapi_DsReplicaObjectIdentifier3Binary *r, int flags)
+{
+ return ndr_size_struct((const struct drsuapi_DsReplicaObjectIdentifier3 *)r, flags, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
+}
+
+_PUBLIC_ void ndr_print_drsuapi_SecBufferType(struct ndr_print *ndr, const char *name, enum drsuapi_SecBufferType r)
+{
+ const char *val = NULL;
+
+ switch (r & 0x00000007) {
+ case DRSUAPI_SECBUFFER_EMPTY: val = "DRSUAPI_SECBUFFER_EMPTY"; break;
+ case DRSUAPI_SECBUFFER_DATA: val = "DRSUAPI_SECBUFFER_DATA"; break;
+ case DRSUAPI_SECBUFFER_TOKEN: val = "DRSUAPI_SECBUFFER_TOKEN"; break;
+ case DRSUAPI_SECBUFFER_PKG_PARAMS: val = "DRSUAPI_SECBUFFER_PKG_PARAMS"; break;
+ case DRSUAPI_SECBUFFER_MISSING: val = "DRSUAPI_SECBUFFER_MISSING"; break;
+ case DRSUAPI_SECBUFFER_EXTRA: val = "DRSUAPI_SECBUFFER_EXTRA"; break;
+ case DRSUAPI_SECBUFFER_STREAM_TRAILER: val = "DRSUAPI_SECBUFFER_STREAM_TRAILER"; break;
+ case DRSUAPI_SECBUFFER_STREAM_HEADER: val = "DRSUAPI_SECBUFFER_STREAM_HEADER"; break;
+ }
+
+ if (r & DRSUAPI_SECBUFFER_READONLY) {
+ char *v = talloc_asprintf(ndr, "DRSUAPI_SECBUFFER_READONLY | %s", val);
+ ndr_print_enum(ndr, name, "ENUM", v, r);
+ } else {
+ ndr_print_enum(ndr, name, "ENUM", val, r);
+ }
+}
+
+_PUBLIC_ void ndr_print_drsuapi_DsAddEntry_AttrErrListItem_V1(struct ndr_print *ndr, const char *name, const struct drsuapi_DsAddEntry_AttrErrListItem_V1 *r)
+{
+ ndr_print_struct(ndr, name, "drsuapi_DsAddEntry_AttrErrListItem_V1");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "next", r->next);
+ ndr_print_drsuapi_DsAddEntry_AttrErr_V1(ndr, "err_data", &r->err_data);
+ ndr->depth--;
+ if (r->next) {
+ ndr_print_drsuapi_DsAddEntry_AttrErrListItem_V1(ndr, "next", r->next);
+ }
+}
+
+enum ndr_err_code ndr_push_drsuapi_DsBindInfo(struct ndr_push *ndr, int ndr_flags, const union drsuapi_DsBindInfo *r)
+{
+ uint32_t _flags_save = ndr->flags;
+ ndr->flags = ndr->flags & ~LIBNDR_FLAG_NDR64;
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ uint32_t level;
+ NDR_CHECK(ndr_push_steal_switch_value(ndr, r, &level));
+ NDR_CHECK(ndr_push_union_align(ndr, 4));
+ switch (level) {
+ case 24: {
+ {
+ struct ndr_push *_ndr_info24;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_info24, 0, 24));
+ NDR_CHECK(ndr_push_drsuapi_DsBindInfo24(_ndr_info24, NDR_SCALARS, &r->info24));
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_info24, 0, 24));
+ }
+ break; }
+
+ case 28: {
+ {
+ struct ndr_push *_ndr_info28;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_info28, 0, 28));
+ NDR_CHECK(ndr_push_drsuapi_DsBindInfo28(_ndr_info28, NDR_SCALARS, &r->info28));
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_info28, 0, 28));
+ }
+ break; }
+
+ case 48: {
+ {
+ struct ndr_push *_ndr_info48;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_info48, 0, 48));
+ NDR_CHECK(ndr_push_drsuapi_DsBindInfo48(_ndr_info48, NDR_SCALARS, &r->info48));
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_info48, 0, 48));
+ }
+ break; }
+
+ case 52: {
+ {
+ struct ndr_push *_ndr_info52;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_info52, 0, 52));
+ NDR_CHECK(ndr_push_drsuapi_DsBindInfo52(_ndr_info52, NDR_SCALARS, &r->info52));
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_info52, 0, 52));
+ }
+ break; }
+
+ default: {
+ {
+ struct ndr_push *_ndr_Fallback;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_Fallback, 0, level));
+ NDR_CHECK(ndr_push_drsuapi_DsBindInfoFallBack(_ndr_Fallback, NDR_SCALARS, &r->Fallback));
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_Fallback, 0, level));
+ }
+ break; }
+
+ }
+ }
+ ndr->flags = _flags_save;
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_drsuapi_DsBindInfo(struct ndr_pull *ndr, int ndr_flags, union drsuapi_DsBindInfo *r)
+{
+ uint32_t _flags_save = ndr->flags;
+ ndr->flags = ndr->flags & ~LIBNDR_FLAG_NDR64;
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ uint32_t level;
+ NDR_CHECK(ndr_pull_steal_switch_value(ndr, r, &level));
+ NDR_CHECK(ndr_pull_union_align(ndr, 4));
+ switch (level) {
+ case 24: {
+ {
+ struct ndr_pull *_ndr_info24;
+ NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_info24, 0, 24));
+ NDR_CHECK(ndr_pull_drsuapi_DsBindInfo24(_ndr_info24, NDR_SCALARS, &r->info24));
+ NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_info24, 0, 24));
+ }
+ break; }
+
+ case 28: {
+ {
+ struct ndr_pull *_ndr_info28;
+ NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_info28, 0, 28));
+ NDR_CHECK(ndr_pull_drsuapi_DsBindInfo28(_ndr_info28, NDR_SCALARS, &r->info28));
+ NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_info28, 0, 28));
+ }
+ break; }
+
+ case 48: {
+ {
+ struct ndr_pull *_ndr_info48;
+ NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_info48, 0, 48));
+ NDR_CHECK(ndr_pull_drsuapi_DsBindInfo48(_ndr_info48, NDR_SCALARS, &r->info48));
+ NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_info48, 0, 48));
+ }
+ break; }
+
+ case 52: {
+ {
+ struct ndr_pull *_ndr_info52;
+ NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_info52, 0, 52));
+ NDR_CHECK(ndr_pull_drsuapi_DsBindInfo52(_ndr_info52, NDR_SCALARS, &r->info52));
+ NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_info52, 0, 52));
+ }
+ break; }
+
+ default: {
+ {
+ struct ndr_pull *_ndr_Fallback;
+ NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_Fallback, 0, level));
+ NDR_CHECK(ndr_pull_drsuapi_DsBindInfoFallBack(_ndr_Fallback, NDR_SCALARS, &r->Fallback));
+ NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_Fallback, 0, level));
+ }
+ break; }
+
+ }
+ }
+ ndr->flags = _flags_save;
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_drsuapi_DsBindInfo(struct ndr_print *ndr, const char *name, const union drsuapi_DsBindInfo *r)
+{
+ uint32_t level;
+ level = ndr_print_steal_switch_value(ndr, r);
+ ndr_print_union(ndr, name, level, "drsuapi_DsBindInfo");
+ switch (level) {
+ case 24:
+ ndr_print_drsuapi_DsBindInfo24(ndr, "info24", &r->info24);
+ break;
+
+ case 28:
+ ndr_print_drsuapi_DsBindInfo28(ndr, "info28", &r->info28);
+ break;
+
+ case 48:
+ ndr_print_drsuapi_DsBindInfo48(ndr, "info48", &r->info48);
+ break;
+
+ case 52:
+ ndr_print_drsuapi_DsBindInfo52(ndr, "info52", &r->info52);
+ break;
+
+ default:
+ ndr_print_drsuapi_DsBindInfoFallBack(ndr, "Fallback", &r->Fallback);
+ break;
+
+ }
+}
diff --git a/librpc/ndr/ndr_drsuapi.h b/librpc/ndr/ndr_drsuapi.h
new file mode 100644
index 0000000..9d1d371
--- /dev/null
+++ b/librpc/ndr/ndr_drsuapi.h
@@ -0,0 +1,34 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for printing some linked list structs in DRSUAPI
+
+ Copyright (C) Stefan (metze) Metzmacher 2005-2006
+
+ 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_DRSUAPI_H
+#define _LIBRPC_NDR_NDR_DRSUAPI_H
+
+void ndr_print_drsuapi_DsReplicaObjectListItem(struct ndr_print *ndr, const char *name,
+ const struct drsuapi_DsReplicaObjectListItem *r);
+
+void ndr_print_drsuapi_DsReplicaObjectListItemEx(struct ndr_print *ndr, const char *name,
+ const struct drsuapi_DsReplicaObjectListItemEx *r);
+
+size_t ndr_size_drsuapi_DsReplicaObjectIdentifier3Binary_without_Binary(const struct drsuapi_DsReplicaObjectIdentifier3Binary *r, int flags);
+
+
+#endif /* _LIBRPC_NDR_NDR_DRSUAPI_H */
diff --git a/librpc/ndr/ndr_frsrpc.c b/librpc/ndr/ndr_frsrpc.c
new file mode 100644
index 0000000..96d3468
--- /dev/null
+++ b/librpc/ndr/ndr_frsrpc.c
@@ -0,0 +1,92 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ helper routines for FRSRPC marshalling
+
+ Copyright (C) Stefan (metze) Metzmacher 2009
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_frsrpc.h"
+
+enum ndr_err_code ndr_push_frsrpc_CommPktChunkCtr(struct ndr_push *ndr,
+ int ndr_flags,
+ const struct frsrpc_CommPktChunkCtr *r)
+{
+ uint32_t cntr_chunks_0;
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 2));
+ for (cntr_chunks_0 = 0; cntr_chunks_0 < r->num_chunks; cntr_chunks_0++) {
+ NDR_CHECK(ndr_push_frsrpc_CommPktChunk(ndr, NDR_SCALARS, &r->chunks[cntr_chunks_0]));
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+#define _TMP_PULL_REALLOC_N(ndr, s, t, n) do { \
+ _NDR_PULL_FIX_CURRENT_MEM_CTX(ndr);\
+ (s) = talloc_realloc(ndr->current_mem_ctx, (s), t, n); \
+ if (!(s)) { \
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC, \
+ "Alloc %u * %s failed: %s\n", \
+ (unsigned)n, # s, __location__); \
+ } \
+} while (0)
+
+enum ndr_err_code ndr_pull_frsrpc_CommPktChunkCtr(struct ndr_pull *ndr,
+ int ndr_flags,
+ struct frsrpc_CommPktChunkCtr *r)
+{
+ uint32_t cntr_chunks_0;
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ if (ndr_flags & NDR_SCALARS) {
+ uint32_t remaining = ndr->data_size - ndr->offset;
+ r->num_chunks = 0;
+ r->chunks = NULL;
+ for (cntr_chunks_0 = 0; remaining > 0; cntr_chunks_0++) {
+ r->num_chunks += 1;
+ _TMP_PULL_REALLOC_N(ndr, r->chunks,
+ struct frsrpc_CommPktChunk,
+ r->num_chunks);
+ NDR_CHECK(ndr_pull_frsrpc_CommPktChunk(ndr,
+ NDR_SCALARS,
+ &r->chunks[cntr_chunks_0]));
+ remaining = ndr->data_size - ndr->offset;
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+size_t ndr_size_frsrpc_CommPktChunkCtr(const struct frsrpc_CommPktChunkCtr *r,
+ int flags)
+{
+ flags |= LIBNDR_FLAG_NOALIGN;
+ return ndr_size_struct(r, flags,
+ (ndr_push_flags_fn_t)ndr_push_frsrpc_CommPktChunkCtr);
+}
diff --git a/librpc/ndr/ndr_frsrpc.h b/librpc/ndr/ndr_frsrpc.h
new file mode 100644
index 0000000..9e5ac92
--- /dev/null
+++ b/librpc/ndr/ndr_frsrpc.h
@@ -0,0 +1,34 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ helper routines for FRSRPC marshalling
+
+ Copyright (C) Stefan (metze) Metzmacher 2009
+
+ 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_FRSRPC_H
+#define _LIBRPC_NDR_NDR_FRSRPC_H
+
+enum ndr_err_code ndr_push_frsrpc_CommPktChunkCtr(struct ndr_push *ndr,
+ int ndr_flags,
+ const struct frsrpc_CommPktChunkCtr *r);
+enum ndr_err_code ndr_pull_frsrpc_CommPktChunkCtr(struct ndr_pull *ndr,
+ int ndr_flags,
+ struct frsrpc_CommPktChunkCtr *r);
+size_t ndr_size_frsrpc_CommPktChunkCtr(const struct frsrpc_CommPktChunkCtr *r,
+ int flags);
+
+#endif /* _LIBRPC_NDR_NDR_FRSRPC_H */
diff --git a/librpc/ndr/ndr_ioctl.c b/librpc/ndr/ndr_ioctl.c
new file mode 100644
index 0000000..7e76abc
--- /dev/null
+++ b/librpc/ndr/ndr_ioctl.c
@@ -0,0 +1,40 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Manually parsed structures for IOCTL/FSCTL
+
+ Copyright (C) Stefan Metzmacher 2014
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_ioctl.h"
+
+_PUBLIC_ void ndr_print_fsctl_net_iface_info(struct ndr_print *ndr, const char *name, const struct fsctl_net_iface_info *r)
+{
+ ndr_print_struct(ndr, name, "fsctl_net_iface_info");
+ if (r == NULL) { ndr_print_null(ndr); return; }
+ ndr->depth++;
+ ndr_print_ptr(ndr, "next", r->next);
+ ndr_print_uint32(ndr, "ifindex", r->ifindex);
+ ndr_print_fsctl_net_iface_capability(ndr, "capability", r->capability);
+ ndr_print_uint32(ndr, "reserved", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?0:r->reserved);
+ ndr_print_hyper(ndr, "linkspeed", r->linkspeed);
+ ndr_print_fsctl_sockaddr_storage(ndr, "sockaddr", &r->sockaddr);
+ ndr->depth--;
+ if (r->next) {
+ ndr_print_fsctl_net_iface_info(ndr, "next", r->next);
+ }
+}
diff --git a/librpc/ndr/ndr_krb5pac.c b/librpc/ndr/ndr_krb5pac.c
new file mode 100644
index 0000000..57b28df
--- /dev/null
+++ b/librpc/ndr/ndr_krb5pac.c
@@ -0,0 +1,130 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling spoolss subcontext buffer structures
+
+ Copyright (C) Stefan Metzmacher 2005
+
+ 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/>.
+*/
+
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_krb5pac.h"
+
+size_t _ndr_size_PAC_INFO(const union PAC_INFO *r, uint32_t level, int flags)
+{
+ size_t s = ndr_size_PAC_INFO(r, level, flags);
+ switch (level) {
+ case PAC_TYPE_LOGON_INFO:
+ return NDR_ROUND(s,8);
+ case PAC_TYPE_UPN_DNS_INFO:
+ return NDR_ROUND(s,8);
+ default:
+ return s;
+ }
+}
+
+enum ndr_err_code ndr_push_PAC_BUFFER(struct ndr_push *ndr, int ndr_flags, const struct PAC_BUFFER *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_PAC_TYPE(ndr, NDR_SCALARS, r->type));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, _ndr_size_PAC_INFO(r->info,r->type,LIBNDR_FLAG_ALIGN8)));
+ {
+ uint32_t _flags_save_PAC_INFO = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN8);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->info));
+ ndr->flags = _flags_save_PAC_INFO;
+ }
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ {
+ uint32_t _flags_save_PAC_INFO = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN8);
+ if (r->info) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->info));
+ {
+ struct ndr_push *_ndr_info_pad;
+ struct ndr_push *_ndr_info;
+ size_t _ndr_size = _ndr_size_PAC_INFO(r->info, r->type, LIBNDR_FLAG_ALIGN8);
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_info_pad, 0, NDR_ROUND(_ndr_size, 8)));
+ NDR_CHECK(ndr_push_subcontext_start(_ndr_info_pad, &_ndr_info, 0, _ndr_size));
+ NDR_CHECK(ndr_push_set_switch_value(_ndr_info, r->info, r->type));
+ NDR_CHECK(ndr_push_PAC_INFO(_ndr_info, NDR_SCALARS|NDR_BUFFERS, r->info));
+ NDR_CHECK(ndr_push_subcontext_end(_ndr_info_pad, _ndr_info, 0, _ndr_size));
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_info_pad, 0, NDR_ROUND(_ndr_size, 8)));
+ }
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->info));
+ }
+ ndr->flags = _flags_save_PAC_INFO;
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_PAC_BUFFER(struct ndr_pull *ndr, int ndr_flags, struct PAC_BUFFER *r)
+{
+ uint32_t _ptr_info;
+ TALLOC_CTX *_mem_save_info_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_PAC_TYPE(ndr, NDR_SCALARS, &r->type));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->_ndr_size));
+ {
+ uint32_t _flags_save_PAC_INFO = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN8);
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info));
+ if (_ptr_info) {
+ NDR_PULL_ALLOC(ndr, r->info);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->info, _ptr_info));
+ } else {
+ r->info = NULL;
+ }
+ ndr->flags = _flags_save_PAC_INFO;
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->_pad));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ {
+ uint32_t _flags_save_PAC_INFO = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN8);
+ if (r->info) {
+ uint32_t _relative_save_offset;
+ _relative_save_offset = ndr->offset;
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->info));
+ _mem_save_info_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->info, 0);
+ {
+ struct ndr_pull *_ndr_info_pad;
+ struct ndr_pull *_ndr_info;
+ NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_info_pad, 0, NDR_ROUND(r->_ndr_size, 8)));
+ NDR_CHECK(ndr_pull_subcontext_start(_ndr_info_pad, &_ndr_info, 0, r->_ndr_size));
+ NDR_CHECK(ndr_pull_set_switch_value(_ndr_info, r->info, r->type));
+ NDR_CHECK(ndr_pull_PAC_INFO(_ndr_info, NDR_SCALARS|NDR_BUFFERS, r->info));
+ NDR_CHECK(ndr_pull_subcontext_end(_ndr_info_pad, _ndr_info, 0, r->_ndr_size));
+ NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_info_pad, 0, NDR_ROUND(r->_ndr_size, 8)));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info_0, 0);
+ if (ndr->offset > ndr->relative_highest_offset) {
+ ndr->relative_highest_offset = ndr->offset;
+ }
+ ndr->offset = _relative_save_offset;
+ }
+ ndr->flags = _flags_save_PAC_INFO;
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_krb5pac.h b/librpc/ndr/ndr_krb5pac.h
new file mode 100644
index 0000000..f539161
--- /dev/null
+++ b/librpc/ndr/ndr_krb5pac.h
@@ -0,0 +1,26 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling spoolss subcontext buffer structures
+
+ Copyright (C) Stefan Metzmacher 2005
+
+ 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/>.
+*/
+
+
+#include "librpc/gen_ndr/ndr_krb5pac.h"
+
+size_t _ndr_size_PAC_INFO(const union PAC_INFO *r, uint32_t level, int flags);
+
diff --git a/librpc/ndr/ndr_misc.c b/librpc/ndr/ndr_misc.c
new file mode 100644
index 0000000..d7ebb06
--- /dev/null
+++ b/librpc/ndr/ndr_misc.c
@@ -0,0 +1,77 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ UUID/GUID/policy_handle functions
+
+ Copyright (C) Andrew Tridgell 2003.
+ Copyright (C) Stefan (metze) Metzmacher 2004.
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "system/network.h"
+#include "librpc/ndr/libndr.h"
+#include "libcli/util/ntstatus.h"
+#include "lib/util/util_str_hex.h"
+
+_PUBLIC_ void ndr_print_GUID(struct ndr_print *ndr, const char *name, const struct GUID *guid)
+{
+ struct GUID_txt_buf buf;
+ ndr->print(ndr, "%-25s: %s", name, GUID_buf_string(guid, &buf));
+}
+
+bool ndr_syntax_id_equal(const struct ndr_syntax_id *i1,
+ const struct ndr_syntax_id *i2)
+{
+ return GUID_equal(&i1->uuid, &i2->uuid)
+ && (i1->if_version == i2->if_version);
+}
+
+char *ndr_syntax_id_buf_string(
+ const struct ndr_syntax_id *id, struct ndr_syntax_id_buf *dst)
+{
+ struct GUID_txt_buf guid_buf;
+
+ snprintf(dst->buf,
+ sizeof(dst->buf),
+ "%s/0x%08x",
+ GUID_buf_string(&id->uuid, &guid_buf),
+ (unsigned int)id->if_version);
+
+ return dst->buf;
+}
+
+_PUBLIC_ char *ndr_syntax_id_to_string(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *id)
+{
+ struct ndr_syntax_id_buf buf;
+ return talloc_strdup(mem_ctx, ndr_syntax_id_buf_string(id, &buf));
+}
+
+_PUBLIC_ bool ndr_syntax_id_from_string(const char *s, struct ndr_syntax_id *id)
+{
+ bool ok;
+
+ ok = parse_guid_string(s, &id->uuid);
+ if (!ok) {
+ return false;
+ }
+
+ if (strncmp(s + 36, "/0x", 3) != 0) {
+ return false;
+ }
+
+ ok = hex_uint32(s+39, &id->if_version);
+ return ok;
+}
diff --git a/librpc/ndr/ndr_nbt.c b/librpc/ndr/ndr_nbt.c
new file mode 100644
index 0000000..8ed9f0a
--- /dev/null
+++ b/librpc/ndr/ndr_nbt.c
@@ -0,0 +1,406 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ CLDAP server structures
+
+ Copyright (C) Andrew Tridgell 2005
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
+
+ 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/>.
+*/
+
+/* parser auto-generated by pidl, then hand-modified by abartlet */
+
+#include "includes.h"
+#include "../libcli/nbt/libnbt.h"
+#include "../libcli/netlogon/netlogon.h"
+#include "ndr_dns_utils.h"
+
+
+/* don't allow an unlimited number of name components */
+#define MAX_COMPONENTS 128
+
+/**
+ print a nbt string
+*/
+_PUBLIC_ void ndr_print_nbt_string(struct ndr_print *ndr, const char *name, const char *s)
+{
+ ndr_print_string(ndr, name, s);
+}
+
+/*
+ pull one component of a nbt_string
+*/
+static enum ndr_err_code ndr_pull_component(struct ndr_pull *ndr,
+ uint8_t **component,
+ uint32_t *offset,
+ uint32_t *max_offset)
+{
+ uint8_t len;
+ unsigned int loops = 0;
+ while (loops < 5) {
+ if (*offset >= ndr->data_size) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING,
+ "BAD NBT NAME component");
+ }
+ len = ndr->data[*offset];
+ if (len == 0) {
+ *offset += 1;
+ *max_offset = MAX(*max_offset, *offset);
+ *component = NULL;
+ return NDR_ERR_SUCCESS;
+ }
+ if ((len & 0xC0) == 0xC0) {
+ /* its a label pointer */
+ if (1 + *offset >= ndr->data_size) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING,
+ "BAD NBT NAME component");
+ }
+ *max_offset = MAX(*max_offset, *offset + 2);
+ *offset = ((len&0x3F)<<8) | ndr->data[1 + *offset];
+ *max_offset = MAX(*max_offset, *offset);
+ loops++;
+ continue;
+ }
+ if ((len & 0xC0) != 0) {
+ /* its a reserved length field */
+ return ndr_pull_error(ndr, NDR_ERR_STRING,
+ "BAD NBT NAME component");
+ }
+ if (*offset + len + 1 > ndr->data_size) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING,
+ "BAD NBT NAME component");
+ }
+ *component = (uint8_t*)talloc_strndup(
+ ndr->current_mem_ctx,
+ (const char *)&ndr->data[1 + *offset], len);
+ NDR_ERR_HAVE_NO_MEMORY(*component);
+ *offset += len + 1;
+ *max_offset = MAX(*max_offset, *offset);
+ return NDR_ERR_SUCCESS;
+ }
+
+ /* too many pointers */
+ return ndr_pull_error(ndr, NDR_ERR_STRING, "BAD NBT NAME component");
+}
+
+/**
+ pull a nbt_string from the wire
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_nbt_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
+{
+ uint32_t offset = ndr->offset;
+ uint32_t max_offset = offset;
+ unsigned num_components;
+ char *name;
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ name = NULL;
+
+ /* break up name into a list of components */
+ for (num_components=0;num_components<MAX_COMPONENTS;num_components++) {
+ uint8_t *component = NULL;
+ NDR_CHECK(ndr_pull_component(ndr, &component, &offset, &max_offset));
+ if (component == NULL) break;
+ if (name) {
+ name = talloc_asprintf_append_buffer(name, ".%s", component);
+ NDR_ERR_HAVE_NO_MEMORY(name);
+ } else {
+ name = (char *)component;
+ }
+ }
+ if (num_components == MAX_COMPONENTS) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING,
+ "BAD NBT NAME too many components");
+ }
+ if (num_components == 0) {
+ name = talloc_strdup(ndr->current_mem_ctx, "");
+ NDR_ERR_HAVE_NO_MEMORY(name);
+ }
+
+ (*s) = name;
+ ndr->offset = max_offset;
+
+ return NDR_ERR_SUCCESS;
+}
+
+/**
+ push a nbt string to the wire
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_nbt_string(struct ndr_push *ndr, int ndr_flags, const char *s)
+{
+ return ndr_push_dns_string_list(ndr,
+ &ndr->dns_string_list,
+ ndr_flags,
+ s,
+ true);
+}
+
+
+/* Manually modified to handle the dom_sid being optional based on if it is present or all zero */
+enum ndr_err_code ndr_push_NETLOGON_SAM_LOGON_REQUEST(struct ndr_push *ndr, int ndr_flags, const struct NETLOGON_SAM_LOGON_REQUEST *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->request_count));
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->computer_name));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->user_name));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->mailslot_name));
+ ndr->flags = _flags_save_string;
+ }
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->acct_control));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_size_dom_sid0(&r->sid, ndr->flags)));
+ if (ndr_size_dom_sid0(&r->sid, ndr->flags)) {
+ struct ndr_push *_ndr_sid;
+ uint32_t _flags_save_DATA_BLOB = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN4);
+ NDR_CHECK(ndr_push_DATA_BLOB(ndr, NDR_SCALARS, r->_pad));
+ ndr->flags = _flags_save_DATA_BLOB;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_sid, 0, ndr_size_dom_sid0(&r->sid, ndr->flags)));
+ NDR_CHECK(ndr_push_dom_sid0(_ndr_sid, NDR_SCALARS|NDR_BUFFERS, &r->sid));
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_sid, 0, ndr_size_dom_sid0(&r->sid, ndr->flags)));
+ }
+ NDR_CHECK(ndr_push_netlogon_nt_version_flags(ndr, NDR_SCALARS, r->nt_version));
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->lmnt_token));
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->lm20_token));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+/* Manually modified to handle the dom_sid being optional based on if it is present (size is non-zero) or not */
+enum ndr_err_code ndr_pull_NETLOGON_SAM_LOGON_REQUEST(struct ndr_pull *ndr, int ndr_flags, struct NETLOGON_SAM_LOGON_REQUEST *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->request_count));
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->computer_name));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->user_name));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->mailslot_name));
+ ndr->flags = _flags_save_string;
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->acct_control));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sid_size));
+ if (r->sid_size) {
+ uint32_t _flags_save_DATA_BLOB = ndr->flags;
+ struct ndr_pull *_ndr_sid;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN4);
+ NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS, &r->_pad));
+ ndr->flags = _flags_save_DATA_BLOB;
+ NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_sid, 0, r->sid_size));
+ NDR_CHECK(ndr_pull_dom_sid0(_ndr_sid, NDR_SCALARS|NDR_BUFFERS, &r->sid));
+ NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_sid, 0, r->sid_size));
+ } else {
+ ZERO_STRUCT(r->sid);
+ }
+ NDR_CHECK(ndr_pull_netlogon_nt_version_flags(ndr, NDR_SCALARS, &r->nt_version));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->lmnt_token));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->lm20_token));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+/* Manually modified to only push some parts of the structure if certain flags are set */
+enum ndr_err_code ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags(struct ndr_push *ndr, int ndr_flags, const struct NETLOGON_SAM_LOGON_RESPONSE_EX *r)
+{
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_netlogon_command(ndr, NDR_SCALARS, r->command));
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->sbz));
+ NDR_CHECK(ndr_push_nbt_server_type(ndr, NDR_SCALARS, r->server_type));
+ NDR_CHECK(ndr_push_GUID(ndr, NDR_SCALARS, &r->domain_uuid));
+ NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->forest));
+ NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->dns_domain));
+ NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->pdc_dns_name));
+ NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->domain_name));
+ NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->pdc_name));
+ NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->user_name));
+ NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->server_site));
+ NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->client_site));
+ if (r->nt_version & NETLOGON_NT_VERSION_5EX_WITH_IP) {
+ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, ndr_size_nbt_sockaddr(&r->sockaddr, ndr->flags)));
+ {
+ struct ndr_push *_ndr_sockaddr;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_sockaddr, 0, ndr_size_nbt_sockaddr(&r->sockaddr, ndr->flags)));
+ NDR_CHECK(ndr_push_nbt_sockaddr(_ndr_sockaddr, NDR_SCALARS|NDR_BUFFERS, &r->sockaddr));
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_sockaddr, 0, ndr_size_nbt_sockaddr(&r->sockaddr, ndr->flags)));
+ }
+ }
+ if (r->nt_version & NETLOGON_NT_VERSION_WITH_CLOSEST_SITE) {
+ NDR_CHECK(ndr_push_nbt_string(ndr, NDR_SCALARS, r->next_closest_site));
+ }
+ NDR_CHECK(ndr_push_netlogon_nt_version_flags(ndr, NDR_SCALARS, r->nt_version));
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->lmnt_token));
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->lm20_token));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ NDR_CHECK(ndr_push_GUID(ndr, NDR_BUFFERS, &r->domain_uuid));
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+/* Manually modified to only pull some parts of the structure if certain flags provided */
+enum ndr_err_code ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags(struct ndr_pull *ndr, int ndr_flags, struct NETLOGON_SAM_LOGON_RESPONSE_EX *r,
+ uint32_t nt_version_flags)
+{
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ZERO_STRUCTP(r);
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_netlogon_command(ndr, NDR_SCALARS, &r->command));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->sbz));
+ NDR_CHECK(ndr_pull_nbt_server_type(ndr, NDR_SCALARS, &r->server_type));
+ NDR_CHECK(ndr_pull_GUID(ndr, NDR_SCALARS, &r->domain_uuid));
+ NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->forest));
+ NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->dns_domain));
+ NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->pdc_dns_name));
+ NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->domain_name));
+ NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->pdc_name));
+ NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->user_name));
+ NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->server_site));
+ NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->client_site));
+ if (nt_version_flags & NETLOGON_NT_VERSION_5EX_WITH_IP) {
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->sockaddr_size));
+ {
+ struct ndr_pull *_ndr_sockaddr;
+ NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_sockaddr, 0, r->sockaddr_size));
+ NDR_CHECK(ndr_pull_nbt_sockaddr(_ndr_sockaddr, NDR_SCALARS|NDR_BUFFERS, &r->sockaddr));
+ NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_sockaddr, 0, r->sockaddr_size));
+ }
+ }
+ if (nt_version_flags & NETLOGON_NT_VERSION_WITH_CLOSEST_SITE) {
+ NDR_CHECK(ndr_pull_nbt_string(ndr, NDR_SCALARS, &r->next_closest_site));
+ }
+ NDR_CHECK(ndr_pull_netlogon_nt_version_flags(ndr, NDR_SCALARS, &r->nt_version));
+ if (r->nt_version != nt_version_flags) {
+ return NDR_ERR_VALIDATE;
+ }
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->lmnt_token));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->lm20_token));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ NDR_CHECK(ndr_pull_GUID(ndr, NDR_BUFFERS, &r->domain_uuid));
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_netlogon_samlogon_response(struct ndr_push *ndr, int ndr_flags, const struct netlogon_samlogon_response *r)
+{
+ if (r->ntver == NETLOGON_NT_VERSION_1) {
+ NDR_CHECK(ndr_push_NETLOGON_SAM_LOGON_RESPONSE_NT40(
+ ndr, ndr_flags, &r->data.nt4));
+ } else if (r->ntver & NETLOGON_NT_VERSION_5EX) {
+ NDR_CHECK(ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags(
+ ndr, ndr_flags, &r->data.nt5_ex));
+ } else if (r->ntver & NETLOGON_NT_VERSION_5) {
+ NDR_CHECK(ndr_push_NETLOGON_SAM_LOGON_RESPONSE(
+ ndr, ndr_flags, &r->data.nt5));
+ } else {
+ return NDR_ERR_BAD_SWITCH;
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_netlogon_samlogon_response(struct ndr_pull *ndr, int ndr_flags, struct netlogon_samlogon_response *r)
+{
+ if (ndr->data_size < 8) {
+ return NDR_ERR_BUFSIZE;
+ }
+
+ /* lmnttoken */
+ if (SVAL(ndr->data, ndr->data_size - 4) != 0xffff) {
+ return NDR_ERR_TOKEN;
+ }
+ /* lm20token */
+ if (SVAL(ndr->data, ndr->data_size - 2) != 0xffff) {
+ return NDR_ERR_TOKEN;
+ }
+
+ r->ntver = IVAL(ndr->data, ndr->data_size - 8);
+
+ if (r->ntver == NETLOGON_NT_VERSION_1) {
+ NDR_CHECK(ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_NT40(
+ ndr, ndr_flags, &r->data.nt4));
+ } else if (r->ntver & NETLOGON_NT_VERSION_5EX) {
+ NDR_CHECK(ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags(
+ ndr, ndr_flags, &r->data.nt5_ex, r->ntver));
+ if (ndr->offset < ndr->data_size) {
+ return ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
+ "not all bytes consumed ofs[%u] size[%u]",
+ ndr->offset, ndr->data_size);
+ }
+ } else if (r->ntver & NETLOGON_NT_VERSION_5) {
+ NDR_CHECK(ndr_pull_NETLOGON_SAM_LOGON_RESPONSE(
+ ndr, ndr_flags, &r->data.nt5));
+ } else {
+ return NDR_ERR_BAD_SWITCH;
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_netlogon_samlogon_response(struct ndr_print *ndr, const char *name, struct netlogon_samlogon_response *r)
+{
+ ndr_print_struct(ndr, name, "netlogon_samlogon_response");
+ if (r == NULL) { ndr_print_null(ndr); return; }
+ if (r->ntver == NETLOGON_NT_VERSION_1) {
+ ndr_print_NETLOGON_SAM_LOGON_RESPONSE_NT40(ndr, "data.nt4", &r->data.nt4);
+ } else if (r->ntver & NETLOGON_NT_VERSION_5EX) {
+ ndr_print_NETLOGON_SAM_LOGON_RESPONSE_EX(ndr, "data.nt5_ex", &r->data.nt5_ex);
+ } else if (r->ntver & NETLOGON_NT_VERSION_5) {
+ ndr_print_NETLOGON_SAM_LOGON_RESPONSE(ndr, "data.nt5", &r->data.nt5);
+ }
+}
diff --git a/librpc/ndr/ndr_nbt.h b/librpc/ndr/ndr_nbt.h
new file mode 100644
index 0000000..7c06301
--- /dev/null
+++ b/librpc/ndr/ndr_nbt.h
@@ -0,0 +1,42 @@
+#/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling special netlogon types
+
+ Copyright (C) Andrew Tridgell 2005
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
+ Copyright (C) Guenther Deschner 2011
+
+ 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/>.
+*/
+
+/* The following definitions come from ../librpc/ndr/ndr_nbt.c */
+
+#ifndef _LIBRPC_NDR_NDR_NBT_H
+#define _LIBRPC_NDR_NDR_NBT_H
+
+#include "librpc/gen_ndr/nbt.h"
+
+NDR_SCALAR_PROTO(nbt_string, const char *)
+
+enum ndr_err_code ndr_push_NETLOGON_SAM_LOGON_REQUEST(struct ndr_push *ndr, int ndr_flags, const struct NETLOGON_SAM_LOGON_REQUEST *r);
+enum ndr_err_code ndr_pull_NETLOGON_SAM_LOGON_REQUEST(struct ndr_pull *ndr, int ndr_flags, struct NETLOGON_SAM_LOGON_REQUEST *r);
+enum ndr_err_code ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags(struct ndr_push *ndr, int ndr_flags, const struct NETLOGON_SAM_LOGON_RESPONSE_EX *r);
+enum ndr_err_code ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags(struct ndr_pull *ndr, int ndr_flags, struct NETLOGON_SAM_LOGON_RESPONSE_EX *r,
+ uint32_t nt_version_flags);
+enum ndr_err_code ndr_push_netlogon_samlogon_response(struct ndr_push *ndr, int ndr_flags, const struct netlogon_samlogon_response *r);
+enum ndr_err_code ndr_pull_netlogon_samlogon_response(struct ndr_pull *ndr, int ndr_flags, struct netlogon_samlogon_response *r);
+void ndr_print_netlogon_samlogon_response(struct ndr_print *ndr, const char *name, struct netlogon_samlogon_response *r);
+
+#endif /* _LIBRPC_NDR_NDR_NBT_H */
diff --git a/librpc/ndr/ndr_negoex.c b/librpc/ndr/ndr_negoex.c
new file mode 100644
index 0000000..72c8774
--- /dev/null
+++ b/librpc/ndr/ndr_negoex.c
@@ -0,0 +1,521 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling special NEGOEX structures
+
+ Copyright (C) Stefan Metzmacher 2015
+
+ 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/>.
+*/
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_negoex.h"
+#include "librpc/gen_ndr/ndr_misc.h"
+#include "librpc/ndr/ndr_negoex.h"
+
+void ndr_print_negoex_BYTE_VECTOR(struct ndr_print *ndr, const char *name, const struct negoex_BYTE_VECTOR *r)
+{
+ ndr_print_struct(ndr, name, "negoex_BYTE_VECTOR");
+ if (r == NULL) { ndr_print_null(ndr); return; }
+ ndr->depth++;
+ ndr_print_DATA_BLOB(ndr, "blob", r->blob);
+ ndr->depth--;
+}
+
+enum ndr_err_code ndr_push_negoex_BYTE_VECTOR(struct ndr_push *ndr, int ndr_flags, const struct negoex_BYTE_VECTOR *r)
+{
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 5));
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->blob.data));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->blob.length));
+ NDR_CHECK(ndr_push_trailer_align(ndr, 5));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->blob.data) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->blob.data));
+#if 0
+ NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, r->blob.length));
+#endif
+ NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->blob.data, r->blob.length));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->blob.data));
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_negoex_BYTE_VECTOR(struct ndr_pull *ndr, int ndr_flags, struct negoex_BYTE_VECTOR *r)
+{
+ uint32_t _ptr_data;
+ uint32_t size_data_1 = 0;
+ TALLOC_CTX *_mem_save_data_0 = NULL;
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ r->_dummy = NULL;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 5));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_data));
+ if (_ptr_data) {
+ NDR_PULL_ALLOC(ndr, r->blob.data);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->blob.data, _ptr_data));
+ } else {
+ r->blob.data = NULL;
+ }
+ r->blob.length = 0;
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &size_data_1));
+ r->_length = size_data_1;
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 5));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->blob.data) {
+ uint32_t _relative_save_offset;
+ _relative_save_offset = ndr->offset;
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->blob.data));
+ _mem_save_data_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->blob.data, 0);
+#if 0
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->blob.data));
+ size_data_1 = ndr_get_array_size(ndr, &r->blob.data);
+#else
+ size_data_1 = r->_length;
+#endif
+ NDR_PULL_ALLOC_N(ndr, r->blob.data, size_data_1);
+ NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->blob.data, size_data_1));
+ r->blob.length = size_data_1;
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_data_0, 0);
+ if (ndr->offset > ndr->relative_highest_offset) {
+ ndr->relative_highest_offset = ndr->offset;
+ }
+ ndr->offset = _relative_save_offset;
+ }
+#if 0
+ if (r->blob.data) {
+ NDR_CHECK(ndr_check_steal_array_size(ndr, (void*)&r->blob.data, r->blob.length));
+ }
+#endif
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_push_negoex_AUTH_SCHEME_VECTOR(struct ndr_push *ndr, int ndr_flags, const struct negoex_AUTH_SCHEME_VECTOR *r)
+{
+ uint32_t cntr_array_1;
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 5));
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->array));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->count));
+ NDR_CHECK(ndr_push_trailer_align(ndr, 5));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->array) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->array));
+#if 0
+ NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, r->count));
+#endif
+ for (cntr_array_1 = 0; cntr_array_1 < (r->count); cntr_array_1++) {
+ NDR_CHECK(ndr_push_negoex_AUTH_SCHEME(ndr, NDR_SCALARS, &r->array[cntr_array_1]));
+ }
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->array));
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_negoex_AUTH_SCHEME_VECTOR(struct ndr_pull *ndr, int ndr_flags, struct negoex_AUTH_SCHEME_VECTOR *r)
+{
+ uint32_t _ptr_array;
+ uint32_t size_array_1 = 0;
+ uint32_t cntr_array_1;
+ TALLOC_CTX *_mem_save_array_0 = NULL;
+ TALLOC_CTX *_mem_save_array_1 = NULL;
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 5));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_array));
+ if (_ptr_array) {
+ NDR_PULL_ALLOC(ndr, r->array);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->array, _ptr_array));
+ } else {
+ r->array = NULL;
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->count));
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 5));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->array) {
+ uint32_t _relative_save_offset;
+ _relative_save_offset = ndr->offset;
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->array));
+ _mem_save_array_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->array, 0);
+#if 0
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->array));
+ size_array_1 = ndr_get_array_size(ndr, &r->array);
+#else
+ size_array_1 = r->count;
+#endif
+ NDR_PULL_ALLOC_N(ndr, r->array, size_array_1);
+ _mem_save_array_1 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->array, 0);
+ for (cntr_array_1 = 0; cntr_array_1 < (size_array_1); cntr_array_1++) {
+ NDR_CHECK(ndr_pull_negoex_AUTH_SCHEME(ndr, NDR_SCALARS, &r->array[cntr_array_1]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_array_1, 0);
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_array_0, 0);
+ if (ndr->offset > ndr->relative_highest_offset) {
+ ndr->relative_highest_offset = ndr->offset;
+ }
+ ndr->offset = _relative_save_offset;
+ }
+#if 0
+ if (r->array) {
+ NDR_CHECK(ndr_check_steal_array_size(ndr, (void*)&r->array, r->count));
+ }
+#endif
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_push_negoex_EXTENSION_VECTOR(struct ndr_push *ndr, int ndr_flags, const struct negoex_EXTENSION_VECTOR *r)
+{
+ uint32_t cntr_array_1;
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 5));
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->array));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->count));
+ NDR_CHECK(ndr_push_trailer_align(ndr, 5));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->array) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->array));
+#if 0
+ NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, r->count));
+#endif
+ for (cntr_array_1 = 0; cntr_array_1 < (r->count); cntr_array_1++) {
+ NDR_CHECK(ndr_push_negoex_EXTENSION(ndr, NDR_SCALARS, &r->array[cntr_array_1]));
+ }
+ for (cntr_array_1 = 0; cntr_array_1 < (r->count); cntr_array_1++) {
+ NDR_CHECK(ndr_push_negoex_EXTENSION(ndr, NDR_BUFFERS, &r->array[cntr_array_1]));
+ }
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->array));
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_negoex_EXTENSION_VECTOR(struct ndr_pull *ndr, int ndr_flags, struct negoex_EXTENSION_VECTOR *r)
+{
+ uint32_t _ptr_array;
+ uint32_t size_array_1 = 0;
+ uint32_t cntr_array_1;
+ TALLOC_CTX *_mem_save_array_0 = NULL;
+ TALLOC_CTX *_mem_save_array_1 = NULL;
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 5));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_array));
+ if (_ptr_array) {
+ NDR_PULL_ALLOC(ndr, r->array);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->array, _ptr_array));
+ } else {
+ r->array = NULL;
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->count));
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 5));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->array) {
+ uint32_t _relative_save_offset;
+ _relative_save_offset = ndr->offset;
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->array));
+ _mem_save_array_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->array, 0);
+#if 0
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->array));
+ size_array_1 = ndr_get_array_size(ndr, &r->array);
+#else
+ size_array_1 = r->count;
+#endif
+ NDR_PULL_ALLOC_N(ndr, r->array, size_array_1);
+ _mem_save_array_1 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->array, 0);
+ for (cntr_array_1 = 0; cntr_array_1 < (size_array_1); cntr_array_1++) {
+ NDR_CHECK(ndr_pull_negoex_EXTENSION(ndr, NDR_SCALARS, &r->array[cntr_array_1]));
+ }
+ for (cntr_array_1 = 0; cntr_array_1 < (size_array_1); cntr_array_1++) {
+ NDR_CHECK(ndr_pull_negoex_EXTENSION(ndr, NDR_BUFFERS, &r->array[cntr_array_1]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_array_1, 0);
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_array_0, 0);
+ if (ndr->offset > ndr->relative_highest_offset) {
+ ndr->relative_highest_offset = ndr->offset;
+ }
+ ndr->offset = _relative_save_offset;
+ }
+#if 0
+ if (r->array) {
+ NDR_CHECK(ndr_check_steal_array_size(ndr, (void*)&r->array, r->count));
+ }
+#endif
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_push_negoex_ALERT_VECTOR(struct ndr_push *ndr, int ndr_flags, const struct negoex_ALERT_VECTOR *r)
+{
+ uint32_t cntr_array_1;
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 5));
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->array));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->count));
+ NDR_CHECK(ndr_push_trailer_align(ndr, 5));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->array) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->array));
+#if 0
+ NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, r->count));
+#endif
+ for (cntr_array_1 = 0; cntr_array_1 < (r->count); cntr_array_1++) {
+ NDR_CHECK(ndr_push_negoex_ALERT(ndr, NDR_SCALARS, &r->array[cntr_array_1]));
+ }
+ for (cntr_array_1 = 0; cntr_array_1 < (r->count); cntr_array_1++) {
+ NDR_CHECK(ndr_push_negoex_ALERT(ndr, NDR_BUFFERS, &r->array[cntr_array_1]));
+ }
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->array));
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_negoex_ALERT_VECTOR(struct ndr_pull *ndr, int ndr_flags, struct negoex_ALERT_VECTOR *r)
+{
+ uint32_t _ptr_array;
+ uint32_t size_array_1 = 0;
+ uint32_t cntr_array_1;
+ TALLOC_CTX *_mem_save_array_0 = NULL;
+ TALLOC_CTX *_mem_save_array_1 = NULL;
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 5));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_array));
+ if (_ptr_array) {
+ NDR_PULL_ALLOC(ndr, r->array);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->array, _ptr_array));
+ } else {
+ r->array = NULL;
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->count));
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 5));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->array) {
+ uint32_t _relative_save_offset;
+ _relative_save_offset = ndr->offset;
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->array));
+ _mem_save_array_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->array, 0);
+#if 0
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->array));
+ size_array_1 = ndr_get_array_size(ndr, &r->array);
+#else
+ size_array_1 = r->count;
+#endif
+ NDR_PULL_ALLOC_N(ndr, r->array, size_array_1);
+ _mem_save_array_1 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->array, 0);
+ for (cntr_array_1 = 0; cntr_array_1 < (size_array_1); cntr_array_1++) {
+ NDR_CHECK(ndr_pull_negoex_ALERT(ndr, NDR_SCALARS, &r->array[cntr_array_1]));
+ }
+ for (cntr_array_1 = 0; cntr_array_1 < (size_array_1); cntr_array_1++) {
+ NDR_CHECK(ndr_pull_negoex_ALERT(ndr, NDR_BUFFERS, &r->array[cntr_array_1]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_array_1, 0);
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_array_0, 0);
+ if (ndr->offset > ndr->relative_highest_offset) {
+ ndr->relative_highest_offset = ndr->offset;
+ }
+ ndr->offset = _relative_save_offset;
+ }
+#if 0
+ if (r->array) {
+ NDR_CHECK(ndr_check_steal_array_size(ndr, (void*)&r->array, r->count));
+ }
+#endif
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+size_t ndr_negoex_MESSAGE_header_length(const struct negoex_MESSAGE *r)
+{
+ size_t size = 0;
+
+ size += 8; /* signature */
+ size += 4; /* type */
+ size += 4; /* sequence_number */
+ size += 4; /* header_length */
+ size += 4; /* message_length */
+ size += 16; /* conversation_id */
+
+ switch (r->type) {
+ case NEGOEX_MESSAGE_TYPE_INITIATOR_NEGO:
+ case NEGOEX_MESSAGE_TYPE_ACCEPTOR_NEGO:
+ size += 32; /* random */
+ size += 8; /* protocol_version */
+ size += 8; /* auth_schemes */
+ size += 8; /* extensions */
+ break;
+
+ case NEGOEX_MESSAGE_TYPE_INITIATOR_META_DATA:
+ case NEGOEX_MESSAGE_TYPE_ACCEPTOR_META_DATA:
+ case NEGOEX_MESSAGE_TYPE_CHALLENGE:
+ case NEGOEX_MESSAGE_TYPE_AP_REQUEST:
+ size += 16; /* auth_scheme */
+ size += 8; /* exchange */
+ break;
+
+ case NEGOEX_MESSAGE_TYPE_VERIFY:
+ size += 16; /* auth_scheme */
+ size += 4; /* checksum.header_length */
+ size += 4; /* checksum.scheme */
+ size += 4; /* checksum.type */
+ size += 8; /* checksum.value */
+ break;
+
+ case NEGOEX_MESSAGE_TYPE_ALERT:
+ size += 16; /* auth_scheme */
+ size += 4; /* status */
+ size += 8; /* alerts */
+ break;
+ }
+
+ return size;
+}
+
+enum ndr_err_code ndr_pull_negoex_MESSAGE(struct ndr_pull *ndr, int ndr_flags, struct negoex_MESSAGE *r)
+{
+ uint32_t _save_relative_base_offset = ndr_pull_get_relative_base_offset(ndr);
+ uint32_t size_signature_0 = 0;
+ uint32_t start_data_size = ndr->data_size;
+ uint32_t saved_offset = 0;
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 5));
+ NDR_CHECK(ndr_pull_setup_relative_base_offset1(ndr, r, ndr->offset));
+ size_signature_0 = 8;
+ NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->signature, size_signature_0, sizeof(uint8_t), CH_DOS));
+ NDR_CHECK(ndr_pull_negoex_MESSAGE_TYPE(ndr, NDR_SCALARS, &r->type));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sequence_number));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->header_length));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->message_length));
+ saved_offset = ndr->offset;
+ ndr->offset = ndr->relative_base_offset;
+ NDR_PULL_NEED_BYTES(ndr, r->message_length);
+ ndr->data_size = ndr->offset + r->message_length;
+ ndr->offset = saved_offset;
+ NDR_CHECK(ndr_pull_GUID(ndr, NDR_SCALARS, &r->conversation_id));
+ NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->p, r->type));
+ NDR_CHECK(ndr_pull_negoex_PAYLOAD(ndr, NDR_SCALARS, &r->p));
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 5));
+ ndr->offset = ndr->data_size;
+ ndr->data_size = start_data_size;
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ NDR_CHECK(ndr_pull_setup_relative_base_offset2(ndr, r));
+ saved_offset = ndr->offset;
+ ndr->offset = ndr->relative_base_offset;
+ NDR_PULL_NEED_BYTES(ndr, r->message_length);
+ ndr->data_size = ndr->offset + r->message_length;
+ ndr->offset = saved_offset;
+ NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->p, r->type));
+ NDR_CHECK(ndr_pull_negoex_PAYLOAD(ndr, NDR_BUFFERS, &r->p));
+ ndr->offset = ndr->data_size;
+ ndr->data_size = start_data_size;
+ }
+ ndr_pull_restore_relative_base_offset(ndr, _save_relative_base_offset);
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_push_negoex_MESSAGE_ARRAY(struct ndr_push *ndr, int ndr_flags, const struct negoex_MESSAGE_ARRAY *r)
+{
+ uint32_t cntr_messages_0;
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 5));
+ for (cntr_messages_0 = 0; cntr_messages_0 < (r->count); cntr_messages_0++) {
+ NDR_CHECK(ndr_push_negoex_MESSAGE(ndr, NDR_SCALARS|NDR_BUFFERS, &r->messages[cntr_messages_0]));
+ }
+ NDR_CHECK(ndr_push_trailer_align(ndr, 5));
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_negoex_MESSAGE_ARRAY(struct ndr_pull *ndr, int ndr_flags, struct negoex_MESSAGE_ARRAY *r)
+{
+ uint32_t size_messages_0 = 0;
+ uint32_t cntr_messages_0;
+ TALLOC_CTX *_mem_save_messages_0 = NULL;
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ uint32_t saved_offset = ndr->offset;
+ uint32_t available = 0;
+ NDR_CHECK(ndr_pull_align(ndr, 5));
+ r->count = 0;
+ available = ndr->data_size - ndr->offset;
+ while (available > 0) {
+ uint32_t length;
+
+ /*
+ * The common header is 40 bytes
+ * and message_length is at offset 20
+ */
+ NDR_PULL_NEED_BYTES(ndr, 40);
+ ndr->offset += 20;
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length));
+ ndr->offset -= 24;
+ if (length < 40) {
+ /*
+ * let the pull function catch the error
+ */
+ length = 40;
+ }
+ NDR_PULL_NEED_BYTES(ndr, length);
+ ndr->offset += length;
+ available -= length;
+ r->count++;
+ }
+ ndr->offset = saved_offset;
+ size_messages_0 = r->count;
+ NDR_PULL_ALLOC_N(ndr, r->messages, size_messages_0);
+ _mem_save_messages_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->messages, 0);
+ for (cntr_messages_0 = 0; cntr_messages_0 < (size_messages_0); cntr_messages_0++) {
+ NDR_CHECK(ndr_pull_negoex_MESSAGE(ndr, NDR_SCALARS|NDR_BUFFERS, &r->messages[cntr_messages_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_messages_0, 0);
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 5));
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_negoex.h b/librpc/ndr/ndr_negoex.h
new file mode 100644
index 0000000..d3c39b2
--- /dev/null
+++ b/librpc/ndr/ndr_negoex.h
@@ -0,0 +1,37 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling special NEGOEX structures
+
+ Copyright (C) Stefan Metzmacher 2015
+
+ 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/>.
+*/
+
+#include "librpc/ndr/libndr.h"
+#include "librpc/gen_ndr/negoex.h"
+
+_PUBLIC_ void ndr_print_negoex_BYTE_VECTOR(struct ndr_print *ndr, const char *name, const struct negoex_BYTE_VECTOR *r);
+_PUBLIC_ enum ndr_err_code ndr_push_negoex_BYTE_VECTOR(struct ndr_push *ndr, int ndr_flags, const struct negoex_BYTE_VECTOR *r);
+_PUBLIC_ enum ndr_err_code ndr_pull_negoex_BYTE_VECTOR(struct ndr_pull *ndr, int ndr_flags, struct negoex_BYTE_VECTOR *r);
+_PUBLIC_ enum ndr_err_code ndr_push_negoex_AUTH_SCHEME_VECTOR(struct ndr_push *ndr, int ndr_flags, const struct negoex_AUTH_SCHEME_VECTOR *r);
+_PUBLIC_ enum ndr_err_code ndr_pull_negoex_AUTH_SCHEME_VECTOR(struct ndr_pull *ndr, int ndr_flags, struct negoex_AUTH_SCHEME_VECTOR *r);
+_PUBLIC_ enum ndr_err_code ndr_push_negoex_EXTENSION_VECTOR(struct ndr_push *ndr, int ndr_flags, const struct negoex_EXTENSION_VECTOR *r);
+_PUBLIC_ enum ndr_err_code ndr_pull_negoex_EXTENSION_VECTOR(struct ndr_pull *ndr, int ndr_flags, struct negoex_EXTENSION_VECTOR *r);
+_PUBLIC_ enum ndr_err_code ndr_push_negoex_ALERT_VECTOR(struct ndr_push *ndr, int ndr_flags, const struct negoex_ALERT_VECTOR *r);
+_PUBLIC_ enum ndr_err_code ndr_pull_negoex_ALERT_VECTOR(struct ndr_pull *ndr, int ndr_flags, struct negoex_ALERT_VECTOR *r);
+_PUBLIC_ size_t ndr_negoex_MESSAGE_header_length(const struct negoex_MESSAGE *r);
+_PUBLIC_ enum ndr_err_code ndr_pull_negoex_MESSAGE(struct ndr_pull *ndr, int ndr_flags, struct negoex_MESSAGE *r);
+_PUBLIC_ enum ndr_err_code ndr_push_negoex_MESSAGE_ARRAY(struct ndr_push *ndr, int ndr_flags, const struct negoex_MESSAGE_ARRAY *r);
+_PUBLIC_ enum ndr_err_code ndr_pull_negoex_MESSAGE_ARRAY(struct ndr_pull *ndr, int ndr_flags, struct negoex_MESSAGE_ARRAY *r);
diff --git a/librpc/ndr/ndr_netlogon.c b/librpc/ndr/ndr_netlogon.c
new file mode 100644
index 0000000..411f3b9
--- /dev/null
+++ b/librpc/ndr/ndr_netlogon.c
@@ -0,0 +1,65 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling special netlogon types
+
+ Copyright (C) Guenther Deschner 2008
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_netlogon.h"
+#include "librpc/gen_ndr/ndr_misc.h"
+#include "librpc/gen_ndr/ndr_samr.h"
+
+_PUBLIC_ enum ndr_err_code ndr_push_netr_SamDatabaseID8Bit(struct ndr_push *ndr, int ndr_flags, enum netr_SamDatabaseID8Bit r)
+{
+ if (r > 0xff) return NDR_ERR_BUFSIZE;
+ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r));
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_netr_SamDatabaseID8Bit(struct ndr_pull *ndr, int ndr_flags, enum netr_SamDatabaseID8Bit *r)
+{
+ uint8_t v;
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &v));
+ *r = v;
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_netr_SamDatabaseID8Bit(struct ndr_print *ndr, const char *name, enum netr_SamDatabaseID8Bit r)
+{
+ ndr_print_netr_SamDatabaseID(ndr, name, r);
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_netr_DeltaEnum8Bit(struct ndr_push *ndr, int ndr_flags, enum netr_DeltaEnum8Bit r)
+{
+ if (r > 0xff) return NDR_ERR_BUFSIZE;
+ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r));
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_netr_DeltaEnum8Bit(struct ndr_pull *ndr, int ndr_flags, enum netr_DeltaEnum8Bit *r)
+{
+ uint8_t v;
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &v));
+ *r = v;
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_netr_DeltaEnum8Bit(struct ndr_print *ndr, const char *name, enum netr_DeltaEnum8Bit r)
+{
+ ndr_print_netr_DeltaEnum(ndr, name, r);
+}
diff --git a/librpc/ndr/ndr_netlogon.h b/librpc/ndr/ndr_netlogon.h
new file mode 100644
index 0000000..0e6bd6a
--- /dev/null
+++ b/librpc/ndr/ndr_netlogon.h
@@ -0,0 +1,28 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling special netlogon types
+
+ Copyright (C) Guenther Deschner 2008
+
+ 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/>.
+*/
+
+_PUBLIC_ enum ndr_err_code ndr_push_netr_SamDatabaseID8Bit(struct ndr_push *ndr, int ndr_flags, enum netr_SamDatabaseID8Bit r);
+_PUBLIC_ enum ndr_err_code ndr_pull_netr_SamDatabaseID8Bit(struct ndr_pull *ndr, int ndr_flags, enum netr_SamDatabaseID8Bit *r);
+_PUBLIC_ void ndr_print_netr_SamDatabaseID8Bit(struct ndr_print *ndr, const char *name, enum netr_SamDatabaseID8Bit r);
+
+_PUBLIC_ enum ndr_err_code ndr_push_netr_DeltaEnum8Bit(struct ndr_push *ndr, int ndr_flags, enum netr_DeltaEnum8Bit r);
+_PUBLIC_ enum ndr_err_code ndr_pull_netr_DeltaEnum8Bit(struct ndr_pull *ndr, int ndr_flags, enum netr_DeltaEnum8Bit *r);
+_PUBLIC_ void ndr_print_netr_DeltaEnum8Bit(struct ndr_print *ndr, const char *name, enum netr_DeltaEnum8Bit r);
diff --git a/librpc/ndr/ndr_ntlmssp.c b/librpc/ndr/ndr_ntlmssp.c
new file mode 100644
index 0000000..021bc40
--- /dev/null
+++ b/librpc/ndr/ndr_ntlmssp.c
@@ -0,0 +1,195 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling special ntlmssp structures
+
+ Copyright (C) Guenther Deschner 2009
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "../librpc/gen_ndr/ndr_ntlmssp.h"
+
+_PUBLIC_ size_t ndr_ntlmssp_string_length(uint32_t negotiate_flags, const char *s)
+{
+ if (!s) {
+ return 0;
+ }
+
+ if (negotiate_flags & NTLMSSP_NEGOTIATE_UNICODE) {
+ return strlen(s) * 2;
+ }
+
+ return strlen(s);
+}
+
+_PUBLIC_ uint32_t ndr_ntlmssp_negotiated_string_flags(uint32_t negotiate_flags)
+{
+ uint32_t flags = LIBNDR_FLAG_STR_NOTERM |
+ LIBNDR_FLAG_STR_CHARLEN |
+ LIBNDR_FLAG_REMAINING;
+
+ if (!(negotiate_flags & NTLMSSP_NEGOTIATE_UNICODE)) {
+ flags |= LIBNDR_FLAG_STR_ASCII;
+ }
+
+ return flags;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_AV_PAIR_LIST(struct ndr_push *ndr, int ndr_flags, const struct AV_PAIR_LIST *r)
+{
+ uint32_t cntr_pair_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ for (cntr_pair_0 = 0; cntr_pair_0 < r->count; cntr_pair_0++) {
+ NDR_CHECK(ndr_push_AV_PAIR(ndr, NDR_SCALARS, &r->pair[cntr_pair_0]));
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ for (cntr_pair_0 = 0; cntr_pair_0 < r->count; cntr_pair_0++) {
+ NDR_CHECK(ndr_push_AV_PAIR(ndr, NDR_BUFFERS, &r->pair[cntr_pair_0]));
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_AV_PAIR_LIST(struct ndr_pull *ndr, int ndr_flags, struct AV_PAIR_LIST *r)
+{
+ uint32_t cntr_pair_0;
+ TALLOC_CTX *_mem_save_pair_0;
+ if (ndr_flags & NDR_SCALARS) {
+ uint32_t offset = 0;
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ r->count = 0;
+ if (ndr->data_size > 0) {
+ NDR_PULL_NEED_BYTES(ndr, 4);
+ }
+ while (offset + 4 <= ndr->data_size) {
+ uint16_t length;
+ uint16_t type;
+ type = SVAL(ndr->data + offset, 0);
+ if (type == MsvAvEOL) {
+ r->count++;
+ break;
+ }
+ length = SVAL(ndr->data + offset, 2);
+ offset += length + 4;
+ r->count++;
+ }
+ NDR_PULL_ALLOC_N(ndr, r->pair, r->count);
+ _mem_save_pair_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->pair, 0);
+ for (cntr_pair_0 = 0; cntr_pair_0 < r->count; cntr_pair_0++) {
+ NDR_CHECK(ndr_pull_AV_PAIR(ndr, NDR_SCALARS, &r->pair[cntr_pair_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_pair_0, 0);
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ _mem_save_pair_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->pair, 0);
+ for (cntr_pair_0 = 0; cntr_pair_0 < r->count; cntr_pair_0++) {
+ NDR_CHECK(ndr_pull_AV_PAIR(ndr, NDR_BUFFERS, &r->pair[cntr_pair_0]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_pair_0, 0);
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_ntlmssp_nt_response(TALLOC_CTX *mem_ctx,
+ const DATA_BLOB *nt_response,
+ bool ntlmv2)
+{
+ enum ndr_err_code ndr_err;
+
+ if (ntlmv2) {
+ struct NTLMv2_RESPONSE nt;
+ if (nt_response->length > 24) {
+ ndr_err = ndr_pull_struct_blob(nt_response, mem_ctx, &nt,
+ (ndr_pull_flags_fn_t)ndr_pull_NTLMv2_RESPONSE);
+ if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NDR_PRINT_DEBUG(NTLMv2_RESPONSE, &nt);
+ }
+ }
+ } else {
+ struct NTLM_RESPONSE nt;
+ if (nt_response->length == 24) {
+ ndr_err = ndr_pull_struct_blob(nt_response, mem_ctx, &nt,
+ (ndr_pull_flags_fn_t)ndr_pull_NTLM_RESPONSE);
+ if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NDR_PRINT_DEBUG(NTLM_RESPONSE, &nt);
+ }
+ }
+ }
+}
+
+_PUBLIC_ void ndr_print_ntlmssp_lm_response(TALLOC_CTX *mem_ctx,
+ const DATA_BLOB *lm_response,
+ bool ntlmv2)
+{
+ enum ndr_err_code ndr_err;
+
+ if (ntlmv2) {
+ struct LMv2_RESPONSE lm;
+ if (lm_response->length == 24) {
+ ndr_err = ndr_pull_struct_blob(lm_response, mem_ctx, &lm,
+ (ndr_pull_flags_fn_t)ndr_pull_LMv2_RESPONSE);
+ if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NDR_PRINT_DEBUG(LMv2_RESPONSE, &lm);
+ }
+ }
+ } else {
+ struct LM_RESPONSE lm;
+ if (lm_response->length == 24) {
+ ndr_err = ndr_pull_struct_blob(lm_response, mem_ctx, &lm,
+ (ndr_pull_flags_fn_t)ndr_pull_LM_RESPONSE);
+ if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NDR_PRINT_DEBUG(LM_RESPONSE, &lm);
+ }
+ }
+ }
+}
+
+_PUBLIC_ void ndr_print_ntlmssp_Version(struct ndr_print *ndr, const char *name, const union ntlmssp_Version *r)
+{
+ int level;
+ level = ndr_print_steal_switch_value(ndr, r);
+ switch (level) {
+ case NTLMSSP_NEGOTIATE_VERSION:
+ ndr_print_ntlmssp_VERSION(ndr, name, &r->version);
+ break;
+
+ default:
+ break;
+
+ }
+}
+
+_PUBLIC_ struct AV_PAIR *ndr_ntlmssp_find_av(const struct AV_PAIR_LIST *av_list,
+ enum ntlmssp_AvId AvId)
+{
+ struct AV_PAIR *res = NULL;
+ uint32_t i = 0;
+
+ for (i = 0; i < av_list->count; i++) {
+ if (av_list->pair[i].AvId != AvId) {
+ continue;
+ }
+
+ res = discard_const_p(struct AV_PAIR, &av_list->pair[i]);
+ break;
+ }
+
+ return res;
+}
diff --git a/librpc/ndr/ndr_ntlmssp.h b/librpc/ndr/ndr_ntlmssp.h
new file mode 100644
index 0000000..5c979ff
--- /dev/null
+++ b/librpc/ndr/ndr_ntlmssp.h
@@ -0,0 +1,35 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling special ntlmssp structures
+
+ Copyright (C) Guenther Deschner 2009
+
+ 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/>.
+*/
+
+_PUBLIC_ size_t ndr_ntlmssp_string_length(uint32_t negotiate_flags, const char *s);
+_PUBLIC_ uint32_t ndr_ntlmssp_negotiated_string_flags(uint32_t negotiate_flags);
+_PUBLIC_ enum ndr_err_code ndr_push_AV_PAIR_LIST(struct ndr_push *ndr, int ndr_flags, const struct AV_PAIR_LIST *r);
+_PUBLIC_ enum ndr_err_code ndr_pull_AV_PAIR_LIST(struct ndr_pull *ndr, int ndr_flags, struct AV_PAIR_LIST *r);
+_PUBLIC_ void ndr_print_ntlmssp_nt_response(TALLOC_CTX *mem_ctx,
+ const DATA_BLOB *nt_response,
+ bool ntlmv2);
+_PUBLIC_ void ndr_print_ntlmssp_lm_response(TALLOC_CTX *mem_ctx,
+ const DATA_BLOB *lm_response,
+ bool ntlmv2);
+_PUBLIC_ void ndr_print_ntlmssp_Version(struct ndr_print *ndr, const char *name, const union ntlmssp_Version *r);
+
+_PUBLIC_ struct AV_PAIR *ndr_ntlmssp_find_av(const struct AV_PAIR_LIST *av_list,
+ enum ntlmssp_AvId AvId);
diff --git a/librpc/ndr/ndr_ntprinting.c b/librpc/ndr/ndr_ntprinting.c
new file mode 100644
index 0000000..e4f47bb
--- /dev/null
+++ b/librpc/ndr/ndr_ntprinting.c
@@ -0,0 +1,87 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling special ntprinting structures
+
+ Copyright (C) Guenther Deschner 2010
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "../librpc/gen_ndr/ndr_ntprinting.h"
+
+_PUBLIC_ uint32_t ndr_ntprinting_string_flags(uint32_t string_flags)
+{
+ uint32_t flags = LIBNDR_FLAG_STR_NULLTERM;
+
+ if (string_flags & LIBNDR_FLAG_STR_ASCII) {
+ flags |= LIBNDR_FLAG_STR_ASCII;
+ } else if (string_flags & LIBNDR_FLAG_STR_RAW8) {
+ flags |= LIBNDR_FLAG_STR_RAW8;
+ } else {
+ flags |= LIBNDR_FLAG_STR_UTF8;
+ }
+
+ return flags;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_ntprinting_printer(struct ndr_pull *ndr, int ndr_flags, struct ntprinting_printer *r)
+{
+ uint32_t _ptr_devmode;
+ TALLOC_CTX *_mem_save_devmode_0;
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 5));
+ NDR_CHECK(ndr_pull_ntprinting_printer_info(ndr, NDR_SCALARS, &r->info));
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_devmode));
+ if (_ptr_devmode) {
+ NDR_PULL_ALLOC(ndr, r->devmode);
+ } else {
+ r->devmode = NULL;
+ }
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->devmode) {
+ _mem_save_devmode_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->devmode, 0);
+ r->devmode->string_flags = r->info.string_flags;
+ NDR_CHECK(ndr_pull_ntprinting_devicemode(ndr, NDR_SCALARS|NDR_BUFFERS, r->devmode));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_devmode_0, 0);
+ }
+ }
+ if (ndr_flags & NDR_SCALARS) {
+ r->count = 0;
+ NDR_PULL_ALLOC_N(ndr, r->printer_data, r->count);
+ while (ndr->offset + 4 <= ndr->data_size) {
+ uint32_t ptr = 0;
+ ptr = IVAL(ndr->data, ndr->offset);
+ if (ptr == 0) {
+ ndr->offset = ndr->offset + 4;
+ break;
+ }
+ r->printer_data = talloc_realloc(ndr, r->printer_data, struct ntprinting_printer_data, r->count + 1);
+ NDR_ERR_HAVE_NO_MEMORY(r->printer_data);
+ r->printer_data[r->count].string_flags = r->info.string_flags;
+ NDR_CHECK(ndr_pull_ntprinting_printer_data(ndr, NDR_SCALARS, &r->printer_data[r->count]));
+ r->count++;
+ }
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 5));
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_ntprinting.h b/librpc/ndr/ndr_ntprinting.h
new file mode 100644
index 0000000..3b6ee01
--- /dev/null
+++ b/librpc/ndr/ndr_ntprinting.h
@@ -0,0 +1,27 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling special ntprinting structures
+
+ Copyright (C) Guenther Deschner 2010
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "../librpc/gen_ndr/ndr_ntprinting.h"
+
+_PUBLIC_ uint32_t ndr_ntprinting_string_flags(uint32_t string_flags);
+
+_PUBLIC_ enum ndr_err_code ndr_pull_ntprinting_printer(struct ndr_pull *ndr, int ndr_flags, struct ntprinting_printer *r);
diff --git a/librpc/ndr/ndr_orpc.c b/librpc/ndr/ndr_orpc.c
new file mode 100644
index 0000000..01ba885
--- /dev/null
+++ b/librpc/ndr/ndr_orpc.c
@@ -0,0 +1,163 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling DCOM string arrays
+
+ Copyright (C) Jelmer Vernooij 2004
+
+ 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/>.
+*/
+
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_orpc.h"
+
+enum ndr_err_code ndr_pull_DUALSTRINGARRAY(struct ndr_pull *ndr, int ndr_flags, struct DUALSTRINGARRAY *ar)
+{
+ uint16_t num_entries, security_offset;
+ uint16_t towerid;
+ uint32_t towernum = 0, conformant_size;
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &conformant_size));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &num_entries));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &security_offset));
+
+ ar->stringbindings = talloc_array(ndr, struct STRINGBINDING *, 1);
+ ar->stringbindings[0] = NULL;
+
+ do {
+ /* 'Peek' */
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &towerid));
+
+ if (towerid > 0) {
+ ndr->offset -= 2;
+ ar->stringbindings = talloc_realloc(ndr, ar->stringbindings, struct STRINGBINDING *, towernum+2);
+ ar->stringbindings[towernum] = talloc(ndr, struct STRINGBINDING);
+ NDR_CHECK(ndr_pull_STRINGBINDING(ndr, ndr_flags, ar->stringbindings[towernum]));
+ towernum++;
+ }
+ } while (towerid != 0);
+
+ ar->stringbindings[towernum] = NULL;
+ towernum = 0;
+
+ ar->securitybindings = talloc_array(ndr, struct SECURITYBINDING *, 1);
+ ar->securitybindings[0] = NULL;
+
+ do {
+ /* 'Peek' */
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &towerid));
+
+ if (towerid > 0) {
+ ndr->offset -= 2;
+ ar->securitybindings = talloc_realloc(ndr, ar->securitybindings, struct SECURITYBINDING *, towernum+2);
+ ar->securitybindings[towernum] = talloc(ndr, struct SECURITYBINDING);
+ NDR_CHECK(ndr_pull_SECURITYBINDING(ndr, ndr_flags, ar->securitybindings[towernum]));
+ towernum++;
+ }
+ } while (towerid != 0);
+
+ ar->securitybindings[towernum] = NULL;
+
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_push_DUALSTRINGARRAY(struct ndr_push *ndr, int ndr_flags, const struct DUALSTRINGARRAY *ar)
+{
+ return ndr_push_error(ndr, NDR_ERR_STRING, "ndr_push_DUALSTRINGARRAY not implemented");
+}
+
+/*
+ print a dom_sid
+*/
+void ndr_print_DUALSTRINGARRAY(struct ndr_print *ndr, const char *name, const struct DUALSTRINGARRAY *ar)
+{
+ int i;
+ ndr->print(ndr, "%-25s: DUALSTRINGARRAY", name);
+ ndr->depth++;
+ ndr->print(ndr, "STRING BINDINGS");
+ ndr->depth++;
+ for (i=0;ar->stringbindings[i];i++) {
+ char idx[13]; /* 2^32 has 10 digits */
+ snprintf(idx, sizeof(idx), "[%d]", i);
+ ndr_print_STRINGBINDING(ndr, idx, ar->stringbindings[i]);
+ }
+ ndr->depth--;
+ ndr->print(ndr, "SECURITY BINDINGS");
+ ndr->depth++;
+ for (i=0;ar->securitybindings[i];i++) {
+ char idx[13]; /* 2^32 has 10 digits */
+ snprintf(idx, sizeof(idx), "[%d]", i);
+ ndr_print_SECURITYBINDING(ndr, idx, ar->securitybindings[i]);
+ }
+ ndr->depth--;
+}
+
+enum ndr_err_code ndr_pull_STRINGARRAY(struct ndr_pull *ndr, int ndr_flags, struct STRINGARRAY *ar)
+{
+ uint16_t towerid;
+ uint32_t towernum = 0;
+ uint16_t num_entries;
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &num_entries));
+
+ ar->stringbindings = talloc_array(ndr, struct STRINGBINDING *, 1);
+ ar->stringbindings[0] = NULL;
+
+ do {
+ /* 'Peek' */
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &towerid));
+
+ if (towerid > 0) {
+ ndr->offset -= 2;
+ ar->stringbindings = talloc_realloc(ndr, ar->stringbindings, struct STRINGBINDING *, towernum+2);
+ ar->stringbindings[towernum] = talloc(ndr, struct STRINGBINDING);
+ NDR_CHECK(ndr_pull_STRINGBINDING(ndr, ndr_flags, ar->stringbindings[towernum]));
+ towernum++;
+ }
+ } while (towerid != 0);
+
+ ar->stringbindings[towernum] = NULL;
+
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_push_STRINGARRAY(struct ndr_push *ndr, int ndr_flags, const struct STRINGARRAY *ar)
+{
+ return ndr_push_error(ndr, NDR_ERR_STRING, "ndr_push_STRINGARRAY not implemented");
+}
+
+/*
+ print a dom_sid
+*/
+void ndr_print_STRINGARRAY(struct ndr_print *ndr, const char *name, const struct STRINGARRAY *ar)
+{
+ int i;
+ ndr->print(ndr, "%-25s: STRINGARRAY", name);
+ ndr->depth++;
+ for (i=0;ar->stringbindings[i];i++) {
+ char idx[13]; /* 2^32 has 10 digits */
+ snprintf(idx, sizeof(idx), "[%d]", i);
+ ndr_print_STRINGBINDING(ndr, idx, ar->stringbindings[i]);
+ }
+ ndr->depth--;
+}
diff --git a/librpc/ndr/ndr_preg.c b/librpc/ndr/ndr_preg.c
new file mode 100644
index 0000000..2c684e2
--- /dev/null
+++ b/librpc/ndr/ndr_preg.c
@@ -0,0 +1,69 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling preg structures
+
+ Copyright (C) Guenther Deschner 2010
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_preg.h"
+
+_PUBLIC_ enum ndr_err_code ndr_push_preg_file(struct ndr_push *ndr, int ndr_flags, const struct preg_file *r)
+{
+ uint32_t cntr_entries_0;
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_preg_header(ndr, NDR_SCALARS, &r->header));
+ for (cntr_entries_0 = 0; cntr_entries_0 < r->num_entries; cntr_entries_0++) {
+ NDR_CHECK(ndr_push_preg_entry(ndr, NDR_SCALARS, &r->entries[cntr_entries_0]));
+ }
+ NDR_CHECK(ndr_push_trailer_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_preg_file(struct ndr_pull *ndr, int ndr_flags, struct preg_file *r)
+{
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_preg_header(ndr, NDR_SCALARS, &r->header));
+ r->num_entries = 0;
+ NDR_PULL_ALLOC_N(ndr, r->entries, r->num_entries);
+ while (ndr->offset + 12 <= ndr->data_size) {
+ r->entries = talloc_realloc(ndr, r->entries, struct preg_entry, r->num_entries + 1);
+ NDR_ERR_HAVE_NO_MEMORY(r->entries);
+ NDR_CHECK(ndr_pull_preg_entry(ndr, NDR_SCALARS, &r->entries[r->num_entries]));
+ r->num_entries++;
+ }
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_preg.h b/librpc/ndr/ndr_preg.h
new file mode 100644
index 0000000..d781e13
--- /dev/null
+++ b/librpc/ndr/ndr_preg.h
@@ -0,0 +1,23 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling preg structures
+
+ Copyright (C) Guenther Deschner 2010
+
+ 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/>.
+*/
+
+_PUBLIC_ enum ndr_err_code ndr_push_preg_file(struct ndr_push *ndr, int ndr_flags, const struct preg_file *r);
+_PUBLIC_ enum ndr_err_code ndr_pull_preg_file(struct ndr_pull *ndr, int ndr_flags, struct preg_file *r);
diff --git a/librpc/ndr/ndr_private.h b/librpc/ndr/ndr_private.h
new file mode 100644
index 0000000..08521be
--- /dev/null
+++ b/librpc/ndr/ndr_private.h
@@ -0,0 +1,32 @@
+/*
+ Unix SMB/CIFS implementation.
+ rpc interface definitions
+
+ Copyright (C) Andrew Tridgell 2003
+
+ 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/>.
+*/
+
+/* This is not a public header file that is installed as part of Samba.
+ *
+ * Instead, this is to allow our python layer to get to the
+ * NDR_TOKEN_MAX_LIST_SIZE
+*/
+
+#ifndef __NDR_PRIVATE_H__
+#define __NDR_PRIVATE_H__
+
+size_t ndr_token_max_list_size(void);
+
+#endif
diff --git a/librpc/ndr/ndr_rap.c b/librpc/ndr/ndr_rap.c
new file mode 100644
index 0000000..ea18a08
--- /dev/null
+++ b/librpc/ndr/ndr_rap.c
@@ -0,0 +1,28 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling special rap types
+
+ Copyright (C) Guenther Deschner 2010
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_rap.h"
+
+_PUBLIC_ void ndr_print_rap_status(struct ndr_print *ndr, const char *name, enum rap_status r)
+{
+ ndr_print_WERROR(ndr, name, W_ERROR(r));
+}
diff --git a/librpc/ndr/ndr_rap.h b/librpc/ndr/ndr_rap.h
new file mode 100644
index 0000000..35a03b1
--- /dev/null
+++ b/librpc/ndr/ndr_rap.h
@@ -0,0 +1,22 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling special rap types
+
+ Copyright (C) Guenther Deschner 2010
+
+ 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/>.
+*/
+
+_PUBLIC_ void ndr_print_rap_status(struct ndr_print *ndr, const char *name, enum rap_status r);
diff --git a/librpc/ndr/ndr_schannel.c b/librpc/ndr/ndr_schannel.c
new file mode 100644
index 0000000..6b08a79
--- /dev/null
+++ b/librpc/ndr/ndr_schannel.c
@@ -0,0 +1,107 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling special schannel structures
+
+ Copyright (C) Guenther Deschner 2009
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "../librpc/gen_ndr/ndr_schannel.h"
+#include "../librpc/ndr/ndr_schannel.h"
+#include "../libcli/nbt/libnbt.h"
+
+_PUBLIC_ void ndr_print_NL_AUTH_MESSAGE_BUFFER(struct ndr_print *ndr, const char *name, const union NL_AUTH_MESSAGE_BUFFER *r)
+{
+ int level;
+ level = ndr_print_steal_switch_value(ndr, r);
+ switch (level) {
+ case NL_FLAG_OEM_NETBIOS_DOMAIN_NAME:
+ ndr_print_string(ndr, name, r->a);
+ break;
+
+ case NL_FLAG_OEM_NETBIOS_COMPUTER_NAME:
+ ndr_print_string(ndr, name, r->a);
+ break;
+
+ case NL_FLAG_UTF8_DNS_DOMAIN_NAME:
+ ndr_print_nbt_string(ndr, name, r->u);
+ break;
+
+ case NL_FLAG_UTF8_DNS_HOST_NAME:
+ ndr_print_nbt_string(ndr, name, r->u);
+ break;
+
+ case NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME:
+ ndr_print_nbt_string(ndr, name, r->u);
+ break;
+
+ default:
+ break;
+
+ }
+}
+
+_PUBLIC_ void ndr_print_NL_AUTH_MESSAGE_BUFFER_REPLY(struct ndr_print *ndr, const char *name, const union NL_AUTH_MESSAGE_BUFFER_REPLY *r)
+{
+ int level;
+ level = ndr_print_steal_switch_value(ndr, r);
+ switch (level) {
+ case NL_NEGOTIATE_RESPONSE:
+ ndr_print_uint32(ndr, name, r->dummy);
+ break;
+
+ default:
+ break;
+
+ }
+}
+
+void dump_NL_AUTH_SIGNATURE(TALLOC_CTX *mem_ctx,
+ const DATA_BLOB *blob)
+{
+ enum ndr_err_code ndr_err;
+ uint16_t signature_algorithm;
+
+ if (blob->length < 2) {
+ return;
+ }
+
+ signature_algorithm = SVAL(blob->data, 0);
+
+ switch (signature_algorithm) {
+ case NL_SIGN_HMAC_MD5: {
+ struct NL_AUTH_SIGNATURE r;
+ ndr_err = ndr_pull_struct_blob(blob, mem_ctx, &r,
+ (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_SIGNATURE);
+ if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NDR_PRINT_DEBUG(NL_AUTH_SIGNATURE, &r);
+ }
+ break;
+ }
+ case NL_SIGN_HMAC_SHA256: {
+ struct NL_AUTH_SHA2_SIGNATURE r;
+ ndr_err = ndr_pull_struct_blob(blob, mem_ctx, &r,
+ (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_SHA2_SIGNATURE);
+ if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NDR_PRINT_DEBUG(NL_AUTH_SHA2_SIGNATURE, &r);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
diff --git a/librpc/ndr/ndr_schannel.h b/librpc/ndr/ndr_schannel.h
new file mode 100644
index 0000000..d57278c
--- /dev/null
+++ b/librpc/ndr/ndr_schannel.h
@@ -0,0 +1,25 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling special schannel structures
+
+ Copyright (C) Guenther Deschner 2009
+
+ 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/>.
+*/
+
+void ndr_print_NL_AUTH_MESSAGE_BUFFER(struct ndr_print *ndr, const char *name, const union NL_AUTH_MESSAGE_BUFFER *r);
+void ndr_print_NL_AUTH_MESSAGE_BUFFER_REPLY(struct ndr_print *ndr, const char *name, const union NL_AUTH_MESSAGE_BUFFER_REPLY *r);
+void dump_NL_AUTH_SIGNATURE(TALLOC_CTX *mem_ctx,
+ const DATA_BLOB *blob);
diff --git a/librpc/ndr/ndr_sec_helper.c b/librpc/ndr/ndr_sec_helper.c
new file mode 100644
index 0000000..3adb46f
--- /dev/null
+++ b/librpc/ndr/ndr_sec_helper.c
@@ -0,0 +1,338 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ fast routines for getting the wire size of security objects
+
+ Copyright (C) Andrew Tridgell 2003
+ Copyright (C) Stefan Metzmacher 2006-2008
+
+ 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/>.
+*/
+
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#include "../libcli/security/security.h"
+
+/*
+ return the wire size of a security_ace
+*/
+size_t ndr_size_security_ace(const struct security_ace *ace, int flags)
+{
+ size_t ret;
+
+ if (!ace) return 0;
+
+ ret = 8 + ndr_size_dom_sid(&ace->trustee, flags);
+
+ switch (ace->type) {
+ case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
+ case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
+ case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT:
+ case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT:
+ ret += 4; /* uint32 bitmap ace->object.object.flags */
+ if (ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT) {
+ ret += 16; /* GUID ace->object.object.type.type */
+ }
+ if (ace->object.object.flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT) {
+ ret += 16; /* GUID ace->object.object.inherited_typeinherited_type */
+ }
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+enum ndr_err_code ndr_pull_security_ace(struct ndr_pull *ndr, int ndr_flags, struct security_ace *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ uint32_t start_ofs = ndr->offset;
+ uint32_t size = 0;
+ uint32_t pad = 0;
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_security_ace_type(ndr, NDR_SCALARS, &r->type));
+ NDR_CHECK(ndr_pull_security_ace_flags(ndr, NDR_SCALARS, &r->flags));
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->size));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->access_mask));
+ NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->object, r->type));
+ NDR_CHECK(ndr_pull_security_ace_object_ctr(ndr, NDR_SCALARS, &r->object));
+ NDR_CHECK(ndr_pull_dom_sid(ndr, NDR_SCALARS, &r->trustee));
+ size = ndr->offset - start_ofs;
+ if (r->size < size) {
+ return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
+ "ndr_pull_security_ace: r->size %u < size %u",
+ (unsigned)r->size, size);
+ }
+ pad = r->size - size;
+ NDR_PULL_NEED_BYTES(ndr, pad);
+ ndr->offset += pad;
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->object, r->type));
+ NDR_CHECK(ndr_pull_security_ace_object_ctr(ndr, NDR_BUFFERS, &r->object));
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ return the wire size of a security_acl
+*/
+size_t ndr_size_security_acl(const struct security_acl *theacl, int flags)
+{
+ size_t ret;
+ int i;
+ if (!theacl) return 0;
+ ret = 8;
+ for (i=0;i<theacl->num_aces;i++) {
+ ret += ndr_size_security_ace(&theacl->aces[i], flags);
+ }
+ return ret;
+}
+
+/*
+ return the wire size of a security descriptor
+*/
+size_t ndr_size_security_descriptor(const struct security_descriptor *sd, int flags)
+{
+ size_t ret;
+ if (!sd) return 0;
+
+ ret = 20;
+ ret += ndr_size_dom_sid(sd->owner_sid, flags);
+ ret += ndr_size_dom_sid(sd->group_sid, flags);
+ ret += ndr_size_security_acl(sd->dacl, flags);
+ ret += ndr_size_security_acl(sd->sacl, flags);
+ return ret;
+}
+
+/*
+ return the wire size of a dom_sid
+*/
+size_t ndr_size_dom_sid(const struct dom_sid *sid, int flags)
+{
+ if (!sid) return 0;
+ return 8 + 4*sid->num_auths;
+}
+
+size_t ndr_size_dom_sid28(const struct dom_sid *sid, int flags)
+{
+ if (!sid) return 0;
+
+ if (all_zero((const uint8_t *)sid, sizeof(struct dom_sid))) {
+ return 0;
+ }
+
+ return 8 + 4*sid->num_auths;
+}
+
+size_t ndr_size_dom_sid0(const struct dom_sid *sid, int flags)
+{
+ return ndr_size_dom_sid28(sid, flags);
+}
+
+/*
+ print a dom_sid
+*/
+void ndr_print_dom_sid(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
+{
+ struct dom_sid_buf buf;
+ ndr->print(ndr, "%-25s: %s", name, dom_sid_str_buf(sid, &buf));
+}
+
+void ndr_print_dom_sid2(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
+{
+ ndr_print_dom_sid(ndr, name, sid);
+}
+
+void ndr_print_dom_sid28(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
+{
+ ndr_print_dom_sid(ndr, name, sid);
+}
+
+void ndr_print_dom_sid0(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
+{
+ ndr_print_dom_sid(ndr, name, sid);
+}
+
+
+/*
+ parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
+*/
+enum ndr_err_code ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
+{
+ uint32_t num_auths;
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+ NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &num_auths));
+ NDR_CHECK(ndr_pull_dom_sid(ndr, ndr_flags, sid));
+ if (sid->num_auths != num_auths) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
+ "Bad array size %u should exceed %u",
+ num_auths, sid->num_auths);
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
+*/
+enum ndr_err_code ndr_push_dom_sid2(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
+{
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+ NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, sid->num_auths));
+ return ndr_push_dom_sid(ndr, ndr_flags, sid);
+}
+
+/*
+ parse a dom_sid28 - this is a dom_sid in a fixed 28 byte buffer, so we need to ensure there are only up to 5 sub_auth
+*/
+enum ndr_err_code ndr_pull_dom_sid28(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
+{
+ enum ndr_err_code status;
+ struct ndr_pull *subndr;
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ subndr = talloc_zero(ndr, struct ndr_pull);
+ NDR_ERR_HAVE_NO_MEMORY(subndr);
+ subndr->flags = ndr->flags;
+ subndr->current_mem_ctx = ndr->current_mem_ctx;
+
+ subndr->data = ndr->data + ndr->offset;
+ subndr->data_size = 28;
+ subndr->offset = 0;
+
+ NDR_CHECK(ndr_pull_advance(ndr, 28));
+
+ status = ndr_pull_dom_sid(subndr, ndr_flags, sid);
+ if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
+ /* handle a w2k bug which send random data in the buffer */
+ ZERO_STRUCTP(sid);
+ } else if (sid->num_auths == 0) {
+ ZERO_STRUCT(sid->sub_auths);
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ push a dom_sid28 - this is a dom_sid in a 28 byte fixed buffer
+*/
+enum ndr_err_code ndr_push_dom_sid28(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
+{
+ uint32_t old_offset;
+ uint32_t padding;
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ if (sid->num_auths > 5) {
+ return ndr_push_error(ndr, NDR_ERR_RANGE,
+ "dom_sid28 allows only up to 5 sub auth [%u]",
+ sid->num_auths);
+ }
+
+ old_offset = ndr->offset;
+ NDR_CHECK(ndr_push_dom_sid(ndr, ndr_flags, sid));
+
+ padding = 28 - (ndr->offset - old_offset);
+
+ if (padding > 0) {
+ NDR_CHECK(ndr_push_zero(ndr, padding));
+ }
+
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ parse a dom_sid0 - this is a dom_sid in a variable byte buffer, which is maybe empty
+*/
+enum ndr_err_code ndr_pull_dom_sid0(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
+{
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ if (ndr->data_size == ndr->offset) {
+ ZERO_STRUCTP(sid);
+ return NDR_ERR_SUCCESS;
+ }
+
+ return ndr_pull_dom_sid(ndr, ndr_flags, sid);
+}
+
+/*
+ push a dom_sid0 - this is a dom_sid in a variable byte buffer, which is maybe empty
+*/
+enum ndr_err_code ndr_push_dom_sid0(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
+{
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ if (!sid) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ if (all_zero((const uint8_t *)sid, sizeof(struct dom_sid))) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ return ndr_push_dom_sid(ndr, ndr_flags, sid);
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_dom_sid(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *r)
+{
+ uint32_t cntr_sub_auths_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->sid_rev_num));
+ NDR_CHECK(ndr_push_int8(ndr, NDR_SCALARS, r->num_auths));
+ NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
+ if (r->num_auths < 0 || r->num_auths > ARRAY_SIZE(r->sub_auths)) {
+ return ndr_push_error(ndr, NDR_ERR_RANGE, "value out of range");
+ }
+ for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->sub_auths[cntr_sub_auths_0]));
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_dom_sid(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *r)
+{
+ uint32_t cntr_sub_auths_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->sid_rev_num));
+ NDR_CHECK(ndr_pull_int8(ndr, NDR_SCALARS, &r->num_auths));
+ if (r->num_auths < 0 || r->num_auths > ARRAY_SIZE(r->sub_auths)) {
+ return ndr_pull_error(ndr, NDR_ERR_RANGE, "value out of range");
+ }
+ NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
+ ZERO_STRUCT(r->sub_auths);
+ for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sub_auths[cntr_sub_auths_0]));
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_spoolss_buf.c b/librpc/ndr/ndr_spoolss_buf.c
new file mode 100644
index 0000000..c5fa82c
--- /dev/null
+++ b/librpc/ndr/ndr_spoolss_buf.c
@@ -0,0 +1,1615 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling spoolss subcontext buffer structures
+
+ Copyright (C) Andrew Tridgell 2003
+ Copyright (C) Tim Potter 2003
+ Copyright (C) Guenther Deschner 2009
+
+ 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/>.
+*/
+
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_spoolss.h"
+#include "librpc/gen_ndr/ndr_security.h"
+
+#define NDR_SPOOLSS_PUSH_ENUM_IN(fn) do { \
+ if (!r->in.buffer && r->in.offered != 0) {\
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE,\
+ "SPOOLSS Buffer: r->in.offered[%u] but there's no buffer",\
+ (unsigned)r->in.offered);\
+ } else if (r->in.buffer && r->in.buffer->length != r->in.offered) {\
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE,\
+ "SPOOLSS Buffer: r->in.offered[%u] doesn't match length of r->in.buffer[%u]",\
+ (unsigned)r->in.offered, (unsigned)r->in.buffer->length);\
+ }\
+ _r.in.buffer = r->in.buffer;\
+ _r.in.offered = r->in.offered;\
+ NDR_CHECK(ndr_push__##fn(ndr, flags, &_r));\
+} while(0)
+
+#define NDR_SPOOLSS_PUSH_ENUM_IN_LEVEL(fn) do { \
+ _r.in.level = r->in.level;\
+ NDR_SPOOLSS_PUSH_ENUM_IN(fn);\
+} while(0)
+
+#define NDR_SPOOLSS_PUSH_ENUM_OUT_LEVEL(fn) do { \
+ DATA_BLOB _data_blob_info = data_blob_null;\
+ struct ndr_push *_ndr_info = NULL;\
+ _r.in.level = r->in.level;\
+ _r.in.buffer = r->in.buffer;\
+ _r.in.offered = r->in.offered;\
+ _r.out.info = NULL;\
+ _r.out.needed = r->out.needed;\
+ _r.out.count = r->out.count;\
+ _r.out.result = r->out.result;\
+ if (r->out.info && *r->out.info && !r->in.buffer) {\
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE,\
+ "SPOOLSS Buffer: *r->out.info but there's no r->in.buffer");\
+ }\
+ if (r->in.buffer) {\
+ _ndr_info = ndr_push_init_ctx(ndr);\
+ NDR_ERR_HAVE_NO_MEMORY(_ndr_info);\
+ _ndr_info->flags= ndr->flags;\
+ if (r->out.info) {\
+ struct ndr_push *_subndr_info;\
+ struct __##fn __r;\
+ __r.in.level = r->in.level;\
+ __r.in.count = *r->out.count;\
+ __r.out.info = *r->out.info;\
+ NDR_CHECK(ndr_push_subcontext_start(_ndr_info, &_subndr_info, 0, r->in.offered));\
+ NDR_CHECK(ndr_push___##fn(_subndr_info, flags, &__r)); \
+ NDR_CHECK(ndr_push_subcontext_end(_ndr_info, _subndr_info, 0, r->in.offered));\
+ }\
+ if (r->in.offered > _ndr_info->offset) {\
+ uint32_t _padding_len = r->in.offered - _ndr_info->offset;\
+ NDR_CHECK(ndr_push_zero(_ndr_info, _padding_len));\
+ } else if (r->in.offered < _ndr_info->offset) {\
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE,\
+ "SPOOLSS Buffer: r->in.offered[%u] doesn't match length of out buffer[%u]!",\
+ (unsigned)r->in.offered, (unsigned)_ndr_info->offset);\
+ }\
+ _data_blob_info = ndr_push_blob(_ndr_info);\
+ _r.out.info = &_data_blob_info;\
+ }\
+ NDR_CHECK(ndr_push__##fn(ndr, flags, &_r));\
+} while(0)
+
+#define NDR_SPOOLSS_PUSH_ENUM_OUT(fn) do { \
+ DATA_BLOB _data_blob_info = data_blob_null;\
+ struct ndr_push *_ndr_info = NULL;\
+ _r.in.buffer = r->in.buffer;\
+ _r.in.offered = r->in.offered;\
+ _r.out.info = NULL;\
+ _r.out.needed = r->out.needed;\
+ _r.out.count = r->out.count;\
+ _r.out.result = r->out.result;\
+ if (r->out.info && *r->out.info && !r->in.buffer) {\
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE,\
+ "SPOOLSS Buffer: *r->out.info but there's no r->in.buffer");\
+ }\
+ if (r->in.buffer) {\
+ _ndr_info = ndr_push_init_ctx(ndr);\
+ NDR_ERR_HAVE_NO_MEMORY(_ndr_info);\
+ _ndr_info->flags= ndr->flags;\
+ if (r->out.info) {\
+ struct ndr_push *_subndr_info;\
+ struct __##fn __r;\
+ __r.in.count = *r->out.count;\
+ __r.out.info = *r->out.info;\
+ NDR_CHECK(ndr_push_subcontext_start(_ndr_info, &_subndr_info, 0, r->in.offered));\
+ NDR_CHECK(ndr_push___##fn(_subndr_info, flags, &__r)); \
+ NDR_CHECK(ndr_push_subcontext_end(_ndr_info, _subndr_info, 0, r->in.offered));\
+ }\
+ if (r->in.offered > _ndr_info->offset) {\
+ uint32_t _padding_len = r->in.offered - _ndr_info->offset;\
+ NDR_CHECK(ndr_push_zero(_ndr_info, _padding_len));\
+ } else if (r->in.offered < _ndr_info->offset) {\
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE,\
+ "SPOOLSS Buffer: r->in.offered[%u] doesn't match length of out buffer[%u]!",\
+ (unsigned)r->in.offered, (unsigned)_ndr_info->offset);\
+ }\
+ _data_blob_info = ndr_push_blob(_ndr_info);\
+ _r.out.info = &_data_blob_info;\
+ }\
+ NDR_CHECK(ndr_push__##fn(ndr, flags, &_r));\
+} while(0)
+
+#define NDR_SPOOLSS_PUSH_ENUM_LEVEL(fn,in,out) do { \
+ struct _##fn _r;\
+ if (flags & NDR_IN) {\
+ in;\
+ NDR_SPOOLSS_PUSH_ENUM_IN_LEVEL(fn);\
+ }\
+ if (flags & NDR_OUT) {\
+ out;\
+ NDR_SPOOLSS_PUSH_ENUM_OUT_LEVEL(fn);\
+ }\
+} while(0)
+
+#define NDR_SPOOLSS_PUSH_ENUM(fn,in,out) do { \
+ struct _##fn _r;\
+ if (flags & NDR_IN) {\
+ in;\
+ NDR_SPOOLSS_PUSH_ENUM_IN(fn);\
+ }\
+ if (flags & NDR_OUT) {\
+ out;\
+ NDR_SPOOLSS_PUSH_ENUM_OUT(fn);\
+ }\
+} while(0)
+
+#define NDR_SPOOLSS_PULL_ENUM_IN_COMMON(fn) do { \
+ ZERO_STRUCT(r->out);\
+ r->in.buffer = _r.in.buffer;\
+ r->in.offered = _r.in.offered;\
+ r->out.needed = _r.out.needed;\
+ r->out.count = _r.out.count;\
+ if (!r->in.buffer && r->in.offered != 0) {\
+ return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,\
+ "SPOOLSS Buffer: r->in.offered[%u] but there's no buffer",\
+ (unsigned)r->in.offered);\
+ } else if (r->in.buffer && r->in.buffer->length != r->in.offered) {\
+ return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,\
+ "SPOOLSS Buffer: r->in.offered[%u] doesn't match length of r->in.buffer[%u]",\
+ (unsigned)r->in.offered, (unsigned)r->in.buffer->length);\
+ }\
+ NDR_PULL_ALLOC(ndr, r->out.info);\
+ ZERO_STRUCTP(r->out.info);\
+} while(0)
+
+#define NDR_SPOOLSS_PULL_ENUM_IN(fn) do { \
+ NDR_CHECK(ndr_pull__##fn(ndr, flags, &_r));\
+ NDR_SPOOLSS_PULL_ENUM_IN_COMMON(fn); \
+} while(0)
+
+#define NDR_SPOOLSS_PULL_ENUM_IN_LEVEL(fn) do { \
+ NDR_CHECK(ndr_pull__##fn(ndr, flags, &_r));\
+ r->in.level = _r.in.level;\
+ NDR_SPOOLSS_PULL_ENUM_IN_COMMON(fn); \
+} while(0)
+
+#define NDR_SPOOLSS_PULL_ENUM_OUT_LEVEL(fn) do { \
+ _r.in.level = r->in.level;\
+ _r.in.buffer = r->in.buffer;\
+ _r.in.offered = r->in.offered;\
+ _r.out.needed = r->out.needed;\
+ _r.out.count = r->out.count;\
+ NDR_CHECK(ndr_pull__##fn(ndr, flags, &_r));\
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {\
+ NDR_PULL_ALLOC(ndr, r->out.info);\
+ }\
+ *r->out.info = NULL;\
+ r->out.needed = _r.out.needed;\
+ r->out.count = _r.out.count;\
+ r->out.result = _r.out.result;\
+ if (_r.out.info) {\
+ struct ndr_pull *_ndr_info;\
+ NDR_PULL_ALLOC(ndr, *r->out.info);\
+ _ndr_info = ndr_pull_init_blob(_r.out.info, *r->out.info);\
+ NDR_ERR_HAVE_NO_MEMORY(_ndr_info);\
+ _ndr_info->flags= ndr->flags;\
+ if (r->in.offered != _ndr_info->data_size) {\
+ return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,\
+ "SPOOLSS Buffer: offered[%u] doesn't match length of buffer[%u]",\
+ (unsigned)r->in.offered, (unsigned)_ndr_info->data_size);\
+ }\
+ if (*r->out.needed <= _ndr_info->data_size) {\
+ struct __##fn __r;\
+ __r.in.level = r->in.level;\
+ __r.in.count = *r->out.count;\
+ __r.out.info = NULL;\
+ NDR_CHECK(ndr_pull___##fn(_ndr_info, flags, &__r));\
+ *r->out.info = __r.out.info;\
+ }\
+ }\
+} while(0)
+
+#define NDR_SPOOLSS_PULL_ENUM_OUT(fn) do { \
+ _r.in.buffer = r->in.buffer;\
+ _r.in.offered = r->in.offered;\
+ _r.out.needed = r->out.needed;\
+ _r.out.count = r->out.count;\
+ NDR_CHECK(ndr_pull__##fn(ndr, flags, &_r));\
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {\
+ NDR_PULL_ALLOC(ndr, r->out.info);\
+ }\
+ *r->out.info = NULL;\
+ r->out.needed = _r.out.needed;\
+ r->out.count = _r.out.count;\
+ r->out.result = _r.out.result;\
+ if (_r.out.info) {\
+ struct ndr_pull *_ndr_info;\
+ NDR_PULL_ALLOC(ndr, *r->out.info);\
+ _ndr_info = ndr_pull_init_blob(_r.out.info, *r->out.info);\
+ NDR_ERR_HAVE_NO_MEMORY(_ndr_info);\
+ _ndr_info->flags= ndr->flags;\
+ if (r->in.offered != _ndr_info->data_size) {\
+ return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,\
+ "SPOOLSS Buffer: offered[%u] doesn't match length of buffer[%u]",\
+ (unsigned)r->in.offered, (unsigned)_ndr_info->data_size);\
+ }\
+ if (*r->out.needed <= _ndr_info->data_size) {\
+ struct __##fn __r;\
+ __r.in.count = *r->out.count;\
+ __r.out.info = NULL;\
+ NDR_CHECK(ndr_pull___##fn(_ndr_info, flags, &__r));\
+ *r->out.info = __r.out.info;\
+ }\
+ }\
+} while(0)
+
+#define NDR_SPOOLSS_PULL_ENUM_LEVEL(fn,in,out) do { \
+ struct _##fn _r;\
+ if (flags & NDR_IN) {\
+ out;\
+ NDR_SPOOLSS_PULL_ENUM_IN_LEVEL(fn);\
+ in;\
+ }\
+ if (flags & NDR_OUT) {\
+ out;\
+ NDR_SPOOLSS_PULL_ENUM_OUT_LEVEL(fn);\
+ }\
+} while(0)
+
+#define NDR_SPOOLSS_PULL_ENUM(fn,in,out) do { \
+ struct _##fn _r;\
+ if (flags & NDR_IN) {\
+ out;\
+ NDR_SPOOLSS_PULL_ENUM_IN(fn);\
+ in;\
+ }\
+ if (flags & NDR_OUT) {\
+ out;\
+ NDR_SPOOLSS_PULL_ENUM_OUT(fn);\
+ }\
+} while(0)
+
+#define _NDR_CHECK_UINT32(call) do {\
+ enum ndr_err_code _ndr_err; \
+ _ndr_err = call; \
+ if (!NDR_ERR_CODE_IS_SUCCESS(_ndr_err)) { \
+ return 0; \
+ }\
+} while (0)
+
+/* TODO: set _ndr_info->flags correct */
+#define NDR_SPOOLSS_SIZE_ENUM_LEVEL(fn) do { \
+ struct __##fn __r;\
+ DATA_BLOB _data_blob_info;\
+ struct ndr_push *_ndr_info = ndr_push_init_ctx(mem_ctx);\
+ if (!_ndr_info) return 0;\
+ _ndr_info->flags|=LIBNDR_FLAG_NO_NDR_SIZE;\
+ __r.in.level = level;\
+ __r.in.count = count;\
+ __r.out.info = info;\
+ _NDR_CHECK_UINT32(ndr_push___##fn(_ndr_info, NDR_OUT, &__r)); \
+ _data_blob_info = ndr_push_blob(_ndr_info);\
+ return _data_blob_info.length;\
+} while(0)
+
+/* TODO: set _ndr_info->flags correct */
+#define NDR_SPOOLSS_SIZE_ENUM(fn) do { \
+ struct __##fn __r;\
+ DATA_BLOB _data_blob_info;\
+ struct ndr_push *_ndr_info = ndr_push_init_ctx(mem_ctx);\
+ if (!_ndr_info) return 0;\
+ _ndr_info->flags|=LIBNDR_FLAG_NO_NDR_SIZE;\
+ __r.in.count = count;\
+ __r.out.info = info;\
+ _NDR_CHECK_UINT32(ndr_push___##fn(_ndr_info, NDR_OUT, &__r)); \
+ _data_blob_info = ndr_push_blob(_ndr_info);\
+ return _data_blob_info.length;\
+} while(0)
+
+
+/*
+ spoolss_EnumPrinters
+*/
+enum ndr_err_code ndr_push_spoolss_EnumPrinters(struct ndr_push *ndr, int flags, const struct spoolss_EnumPrinters *r)
+{
+ NDR_SPOOLSS_PUSH_ENUM_LEVEL(spoolss_EnumPrinters,{
+ _r.in.flags = r->in.flags;
+ _r.in.server = r->in.server;
+ },{
+ _r.in.flags = r->in.flags;
+ _r.in.server = r->in.server;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_spoolss_EnumPrinters(struct ndr_pull *ndr, int flags, struct spoolss_EnumPrinters *r)
+{
+ NDR_SPOOLSS_PULL_ENUM_LEVEL(spoolss_EnumPrinters,{
+ r->in.flags = _r.in.flags;
+ r->in.server = _r.in.server;
+ },{
+ _r.in.flags = r->in.flags;
+ _r.in.server = r->in.server;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+uint32_t ndr_size_spoolss_EnumPrinters_info(TALLOC_CTX *mem_ctx, uint32_t level, uint32_t count, union spoolss_PrinterInfo *info)
+{
+ NDR_SPOOLSS_SIZE_ENUM_LEVEL(spoolss_EnumPrinters);
+}
+
+/*
+ spoolss_EnumJobs
+*/
+enum ndr_err_code ndr_push_spoolss_EnumJobs(struct ndr_push *ndr, int flags, const struct spoolss_EnumJobs *r)
+{
+ NDR_SPOOLSS_PUSH_ENUM_LEVEL(spoolss_EnumJobs,{
+ _r.in.handle = r->in.handle;
+ _r.in.firstjob = r->in.firstjob;
+ _r.in.numjobs = r->in.numjobs;
+ },{
+ _r.in.handle = r->in.handle;
+ _r.in.firstjob = r->in.firstjob;
+ _r.in.numjobs = r->in.numjobs;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_spoolss_EnumJobs(struct ndr_pull *ndr, int flags, struct spoolss_EnumJobs *r)
+{
+ NDR_SPOOLSS_PULL_ENUM_LEVEL(spoolss_EnumJobs,{
+ r->in.handle = _r.in.handle;
+ r->in.firstjob = _r.in.firstjob;
+ r->in.numjobs = _r.in.numjobs;
+ },{
+ _r.in.handle = r->in.handle;
+ _r.in.firstjob = r->in.firstjob;
+ _r.in.numjobs = r->in.numjobs;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+uint32_t ndr_size_spoolss_EnumJobs_info(TALLOC_CTX *mem_ctx, uint32_t level, uint32_t count, union spoolss_JobInfo *info)
+{
+ NDR_SPOOLSS_SIZE_ENUM_LEVEL(spoolss_EnumJobs);
+}
+
+/*
+ spoolss_EnumPrinterDrivers
+*/
+enum ndr_err_code ndr_push_spoolss_EnumPrinterDrivers(struct ndr_push *ndr, int flags, const struct spoolss_EnumPrinterDrivers *r)
+{
+ NDR_SPOOLSS_PUSH_ENUM_LEVEL(spoolss_EnumPrinterDrivers,{
+ _r.in.server = r->in.server;
+ _r.in.environment = r->in.environment;
+ },{
+ _r.in.server = r->in.server;
+ _r.in.environment = r->in.environment;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_spoolss_EnumPrinterDrivers(struct ndr_pull *ndr, int flags, struct spoolss_EnumPrinterDrivers *r)
+{
+ NDR_SPOOLSS_PULL_ENUM_LEVEL(spoolss_EnumPrinterDrivers,{
+ r->in.server = _r.in.server;
+ r->in.environment = _r.in.environment;
+ },{
+ _r.in.server = r->in.server;
+ _r.in.environment = r->in.environment;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+uint32_t ndr_size_spoolss_EnumPrinterDrivers_info(TALLOC_CTX *mem_ctx, uint32_t level, uint32_t count, union spoolss_DriverInfo *info)
+{
+ NDR_SPOOLSS_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers);
+}
+
+/*
+ spoolss_EnumForms
+*/
+enum ndr_err_code ndr_push_spoolss_EnumForms(struct ndr_push *ndr, int flags, const struct spoolss_EnumForms *r)
+{
+ NDR_SPOOLSS_PUSH_ENUM_LEVEL(spoolss_EnumForms,{
+ _r.in.handle = r->in.handle;
+ },{
+ _r.in.handle = r->in.handle;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_spoolss_EnumForms(struct ndr_pull *ndr, int flags, struct spoolss_EnumForms *r)
+{
+ NDR_SPOOLSS_PULL_ENUM_LEVEL(spoolss_EnumForms,{
+ r->in.handle = _r.in.handle;
+ },{
+ _r.in.handle = r->in.handle;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+uint32_t ndr_size_spoolss_EnumForms_info(TALLOC_CTX *mem_ctx, uint32_t level, uint32_t count, union spoolss_FormInfo *info)
+{
+ NDR_SPOOLSS_SIZE_ENUM_LEVEL(spoolss_EnumForms);
+}
+
+/*
+ spoolss_EnumPorts
+*/
+enum ndr_err_code ndr_push_spoolss_EnumPorts(struct ndr_push *ndr, int flags, const struct spoolss_EnumPorts *r)
+{
+ NDR_SPOOLSS_PUSH_ENUM_LEVEL(spoolss_EnumPorts,{
+ _r.in.servername= r->in.servername;
+ },{
+ _r.in.servername= r->in.servername;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_spoolss_EnumPorts(struct ndr_pull *ndr, int flags, struct spoolss_EnumPorts *r)
+{
+ NDR_SPOOLSS_PULL_ENUM_LEVEL(spoolss_EnumPorts,{
+ r->in.servername= _r.in.servername;
+ },{
+ _r.in.servername= r->in.servername;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+uint32_t ndr_size_spoolss_EnumPorts_info(TALLOC_CTX *mem_ctx, uint32_t level, uint32_t count, union spoolss_PortInfo *info)
+{
+ NDR_SPOOLSS_SIZE_ENUM_LEVEL(spoolss_EnumPorts);
+}
+
+/*
+ spoolss_EnumMonitors
+*/
+enum ndr_err_code ndr_push_spoolss_EnumMonitors(struct ndr_push *ndr, int flags, const struct spoolss_EnumMonitors *r)
+{
+ NDR_SPOOLSS_PUSH_ENUM_LEVEL(spoolss_EnumMonitors,{
+ _r.in.servername= r->in.servername;
+ },{
+ _r.in.servername= r->in.servername;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_spoolss_EnumMonitors(struct ndr_pull *ndr, int flags, struct spoolss_EnumMonitors *r)
+{
+ NDR_SPOOLSS_PULL_ENUM_LEVEL(spoolss_EnumMonitors,{
+ r->in.servername= _r.in.servername;
+ },{
+ _r.in.servername= r->in.servername;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+uint32_t ndr_size_spoolss_EnumMonitors_info(TALLOC_CTX *mem_ctx, uint32_t level, uint32_t count, union spoolss_MonitorInfo *info)
+{
+ NDR_SPOOLSS_SIZE_ENUM_LEVEL(spoolss_EnumMonitors);
+}
+
+/*
+ spoolss_EnumPrintProcessors
+*/
+enum ndr_err_code ndr_push_spoolss_EnumPrintProcessors(struct ndr_push *ndr, int flags, const struct spoolss_EnumPrintProcessors *r)
+{
+ NDR_SPOOLSS_PUSH_ENUM_LEVEL(spoolss_EnumPrintProcessors,{
+ _r.in.servername = r->in.servername;
+ _r.in.environment = r->in.environment;
+ },{
+ _r.in.servername = r->in.servername;
+ _r.in.environment = r->in.environment;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_spoolss_EnumPrintProcessors(struct ndr_pull *ndr, int flags, struct spoolss_EnumPrintProcessors *r)
+{
+ NDR_SPOOLSS_PULL_ENUM_LEVEL(spoolss_EnumPrintProcessors,{
+ r->in.servername = _r.in.servername;
+ r->in.environment = _r.in.environment;
+ },{
+ _r.in.servername = r->in.servername;
+ _r.in.environment = r->in.environment;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+uint32_t ndr_size_spoolss_EnumPrintProcessors_info(TALLOC_CTX *mem_ctx,
+ uint32_t level, uint32_t count, union spoolss_PrintProcessorInfo *info)
+{
+ NDR_SPOOLSS_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors);
+}
+
+/*
+ spoolss_EnumPrintProcessors
+*/
+enum ndr_err_code ndr_push_spoolss_EnumPrintProcessorDataTypes(struct ndr_push *ndr, int flags, const struct spoolss_EnumPrintProcessorDataTypes *r)
+{
+ NDR_SPOOLSS_PUSH_ENUM_LEVEL(spoolss_EnumPrintProcessorDataTypes,{
+ _r.in.servername = r->in.servername;
+ _r.in.print_processor_name = r->in.print_processor_name;
+ },{
+ _r.in.servername = r->in.servername;
+ _r.in.print_processor_name = r->in.print_processor_name;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_spoolss_EnumPrintProcessorDataTypes(struct ndr_pull *ndr, int flags, struct spoolss_EnumPrintProcessorDataTypes *r)
+{
+ NDR_SPOOLSS_PULL_ENUM_LEVEL(spoolss_EnumPrintProcessorDataTypes,{
+ r->in.servername = _r.in.servername;
+ r->in.print_processor_name = _r.in.print_processor_name;
+ },{
+ _r.in.servername = r->in.servername;
+ _r.in.print_processor_name = r->in.print_processor_name;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+uint32_t ndr_size_spoolss_EnumPrintProcessorDataTypes_info(TALLOC_CTX *mem_ctx,
+ uint32_t level, uint32_t count, union spoolss_PrintProcDataTypesInfo *info)
+{
+ NDR_SPOOLSS_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessorDataTypes);
+}
+
+/*
+ spoolss_EnumPerMachineConnections
+*/
+enum ndr_err_code ndr_push_spoolss_EnumPerMachineConnections(struct ndr_push *ndr, int flags, const struct spoolss_EnumPerMachineConnections *r)
+{
+ NDR_SPOOLSS_PUSH_ENUM(spoolss_EnumPerMachineConnections,{
+ _r.in.server = r->in.server;
+ },{
+ _r.in.server = r->in.server;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_spoolss_EnumPerMachineConnections(struct ndr_pull *ndr, int flags, struct spoolss_EnumPerMachineConnections *r)
+{
+ NDR_SPOOLSS_PULL_ENUM(spoolss_EnumPerMachineConnections,{
+ r->in.server = _r.in.server;
+ },{
+ _r.in.server = r->in.server;
+ });
+ return NDR_ERR_SUCCESS;
+}
+
+uint32_t ndr_size_spoolss_EnumPerMachineConnections_info(TALLOC_CTX *mem_ctx, uint32_t count, struct spoolss_PrinterInfo4 *info)
+{
+ NDR_SPOOLSS_SIZE_ENUM(spoolss_EnumPerMachineConnections);
+}
+
+/*
+ spoolss_EnumPrinterDataEx
+*/
+
+enum ndr_err_code ndr_push_spoolss_EnumPrinterDataEx(struct ndr_push *ndr, int flags, const struct spoolss_EnumPrinterDataEx *r)
+{
+ struct _spoolss_EnumPrinterDataEx _r;
+ if (flags & NDR_IN) {
+ _r.in.handle = r->in.handle;
+ _r.in.key_name = r->in.key_name;
+ _r.in.offered = r->in.offered;
+ NDR_CHECK(ndr_push__spoolss_EnumPrinterDataEx(ndr, flags, &_r));
+ }
+ if (flags & NDR_OUT) {
+ struct ndr_push *_ndr_info;
+ _r.in.handle = r->in.handle;
+ _r.in.key_name = r->in.key_name;
+ _r.in.offered = r->in.offered;
+ _r.out.count = r->out.count;
+ _r.out.needed = r->out.needed;
+ _r.out.result = r->out.result;
+ _r.out.info = data_blob(NULL, 0);
+ if (r->in.offered >= *r->out.needed) {
+ struct ndr_push *_subndr_info;
+ struct __spoolss_EnumPrinterDataEx __r;
+ _ndr_info = ndr_push_init_ctx(ndr);
+ NDR_ERR_HAVE_NO_MEMORY(_ndr_info);
+ _ndr_info->flags= ndr->flags;
+ __r.in.count = *r->out.count;
+ __r.out.info = *r->out.info;
+ NDR_CHECK(ndr_push_subcontext_start(_ndr_info, &_subndr_info, 0, r->in.offered));
+ NDR_CHECK(ndr_push___spoolss_EnumPrinterDataEx(_subndr_info, flags, &__r));
+ NDR_CHECK(ndr_push_subcontext_end(_ndr_info, _subndr_info, 0, r->in.offered));
+ if (r->in.offered > _ndr_info->offset) {
+ uint32_t _padding_len = r->in.offered - _ndr_info->offset;
+ NDR_CHECK(ndr_push_zero(_ndr_info, _padding_len));
+ }
+ _r.out.info = ndr_push_blob(_ndr_info);
+ }
+ NDR_CHECK(ndr_push__spoolss_EnumPrinterDataEx(ndr, flags, &_r));
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_spoolss_EnumPrinterDataEx(struct ndr_pull *ndr, int flags, struct spoolss_EnumPrinterDataEx *r)
+{
+ struct _spoolss_EnumPrinterDataEx _r;
+ if (flags & NDR_IN) {
+ _r.in.handle = r->in.handle;
+ _r.in.key_name = r->in.key_name;
+ ZERO_STRUCT(r->out);
+ NDR_CHECK(ndr_pull__spoolss_EnumPrinterDataEx(ndr, flags, &_r));
+ r->in.handle = _r.in.handle;
+ r->in.key_name = _r.in.key_name;
+ r->in.offered = _r.in.offered;
+ r->out.needed = _r.out.needed;
+ r->out.count = _r.out.count;
+ NDR_PULL_ALLOC(ndr, r->out.info);
+ ZERO_STRUCTP(r->out.info);
+ }
+ if (flags & NDR_OUT) {
+ _r.in.handle = r->in.handle;
+ _r.in.key_name = r->in.key_name;
+ _r.in.offered = r->in.offered;
+ _r.out.count = r->out.count;
+ _r.out.needed = r->out.needed;
+ NDR_CHECK(ndr_pull__spoolss_EnumPrinterDataEx(ndr, flags, &_r));
+ if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
+ NDR_PULL_ALLOC(ndr, r->out.info);
+ }
+ *r->out.info = NULL;
+ r->out.needed = _r.out.needed;
+ r->out.count = _r.out.count;
+ r->out.result = _r.out.result;
+ if (_r.out.info.length) {
+ struct ndr_pull *_ndr_info;
+ NDR_PULL_ALLOC(ndr, *r->out.info);
+ _ndr_info = ndr_pull_init_blob(&_r.out.info, *r->out.info);
+ NDR_ERR_HAVE_NO_MEMORY(_ndr_info);
+ _ndr_info->flags= ndr->flags;
+ if (r->in.offered != _ndr_info->data_size) {
+ return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
+ "SPOOLSS Buffer: offered[%u] doesn't match length of buffer[%u]",
+ (unsigned)r->in.offered, (unsigned)_ndr_info->data_size);
+ }
+ if (*r->out.needed <= _ndr_info->data_size) {
+ struct __spoolss_EnumPrinterDataEx __r;
+ __r.in.count = *r->out.count;
+ __r.out.info = NULL;
+ NDR_CHECK(ndr_pull___spoolss_EnumPrinterDataEx(_ndr_info, flags, &__r));
+ *r->out.info = __r.out.info;
+ }
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+uint32_t ndr_size_spoolss_EnumPrinterDataEx_info(TALLOC_CTX *mem_ctx,
+ uint32_t count, struct spoolss_PrinterEnumValues *info)
+{
+ NDR_SPOOLSS_SIZE_ENUM(spoolss_EnumPrinterDataEx);
+}
+
+uint32_t _ndr_size_spoolss_DeviceMode(struct spoolss_DeviceMode *devmode, uint32_t flags)
+{
+ if (!devmode) return 0;
+ return ndr_size_spoolss_DeviceMode(devmode, flags);
+}
+
+_PUBLIC_ size_t ndr_size_spoolss_StringArray(const struct spoolss_StringArray *r, int flags)
+{
+ if (!r) {
+ return 4;
+ }
+
+ return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_spoolss_StringArray);
+}
+
+/* hand marshall as pidl cannot (yet) generate a relative pointer to a fixed array of
+ * structs */
+
+_PUBLIC_ enum ndr_err_code ndr_push_spoolss_DriverInfo101(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo101 *r)
+{
+ uint32_t cntr_file_info_1;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 8));
+ NDR_CHECK(ndr_push_spoolss_DriverOSVersion(ndr, NDR_SCALARS, r->version));
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->driver_name));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->architecture));
+ ndr->flags = _flags_save_string;
+ }
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->file_info));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->file_count));
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->monitor_name));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->default_datatype));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string_array = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->previous_names));
+ ndr->flags = _flags_save_string_array;
+ }
+ NDR_CHECK(ndr_push_NTTIME(ndr, NDR_SCALARS, r->driver_date));
+ NDR_CHECK(ndr_push_hyper(ndr, NDR_SCALARS, r->driver_version));
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->manufacturer_name));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->manufacturer_url));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->hardware_id));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->provider));
+ ndr->flags = _flags_save_string;
+ }
+ NDR_CHECK(ndr_push_trailer_align(ndr, 8));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->driver_name) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->driver_name));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->driver_name));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->driver_name));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->architecture) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->architecture));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->architecture));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->architecture));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ if (r->file_info) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->file_info));
+#if 0
+ NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, r->file_count));
+#endif
+ for (cntr_file_info_1 = 0; cntr_file_info_1 < r->file_count; cntr_file_info_1++) {
+ NDR_CHECK(ndr_push_spoolss_DriverFileInfo(ndr, NDR_SCALARS, &r->file_info[cntr_file_info_1]));
+ }
+ for (cntr_file_info_1 = 0; cntr_file_info_1 < r->file_count; cntr_file_info_1++) {
+ NDR_CHECK(ndr_push_spoolss_DriverFileInfo(ndr, NDR_BUFFERS, &r->file_info[cntr_file_info_1]));
+ }
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->file_info));
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->monitor_name) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->monitor_name));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->monitor_name));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->monitor_name));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->default_datatype) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->default_datatype));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->default_datatype));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->default_datatype));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string_array = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->previous_names) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->previous_names));
+ NDR_CHECK(ndr_push_string_array(ndr, NDR_SCALARS, r->previous_names));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->previous_names));
+ }
+ ndr->flags = _flags_save_string_array;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->manufacturer_name) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->manufacturer_name));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->manufacturer_name));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->manufacturer_name));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->manufacturer_url) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->manufacturer_url));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->manufacturer_url));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->manufacturer_url));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->hardware_id) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->hardware_id));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->hardware_id));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->hardware_id));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->provider) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->provider));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->provider));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->provider));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_spoolss_DriverInfo101(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo101 *r)
+{
+ uint32_t _ptr_driver_name;
+ TALLOC_CTX *_mem_save_driver_name_0;
+ uint32_t _ptr_architecture;
+ TALLOC_CTX *_mem_save_architecture_0;
+ uint32_t _ptr_file_info;
+ uint32_t cntr_file_info_1;
+ TALLOC_CTX *_mem_save_file_info_0;
+ TALLOC_CTX *_mem_save_file_info_1;
+ uint32_t _ptr_monitor_name;
+ TALLOC_CTX *_mem_save_monitor_name_0;
+ uint32_t _ptr_default_datatype;
+ TALLOC_CTX *_mem_save_default_datatype_0;
+ uint32_t _ptr_previous_names;
+ TALLOC_CTX *_mem_save_previous_names_0;
+ uint32_t _ptr_manufacturer_name;
+ TALLOC_CTX *_mem_save_manufacturer_name_0;
+ uint32_t _ptr_manufacturer_url;
+ TALLOC_CTX *_mem_save_manufacturer_url_0;
+ uint32_t _ptr_hardware_id;
+ TALLOC_CTX *_mem_save_hardware_id_0;
+ uint32_t _ptr_provider;
+ TALLOC_CTX *_mem_save_provider_0;
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 8));
+ NDR_CHECK(ndr_pull_spoolss_DriverOSVersion(ndr, NDR_SCALARS, &r->version));
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_driver_name));
+ if (_ptr_driver_name) {
+ NDR_PULL_ALLOC(ndr, r->driver_name);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->driver_name, _ptr_driver_name));
+ } else {
+ r->driver_name = NULL;
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_architecture));
+ if (_ptr_architecture) {
+ NDR_PULL_ALLOC(ndr, r->architecture);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->architecture, _ptr_architecture));
+ } else {
+ r->architecture = NULL;
+ }
+ ndr->flags = _flags_save_string;
+ }
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_file_info));
+ if (_ptr_file_info) {
+ NDR_PULL_ALLOC(ndr, r->file_info);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->file_info, _ptr_file_info));
+ } else {
+ r->file_info = NULL;
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->file_count));
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_monitor_name));
+ if (_ptr_monitor_name) {
+ NDR_PULL_ALLOC(ndr, r->monitor_name);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->monitor_name, _ptr_monitor_name));
+ } else {
+ r->monitor_name = NULL;
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_default_datatype));
+ if (_ptr_default_datatype) {
+ NDR_PULL_ALLOC(ndr, r->default_datatype);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->default_datatype, _ptr_default_datatype));
+ } else {
+ r->default_datatype = NULL;
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string_array = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_previous_names));
+ if (_ptr_previous_names) {
+ NDR_PULL_ALLOC(ndr, r->previous_names);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->previous_names, _ptr_previous_names));
+ } else {
+ r->previous_names = NULL;
+ }
+ ndr->flags = _flags_save_string_array;
+ }
+ NDR_CHECK(ndr_pull_NTTIME(ndr, NDR_SCALARS, &r->driver_date));
+ NDR_CHECK(ndr_pull_hyper(ndr, NDR_SCALARS, &r->driver_version));
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_manufacturer_name));
+ if (_ptr_manufacturer_name) {
+ NDR_PULL_ALLOC(ndr, r->manufacturer_name);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->manufacturer_name, _ptr_manufacturer_name));
+ } else {
+ r->manufacturer_name = NULL;
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_manufacturer_url));
+ if (_ptr_manufacturer_url) {
+ NDR_PULL_ALLOC(ndr, r->manufacturer_url);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->manufacturer_url, _ptr_manufacturer_url));
+ } else {
+ r->manufacturer_url = NULL;
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_hardware_id));
+ if (_ptr_hardware_id) {
+ NDR_PULL_ALLOC(ndr, r->hardware_id);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->hardware_id, _ptr_hardware_id));
+ } else {
+ r->hardware_id = NULL;
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_provider));
+ if (_ptr_provider) {
+ NDR_PULL_ALLOC(ndr, r->provider);
+ NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->provider, _ptr_provider));
+ } else {
+ r->provider = NULL;
+ }
+ ndr->flags = _flags_save_string;
+ }
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 8));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->driver_name) {
+ uint32_t _relative_save_offset;
+ _relative_save_offset = ndr->offset;
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->driver_name));
+ _mem_save_driver_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->driver_name, 0);
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->driver_name));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_driver_name_0, 0);
+ if (ndr->offset > ndr->relative_highest_offset) {
+ ndr->relative_highest_offset = ndr->offset;
+ }
+ ndr->offset = _relative_save_offset;
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->architecture) {
+ uint32_t _relative_save_offset;
+ _relative_save_offset = ndr->offset;
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->architecture));
+ _mem_save_architecture_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->architecture, 0);
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->architecture));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_architecture_0, 0);
+ if (ndr->offset > ndr->relative_highest_offset) {
+ ndr->relative_highest_offset = ndr->offset;
+ }
+ ndr->offset = _relative_save_offset;
+ }
+ ndr->flags = _flags_save_string;
+ }
+ if (r->file_info) {
+ uint32_t _relative_save_offset;
+ _relative_save_offset = ndr->offset;
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->file_info));
+ _mem_save_file_info_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->file_info, 0);
+#if 0
+ NDR_CHECK(ndr_pull_array_size(ndr, &r->file_info));
+#else
+ NDR_CHECK(ndr_token_store(ndr, &ndr->array_size_list, &r->file_info, r->file_count));
+#endif
+ NDR_PULL_ALLOC_N(ndr, r->file_info, r->file_count);
+ _mem_save_file_info_1 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->file_info, 0);
+ for (cntr_file_info_1 = 0; cntr_file_info_1 < r->file_count; cntr_file_info_1++) {
+ NDR_CHECK(ndr_pull_spoolss_DriverFileInfo(ndr, NDR_SCALARS, &r->file_info[cntr_file_info_1]));
+ }
+ for (cntr_file_info_1 = 0; cntr_file_info_1 < r->file_count; cntr_file_info_1++) {
+ NDR_CHECK(ndr_pull_spoolss_DriverFileInfo(ndr, NDR_BUFFERS, &r->file_info[cntr_file_info_1]));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_file_info_1, 0);
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_file_info_0, 0);
+ if (ndr->offset > ndr->relative_highest_offset) {
+ ndr->relative_highest_offset = ndr->offset;
+ }
+ ndr->offset = _relative_save_offset;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->monitor_name) {
+ uint32_t _relative_save_offset;
+ _relative_save_offset = ndr->offset;
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->monitor_name));
+ _mem_save_monitor_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->monitor_name, 0);
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->monitor_name));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_monitor_name_0, 0);
+ if (ndr->offset > ndr->relative_highest_offset) {
+ ndr->relative_highest_offset = ndr->offset;
+ }
+ ndr->offset = _relative_save_offset;
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->default_datatype) {
+ uint32_t _relative_save_offset;
+ _relative_save_offset = ndr->offset;
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->default_datatype));
+ _mem_save_default_datatype_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->default_datatype, 0);
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->default_datatype));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_default_datatype_0, 0);
+ if (ndr->offset > ndr->relative_highest_offset) {
+ ndr->relative_highest_offset = ndr->offset;
+ }
+ ndr->offset = _relative_save_offset;
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string_array = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->previous_names) {
+ uint32_t _relative_save_offset;
+ _relative_save_offset = ndr->offset;
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->previous_names));
+ _mem_save_previous_names_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->previous_names, 0);
+ NDR_CHECK(ndr_pull_string_array(ndr, NDR_SCALARS, &r->previous_names));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_previous_names_0, 0);
+ if (ndr->offset > ndr->relative_highest_offset) {
+ ndr->relative_highest_offset = ndr->offset;
+ }
+ ndr->offset = _relative_save_offset;
+ }
+ ndr->flags = _flags_save_string_array;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->manufacturer_name) {
+ uint32_t _relative_save_offset;
+ _relative_save_offset = ndr->offset;
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->manufacturer_name));
+ _mem_save_manufacturer_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->manufacturer_name, 0);
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->manufacturer_name));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_manufacturer_name_0, 0);
+ if (ndr->offset > ndr->relative_highest_offset) {
+ ndr->relative_highest_offset = ndr->offset;
+ }
+ ndr->offset = _relative_save_offset;
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->manufacturer_url) {
+ uint32_t _relative_save_offset;
+ _relative_save_offset = ndr->offset;
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->manufacturer_url));
+ _mem_save_manufacturer_url_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->manufacturer_url, 0);
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->manufacturer_url));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_manufacturer_url_0, 0);
+ if (ndr->offset > ndr->relative_highest_offset) {
+ ndr->relative_highest_offset = ndr->offset;
+ }
+ ndr->offset = _relative_save_offset;
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->hardware_id) {
+ uint32_t _relative_save_offset;
+ _relative_save_offset = ndr->offset;
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->hardware_id));
+ _mem_save_hardware_id_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->hardware_id, 0);
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->hardware_id));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_hardware_id_0, 0);
+ if (ndr->offset > ndr->relative_highest_offset) {
+ ndr->relative_highest_offset = ndr->offset;
+ }
+ ndr->offset = _relative_save_offset;
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->provider) {
+ uint32_t _relative_save_offset;
+ _relative_save_offset = ndr->offset;
+ NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->provider));
+ _mem_save_provider_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->provider, 0);
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->provider));
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_provider_0, 0);
+ if (ndr->offset > ndr->relative_highest_offset) {
+ ndr->relative_highest_offset = ndr->offset;
+ }
+ ndr->offset = _relative_save_offset;
+ }
+ ndr->flags = _flags_save_string;
+ }
+ if (r->file_info) {
+ NDR_CHECK(ndr_check_steal_array_size(ndr, (void*)&r->file_info, r->file_count));
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+void ndr_print_spoolss_Field(struct ndr_print *ndr, const char *name, const union spoolss_Field *r)
+{
+ int level;
+ level = ndr_print_steal_switch_value(ndr, r);
+ ndr_print_union(ndr, name, level, "spoolss_Field");
+ switch (level) {
+ case PRINTER_NOTIFY_TYPE:
+ ndr_print_spoolss_PrintNotifyField(ndr, "field", r->field);
+ break;
+
+ case JOB_NOTIFY_TYPE:
+ ndr_print_spoolss_JobNotifyField(ndr, "field", r->field);
+ break;
+
+ default:
+ ndr_print_uint16(ndr, "field", r->field);
+ break;
+
+ }
+}
+
+_PUBLIC_ size_t ndr_size_spoolss_PrinterData(const union spoolss_PrinterData *r, uint32_t level, int flags)
+{
+ if (!r) {
+ return 0;
+ }
+ return ndr_size_union(r, flags, level, (ndr_push_flags_fn_t)ndr_push_spoolss_PrinterData);
+}
+
+void ndr_print_spoolss_security_descriptor(struct ndr_print *ndr, const char *name, const struct security_descriptor *r)
+{
+ ndr_print_security_descriptor(ndr, name, r);
+}
+
+enum ndr_err_code ndr_pull_spoolss_security_descriptor(struct ndr_pull *ndr, int ndr_flags, struct security_descriptor *r)
+{
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NO_RELATIVE_REVERSE);
+ NDR_CHECK(ndr_pull_security_descriptor(ndr, ndr_flags, r));
+ ndr->flags = _flags_save_STRUCT;
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_push_spoolss_security_descriptor(struct ndr_push *ndr, int ndr_flags, const struct security_descriptor *r)
+{
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN|LIBNDR_FLAG_NO_RELATIVE_REVERSE);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 5));
+ NDR_CHECK(ndr_push_security_descriptor_revision(ndr, NDR_SCALARS, r->revision));
+ NDR_CHECK(ndr_push_security_descriptor_type(ndr, NDR_SCALARS, r->type));
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->owner_sid));
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->group_sid));
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->sacl));
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->dacl));
+ NDR_CHECK(ndr_push_trailer_align(ndr, 5));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ if (r->sacl) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->sacl));
+ NDR_CHECK(ndr_push_security_acl(ndr, NDR_SCALARS|NDR_BUFFERS, r->sacl));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->sacl));
+ }
+ if (r->dacl) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->dacl));
+ NDR_CHECK(ndr_push_security_acl(ndr, NDR_SCALARS|NDR_BUFFERS, r->dacl));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->dacl));
+ }
+ if (r->owner_sid) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->owner_sid));
+ NDR_CHECK(ndr_push_dom_sid(ndr, NDR_SCALARS, r->owner_sid));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->owner_sid));
+ }
+ if (r->group_sid) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->group_sid));
+ NDR_CHECK(ndr_push_dom_sid(ndr, NDR_SCALARS, r->group_sid));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->group_sid));
+ }
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_spoolss_PrinterInfo2(struct ndr_push *ndr, int ndr_flags, const struct spoolss_PrinterInfo2 *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 5));
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->servername));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->printername));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->sharename));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->portname));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->drivername));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->comment));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->location));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_spoolss_DeviceMode = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN4);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->devmode));
+ ndr->flags = _flags_save_spoolss_DeviceMode;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->sepfile));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->printprocessor));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->datatype));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->parameters));
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_spoolss_security_descriptor = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN4);
+ NDR_CHECK(ndr_push_relative_ptr1(ndr, r->secdesc));
+ ndr->flags = _flags_save_spoolss_security_descriptor;
+ }
+ NDR_CHECK(ndr_push_spoolss_PrinterAttributes(ndr, NDR_SCALARS, r->attributes));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->priority));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->defaultpriority));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->starttime));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->untiltime));
+ NDR_CHECK(ndr_push_spoolss_PrinterStatus(ndr, NDR_SCALARS, r->status));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->cjobs));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->averageppm));
+ NDR_CHECK(ndr_push_trailer_align(ndr, 5));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->servername) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->servername));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->servername));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->servername));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->printername) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->printername));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->printername));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->printername));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->sharename) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->sharename));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->sharename));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->sharename));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->portname) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->portname));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->portname));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->portname));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->drivername) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->drivername));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->drivername));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->drivername));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->comment) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->comment));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->comment));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->comment));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->location) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->location));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->location));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->location));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->sepfile) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->sepfile));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->sepfile));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->sepfile));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->printprocessor) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->printprocessor));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->printprocessor));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->printprocessor));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->datatype) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->datatype));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->datatype));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->datatype));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+ if (r->parameters) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->parameters));
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->parameters));
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->parameters));
+ }
+ ndr->flags = _flags_save_string;
+ }
+ {
+ uint32_t _flags_save_spoolss_DeviceMode = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN4);
+ if (r->devmode) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->devmode));
+ {
+ struct ndr_push *_ndr_devmode;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_devmode, 0, -1));
+ NDR_CHECK(ndr_push_spoolss_DeviceMode(_ndr_devmode, NDR_SCALARS, r->devmode));
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_devmode, 0, -1));
+ }
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->devmode));
+ }
+ ndr->flags = _flags_save_spoolss_DeviceMode;
+ }
+ {
+ uint32_t _flags_save_spoolss_security_descriptor = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN4);
+ if (r->secdesc) {
+ NDR_CHECK(ndr_push_relative_ptr2_start(ndr, r->secdesc));
+ {
+ struct ndr_push *_ndr_secdesc;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_secdesc, 0, -1));
+ NDR_CHECK(ndr_push_spoolss_security_descriptor(_ndr_secdesc, NDR_SCALARS|NDR_BUFFERS, r->secdesc));
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_secdesc, 0, -1));
+ }
+ NDR_CHECK(ndr_push_relative_ptr2_end(ndr, r->secdesc));
+ }
+ ndr->flags = _flags_save_spoolss_security_descriptor;
+ }
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_Time(struct ndr_print *ndr, const char *name, const struct spoolss_Time *r)
+{
+ struct tm tm;
+ time_t t;
+ char *str;
+
+ tm.tm_sec = r->second;
+ tm.tm_min = r->minute;
+ tm.tm_hour = r->hour;
+ tm.tm_mday = r->day;
+ tm.tm_mon = r->month - 1;
+ tm.tm_year = r->year - 1900;
+ tm.tm_wday = r->day_of_week;
+ tm.tm_yday = 0;
+ tm.tm_isdst = -1;
+
+ t = mktime(&tm);
+
+ str = timestring(ndr, t);
+
+ ndr_print_struct(ndr, name, "spoolss_Time");
+ ndr->depth++;
+ ndr_print_string(ndr, "", str);
+ ndr->depth--;
+ talloc_free(str);
+}
+
+_PUBLIC_ uint32_t ndr_spoolss_PrinterEnumValues_align(enum winreg_Type type)
+{
+ switch(type) {
+ case REG_NONE:
+ return 0;
+ case REG_SZ:
+ return LIBNDR_FLAG_ALIGN2;
+ case REG_EXPAND_SZ:
+ return LIBNDR_FLAG_ALIGN2;
+ case REG_BINARY:
+ return 0;
+ case REG_DWORD:
+ return LIBNDR_FLAG_ALIGN4;
+ case REG_DWORD_BIG_ENDIAN:
+ return LIBNDR_FLAG_ALIGN4;
+ case REG_LINK:
+ return 0;
+ case REG_MULTI_SZ:
+ return LIBNDR_FLAG_ALIGN2;
+ case REG_RESOURCE_LIST:
+ return LIBNDR_FLAG_ALIGN2;
+ case REG_FULL_RESOURCE_DESCRIPTOR:
+ return LIBNDR_FLAG_ALIGN4;
+ case REG_RESOURCE_REQUIREMENTS_LIST:
+ return LIBNDR_FLAG_ALIGN2;
+ case REG_QWORD:
+ return LIBNDR_FLAG_ALIGN8;
+ }
+
+ return 0;
+}
diff --git a/librpc/ndr/ndr_spoolss_buf.h b/librpc/ndr/ndr_spoolss_buf.h
new file mode 100644
index 0000000..2ede07a
--- /dev/null
+++ b/librpc/ndr/ndr_spoolss_buf.h
@@ -0,0 +1,85 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling spoolss subcontext buffer structures
+
+ Copyright (C) Andrew Tridgell 2003
+ Copyright (C) Tim Potter 2003
+ Copyright (C) Guenther Deschner 2009
+
+ 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 ___SPACE_SRC_SAMBA_SOURCES_SAMBA_GIT_SOURCE3____SOURCE4_LIBRPC_NDR_NDR_SPOOLSS_BUF_H__
+#define ___SPACE_SRC_SAMBA_SOURCES_SAMBA_GIT_SOURCE3____SOURCE4_LIBRPC_NDR_NDR_SPOOLSS_BUF_H__
+
+#undef _PRINTF_ATTRIBUTE
+#define _PRINTF_ATTRIBUTE(a1, a2) PRINTF_ATTRIBUTE(a1, a2)
+/* This file was automatically generated by mkproto.pl. DO NOT EDIT */
+
+/* this file contains prototypes for functions that are private
+ * to this subsystem or library. These functions should not be
+ * used outside this particular subsystem! */
+
+
+/* The following definitions come from /space/src/samba/SOURCES/samba.git/source3/../source4/librpc/ndr/ndr_spoolss_buf.c */
+
+enum ndr_err_code ndr_push_spoolss_EnumPrinters(struct ndr_push *ndr, int flags, const struct spoolss_EnumPrinters *r);
+enum ndr_err_code ndr_pull_spoolss_EnumPrinters(struct ndr_pull *ndr, int flags, struct spoolss_EnumPrinters *r);
+uint32_t ndr_size_spoolss_EnumPrinters_info(TALLOC_CTX *mem_ctx, uint32_t level, uint32_t count, union spoolss_PrinterInfo *info);
+enum ndr_err_code ndr_push_spoolss_EnumJobs(struct ndr_push *ndr, int flags, const struct spoolss_EnumJobs *r);
+enum ndr_err_code ndr_pull_spoolss_EnumJobs(struct ndr_pull *ndr, int flags, struct spoolss_EnumJobs *r);
+uint32_t ndr_size_spoolss_EnumJobs_info(TALLOC_CTX *mem_ctx, uint32_t level, uint32_t count, union spoolss_JobInfo *info);
+enum ndr_err_code ndr_push_spoolss_EnumPrinterDrivers(struct ndr_push *ndr, int flags, const struct spoolss_EnumPrinterDrivers *r);
+enum ndr_err_code ndr_pull_spoolss_EnumPrinterDrivers(struct ndr_pull *ndr, int flags, struct spoolss_EnumPrinterDrivers *r);
+uint32_t ndr_size_spoolss_EnumPrinterDrivers_info(TALLOC_CTX *mem_ctx, uint32_t level, uint32_t count, union spoolss_DriverInfo *info);
+enum ndr_err_code ndr_push_spoolss_EnumForms(struct ndr_push *ndr, int flags, const struct spoolss_EnumForms *r);
+enum ndr_err_code ndr_pull_spoolss_EnumForms(struct ndr_pull *ndr, int flags, struct spoolss_EnumForms *r);
+uint32_t ndr_size_spoolss_EnumForms_info(TALLOC_CTX *mem_ctx, uint32_t level, uint32_t count, union spoolss_FormInfo *info);
+enum ndr_err_code ndr_push_spoolss_EnumPorts(struct ndr_push *ndr, int flags, const struct spoolss_EnumPorts *r);
+enum ndr_err_code ndr_pull_spoolss_EnumPorts(struct ndr_pull *ndr, int flags, struct spoolss_EnumPorts *r);
+uint32_t ndr_size_spoolss_EnumPorts_info(TALLOC_CTX *mem_ctx, uint32_t level, uint32_t count, union spoolss_PortInfo *info);
+enum ndr_err_code ndr_push_spoolss_EnumMonitors(struct ndr_push *ndr, int flags, const struct spoolss_EnumMonitors *r);
+enum ndr_err_code ndr_pull_spoolss_EnumMonitors(struct ndr_pull *ndr, int flags, struct spoolss_EnumMonitors *r);
+uint32_t ndr_size_spoolss_EnumMonitors_info(TALLOC_CTX *mem_ctx, uint32_t level, uint32_t count, union spoolss_MonitorInfo *info);
+enum ndr_err_code ndr_push_spoolss_EnumPrintProcessors(struct ndr_push *ndr, int flags, const struct spoolss_EnumPrintProcessors *r);
+enum ndr_err_code ndr_pull_spoolss_EnumPrintProcessors(struct ndr_pull *ndr, int flags, struct spoolss_EnumPrintProcessors *r);
+uint32_t ndr_size_spoolss_EnumPrintProcessors_info(TALLOC_CTX *mem_ctx,
+ uint32_t level, uint32_t count, union spoolss_PrintProcessorInfo *info);
+enum ndr_err_code ndr_push_spoolss_EnumPrintProcessorDataTypes(struct ndr_push *ndr, int flags, const struct spoolss_EnumPrintProcessorDataTypes *r);
+enum ndr_err_code ndr_pull_spoolss_EnumPrintProcessorDataTypes(struct ndr_pull *ndr, int flags, struct spoolss_EnumPrintProcessorDataTypes *r);
+uint32_t ndr_size_spoolss_EnumPrintProcessorDataTypes_info(TALLOC_CTX *mem_ctx,
+ uint32_t level, uint32_t count, union spoolss_PrintProcDataTypesInfo *info);
+enum ndr_err_code ndr_push_spoolss_EnumPrinterDataEx(struct ndr_push *ndr, int flags, const struct spoolss_EnumPrinterDataEx *r);
+enum ndr_err_code ndr_pull_spoolss_EnumPrinterDataEx(struct ndr_pull *ndr, int flags, struct spoolss_EnumPrinterDataEx *r);
+uint32_t ndr_size_spoolss_EnumPrinterDataEx_info(TALLOC_CTX *mem_ctx,
+ uint32_t count, struct spoolss_PrinterEnumValues *info);
+uint32_t _ndr_size_spoolss_DeviceMode(struct spoolss_DeviceMode *devmode, uint32_t flags);
+size_t ndr_size_spoolss_StringArray(const struct spoolss_StringArray *r, int flags);
+_PUBLIC_ enum ndr_err_code ndr_push_spoolss_DriverInfo101(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo101 *r);
+_PUBLIC_ enum ndr_err_code ndr_pull_spoolss_DriverInfo101(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo101 *r);
+void ndr_print_spoolss_Field(struct ndr_print *ndr, const char *name, const union spoolss_Field *r);
+size_t ndr_size_spoolss_PrinterData(const union spoolss_PrinterData *r, uint32_t level, int flags);
+void ndr_print_spoolss_security_descriptor(struct ndr_print *ndr, const char *name, const struct security_descriptor *r);
+enum ndr_err_code ndr_pull_spoolss_security_descriptor(struct ndr_pull *ndr, int ndr_flags, struct security_descriptor *r);
+enum ndr_err_code ndr_push_spoolss_security_descriptor(struct ndr_push *ndr, int ndr_flags, const struct security_descriptor *r);
+_PUBLIC_ void ndr_print_spoolss_Time(struct ndr_print *ndr, const char *name, const struct spoolss_Time *r);
+_PUBLIC_ uint32_t ndr_spoolss_PrinterEnumValues_align(enum winreg_Type type);
+
+uint32_t ndr_size_spoolss_EnumPerMachineConnections_info(TALLOC_CTX *mem_ctx, uint32_t count, struct spoolss_PrinterInfo4 *info);
+#undef _PRINTF_ATTRIBUTE
+#define _PRINTF_ATTRIBUTE(a1, a2)
+
+#endif /* ___SPACE_SRC_SAMBA_SOURCES_SAMBA_GIT_SOURCE3____SOURCE4_LIBRPC_NDR_NDR_SPOOLSS_BUF_H__ */
+
diff --git a/librpc/ndr/ndr_string.c b/librpc/ndr/ndr_string.c
new file mode 100644
index 0000000..95b0366
--- /dev/null
+++ b/librpc/ndr/ndr_string.c
@@ -0,0 +1,815 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling string types
+
+ Copyright (C) Andrew Tridgell 2003
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/ndr/libndr.h"
+
+/**
+ pull a general string from the wire
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
+{
+ char *as=NULL;
+ uint32_t len1, ofs, len2;
+ uint16_t len3;
+ size_t conv_src_len = 0, converted_size;
+ int do_convert = 1, chset = CH_UTF16;
+ unsigned byte_mul = 2;
+ unsigned flags = ndr->flags;
+ unsigned c_len_term = 0;
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ if (NDR_BE(ndr)) {
+ chset = CH_UTF16BE;
+ }
+
+ if (flags & LIBNDR_FLAG_STR_ASCII) {
+ chset = CH_DOS;
+ byte_mul = 1;
+ flags &= ~LIBNDR_FLAG_STR_ASCII;
+ }
+
+ if (flags & LIBNDR_FLAG_STR_UTF8) {
+ chset = CH_UTF8;
+ byte_mul = 1;
+ flags &= ~LIBNDR_FLAG_STR_UTF8;
+ }
+
+ if (flags & LIBNDR_FLAG_STR_RAW8) {
+ do_convert = 0;
+ byte_mul = 1;
+ flags &= ~LIBNDR_FLAG_STR_RAW8;
+ }
+
+ flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
+ if (flags & LIBNDR_FLAG_STR_CHARLEN) {
+ c_len_term = 1;
+ flags &= ~LIBNDR_FLAG_STR_CHARLEN;
+ }
+
+ switch (flags & LIBNDR_STRING_FLAGS) {
+ case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
+ case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
+ if (ofs != 0) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len2));
+ if (len2 > len1) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING,
+ "Bad string lengths len1=%u ofs=%u len2=%u\n",
+ len1, ofs, len2);
+ } else if (len1 != len2) {
+ DEBUG(6,("len1[%u] != len2[%u] '%s'\n", len1, len2, as));
+ }
+ conv_src_len = len2 + c_len_term;
+ break;
+
+ case LIBNDR_FLAG_STR_SIZE4:
+ case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
+ conv_src_len = len1 + c_len_term;
+ break;
+
+ case LIBNDR_FLAG_STR_LEN4:
+ case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM:
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
+ if (ofs != 0) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
+ }
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
+ conv_src_len = len1 + c_len_term;
+ break;
+
+ case LIBNDR_FLAG_STR_SIZE2:
+ case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
+ conv_src_len = len3 + c_len_term;
+ break;
+
+ case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
+ conv_src_len = len3;
+ byte_mul = 1; /* the length is now absolute */
+ break;
+
+ case LIBNDR_FLAG_STR_NULLTERM:
+ /*
+ * We ensure that conv_str_len cannot return 0 by
+ * requring that there be enough bytes for at least
+ * the NULL terminator
+ */
+ if (byte_mul == 1) {
+ NDR_PULL_NEED_BYTES(ndr, 1);
+ conv_src_len = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset);
+ } else {
+ NDR_PULL_NEED_BYTES(ndr, 2);
+ conv_src_len = utf16_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset);
+ }
+ byte_mul = 1; /* the length is now absolute */
+ break;
+
+ case LIBNDR_FLAG_STR_NOTERM:
+ if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
+ }
+ conv_src_len = ndr->data_size - ndr->offset;
+ byte_mul = 1; /* the length is now absolute */
+ break;
+
+ default:
+ return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
+ }
+
+ NDR_PULL_NEED_BYTES(ndr, conv_src_len * byte_mul);
+ if (conv_src_len == 0) {
+ as = talloc_strdup(ndr->current_mem_ctx, "");
+ converted_size = 0;
+ } else {
+ if (!do_convert) {
+ as = talloc_strndup(ndr->current_mem_ctx,
+ (char *)ndr->data + ndr->offset,
+ conv_src_len);
+ if (!as) {
+ return ndr_pull_error(ndr, NDR_ERR_ALLOC,
+ "Failed to talloc_strndup() in RAW8 ndr_string_pull()");
+ }
+ converted_size = MIN(strlen(as)+1, conv_src_len);
+ } else if (!convert_string_talloc(ndr->current_mem_ctx, chset,
+ CH_UNIX, ndr->data + ndr->offset,
+ conv_src_len * byte_mul,
+ (void **)(void *)&as,
+ &converted_size)) {
+ return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion with flags 0x%x", flags);
+ }
+ }
+
+ /* this is a way of detecting if a string is sent with the wrong
+ termination */
+ if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
+ if (as && converted_size > 0 && as[converted_size-1] == '\0') {
+ DEBUG(6,("short string '%s', sent with NULL termination despite NOTERM flag in IDL\n", as));
+ }
+ } else {
+ if (as && converted_size > 0 && as[converted_size-1] != '\0') {
+ DEBUG(6,("long string '%s', send without NULL termination (which was expected)\n", as));
+ }
+ }
+
+ NDR_CHECK(ndr_pull_advance(ndr, conv_src_len * byte_mul));
+ *s = as;
+
+ return NDR_ERR_SUCCESS;
+}
+
+
+/**
+ push a general string onto the wire
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
+{
+ ssize_t s_len, c_len;
+ size_t d_len;
+ int do_convert = 1, chset = CH_UTF16;
+ unsigned flags = ndr->flags;
+ unsigned byte_mul = 2;
+ uint8_t *dest = NULL;
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ if (NDR_BE(ndr)) {
+ chset = CH_UTF16BE;
+ }
+
+ s_len = s?strlen(s):0;
+
+ if (flags & LIBNDR_FLAG_STR_ASCII) {
+ chset = CH_DOS;
+ byte_mul = 1;
+ flags &= ~LIBNDR_FLAG_STR_ASCII;
+ }
+
+ if (flags & LIBNDR_FLAG_STR_UTF8) {
+ chset = CH_UTF8;
+ byte_mul = 1;
+ flags &= ~LIBNDR_FLAG_STR_UTF8;
+ }
+
+ if (flags & LIBNDR_FLAG_STR_RAW8) {
+ do_convert = 0;
+ byte_mul = 1;
+ flags &= ~LIBNDR_FLAG_STR_RAW8;
+ }
+
+ flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
+
+ if (!(flags & LIBNDR_FLAG_STR_NOTERM)) {
+ s_len++;
+ }
+
+ if (s_len == 0) {
+ d_len = 0;
+ dest = (uint8_t *)talloc_strdup(ndr, "");
+ } else if (!do_convert) {
+ d_len = s_len;
+ dest = (uint8_t *)talloc_strndup(ndr, s, s_len);
+ } else if (!convert_string_talloc(ndr, CH_UNIX, chset, s, s_len,
+ (void **)(void *)&dest, &d_len))
+ {
+ return ndr_push_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character push conversion with flags 0x%x", flags);
+ }
+
+ if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
+ c_len = d_len;
+ flags &= ~LIBNDR_FLAG_STR_BYTESIZE;
+ } else if (flags & LIBNDR_FLAG_STR_CHARLEN) {
+ c_len = (d_len / byte_mul)-1;
+ flags &= ~LIBNDR_FLAG_STR_CHARLEN;
+ } else {
+ c_len = d_len / byte_mul;
+ }
+
+ switch ((flags & LIBNDR_STRING_FLAGS) & ~LIBNDR_FLAG_STR_NOTERM) {
+ case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
+ NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+ break;
+
+ case LIBNDR_FLAG_STR_LEN4:
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
+ NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+ break;
+
+ case LIBNDR_FLAG_STR_SIZE4:
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
+ NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+ break;
+
+ case LIBNDR_FLAG_STR_SIZE2:
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, c_len));
+ NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+ break;
+
+ case LIBNDR_FLAG_STR_NULLTERM:
+ NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+ break;
+
+ default:
+ if (ndr->flags & LIBNDR_FLAG_REMAINING) {
+ NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
+ break;
+ }
+
+ return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
+ }
+
+ talloc_free(dest);
+
+ return NDR_ERR_SUCCESS;
+}
+
+/**
+ push a general string onto the wire
+*/
+_PUBLIC_ size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
+{
+ size_t c_len;
+ unsigned flags = ndr->flags;
+ unsigned byte_mul = 2;
+ unsigned c_len_term = 1;
+
+ if (flags & LIBNDR_FLAG_STR_RAW8) {
+ c_len = s?strlen(s):0;
+ } else {
+ c_len = s?strlen_m(s):0;
+ }
+
+ if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_RAW8|LIBNDR_FLAG_STR_UTF8)) {
+ byte_mul = 1;
+ }
+
+ if (flags & LIBNDR_FLAG_STR_NOTERM) {
+ c_len_term = 0;
+ }
+
+ c_len = c_len + c_len_term;
+
+ if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
+ c_len = c_len * byte_mul;
+ }
+
+ return c_len;
+}
+
+_PUBLIC_ void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
+{
+ if (NDR_HIDE_SECRET(ndr)) {
+ ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name);
+ return;
+ }
+ if (s) {
+ ndr->print(ndr, "%-25s: '%s'", name, s);
+ } else {
+ ndr->print(ndr, "%-25s: NULL", name);
+ }
+}
+
+_PUBLIC_ uint32_t ndr_size_string(int ret, const char * const* string, int flags)
+{
+ /* FIXME: Is this correct for all strings ? */
+ if(!(*string)) return ret;
+ return ret+strlen(*string)+1;
+}
+
+static uint32_t guess_string_array_size(struct ndr_pull *ndr, int ndr_flags)
+{
+ /*
+ * Here we could do something clever like count the number of zeros in
+ * the ndr data, but it is probably sufficient to pick a lowish number
+ * (compared to the overhead of the talloc header) and let the
+ * expontential resizing deal with longer arrays.
+ */
+ return 5;
+}
+
+static enum ndr_err_code extend_string_array(struct ndr_pull *ndr,
+ const char ***_a,
+ uint32_t *count)
+{
+ const char **a = *_a;
+ uint32_t inc = *count / 4 + 3;
+ uint32_t alloc_size = *count + inc;
+
+ if (alloc_size < *count) {
+ /* overflow ! */
+ return NDR_ERR_ALLOC;
+ }
+ /*
+ * We allocate and zero two more bytes than we report back, so that
+ * the string array will always be NULL terminated.
+ */
+ a = talloc_realloc(ndr->current_mem_ctx, a,
+ const char *,
+ alloc_size);
+ NDR_ERR_HAVE_NO_MEMORY(a);
+
+ memset(a + *count, 0, inc * sizeof(a[0]));
+ *_a = a;
+ *count = alloc_size - 2;
+ return NDR_ERR_SUCCESS;
+}
+
+/**
+ pull a general string array from the wire
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_string_array(struct ndr_pull *ndr, int ndr_flags, const char ***_a)
+{
+ const char **a = NULL;
+ uint32_t count;
+ unsigned flags = ndr->flags;
+ unsigned saved_flags = ndr->flags;
+ uint32_t alloc_size;
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ alloc_size = guess_string_array_size(ndr, ndr_flags);
+ a = talloc_zero_array(ndr->current_mem_ctx, const char *, alloc_size + 2);
+ NDR_ERR_HAVE_NO_MEMORY(a);
+
+ switch (flags & (LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_STR_NOTERM)) {
+ case LIBNDR_FLAG_STR_NULLTERM:
+ /*
+ * here the strings are null terminated
+ * but also the array is null terminated if LIBNDR_FLAG_REMAINING
+ * is specified
+ */
+ for (count = 0;; count++) {
+ TALLOC_CTX *tmp_ctx;
+ const char *s = NULL;
+ if (count == alloc_size) {
+ NDR_CHECK(extend_string_array(ndr,
+ &a,
+ &alloc_size));
+ }
+
+ tmp_ctx = ndr->current_mem_ctx;
+ ndr->current_mem_ctx = a;
+ NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
+ ndr->current_mem_ctx = tmp_ctx;
+ if ((ndr->data_size - ndr->offset) == 0 && ndr->flags & LIBNDR_FLAG_REMAINING)
+ {
+ a[count] = s;
+ break;
+ }
+ if (strcmp("", s)==0) {
+ a[count] = NULL;
+ break;
+ } else {
+ a[count] = s;
+ }
+ }
+
+ *_a =a;
+ break;
+
+ case LIBNDR_FLAG_STR_NOTERM:
+ if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
+ }
+ /*
+ * here the strings are not null terminated
+ * but separated by a null terminator
+ *
+ * which means the same as:
+ * Every string is null terminated exept the last
+ * string is terminated by the end of the buffer
+ *
+ * as LIBNDR_FLAG_STR_NULLTERM also end at the end
+ * of the buffer, we can pull each string with this flag
+ *
+ * The big difference with the case LIBNDR_FLAG_STR_NOTERM +
+ * LIBNDR_FLAG_REMAINING is that the last string will not be null terminated
+ */
+ ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
+ ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
+
+ for (count = 0; ((ndr->data_size - ndr->offset) > 0); count++) {
+ TALLOC_CTX *tmp_ctx;
+ const char *s = NULL;
+ if (count == alloc_size) {
+ NDR_CHECK(extend_string_array(ndr,
+ &a,
+ &alloc_size));
+ }
+
+ tmp_ctx = ndr->current_mem_ctx;
+ ndr->current_mem_ctx = a;
+ NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
+ ndr->current_mem_ctx = tmp_ctx;
+ a[count] = s;
+ }
+
+ a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 1);
+ NDR_ERR_HAVE_NO_MEMORY(a);
+ *_a = a;
+ break;
+
+ default:
+ return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
+ }
+
+ ndr->flags = saved_flags;
+ return NDR_ERR_SUCCESS;
+}
+
+/**
+ push a general string array onto the wire
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_string_array(struct ndr_push *ndr, int ndr_flags, const char **a)
+{
+ uint32_t count;
+ unsigned flags = ndr->flags;
+ unsigned saved_flags = ndr->flags;
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return NDR_ERR_SUCCESS;
+ }
+
+ switch (flags & LIBNDR_STRING_FLAGS) {
+ case LIBNDR_FLAG_STR_NULLTERM:
+ for (count = 0; a && a[count]; count++) {
+ NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
+ }
+ /* If LIBNDR_FLAG_REMAINING then we do not add a null terminator to the array */
+ if (!(flags & LIBNDR_FLAG_REMAINING))
+ {
+ NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
+ }
+ break;
+
+ case LIBNDR_FLAG_STR_NOTERM:
+ if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
+ return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
+ }
+
+ for (count = 0; a && a[count]; count++) {
+ if (count > 0) {
+ ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
+ ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
+ NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
+ ndr->flags = saved_flags;
+ }
+ NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
+ }
+
+ break;
+
+ default:
+ return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
+ }
+
+ ndr->flags = saved_flags;
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_string_array(struct ndr_print *ndr, const char *name, const char **a)
+{
+ uint32_t count;
+ uint32_t i;
+
+ for (count = 0; a && a[count]; count++) {}
+
+ ndr->print(ndr, "%s: ARRAY(%d)", name, count);
+ ndr->depth++;
+ for (i=0;i<count;i++) {
+ char *idx=NULL;
+ if (asprintf(&idx, "[%d]", i) != -1) {
+ ndr_print_string(ndr, idx, a[i]);
+ free(idx);
+ }
+ }
+ ndr->depth--;
+}
+
+_PUBLIC_ size_t ndr_size_string_array(const char **a, uint32_t count, int flags)
+{
+ uint32_t i;
+ size_t size = 0;
+ int rawbytes = 0;
+
+ if (flags & LIBNDR_FLAG_STR_RAW8) {
+ rawbytes = 1;
+ flags &= ~LIBNDR_FLAG_STR_RAW8;
+ }
+
+ switch (flags & LIBNDR_STRING_FLAGS) {
+ case LIBNDR_FLAG_STR_NULLTERM:
+ for (i = 0; i < count; i++) {
+ size += rawbytes?strlen(a[i]) + 1:strlen_m_term(a[i]);
+ }
+ break;
+ case LIBNDR_FLAG_STR_NOTERM:
+ for (i = 0; i < count; i++) {
+ size += rawbytes?strlen(a[i]):strlen_m(a[i]);
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ return size;
+}
+
+/**
+ * Return number of elements in a string including the last (zeroed) element
+ */
+_PUBLIC_ uint32_t ndr_string_length(const void *_var, uint32_t element_size)
+{
+ uint32_t i;
+ uint8_t zero[4] = {0,0,0,0};
+ const char *var = (const char *)_var;
+
+ for (i = 0; memcmp(var+i*element_size,zero,element_size) != 0; i++);
+
+ return i+1;
+}
+
+/**
+ * @brief Get the string length including the null terminator if available.
+ *
+ * This checks the string length based on the elements. The returned number
+ * includes the terminating null byte(s) if found.
+ *
+ * @param[in] _var The string the calculate the length for.
+ *
+ * @param[in] length The length of the buffer passed by _var.
+ *
+ * @param[in] element_size The element_size of a string char in bytes.
+ *
+ * @return The length of the strings or 0.
+ */
+static uint32_t ndr_string_n_length(const void *_var,
+ size_t length,
+ uint32_t element_size)
+{
+ size_t i = 0;
+ uint8_t zero[4] = {0,0,0,0};
+ const char *var = (const char *)_var;
+ int cmp;
+
+ if (element_size > 4) {
+ return 0;
+ }
+
+ for (i = 0; i < length; i++, var += element_size) {
+ cmp = memcmp(var, zero, element_size);
+ if (cmp == 0) {
+ break;
+ }
+ }
+
+ if (i == length) {
+ return length;
+ }
+
+ return i + 1;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size)
+{
+ uint32_t i;
+ uint32_t save_offset;
+
+ save_offset = ndr->offset;
+ NDR_CHECK(ndr_pull_advance(ndr, (count - 1) * element_size));
+ NDR_PULL_NEED_BYTES(ndr, element_size);
+
+ for (i = 0; i < element_size; i++) {
+ if (ndr->data[ndr->offset+i] != 0) {
+ ndr->offset = save_offset;
+
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "String terminator not present or outside string boundaries");
+ }
+ }
+
+ ndr->offset = save_offset;
+
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_charset(struct ndr_pull *ndr, int ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset)
+{
+ size_t converted_size;
+
+ if (length == 0) {
+ *var = talloc_strdup(ndr->current_mem_ctx, "");
+ return NDR_ERR_SUCCESS;
+ }
+
+ if (NDR_BE(ndr) && chset == CH_UTF16) {
+ chset = CH_UTF16BE;
+ }
+
+ if ((byte_mul != 0) && (length > UINT32_MAX/byte_mul)) {
+ return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "length overflow");
+ }
+ NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
+
+ if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX,
+ ndr->data+ndr->offset, length*byte_mul,
+ discard_const_p(void *, var),
+ &converted_size))
+ {
+ return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion");
+ }
+ NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
+
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_charset_to_null(struct ndr_pull *ndr, int ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset)
+{
+ size_t converted_size;
+ uint32_t str_len;
+
+ if (length == 0) {
+ *var = talloc_strdup(ndr->current_mem_ctx, "");
+ return NDR_ERR_SUCCESS;
+ }
+
+ if (NDR_BE(ndr) && chset == CH_UTF16) {
+ chset = CH_UTF16BE;
+ }
+
+ NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
+
+ str_len = ndr_string_n_length(ndr->data+ndr->offset, length, byte_mul);
+ if (str_len == 0) {
+ return ndr_pull_error(ndr, NDR_ERR_LENGTH,
+ "Invalid length");
+ }
+
+ if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX,
+ ndr->data+ndr->offset, str_len*byte_mul,
+ discard_const_p(void *, var),
+ &converted_size))
+ {
+ return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion");
+ }
+ NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
+
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_charset(struct ndr_push *ndr, int ndr_flags, const char *var, uint32_t length, uint8_t byte_mul, charset_t chset)
+{
+ size_t required;
+
+ if (NDR_BE(ndr) && chset == CH_UTF16) {
+ chset = CH_UTF16BE;
+ }
+
+ if ((byte_mul != 0) && (length > SIZE_MAX/byte_mul)) {
+ return ndr_push_error(ndr, NDR_ERR_LENGTH, "length overflow");
+ }
+ required = byte_mul * length;
+
+ NDR_PUSH_NEED_BYTES(ndr, required);
+
+ if (required) {
+ size_t size = 0;
+
+ if (var == NULL) {
+ return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
+ }
+
+ if (!convert_string(CH_UNIX, chset,
+ var, strlen(var),
+ ndr->data+ndr->offset, required, &size)) {
+ return ndr_push_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion");
+ }
+
+ /* Make sure the remaining part of the string is filled with zeroes */
+ if (size < required) {
+ memset(ndr->data+ndr->offset+size, 0, required-size);
+ }
+ }
+
+ ndr->offset += required;
+
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_charset_to_null(struct ndr_push *ndr, int ndr_flags, const char *var, uint32_t length, uint8_t byte_mul, charset_t chset)
+{
+ const char *str = var;
+
+ if (str == NULL) {
+ str = "\0"; /* i.e. two zero bytes, for UTF16 null word. */
+ length = 1;
+ }
+
+ return ndr_push_charset(ndr, ndr_flags, str, length, byte_mul, chset);
+}
+
+/* Return number of elements in a string in the specified charset */
+_PUBLIC_ uint32_t ndr_charset_length(const void *var, charset_t chset)
+{
+ switch (chset) {
+ /* case CH_UTF16: this has the same value as CH_UTF16LE */
+ case CH_UTF16LE:
+ case CH_UTF16BE:
+ case CH_UTF16MUNGED:
+ case CH_UTF8:
+ return strlen_m_ext_term((const char *)var, CH_UNIX, chset);
+ case CH_DOS:
+ case CH_UNIX:
+ return strlen((const char *)var)+1;
+ }
+
+ /* Fallback, this should never happen */
+ return strlen((const char *)var)+1;
+}
diff --git a/librpc/ndr/ndr_svcctl.c b/librpc/ndr/ndr_svcctl.c
new file mode 100644
index 0000000..83e581b
--- /dev/null
+++ b/librpc/ndr/ndr_svcctl.c
@@ -0,0 +1,52 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling special svcctl types
+
+ Copyright (C) Guenther Deschner 2009
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_svcctl.h"
+
+_PUBLIC_ enum ndr_err_code ndr_push_ENUM_SERVICE_STATUSW_array(struct ndr_push *ndr, uint32_t count, struct ENUM_SERVICE_STATUSW *r)
+{
+ uint32_t cntr_array_1;
+
+ for (cntr_array_1 = 0; cntr_array_1 < count; cntr_array_1++) {
+ NDR_CHECK(ndr_push_ENUM_SERVICE_STATUSW(ndr, NDR_SCALARS, &r[cntr_array_1]));
+ }
+ for (cntr_array_1 = 0; cntr_array_1 < count; cntr_array_1++) {
+ NDR_CHECK(ndr_push_ENUM_SERVICE_STATUSW(ndr, NDR_BUFFERS, &r[cntr_array_1]));
+ }
+
+ return NDR_ERR_SUCCESS;
+
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_ENUM_SERVICE_STATUSW_array(struct ndr_pull *ndr, uint32_t count, struct ENUM_SERVICE_STATUSW *r)
+{
+ uint32_t cntr_array_1;
+
+ for (cntr_array_1 = 0; cntr_array_1 < count; cntr_array_1++) {
+ NDR_CHECK(ndr_pull_ENUM_SERVICE_STATUSW(ndr, NDR_SCALARS, &r[cntr_array_1]));
+ }
+ for (cntr_array_1 = 0; cntr_array_1 < count; cntr_array_1++) {
+ NDR_CHECK(ndr_pull_ENUM_SERVICE_STATUSW(ndr, NDR_BUFFERS, &r[cntr_array_1]));
+ }
+
+ return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_svcctl.h b/librpc/ndr/ndr_svcctl.h
new file mode 100644
index 0000000..e11ff69
--- /dev/null
+++ b/librpc/ndr/ndr_svcctl.h
@@ -0,0 +1,24 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling special svcctl types
+
+ Copyright (C) Guenther Deschner 2009
+
+ 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/>.
+*/
+
+_PUBLIC_ enum ndr_err_code ndr_push_ENUM_SERVICE_STATUSW_array(struct ndr_push *ndr, uint32_t count, struct ENUM_SERVICE_STATUSW *r);
+_PUBLIC_ enum ndr_err_code ndr_pull_ENUM_SERVICE_STATUSW_array(struct ndr_pull *ndr, uint32_t count, struct ENUM_SERVICE_STATUSW *r);
+
diff --git a/librpc/ndr/ndr_table.c b/librpc/ndr/ndr_table.c
new file mode 100644
index 0000000..bc44fd3
--- /dev/null
+++ b/librpc/ndr/ndr_table.c
@@ -0,0 +1,182 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ dcerpc utility functions
+
+ Copyright (C) Andrew Tridgell 2003
+ Copyright (C) Jelmer Vernooij 2004
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "../lib/util/dlinklist.h"
+#include "librpc/ndr/libndr.h"
+#include "librpc/ndr/ndr_table.h"
+#undef strcasecmp
+
+static struct ndr_interface_list *ndr_interfaces;
+
+/*
+ register a ndr interface table
+*/
+NTSTATUS ndr_table_register(const struct ndr_interface_table *table)
+{
+ struct ndr_interface_list *l;
+
+ for (l = ndr_interfaces; l; l = l->next) {
+ /*
+ * If no GUID is supplied, use the name to determine
+ * uniquness.
+ */
+ if (GUID_all_zero(&table->syntax_id.uuid)) {
+ if (strcmp(table->name,
+ l->table->name) != 0) {
+ continue;
+ }
+ DBG_ERR("Attempt to register interface %s which has the "
+ "same name as already registered interface\n",
+ table->name);
+ } else {
+ if (!GUID_equal(&table->syntax_id.uuid,
+ &l->table->syntax_id.uuid)) {
+ continue;
+ }
+ DBG_ERR("Attempt to register interface %s which has the "
+ "same UUID as already registered interface %s\n",
+ table->name, l->table->name);
+ }
+ return NT_STATUS_OBJECT_NAME_COLLISION;
+ }
+
+ /*
+ * This is a singleton instance guarenteed
+ * by the above check to be only added once
+ * into the list so we can allocate off the NULL
+ * context. We never want this to be freed
+ * until process shutdown. If needed we could
+ * add a deregister function that walks and
+ * frees the list.
+ */
+
+ l = talloc(NULL, struct ndr_interface_list);
+ l->table = table;
+
+ DLIST_ADD(ndr_interfaces, l);
+
+ return NT_STATUS_OK;
+}
+
+/*
+ find the pipe name for a local IDL interface
+*/
+const char *ndr_interface_name(const struct GUID *uuid, uint32_t if_version)
+{
+ const struct ndr_interface_list *l;
+ for (l=ndr_table_list();l;l=l->next) {
+ if (GUID_equal(&l->table->syntax_id.uuid, uuid) &&
+ l->table->syntax_id.if_version == if_version) {
+ return l->table->name;
+ }
+ }
+ return "UNKNOWN";
+}
+
+/*
+ find the number of calls defined by local IDL
+*/
+int ndr_interface_num_calls(const struct GUID *uuid, uint32_t if_version)
+{
+ const struct ndr_interface_list *l;
+ for (l=ndr_table_list();l;l=l->next){
+ if (GUID_equal(&l->table->syntax_id.uuid, uuid) &&
+ l->table->syntax_id.if_version == if_version) {
+ return l->table->num_calls;
+ }
+ }
+ return -1;
+}
+
+
+/*
+ find a dcerpc interface by name
+*/
+const struct ndr_interface_table *ndr_table_by_name(const char *name)
+{
+ const struct ndr_interface_list *l;
+ for (l=ndr_table_list();l;l=l->next) {
+ if (strcasecmp(l->table->name, name) == 0) {
+ return l->table;
+ }
+ }
+ return NULL;
+}
+
+/*
+ find a dcerpc interface by syntax
+*/
+const struct ndr_interface_table *ndr_table_by_syntax(const struct ndr_syntax_id *syntax)
+{
+ const struct ndr_interface_list *l;
+ if (GUID_all_zero(&syntax->uuid)) {
+ /* These are not unique */
+ return NULL;
+ }
+ for (l=ndr_table_list();l;l=l->next) {
+ if (ndr_syntax_id_equal(&l->table->syntax_id, syntax)) {
+ return l->table;
+ }
+ }
+ return NULL;
+}
+
+/*
+ find a dcerpc interface by uuid
+*/
+const struct ndr_interface_table *ndr_table_by_uuid(const struct GUID *uuid)
+{
+ const struct ndr_interface_list *l;
+ if (GUID_all_zero(uuid)) {
+ /* These are not unique */
+ return NULL;
+ }
+ for (l=ndr_table_list();l;l=l->next) {
+ if (GUID_equal(&l->table->syntax_id.uuid, uuid)) {
+ return l->table;
+ }
+ }
+ return NULL;
+}
+
+/*
+ return the list of registered dcerpc_pipes
+*/
+const struct ndr_interface_list *ndr_table_list(void)
+{
+ ndr_table_init();
+ return ndr_interfaces;
+}
+
+
+NTSTATUS ndr_table_init(void)
+{
+ static bool initialized = false;
+
+ if (initialized) return NT_STATUS_OK;
+ initialized = true;
+
+ ndr_table_register_builtin_tables();
+
+ return NT_STATUS_OK;
+}
diff --git a/librpc/ndr/ndr_table.h b/librpc/ndr/ndr_table.h
new file mode 100644
index 0000000..1f6858a
--- /dev/null
+++ b/librpc/ndr/ndr_table.h
@@ -0,0 +1,37 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ dcerpc utility functions
+
+ Copyright (C) Andrew Tridgell 2003
+ Copyright (C) Jelmer Vernooij 2004
+
+ 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 _NDR_TABLE_PROTO_H_
+#define _NDR_TABLE_PROTO_H_
+
+NTSTATUS ndr_table_register(const struct ndr_interface_table *table);
+const char *ndr_interface_name(const struct GUID *uuid, uint32_t if_version);
+int ndr_interface_num_calls(const struct GUID *uuid, uint32_t if_version);
+const struct ndr_interface_table *ndr_table_by_name(const char *name);
+const struct ndr_interface_table *ndr_table_by_syntax(const struct ndr_syntax_id *syntax);
+const struct ndr_interface_table *ndr_table_by_uuid(const struct GUID *uuid);
+const struct ndr_interface_list *ndr_table_list(void);
+NTSTATUS ndr_table_init(void);
+NTSTATUS ndr_table_register_builtin_tables(void);
+
+#endif /* _NDR_TABLE_PROTO_H_ */
+
diff --git a/librpc/ndr/ndr_witness.c b/librpc/ndr/ndr_witness.c
new file mode 100644
index 0000000..288e640
--- /dev/null
+++ b/librpc/ndr/ndr_witness.c
@@ -0,0 +1,110 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling witness structures
+
+ Copyright (C) Guenther Deschner 2015
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_witness.h"
+
+_PUBLIC_ enum ndr_err_code ndr_push_witness_notifyResponse(struct ndr_push *ndr, int ndr_flags, const struct witness_notifyResponse *r)
+{
+ uint32_t cntr_messages_0;
+ {
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX);
+ NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_witness_notifyResponse_type(ndr, NDR_SCALARS, r->type));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_size_witness_notifyResponse(r, ndr->flags) - 20));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->num));
+ NDR_CHECK(ndr_push_unique_ptr(ndr, r->messages));
+ if (r->messages) {
+ uint32_t _flags_save_witness_notifyResponse_message = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
+ {
+ struct ndr_push *_ndr_messages;
+ NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_messages, 4, ndr_size_witness_notifyResponse(r, ndr->flags) - 20));
+ for (cntr_messages_0 = 0; cntr_messages_0 < (r->num); cntr_messages_0++) {
+ NDR_CHECK(ndr_push_set_switch_value(_ndr_messages, &r->messages[cntr_messages_0], r->type));
+ NDR_CHECK(ndr_push_witness_notifyResponse_message(_ndr_messages, NDR_SCALARS, &r->messages[cntr_messages_0]));
+ }
+ NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_messages, 4, ndr_size_witness_notifyResponse(r, ndr->flags) - 20));
+ }
+ ndr->flags = _flags_save_witness_notifyResponse_message;
+ }
+ NDR_CHECK(ndr_push_trailer_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ ndr->flags = _flags_save_STRUCT;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_witness_notifyResponse(struct ndr_pull *ndr, int ndr_flags, struct witness_notifyResponse *r)
+{
+ uint32_t _flags_save_STRUCT = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX);
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ NDR_CHECK(ndr_pull_witness_notifyResponse_type(ndr, NDR_SCALARS, &r->type));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->length));
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->num));
+ {
+ uint32_t _flags_save_witness_notifyResponse_message = ndr->flags;
+ uint32_t _ptr_messages;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
+ NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_messages));
+ if (_ptr_messages) {
+ NDR_PULL_ALLOC(ndr, r->messages);
+ } else {
+ r->messages = NULL;
+ }
+ if (r->messages) {
+ uint32_t size_messages_0 = 0;
+ uint32_t cntr_messages_0;
+ TALLOC_CTX *_mem_save_messages_0;
+
+ size_messages_0 = r->num;
+ NDR_PULL_ALLOC_N(ndr, r->messages, size_messages_0);
+ _mem_save_messages_0 = NDR_PULL_GET_MEM_CTX(ndr);
+ NDR_PULL_SET_MEM_CTX(ndr, r->messages, 0);
+ {
+ struct ndr_pull *_ndr_messages;
+ NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_messages, 4, r->length));
+ for (cntr_messages_0 = 0; cntr_messages_0 < (size_messages_0); cntr_messages_0++) {
+ NDR_CHECK(ndr_pull_set_switch_value(_ndr_messages, &r->messages[cntr_messages_0], r->type));
+ NDR_CHECK(ndr_pull_witness_notifyResponse_message(_ndr_messages, NDR_SCALARS, &r->messages[cntr_messages_0]));
+ }
+ NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_messages, 4, r->length));
+ }
+ NDR_PULL_SET_MEM_CTX(ndr, _mem_save_messages_0, 0);
+ }
+ ndr->flags = _flags_save_witness_notifyResponse_message;
+ }
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 4));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ ndr->flags = _flags_save_STRUCT;
+
+ return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_witness.h b/librpc/ndr/ndr_witness.h
new file mode 100644
index 0000000..e4dd3df
--- /dev/null
+++ b/librpc/ndr/ndr_witness.h
@@ -0,0 +1,23 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling witness structures
+
+ Copyright (C) Guenther Deschner 2015
+
+ 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/>.
+*/
+
+_PUBLIC_ enum ndr_err_code ndr_push_witness_notifyResponse(struct ndr_push *ndr, int ndr_flags, const struct witness_notifyResponse *r);
+_PUBLIC_ enum ndr_err_code ndr_pull_witness_notifyResponse(struct ndr_pull *ndr, int ndr_flags, struct witness_notifyResponse *r);
diff --git a/librpc/ndr/ndr_wmi.c b/librpc/ndr/ndr_wmi.c
new file mode 100644
index 0000000..4748888
--- /dev/null
+++ b/librpc/ndr/ndr_wmi.c
@@ -0,0 +1,60 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling DCOM string arrays
+
+ Copyright (C) Jelmer Vernooij 2004
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+//#define NDR_CHECK_DEBUG
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_dcom.h"
+#include "librpc/gen_ndr/ndr_wmi.h"
+#include "librpc/ndr/ndr_wmi.h"
+
+// Just for debugging
+int NDR_CHECK_depth = 0;
+int NDR_CHECK_shift = 0x18;
+
+enum ndr_err_code ndr_push_BSTR(struct ndr_push *ndr, int ndr_flags, const struct BSTR *r)
+{
+ uint32_t len;
+ uint32_t flags;
+ enum ndr_err_code status;
+ len = strlen(r->data);
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0x72657355));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, len));
+ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 2*len));
+ flags = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NOTERM | LIBNDR_FLAG_STR_SIZE4);
+ status = ndr_push_string(ndr, NDR_SCALARS, r->data);
+ ndr->flags = flags;
+ return status;
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_BSTR(struct ndr_pull *ndr, int ndr_flags, struct BSTR *r)
+{
+ return NDR_ERR_BAD_SWITCH;
+}
+
+void ndr_print_BSTR(struct ndr_print *ndr, const char *name, const struct BSTR *r)
+{
+ ndr->print(ndr, "%-25s: BSTR(\"%s\")", name, r->data);
+}
diff --git a/librpc/ndr/ndr_wmi.h b/librpc/ndr/ndr_wmi.h
new file mode 100644
index 0000000..62d2c53
--- /dev/null
+++ b/librpc/ndr/ndr_wmi.h
@@ -0,0 +1,24 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ routines for marshalling/unmarshalling DCOM string arrays
+
+ Copyright (C) Jelmer Vernooij 2004
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+enum ndr_err_code ndr_push_BSTR(struct ndr_push *ndr, int ndr_flags, const struct BSTR *r);
+enum ndr_err_code ndr_pull_BSTR(struct ndr_pull *ndr, int ndr_flags, struct BSTR *r);
diff --git a/librpc/ndr/ndr_xattr.c b/librpc/ndr/ndr_xattr.c
new file mode 100644
index 0000000..930f510
--- /dev/null
+++ b/librpc/ndr/ndr_xattr.c
@@ -0,0 +1,148 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ helper routines for XATTR marshalling
+
+ Copyright (C) Stefan (metze) Metzmacher 2009
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_xattr.h"
+
+static char *ndr_compat_xattr_attrib_hex(TALLOC_CTX *mem_ctx,
+ const struct xattr_DOSATTRIB *r)
+{
+ char *attrib_hex = NULL;
+
+ switch (r->version) {
+ case 0xFFFF:
+ attrib_hex = talloc_asprintf(mem_ctx, "0x%x",
+ r->info.compatinfoFFFF.attrib);
+ break;
+ case 1:
+ attrib_hex = talloc_asprintf(mem_ctx, "0x%x",
+ r->info.info1.attrib);
+ break;
+ case 2:
+ attrib_hex = talloc_asprintf(mem_ctx, "0x%x",
+ r->info.oldinfo2.attrib);
+ break;
+ case 3:
+ if (!(r->info.info3.valid_flags & XATTR_DOSINFO_ATTRIB)) {
+ attrib_hex = talloc_strdup(mem_ctx, "");
+ break;
+ }
+ attrib_hex = talloc_asprintf(mem_ctx, "0x%x",
+ r->info.info3.attrib);
+ break;
+ default:
+ attrib_hex = talloc_strdup(mem_ctx, "");
+ break;
+ }
+
+ return attrib_hex;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_xattr_DOSATTRIB(struct ndr_push *ndr,
+ int ndr_flags,
+ const struct xattr_DOSATTRIB *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ char *attrib_hex = NULL;
+
+ attrib_hex = ndr_compat_xattr_attrib_hex(ndr, r);
+ NDR_ERR_HAVE_NO_MEMORY(attrib_hex);
+
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, attrib_hex));
+ ndr->flags = _flags_save_string;
+ }
+ if (r->version == 0xFFFF) {
+ return NDR_ERR_SUCCESS;
+ }
+ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->version));
+ NDR_CHECK(ndr_push_set_switch_value(ndr, &r->info, r->version));
+ NDR_CHECK(ndr_push_xattr_DosInfo(ndr, NDR_SCALARS, &r->info));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_xattr_DOSATTRIB(struct ndr_pull *ndr, int ndr_flags, struct xattr_DOSATTRIB *r)
+{
+ if (ndr_flags & NDR_SCALARS) {
+ NDR_CHECK(ndr_pull_align(ndr, 4));
+ {
+ uint32_t _flags_save_string = ndr->flags;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM);
+ NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->attrib_hex));
+ ndr->flags = _flags_save_string;
+ }
+ if (ndr->offset >= ndr->data_size) {
+ unsigned int dosattr;
+ int ret;
+
+ if (r->attrib_hex[0] != '0') {
+
+ }
+ if (r->attrib_hex[1] != 'x') {
+
+ }
+ ret = sscanf(r->attrib_hex, "%x", &dosattr);
+ if (ret != 1) {
+ }
+ r->version = 0xFFFF;
+ r->info.compatinfoFFFF.attrib = dosattr;
+ return NDR_ERR_SUCCESS;
+ }
+ NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->version));
+ if (r->version == 0xFFFF) {
+ return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH,
+ "ndr_pull_xattr_DOSATTRIB: "
+ "invalid level 0x%02X",
+ r->version);
+ }
+ NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->info, r->version));
+ NDR_CHECK(ndr_pull_xattr_DosInfo(ndr, NDR_SCALARS, &r->info));
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_xattr_DOSATTRIB(struct ndr_print *ndr, const char *name, const struct xattr_DOSATTRIB *r)
+{
+ char *attrib_hex;
+
+ ndr_print_struct(ndr, name, "xattr_DOSATTRIB");
+ ndr->depth++;
+
+ if (ndr->flags & LIBNDR_PRINT_SET_VALUES) {
+ attrib_hex = ndr_compat_xattr_attrib_hex(ndr, r);
+ } else {
+ attrib_hex = talloc_strdup(ndr, r->attrib_hex);
+ }
+ ndr_print_string(ndr, "attrib_hex", attrib_hex);
+
+ ndr_print_uint16(ndr, "version", r->version);
+ ndr_print_set_switch_value(ndr, &r->info, r->version);
+ ndr_print_xattr_DosInfo(ndr, "info", &r->info);
+ ndr->depth--;
+}
diff --git a/librpc/ndr/ndr_xattr.h b/librpc/ndr/ndr_xattr.h
new file mode 100644
index 0000000..bdc530a
--- /dev/null
+++ b/librpc/ndr/ndr_xattr.h
@@ -0,0 +1,37 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ helper routines for XATTR marshalling
+
+ Copyright (C) Stefan (metze) Metzmacher 2009
+
+ 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_XATTR_H
+#define _LIBRPC_NDR_NDR_XATTR_H
+
+_PUBLIC_ enum ndr_err_code ndr_push_xattr_DOSATTRIB(struct ndr_push *ndr,
+ int ndr_flags,
+ const struct xattr_DOSATTRIB *r);
+
+_PUBLIC_ enum ndr_err_code ndr_pull_xattr_DOSATTRIB(struct ndr_pull *ndr,
+ int ndr_flags,
+ struct xattr_DOSATTRIB *r);
+
+_PUBLIC_ void ndr_print_xattr_DOSATTRIB(struct ndr_print *ndr,
+ const char *name,
+ const struct xattr_DOSATTRIB *r);
+
+#endif /* _LIBRPC_NDR_NDR_XATTR_H */
diff --git a/librpc/ndr/util.c b/librpc/ndr/util.c
new file mode 100644
index 0000000..0eb7eba
--- /dev/null
+++ b/librpc/ndr/util.c
@@ -0,0 +1,36 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ libndr interface
+
+ Copyright (C) Andrew Tridgell 2003
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "../librpc/ndr/libndr.h"
+#include "system/network.h"
+#include "lib/util/util_net.h"
+
+_PUBLIC_ void ndr_print_sockaddr_storage(struct ndr_print *ndr, const char *name, const struct sockaddr_storage *ss)
+{
+ char addr[INET6_ADDRSTRLEN];
+ ndr->print(ndr, "%-25s: %s", name, print_sockaddr(addr, sizeof(addr), ss));
+}
+
+_PUBLIC_ void ndr_zero_memory(void *ptr, size_t len)
+{
+ memset_s(ptr, len, 0, len);
+}
diff --git a/librpc/ndr/uuid.c b/librpc/ndr/uuid.c
new file mode 100644
index 0000000..6a8d31e
--- /dev/null
+++ b/librpc/ndr/uuid.c
@@ -0,0 +1,258 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ UUID/GUID functions
+
+ Copyright (C) Theodore Ts'o 1996, 1997,
+ Copyright (C) Jim McDonough 2002.
+ Copyright (C) Andrew Tridgell 2003.
+
+ 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/>.
+*/
+
+#include "replace.h"
+#include "lib/util/samba_util.h"
+#include "lib/util/genrand.h"
+#include "librpc/ndr/libndr.h"
+#include "librpc/gen_ndr/ndr_misc.h"
+#include "lib/util/util_str_hex.h"
+
+_PUBLIC_ NTSTATUS GUID_to_ndr_buf(
+ const struct GUID *guid, struct GUID_ndr_buf *buf)
+{
+ DATA_BLOB b = { .data = buf->buf, .length = sizeof(buf->buf), };
+ enum ndr_err_code ndr_err;
+
+ ndr_err = ndr_push_struct_into_fixed_blob(
+ &b, guid, (ndr_push_flags_fn_t)ndr_push_GUID);
+ return ndr_map_error2ntstatus(ndr_err);
+}
+
+/**
+ build a NDR blob from a GUID
+*/
+_PUBLIC_ NTSTATUS GUID_to_ndr_blob(const struct GUID *guid, TALLOC_CTX *mem_ctx, DATA_BLOB *b)
+{
+ struct GUID_ndr_buf buf = { .buf = {0}, };
+ NTSTATUS status;
+
+ status = GUID_to_ndr_buf(guid, &buf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ *b = data_blob_talloc(mem_ctx, buf.buf, sizeof(buf.buf));
+ if (b->data == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ return NT_STATUS_OK;
+}
+
+
+/**
+ build a GUID from a NDR data blob
+*/
+_PUBLIC_ NTSTATUS GUID_from_ndr_blob(const DATA_BLOB *b, struct GUID *guid)
+{
+ enum ndr_err_code ndr_err =
+ ndr_pull_struct_blob_all_noalloc(b, guid,
+ (ndr_pull_flags_fn_t)ndr_pull_GUID);
+ return ndr_map_error2ntstatus(ndr_err);
+}
+
+
+/**
+ build a GUID from a string
+*/
+_PUBLIC_ NTSTATUS GUID_from_data_blob(const DATA_BLOB *s, struct GUID *guid)
+{
+ bool ok;
+
+ if (s->data == NULL) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (s->length == 36) {
+ ok = parse_guid_string((char *)s->data, guid);
+ return ok ? NT_STATUS_OK : NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (s->length == 38) {
+ if (s->data[0] != '{' || s->data[37] != '}') {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ ok = parse_guid_string((char *)s->data + 1, guid);
+ return ok ? NT_STATUS_OK : NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (s->length == 32) {
+ uint8_t buf16[16] = {0};
+ DATA_BLOB blob16 = { .data = buf16, .length = sizeof(buf16) };
+ size_t rlen = strhex_to_str((char *)blob16.data, blob16.length,
+ (const char *)s->data, s->length);
+ if (rlen != blob16.length) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ return GUID_from_ndr_blob(&blob16, guid);
+ }
+
+ if (s->length == 16) {
+ return GUID_from_ndr_blob(s, guid);
+ }
+
+ return NT_STATUS_INVALID_PARAMETER;
+}
+
+/**
+ build a GUID from a string
+*/
+_PUBLIC_ NTSTATUS GUID_from_string(const char *s, struct GUID *guid)
+{
+ DATA_BLOB blob = data_blob_string_const(s);
+ return GUID_from_data_blob(&blob, guid);
+}
+
+/**
+ * generate a random GUID
+ */
+_PUBLIC_ struct GUID GUID_random(void)
+{
+ struct GUID guid;
+
+ generate_random_buffer((uint8_t *)&guid, sizeof(guid));
+ guid.clock_seq[0] = (guid.clock_seq[0] & 0x3F) | 0x80;
+ guid.time_hi_and_version = (guid.time_hi_and_version & 0x0FFF) | 0x4000;
+
+ return guid;
+}
+
+/**
+ * generate an empty GUID
+ */
+_PUBLIC_ struct GUID GUID_zero(void)
+{
+ return (struct GUID) { .time_low = 0 };
+}
+
+_PUBLIC_ bool GUID_all_zero(const struct GUID *u)
+{
+ if (u->time_low != 0 ||
+ u->time_mid != 0 ||
+ u->time_hi_and_version != 0 ||
+ u->clock_seq[0] != 0 ||
+ u->clock_seq[1] != 0 ||
+ !all_zero(u->node, 6)) {
+ return false;
+ }
+ return true;
+}
+
+_PUBLIC_ bool GUID_equal(const struct GUID *u1, const struct GUID *u2)
+{
+ return (GUID_compare(u1, u2) == 0);
+}
+
+_PUBLIC_ int GUID_compare(const struct GUID *u1, const struct GUID *u2)
+{
+ if (u1->time_low != u2->time_low) {
+ return u1->time_low > u2->time_low ? 1 : -1;
+ }
+
+ if (u1->time_mid != u2->time_mid) {
+ return u1->time_mid > u2->time_mid ? 1 : -1;
+ }
+
+ if (u1->time_hi_and_version != u2->time_hi_and_version) {
+ return u1->time_hi_and_version > u2->time_hi_and_version ? 1 : -1;
+ }
+
+ if (u1->clock_seq[0] != u2->clock_seq[0]) {
+ return u1->clock_seq[0] > u2->clock_seq[0] ? 1 : -1;
+ }
+
+ if (u1->clock_seq[1] != u2->clock_seq[1]) {
+ return u1->clock_seq[1] > u2->clock_seq[1] ? 1 : -1;
+ }
+
+ return memcmp(u1->node, u2->node, 6);
+}
+
+/**
+ its useful to be able to display these in debugging messages
+*/
+_PUBLIC_ char *GUID_string(TALLOC_CTX *mem_ctx, const struct GUID *guid)
+{
+ struct GUID_txt_buf buf;
+ return talloc_strdup(mem_ctx, GUID_buf_string(guid, &buf));
+}
+
+/**
+ * Does the same without allocating memory, using the structure buffer.
+ * Useful for debug messages, so that you do not have to talloc_free the result
+ */
+_PUBLIC_ char* GUID_buf_string(const struct GUID *guid,
+ struct GUID_txt_buf *dst)
+{
+ if (!guid) {
+ return NULL;
+ }
+ snprintf(dst->buf, sizeof(dst->buf),
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ guid->time_low, guid->time_mid,
+ guid->time_hi_and_version,
+ guid->clock_seq[0],
+ guid->clock_seq[1],
+ guid->node[0], guid->node[1],
+ guid->node[2], guid->node[3],
+ guid->node[4], guid->node[5]);
+ return dst->buf;
+}
+
+_PUBLIC_ char *GUID_string2(TALLOC_CTX *mem_ctx, const struct GUID *guid)
+{
+ struct GUID_txt_buf buf;
+ char *ret = talloc_asprintf(
+ mem_ctx, "{%s}", GUID_buf_string(guid, &buf));
+ return ret;
+}
+
+_PUBLIC_ char *GUID_hexstring(TALLOC_CTX *mem_ctx, const struct GUID *guid)
+{
+ char *ret = NULL;
+ DATA_BLOB guid_blob = { .data = NULL };
+ NTSTATUS status;
+
+ status = GUID_to_ndr_blob(guid, mem_ctx, &guid_blob);
+ if (NT_STATUS_IS_OK(status)) {
+ ret = data_blob_hex_string_upper(mem_ctx, &guid_blob);
+ }
+ TALLOC_FREE(guid_blob.data);
+ return ret;
+}
+
+_PUBLIC_ bool ndr_policy_handle_empty(const struct policy_handle *h)
+{
+ return (h->handle_type == 0 && GUID_all_zero(&h->uuid));
+}
+
+_PUBLIC_ bool ndr_policy_handle_equal(const struct policy_handle *hnd1,
+ const struct policy_handle *hnd2)
+{
+ if (!hnd1 || !hnd2) {
+ return false;
+ }
+
+ return (memcmp(hnd1, hnd2, sizeof(*hnd1)) == 0);
+}
diff --git a/librpc/ndr_krb5pac.pc.in b/librpc/ndr_krb5pac.pc.in
new file mode 100644
index 0000000..581b7e5
--- /dev/null
+++ b/librpc/ndr_krb5pac.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ndr-krb5pac
+Description: NDR marshallers for the KRB5 PAC formats
+Requires: ndr ndr_standard
+Version: @PACKAGE_VERSION@
+Libs: @LIB_RPATH@ -L${libdir} -lndr-krb5pac
+Cflags: -I${includedir} -DHAVE_IMMEDIATE_STRUCTURES=1 -D_GNU_SOURCE=1
diff --git a/librpc/ndr_nbt.pc.in b/librpc/ndr_nbt.pc.in
new file mode 100644
index 0000000..2083e2d
--- /dev/null
+++ b/librpc/ndr_nbt.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ndr-nbt
+Description: NDR marshallers for nbt formats
+Requires: ndr
+Version: @PACKAGE_VERSION@
+Libs: @LIB_RPATH@ -L${libdir} -lndr-nbt
+Cflags: -I${includedir} -DHAVE_IMMEDIATE_STRUCTURES=1 -D_GNU_SOURCE=1
diff --git a/librpc/ndr_standard.pc.in b/librpc/ndr_standard.pc.in
new file mode 100644
index 0000000..97687ba
--- /dev/null
+++ b/librpc/ndr_standard.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ndr-standard
+Description: NDR marshallers for the standard set of DCE/RPC interfaces
+Requires: ndr
+Version: @PACKAGE_VERSION@
+Libs: @LIB_RPATH@ -L${libdir} -lndr-standard
+Cflags: -I${includedir} -DHAVE_IMMEDIATE_STRUCTURES=1 -D_GNU_SOURCE=1