1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-28 01:58:17 +03:00

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>
This commit is contained in:
David Disseldorp 2012-07-06 14:00:27 +02:00 committed by Günther Deschner
parent 66514f8bbe
commit 0d3249b927

View File

@ -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);