summaryrefslogtreecommitdiff
path: root/librpc/ndr
diff options
context:
space:
mode:
Diffstat (limited to 'librpc/ndr')
-rw-r--r--librpc/ndr/libndr.h37
-rw-r--r--librpc/ndr/ndr.c17
-rw-r--r--librpc/ndr/ndr_basic.c128
-rw-r--r--librpc/ndr/ndr_sec_helper.c4
4 files changed, 159 insertions, 27 deletions
diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h
index d01b68ef51..03b4362b37 100644
--- a/librpc/ndr/libndr.h
+++ b/librpc/ndr/libndr.h
@@ -141,6 +141,8 @@ struct ndr_print {
/* used to check if alignment padding is zero */
#define LIBNDR_FLAG_PAD_CHECK (1<<28)
+#define LIBNDR_FLAG_NDR64 (1<<29)
+
/* set if an object uuid will be present */
#define LIBNDR_FLAG_OBJECT_PRESENT (1<<30)
@@ -163,7 +165,7 @@ struct ndr_print {
#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_BE(ndr) (((ndr)->flags & (LIBNDR_FLAG_BIGENDIAN|LIBNDR_FLAG_LITTLE_ENDIAN)) == LIBNDR_FLAG_BIGENDIAN)
+#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,
@@ -183,7 +185,8 @@ enum ndr_err_code {
NDR_ERR_TOKEN,
NDR_ERR_IPV4ADDRESS,
NDR_ERR_INVALID_POINTER,
- NDR_ERR_UNREAD_BYTES
+ NDR_ERR_UNREAD_BYTES,
+ NDR_ERR_NDR64
};
#define NDR_ERR_CODE_IS_SUCCESS(x) (x == NDR_ERR_SUCCESS)
@@ -214,7 +217,7 @@ enum ndr_compression_alg {
#define NDR_SET_VALUES 4
#define NDR_PULL_NEED_BYTES(ndr, n) do { \
- if ((n) > ndr->data_size || ndr->offset + (n) > ndr->data_size) { \
+ if (unlikely((n) > ndr->data_size || ndr->offset + (n) > ndr->data_size)) { \
return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "Pull bytes %u (%s)", (unsigned)n, __location__); \
} \
} while(0)
@@ -224,13 +227,13 @@ enum ndr_compression_alg {
#define NDR_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
#define NDR_PULL_ALIGN(ndr, n) do { \
- if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) { \
- if (ndr->flags & LIBNDR_FLAG_PAD_CHECK) { \
+ if (unlikely(!(ndr->flags & LIBNDR_FLAG_NOALIGN))) { \
+ if (unlikely(ndr->flags & LIBNDR_FLAG_PAD_CHECK)) { \
ndr_check_padding(ndr, n); \
} \
ndr->offset = (ndr->offset + (n-1)) & ~(n-1); \
} \
- if (ndr->offset > ndr->data_size) { \
+ if (unlikely(ndr->offset > ndr->data_size)) { \
return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "Pull align %u", (unsigned)n); \
} \
} while(0)
@@ -238,7 +241,7 @@ enum ndr_compression_alg {
#define NDR_PUSH_NEED_BYTES(ndr, n) NDR_CHECK(ndr_push_expand(ndr, n))
#define NDR_PUSH_ALIGN(ndr, n) do { \
- if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) { \
+ 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)); \
} \
@@ -249,7 +252,7 @@ enum ndr_compression_alg {
#define NDR_CHECK(call) do { \
enum ndr_err_code _status; \
_status = call; \
- if (!NDR_ERR_CODE_IS_SUCCESS(_status)) { \
+ if (unlikely(!NDR_ERR_CODE_IS_SUCCESS(_status))) { \
return _status; \
} \
} while (0)
@@ -258,7 +261,7 @@ enum ndr_compression_alg {
#define NDR_CHECK_FREE(call) do { \
enum ndr_err_code _status; \
_status = call; \
- if (!NDR_ERR_CODE_IS_SUCCESS(_status)) { \
+ if (unlikely(!NDR_ERR_CODE_IS_SUCCESS(_status))) { \
talloc_free(ndr); \
return _status; \
} \
@@ -287,24 +290,24 @@ enum ndr_compression_alg {
#define NDR_PULL_ALLOC(ndr, s) do { \
_NDR_PULL_FIX_CURRENT_MEM_CTX(ndr);\
(s) = talloc_ptrtype(ndr->current_mem_ctx, (s)); \
- if (!(s)) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Alloc %s failed: %s\n", # s, __location__); \
+ 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 (!(s)) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "Alloc %u * %s failed: %s\n", (unsigned)n, # s, __location__); \
+ 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 (!(s)) return ndr_push_error(ndr, NDR_ERR_ALLOC, "push alloc %u failed: %s\n", (unsigned)size, __location__); \
+ 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 (!(s)) return ndr_push_error(ndr, NDR_ERR_ALLOC, "push alloc %s failed: %s\n", # s, __location__); \
+ if (unlikely(!(s))) return ndr_push_error(ndr, NDR_ERR_ALLOC, "push alloc %s failed: %s\n", # s, __location__); \
} while (0)
/* these are used when generic fn pointers are needed for ndr push/pull fns */
@@ -465,6 +468,7 @@ NDR_SCALAR_PROTO(int8, int8_t)
NDR_SCALAR_PROTO(uint16, uint16_t)
NDR_SCALAR_PROTO(int16, int16_t)
NDR_SCALAR_PROTO(uint32, uint32_t)
+NDR_SCALAR_PROTO(uint3264, uint32_t)
NDR_SCALAR_PROTO(int32, int32_t)
NDR_SCALAR_PROTO(udlong, uint64_t)
NDR_SCALAR_PROTO(udlongr, uint64_t)
@@ -537,4 +541,11 @@ char *GUID_hexstring(TALLOC_CTX *mem_ctx, const struct GUID *guid);
char *NS_GUID_string(TALLOC_CTX *mem_ctx, const struct GUID *guid);
struct GUID GUID_random(void);
+_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_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);
+
#endif /* __LIBNDR_H__ */
diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c
index 2b3493b2e3..cb47ca1d60 100644
--- a/librpc/ndr/ndr.c
+++ b/librpc/ndr/ndr.c
@@ -355,9 +355,11 @@ _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_FLAG_REMAINING) {
(*pflags) &= ~LIBNDR_ALIGN_FLAGS;
@@ -457,7 +459,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start(struct ndr_pull *ndr,
case 4: {
uint32_t content_size;
- NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &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) mismatch content_size %d",
(int)size_is, (int)content_size);
@@ -542,7 +544,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start(struct ndr_pull *ndr,
subndr = talloc_zero(ndr, struct ndr_pull);
NDR_ERR_HAVE_NO_MEMORY(subndr);
- subndr->flags = ndr->flags;
+ subndr->flags = ndr->flags & ~LIBNDR_FLAG_NDR64;
subndr->current_mem_ctx = ndr->current_mem_ctx;
subndr->data = ndr->data + ndr->offset;
@@ -586,7 +588,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_subcontext_start(struct ndr_push *ndr,
subndr = ndr_push_init_ctx(ndr, ndr->iconv_convenience);
NDR_ERR_HAVE_NO_MEMORY(subndr);
- subndr->flags = ndr->flags;
+ subndr->flags = ndr->flags & ~LIBNDR_FLAG_NDR64;
*_subndr = subndr;
return NDR_ERR_SUCCESS;
@@ -621,7 +623,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr,
break;
case 4:
- NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, subndr->offset));
+ NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, subndr->offset));
break;
case 0xFFFFFC01:
@@ -736,7 +738,7 @@ _PUBLIC_ uint32_t ndr_token_peek(struct ndr_token_list **list, const void *key)
_PUBLIC_ enum ndr_err_code ndr_pull_array_size(struct ndr_pull *ndr, const void *p)
{
uint32_t size;
- NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &size));
+ NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &size));
return ndr_token_store(ndr, &ndr->array_size_list, p, size);
}
@@ -769,12 +771,12 @@ _PUBLIC_ enum ndr_err_code ndr_check_array_size(struct ndr_pull *ndr, void *p, u
_PUBLIC_ enum ndr_err_code ndr_pull_array_length(struct ndr_pull *ndr, const void *p)
{
uint32_t length, offset;
- NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &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_uint32(ndr, NDR_SCALARS, &length));
+ NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &length));
return ndr_token_store(ndr, &ndr->array_length_list, p, length);
}
@@ -1168,6 +1170,7 @@ const static struct {
{ NDR_ERR_IPV4ADDRESS, "IPv4 Address Error" },
{ NDR_ERR_INVALID_POINTER, "Invalid Pointer" },
{ NDR_ERR_UNREAD_BYTES, "Unread Bytes" },
+ { NDR_ERR_NDR64, "NDR64 assertion error" },
{ 0, NULL }
};
diff --git a/librpc/ndr/ndr_basic.c b/librpc/ndr/ndr_basic.c
index d46590f0cb..00e33ad9d0 100644
--- a/librpc/ndr/ndr_basic.c
+++ b/librpc/ndr/ndr_basic.c
@@ -126,6 +126,26 @@ _PUBLIC_ enum ndr_err_code ndr_pull_uint32(struct ndr_pull *ndr, int ndr_flags,
}
/*
+ 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;
+ enum ndr_err_code err;
+ if (likely(!(ndr->flags & LIBNDR_FLAG_NDR64))) {
+ return ndr_pull_uint32(ndr, ndr_flags, v);
+ }
+ err = ndr_pull_hyper(ndr, ndr_flags, &v64);
+ *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_ERR_NDR64;
+ }
+ return err;
+}
+
+/*
parse a double
*/
_PUBLIC_ enum ndr_err_code ndr_pull_double(struct ndr_pull *ndr, int ndr_flags, double *v)
@@ -142,7 +162,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_double(struct ndr_pull *ndr, int ndr_flags,
*/
_PUBLIC_ enum ndr_err_code ndr_pull_generic_ptr(struct ndr_pull *ndr, uint32_t *v)
{
- NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, v));
+ NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, v));
if (*v != 0) {
ndr->ptr_count++;
}
@@ -154,7 +174,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_generic_ptr(struct ndr_pull *ndr, uint32_t *
*/
_PUBLIC_ enum ndr_err_code ndr_pull_ref_ptr(struct ndr_pull *ndr, uint32_t *v)
{
- NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, v));
+ NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, v));
/* ref pointers always point to data */
*v = 1;
return NDR_ERR_SUCCESS;
@@ -252,6 +272,73 @@ _PUBLIC_ enum ndr_err_code ndr_pull_WERROR(struct ndr_pull *ndr, int ndr_flags,
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 (uint32_t on NDR64)
+*/
+_PUBLIC_ enum ndr_err_code ndr_pull_enum_uint16(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;
+ }
+ NDR_PULL_ALIGN(ndr, 2);
+ NDR_PULL_NEED_BYTES(ndr, 2);
+ *v = NDR_SVAL(ndr, ndr->offset);
+ ndr->offset += 2;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ 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 (uint32_t on NDR64)
+*/
+_PUBLIC_ enum ndr_err_code ndr_push_enum_uint16(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 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 WERROR
*/
@@ -358,6 +445,21 @@ _PUBLIC_ enum ndr_err_code ndr_push_uint32(struct ndr_push *ndr, int ndr_flags,
}
/*
+ 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);
+ }
+ NDR_PUSH_ALIGN(ndr, 4);
+ NDR_PUSH_NEED_BYTES(ndr, 4);
+ NDR_SIVAL(ndr, ndr->offset, v);
+ ndr->offset += 4;
+ return NDR_ERR_SUCCESS;
+}
+
+/*
push a udlong
*/
_PUBLIC_ enum ndr_err_code ndr_push_udlong(struct ndr_push *ndr, int ndr_flags, uint64_t v)
@@ -427,12 +529,28 @@ _PUBLIC_ enum ndr_err_code ndr_push_pointer(struct ndr_push *ndr, int ndr_flags,
_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;
+ }
+ }
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;
+ }
+ }
NDR_PULL_ALIGN(ndr, size);
return NDR_ERR_SUCCESS;
}
@@ -481,7 +599,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_unique_ptr(struct ndr_push *ndr, const void
ptr |= 0x00020000;
ndr->ptr_count++;
}
- return ndr_push_uint32(ndr, NDR_SCALARS, ptr);
+ return ndr_push_uint3264(ndr, NDR_SCALARS, ptr);
}
/*
@@ -499,7 +617,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_full_ptr(struct ndr_push *ndr, const void *p
ndr_token_store(ndr, &ndr->full_ptr_list, p, ptr);
}
}
- return ndr_push_uint32(ndr, NDR_SCALARS, ptr);
+ return ndr_push_uint3264(ndr, NDR_SCALARS, ptr);
}
/*
@@ -507,7 +625,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_full_ptr(struct ndr_push *ndr, const void *p
*/
_PUBLIC_ enum ndr_err_code ndr_push_ref_ptr(struct ndr_push *ndr)
{
- return ndr_push_uint32(ndr, NDR_SCALARS, 0xAEF1AEF1);
+ return ndr_push_uint3264(ndr, NDR_SCALARS, 0xAEF1AEF1);
}
diff --git a/librpc/ndr/ndr_sec_helper.c b/librpc/ndr/ndr_sec_helper.c
index 62194707c2..abc805c8ef 100644
--- a/librpc/ndr/ndr_sec_helper.c
+++ b/librpc/ndr/ndr_sec_helper.c
@@ -181,7 +181,7 @@ enum ndr_err_code ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, struct
if (!(ndr_flags & NDR_SCALARS)) {
return NDR_ERR_SUCCESS;
}
- NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &num_auths));
+ 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,
@@ -199,7 +199,7 @@ enum ndr_err_code ndr_push_dom_sid2(struct ndr_push *ndr, int ndr_flags, const s
if (!(ndr_flags & NDR_SCALARS)) {
return NDR_ERR_SUCCESS;
}
- NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, sid->num_auths));
+ NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, sid->num_auths));
return ndr_push_dom_sid(ndr, ndr_flags, sid);
}