s3-dcerpc: Fix ability to receive Big Endian PDUs
authorSimo Sorce <idra@samba.org>
Fri, 16 Jul 2010 19:15:48 +0000 (15:15 -0400)
committerSimo Sorce <idra@samba.org>
Fri, 16 Jul 2010 20:02:39 +0000 (16:02 -0400)
librpc/rpc/dcerpc_util.c
source3/include/proto.h
source3/librpc/rpc/dcerpc.h
source3/librpc/rpc/dcerpc_helpers.c
source3/rpc_client/cli_pipe.c
source3/rpc_server/srv_pipe.c
source3/rpc_server/srv_pipe_hnd.c

index a4bc096ddde968390c6ab84d3015e92f56501629..c79cfd506a5d5d92b9903f9e0a0965388bfe6580 100644 (file)
@@ -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
index 6f8eebb459119a305cf5d4a63312c6c9cd4e601c..9471f63195d10498d953b31657294ce903e8af99 100644 (file)
@@ -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,
index d18920ca0dba5cf58331ef91f0a8a497ca541c04..bb7bd34de8a0174824eb738ecdaf1d13f256e6bd 100644 (file)
@@ -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__ */
index ce48a691ac6e383cbce623b4253027d893cd6ed2..5c92a792e978f1548729e2bc5b070a2295d9521b 100644 (file)
@@ -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);
index c90e06095ca3f3e0e9dd4dc74786ed7ba0ed1b0a..411b12feef2c3a7aa4eec28cd83c5c0f00476013 100644 (file)
@@ -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;
index 6d37ec2bc2bc1342bfa0f15767d015503ce3b464..968553a28decf772740beee38fc00f61277df267 100644 (file)
@@ -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;
index 3055e1a29c966b13779b16aeba4a334304803e53..51f30cea2544c7aaa398e580e17b7489f2b3833b 100644 (file)
@@ -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));