summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2010-07-16 15:15:48 -0400
committerSimo Sorce <idra@samba.org>2010-07-16 16:02:39 -0400
commit65116adcebe23d3ae42a641515f6001268ed0ef0 (patch)
treee9becdcf344e99d893bcb1dc07709b967a7ea34b
parentec25a000317f863df7af0d97f1fd8948b2f8959d (diff)
downloadsamba-65116adcebe23d3ae42a641515f6001268ed0ef0.tar.gz
samba-65116adcebe23d3ae42a641515f6001268ed0ef0.tar.bz2
samba-65116adcebe23d3ae42a641515f6001268ed0ef0.zip
s3-dcerpc: Fix ability to receive Big Endian PDUs
-rw-r--r--librpc/rpc/dcerpc_util.c5
-rw-r--r--source3/include/proto.h1
-rw-r--r--source3/librpc/rpc/dcerpc.h6
-rw-r--r--source3/librpc/rpc/dcerpc_helpers.c36
-rw-r--r--source3/rpc_client/cli_pipe.c12
-rw-r--r--source3/rpc_server/srv_pipe.c6
-rw-r--r--source3/rpc_server/srv_pipe_hnd.c24
7 files changed, 62 insertions, 28 deletions
diff --git a/librpc/rpc/dcerpc_util.c b/librpc/rpc/dcerpc_util.c
index a4bc096ddd..c79cfd506a 100644
--- a/librpc/rpc/dcerpc_util.c
+++ b/librpc/rpc/dcerpc_util.c
@@ -52,6 +52,11 @@ void dcerpc_set_auth_length(DATA_BLOB *blob, uint16_t v)
}
}
+uint8_t dcerpc_get_endian_flag(DATA_BLOB *blob)
+{
+ return blob->data[DCERPC_DREP_OFFSET];
+}
+
/*
pull an dcerpc_auth structure, taking account of any auth padding in
the blob at the end of the structure
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 6f8eebb459..9471f63195 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -2937,6 +2937,7 @@ NTSTATUS dcerpc_fault_to_nt_status(uint32_t fault_code);
void dcerpc_set_frag_length(DATA_BLOB *blob, uint16_t v);
uint16_t dcerpc_get_frag_length(const DATA_BLOB *blob);
void dcerpc_set_auth_length(DATA_BLOB *blob, uint16_t v);
+uint8_t dcerpc_get_endian_flag(DATA_BLOB *blob);
NTSTATUS dcerpc_pull_auth_trailer(struct ncacn_packet *pkt,
TALLOC_CTX *mem_ctx,
DATA_BLOB *pkt_auth_blob,
diff --git a/source3/librpc/rpc/dcerpc.h b/source3/librpc/rpc/dcerpc.h
index d18920ca0d..bb7bd34de8 100644
--- a/source3/librpc/rpc/dcerpc.h
+++ b/source3/librpc/rpc/dcerpc.h
@@ -123,7 +123,8 @@ NTSTATUS dcerpc_push_ncacn_packet(TALLOC_CTX *mem_ctx,
DATA_BLOB *blob);
NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx,
const DATA_BLOB *blob,
- struct ncacn_packet *r);
+ struct ncacn_packet *r,
+ bool bigendian);
NTSTATUS dcerpc_push_schannel_bind(TALLOC_CTX *mem_ctx,
struct NL_AUTH_MESSAGE *r,
DATA_BLOB *blob);
@@ -136,6 +137,7 @@ NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx,
DATA_BLOB *blob);
NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx,
const DATA_BLOB *blob,
- struct dcerpc_auth *r);
+ struct dcerpc_auth *r,
+ bool bigendian);
#endif /* __DCERPC_H__ */
diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c
index ce48a691ac..5c92a792e9 100644
--- a/source3/librpc/rpc/dcerpc_helpers.c
+++ b/source3/librpc/rpc/dcerpc_helpers.c
@@ -92,15 +92,27 @@ NTSTATUS dcerpc_push_ncacn_packet(TALLOC_CTX *mem_ctx,
*/
NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx,
const DATA_BLOB *blob,
- struct ncacn_packet *r)
+ struct ncacn_packet *r,
+ bool bigendian)
{
enum ndr_err_code ndr_err;
+ struct ndr_pull *ndr;
+
+ ndr = ndr_pull_init_blob(blob, mem_ctx);
+ if (!ndr) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ if (bigendian) {
+ ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
+ }
+
+ ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, r);
- ndr_err = ndr_pull_struct_blob(blob, mem_ctx, r,
- (ndr_pull_flags_fn_t)ndr_pull_ncacn_packet);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ talloc_free(ndr);
return ndr_map_error2ntstatus(ndr_err);
}
+ talloc_free(ndr);
if (DEBUGLEVEL >= 10) {
NDR_PRINT_DEBUG(ncacn_packet, r);
@@ -194,15 +206,27 @@ NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx,
*/
NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx,
const DATA_BLOB *blob,
- struct dcerpc_auth *r)
+ struct dcerpc_auth *r,
+ bool bigendian)
{
enum ndr_err_code ndr_err;
+ struct ndr_pull *ndr;
+
+ ndr = ndr_pull_init_blob(blob, mem_ctx);
+ if (!ndr) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ if (bigendian) {
+ ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
+ }
+
+ ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, r);
- ndr_err = ndr_pull_struct_blob(blob, mem_ctx, r,
- (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ talloc_free(ndr);
return ndr_map_error2ntstatus(ndr_err);
}
+ talloc_free(ndr);
if (DEBUGLEVEL >= 10) {
NDR_PRINT_DEBUG(dcerpc_auth, r);
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index c90e06095c..411b12feef 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -619,7 +619,7 @@ static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli,
DCERPC_AUTH_TRAILER_LENGTH
+ pkt->auth_length);
- status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info);
+ status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info, false);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall dcerpc_auth.\n"));
return status;
@@ -749,7 +749,7 @@ static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli,
+ pkt->auth_length);
- status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info);
+ status = dcerpc_pull_dcerpc_auth(cli, &blob, &auth_info, false);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall dcerpc_auth.\n"));
return status;
@@ -915,7 +915,7 @@ static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
NTSTATUS ret = NT_STATUS_OK;
uint8 ss_padding_len = 0;
- ret = dcerpc_pull_ncacn_packet(cli, pdu, pkt);
+ ret = dcerpc_pull_ncacn_packet(cli, pdu, pkt, false);
if (!NT_STATUS_IS_OK(ret)) {
return ret;
}
@@ -2612,7 +2612,7 @@ static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
status = dcerpc_pull_dcerpc_auth(talloc_tos(),
&r->u.bind_ack.auth_info,
- &auth);
+ &auth, false);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
nt_errstr(status)));
@@ -2694,7 +2694,7 @@ static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
DCERPC_AUTH_TRAILER_LENGTH
+ r->auth_length);
- status = dcerpc_pull_dcerpc_auth(state, &auth_blob, &auth_info);
+ status = dcerpc_pull_dcerpc_auth(state, &auth_blob, &auth_info, false);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n"));
return status;
@@ -2778,7 +2778,7 @@ static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
status = dcerpc_pull_dcerpc_auth(pkt,
&pkt->u.alter_resp.auth_info,
- &auth);
+ &auth, false);
if (!NT_STATUS_IS_OK(status)) {
tevent_req_nterror(req, status);
return;
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
index 6d37ec2bc2..968553a28d 100644
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -568,7 +568,7 @@ bool api_pipe_bind_auth3(pipes_struct *p, struct ncacn_packet *pkt)
status = dcerpc_pull_dcerpc_auth(pkt,
&pkt->u.auth3.auth_info,
- &auth_info);
+ &auth_info, p->endian);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n"));
goto err;
@@ -1303,7 +1303,7 @@ bool api_pipe_bind_req(pipes_struct *p, struct ncacn_packet *pkt)
*/
status = dcerpc_pull_dcerpc_auth(pkt,
&pkt->u.bind.auth_info,
- &auth_info);
+ &auth_info, p->endian);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n"));
goto err_exit;
@@ -1524,7 +1524,7 @@ bool api_pipe_alter_context(pipes_struct *p, struct ncacn_packet *pkt)
status = dcerpc_pull_dcerpc_auth(pkt,
&pkt->u.bind.auth_info,
- &auth_info);
+ &auth_info, p->endian);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n"));
goto err_exit;
diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c
index 3055e1a29c..51f30cea25 100644
--- a/source3/rpc_server/srv_pipe_hnd.c
+++ b/source3/rpc_server/srv_pipe_hnd.c
@@ -406,25 +406,27 @@ static void process_complete_pdu(pipes_struct *p)
goto done;
}
- status = dcerpc_pull_ncacn_packet(pkt, &p->in_data.pdu, pkt);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("Failed to unmarshal rpc packet: %s!\n",
- nt_errstr(status)));
- goto done;
- }
-
- /* Store the call_id */
- p->call_id = pkt->call_id;
-
/*
* Ensure we're using the corrent endianness for both the
* RPC header flags and the raw data we will be reading from.
*/
- if (pkt->drep[0] == DCERPC_DREP_LE) {
+ if (dcerpc_get_endian_flag(&p->in_data.pdu) & DCERPC_DREP_LE) {
p->endian = RPC_LITTLE_ENDIAN;
} else {
p->endian = RPC_BIG_ENDIAN;
}
+ DEBUG(10, ("PDU is in %s Endian format!\n", p->endian?"Big":"Little"));
+
+ status = dcerpc_pull_ncacn_packet(pkt, &p->in_data.pdu,
+ pkt, p->endian);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("Failed to unmarshal rpc packet: %s!\n",
+ nt_errstr(status)));
+ goto done;
+ }
+
+ /* Store the call_id */
+ p->call_id = pkt->call_id;
DEBUG(10, ("Processing packet type %d\n", (int)pkt->ptype));