summaryrefslogtreecommitdiff
path: root/source4/librpc/rpc/dcerpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/librpc/rpc/dcerpc.c')
-rw-r--r--source4/librpc/rpc/dcerpc.c89
1 files changed, 75 insertions, 14 deletions
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c
index 3dcaca83ec..c82d8d67ab 100644
--- a/source4/librpc/rpc/dcerpc.c
+++ b/source4/librpc/rpc/dcerpc.c
@@ -64,6 +64,35 @@ void dcerpc_pipe_close(struct dcerpc_pipe *p)
}
}
+/* we need to be able to get/set the fragment length without doing a full
+ decode */
+void dcerpc_set_frag_length(DATA_BLOB *blob, uint16 v)
+{
+ if (CVAL(blob->data,DCERPC_DREP_OFFSET) & 0x10) {
+ SSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET, v);
+ } else {
+ RSSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET, v);
+ }
+}
+
+uint16 dcerpc_get_frag_length(DATA_BLOB *blob)
+{
+ if (CVAL(blob->data,DCERPC_DREP_OFFSET) & 0x10) {
+ return SVAL(blob->data, DCERPC_FRAG_LEN_OFFSET);
+ } else {
+ return RSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET);
+ }
+}
+
+void dcerpc_set_auth_length(DATA_BLOB *blob, uint16 v)
+{
+ if (CVAL(blob->data,DCERPC_DREP_OFFSET) & 0x10) {
+ SSVAL(blob->data, DCERPC_AUTH_LEN_OFFSET, v);
+ } else {
+ RSSVAL(blob->data, DCERPC_AUTH_LEN_OFFSET, v);
+ }
+}
+
/*
parse a data blob into a dcerpc_packet structure. This handles both
@@ -79,6 +108,10 @@ static NTSTATUS dcerpc_pull(DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
return NT_STATUS_NO_MEMORY;
}
+ if (! (CVAL(blob, DCERPC_DREP_OFFSET) & 0x10)) {
+ ndr->flags |= DCERPC_PULL_BIGENDIAN;
+ }
+
return ndr_pull_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
}
@@ -104,6 +137,10 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p,
return NT_STATUS_NO_MEMORY;
}
+ if (! (CVAL(blob, DCERPC_DREP_OFFSET) & 0x10)) {
+ ndr->flags |= DCERPC_PULL_BIGENDIAN;
+ }
+
/* pull the basic packet */
status = ndr_pull_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
if (!NT_STATUS_IS_OK(status)) {
@@ -132,6 +169,10 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p,
return NT_STATUS_NO_MEMORY;
}
+ if (! (CVAL(blob, DCERPC_DREP_OFFSET) & 0x10)) {
+ ndr->flags |= DCERPC_PULL_BIGENDIAN;
+ }
+
status = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, &auth);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -184,7 +225,7 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p,
/* non-signed packets are simpler */
if (!p->auth_info || !p->ntlmssp_state) {
- return dcerpc_push_auth(blob, mem_ctx, pkt, p->auth_info);
+ return dcerpc_push_auth(blob, mem_ctx, pkt, p->auth_info, p->flags);
}
ndr = ndr_push_init_ctx(mem_ctx);
@@ -192,6 +233,10 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p,
return NT_STATUS_NO_MEMORY;
}
+ if (p->flags & DCERPC_PUSH_BIGENDIAN) {
+ ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
+ }
+
status = ndr_push_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -242,8 +287,8 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p,
/* fill in the fragment length and auth_length, we can't fill
in these earlier as we don't know the signature length (it
could be variable length) */
- SSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET, blob->length);
- SSVAL(blob->data, DCERPC_AUTH_LEN_OFFSET, p->auth_info->credentials.length);
+ dcerpc_set_frag_length(blob, blob->length);
+ dcerpc_set_auth_length(blob, p->auth_info->credentials.length);
data_blob_free(&p->auth_info->credentials);
@@ -254,11 +299,15 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p,
/*
fill in the fixed values in a dcerpc header
*/
-static void init_dcerpc_hdr(struct dcerpc_packet *pkt)
+static void init_dcerpc_hdr(struct dcerpc_pipe *p, struct dcerpc_packet *pkt)
{
pkt->rpc_vers = 5;
pkt->rpc_vers_minor = 0;
- pkt->drep[0] = 0x10; /* Little endian */
+ if (p->flags & DCERPC_PUSH_BIGENDIAN) {
+ pkt->drep[0] = 0;
+ } else {
+ pkt->drep[0] = 0x10;
+ }
pkt->drep[1] = 0;
pkt->drep[2] = 0;
pkt->drep[3] = 0;
@@ -281,7 +330,7 @@ NTSTATUS dcerpc_bind(struct dcerpc_pipe *p,
DATA_BLOB blob;
struct dcerpc_syntax_id tsyntax;
- init_dcerpc_hdr(&pkt);
+ init_dcerpc_hdr(p, &pkt);
pkt.ptype = DCERPC_PKT_BIND;
pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
@@ -304,7 +353,7 @@ NTSTATUS dcerpc_bind(struct dcerpc_pipe *p,
pkt.u.bind.auth_info = data_blob(NULL, 0);
/* construct the NDR form of the packet */
- status = dcerpc_push_auth(&blob, mem_ctx, &pkt, p->auth_info);
+ status = dcerpc_push_auth(&blob, mem_ctx, &pkt, p->auth_info, p->flags);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -353,7 +402,7 @@ NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p,
NTSTATUS status;
DATA_BLOB blob;
- init_dcerpc_hdr(&pkt);
+ init_dcerpc_hdr(p, &pkt);
pkt.ptype = DCERPC_PKT_AUTH3;
pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
@@ -363,7 +412,7 @@ NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p,
pkt.u.auth.auth_info = data_blob(NULL, 0);
/* construct the NDR form of the packet */
- status = dcerpc_push_auth(&blob, mem_ctx, &pkt, p->auth_info);
+ status = dcerpc_push_auth(&blob, mem_ctx, &pkt, p->auth_info, p->flags);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -392,15 +441,13 @@ NTSTATUS dcerpc_bind_byuuid(struct dcerpc_pipe *p,
DEBUG(2,("Invalid uuid string in dcerpc_bind_byuuid\n"));
return status;
}
- syntax.major_version = version;
- syntax.minor_version = 0;
+ syntax.if_version = version;
status = GUID_from_string(NDR_GUID, &transfer_syntax.uuid);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- transfer_syntax.major_version = NDR_GUID_VERSION;
- transfer_syntax.minor_version = 0;
+ transfer_syntax.if_version = NDR_GUID_VERSION;
return dcerpc_bind(p, mem_ctx, &syntax, &transfer_syntax);
}
@@ -420,7 +467,7 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
DATA_BLOB blob, payload;
uint32 remaining, chunk_size;
- init_dcerpc_hdr(&pkt);
+ init_dcerpc_hdr(p, &pkt);
remaining = stub_data_in->length;
@@ -552,6 +599,12 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
*stub_data_out = payload;
}
+ if (!(pkt.drep[0] & 0x10)) {
+ p->flags |= DCERPC_PULL_BIGENDIAN;
+ } else {
+ p->flags &= ~DCERPC_PULL_BIGENDIAN;
+ }
+
return status;
}
@@ -723,6 +776,10 @@ NTSTATUS dcerpc_ndr_request(struct dcerpc_pipe *p,
return NT_STATUS_NO_MEMORY;
}
+ if (p->flags & DCERPC_PUSH_BIGENDIAN) {
+ push->flags |= LIBNDR_FLAG_BIGENDIAN;
+ }
+
/* push the structure into a blob */
status = ndr_push(push, NDR_IN, struct_ptr);
if (!NT_STATUS_IS_OK(status)) {
@@ -755,6 +812,10 @@ NTSTATUS dcerpc_ndr_request(struct dcerpc_pipe *p,
goto failed;
}
+ if (p->flags & DCERPC_PULL_BIGENDIAN) {
+ pull->flags |= LIBNDR_FLAG_BIGENDIAN;
+ }
+
DEBUG(10,("rpc reply data:\n"));
dump_data(10, pull->data, pull->data_size);