diff options
Diffstat (limited to 'librpc/ndr')
-rw-r--r-- | librpc/ndr/libndr.h | 37 | ||||
-rw-r--r-- | librpc/ndr/ndr.c | 17 | ||||
-rw-r--r-- | librpc/ndr/ndr_basic.c | 128 | ||||
-rw-r--r-- | librpc/ndr/ndr_sec_helper.c | 4 |
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); } |