diff options
author | David Disseldorp <ddiss@samba.org> | 2012-07-06 14:00:27 +0200 |
---|---|---|
committer | Günther Deschner <gd@samba.org> | 2012-07-06 19:03:19 +0200 |
commit | 0d3249b927465fdca1765cbd7e17c947364b5ef0 (patch) | |
tree | c80963c820f9c196c7b627d8e2b742500ee8451a | |
parent | 66514f8bbe5f9e2dcd8be90450ef339305a3161c (diff) | |
download | samba-0d3249b927465fdca1765cbd7e17c947364b5ef0.tar.gz samba-0d3249b927465fdca1765cbd7e17c947364b5ef0.tar.bz2 samba-0d3249b927465fdca1765cbd7e17c947364b5ef0.zip |
ndr: fix push/pull DATA_BLOB with NDR_NOALIGN
This change addresses bug 9026.
There are 3 use cases for DATA_BLOB marshalling/unmarshalling:
1)
ndr_push_DATA_BLOB and ndr_pull_DATA_BLOB when called with
LIBNDR_FLAG_ALIGN* alignment flags set, are used to push/pull padding
bytes _only_. The length is determined by the alignment required and
the current ndr offset.
e.g. dcerpc.idl:
typedef struct {
...
[flag(NDR_ALIGN8)] DATA_BLOB _pad;
} dcerpc_request;
2)
When called with the LIBNDR_FLAG_REMAINING flag, all remaining bytes in
the ndr buffer are pushed/pulled.
e.g. dcerpc.idl:
typedef struct {
...
[flag(NDR_REMAINING)] DATA_BLOB stub_and_verifier;
} dcerpc_request;
3)
When called without alignment flags, push/pull a uint32 length _and_ a
corresponding byte array to/from the ndr buffer.
e.g. drsblobs.idl
typedef [public] struct {
...
DATA_BLOB data;
} DsCompressedChunk;
The fix for bug 8373 changed the definition of "alignment flags", such
that when called with LIBNDR_FLAG_NOALIGN ndr_push/pull_DATA_BLOB
behaves as (1: padding bytes) rather than (3: uint32 length + byte
array).
This breaks marshalling/unmarshalling for the following structures.
eventlog.idl:
typedef [flag(NDR_NOALIGN|NDR_PAHEX),public] struct {
...
DATA_BLOB sid;
...
} eventlog_Record_tdb;
ntprinting.idl:
typedef [flag(NDR_NOALIGN),public] struct {
...
DATA_BLOB *nt_dev_private;
} ntprinting_devicemode;
typedef [flag(NDR_NOALIGN),public] struct {
...
DATA_BLOB data;
} ntprinting_printer_data;
Signed-off-by: Günther Deschner <gd@samba.org>
-rw-r--r-- | librpc/ndr/ndr_basic.c | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/librpc/ndr/ndr_basic.c b/librpc/ndr/ndr_basic.c index 7a4e22ad70..1887838779 100644 --- a/librpc/ndr/ndr_basic.c +++ b/librpc/ndr/ndr_basic.c @@ -1247,16 +1247,21 @@ _PUBLIC_ void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_ /* - push a DATA_BLOB onto the wire. -*/ + * 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 uint32 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) { - if (ndr->flags & LIBNDR_FLAG_NOALIGN) { - blob.length = 0; - } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) { + } 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); @@ -1273,18 +1278,23 @@ _PUBLIC_ enum ndr_err_code ndr_push_DATA_BLOB(struct ndr_push *ndr, int ndr_flag } /* - pull a DATA_BLOB from the wire. -*/ + * 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 uint32 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) { - if (ndr->flags & LIBNDR_FLAG_NOALIGN) { - length = 0; - } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) { + } 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); |