diff options
-rw-r--r-- | source4/librpc/rpc/dcerpc.c | 20 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_util.c | 5 | ||||
-rw-r--r-- | source4/param/loadparm.c | 3 | ||||
-rw-r--r-- | source4/rpc_server/dcerpc_server.c | 72 | ||||
-rw-r--r-- | source4/rpc_server/dcesrv_auth.c | 14 |
5 files changed, 65 insertions, 49 deletions
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index f02bdb2a23..d00f2c2986 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -75,7 +75,7 @@ void dcerpc_set_frag_length(DATA_BLOB *blob, uint16 v) } } -uint16 dcerpc_get_frag_length(DATA_BLOB *blob) +uint16 dcerpc_get_frag_length(const DATA_BLOB *blob) { if (CVAL(blob->data,DCERPC_DREP_OFFSET) & DCERPC_DREP_LE) { return SVAL(blob->data, DCERPC_FRAG_LEN_OFFSET); @@ -108,8 +108,8 @@ static NTSTATUS dcerpc_pull(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - if (! (CVAL(blob, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) { - ndr->flags |= DCERPC_PULL_BIGENDIAN; + if (! (CVAL(blob->data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) { + ndr->flags |= LIBNDR_FLAG_BIGENDIAN; } return ndr_pull_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt); @@ -137,8 +137,8 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p, return NT_STATUS_NO_MEMORY; } - if (! (CVAL(blob, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) { - ndr->flags |= DCERPC_PULL_BIGENDIAN; + if (! (CVAL(blob->data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) { + ndr->flags |= LIBNDR_FLAG_BIGENDIAN; } /* pull the basic packet */ @@ -169,8 +169,8 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p, return NT_STATUS_NO_MEMORY; } - if (! (CVAL(blob, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) { - ndr->flags |= DCERPC_PULL_BIGENDIAN; + if (! (CVAL(blob->data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) { + ndr->flags |= LIBNDR_FLAG_BIGENDIAN; } status = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, &auth); @@ -225,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, p->flags); + return dcerpc_push_auth(blob, mem_ctx, pkt, p->auth_info); } ndr = ndr_push_init_ctx(mem_ctx); @@ -353,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, p->flags); + status = dcerpc_push_auth(&blob, mem_ctx, &pkt, p->auth_info); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -412,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, p->flags); + status = dcerpc_push_auth(&blob, mem_ctx, &pkt, p->auth_info); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index bc10f4e92d..e4e67b3cf0 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -223,8 +223,7 @@ const struct dcerpc_interface_table *idl_iface_by_uuid(const char *uuid) */ NTSTATUS dcerpc_push_auth(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, struct dcerpc_packet *pkt, - struct dcerpc_auth *auth_info, - unsigned flags) + struct dcerpc_auth *auth_info) { NTSTATUS status; struct ndr_push *ndr; @@ -234,7 +233,7 @@ NTSTATUS dcerpc_push_auth(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - if (flags & DCERPC_PUSH_BIGENDIAN) { + if (!(pkt->drep[0] & DCERPC_DREP_LE)) { ndr->flags |= LIBNDR_FLAG_BIGENDIAN; } diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c index 6ec4842c6d..aff4a4f12a 100644 --- a/source4/param/loadparm.c +++ b/source4/param/loadparm.c @@ -278,6 +278,7 @@ typedef struct BOOL bUnixExtensions; BOOL bDisableNetbios; BOOL bKernelChangeNotify; + BOOL bRpcBigEndian; int restrict_anonymous; int name_cache_timeout; BOOL client_signing; @@ -869,6 +870,7 @@ static struct parm_struct parm_table[] = { {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER}, {"client signing", P_BOOL, P_GLOBAL, &Globals.client_signing, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"client use spnego", P_BOOL, P_GLOBAL, &Globals.bClientUseSpnego, NULL, NULL, FLAG_DEVELOPER}, + {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER}, {"Tuning Options", P_SEP, P_SEPARATOR}, @@ -1700,6 +1702,7 @@ FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego) FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego) FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups) FN_GLOBAL_BOOL(lp_kernel_change_notify, &Globals.bKernelChangeNotify) +FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian) FN_GLOBAL_INTEGER(lp_os_level, &Globals.os_level) FN_GLOBAL_INTEGER(lp_max_ttl, &Globals.max_ttl) FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl) diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index 081b5b1d5a..d3e2f1917f 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -178,6 +178,20 @@ void dcesrv_endpoint_disconnect(struct dcesrv_state *p) talloc_destroy(p->mem_ctx); } +static void dcesrv_init_hdr(struct dcerpc_packet *pkt) +{ + pkt->rpc_vers = 5; + pkt->rpc_vers_minor = 0; + if (lp_rpc_big_endian()) { + pkt->drep[0] = 0; + } else { + pkt->drep[0] = DCERPC_DREP_LE; + } + pkt->drep[1] = 0; + pkt->drep[2] = 0; + pkt->drep[3] = 0; +} + /* return a dcerpc fault */ @@ -188,12 +202,7 @@ static NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32 fault_code) NTSTATUS status; /* setup a bind_ack */ - pkt.rpc_vers = 5; - pkt.rpc_vers_minor = 0; - pkt.drep[0] = 0x10; /* Little endian */ - pkt.drep[1] = 0; - pkt.drep[2] = 0; - pkt.drep[3] = 0; + dcesrv_init_hdr(&pkt); pkt.auth_length = 0; pkt.call_id = call->pkt.call_id; pkt.ptype = DCERPC_PKT_FAULT; @@ -208,12 +217,12 @@ static NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32 fault_code) return NT_STATUS_NO_MEMORY; } - status = dcerpc_push_auth(&rep->data, call->mem_ctx, &pkt, NULL, 0); + status = dcerpc_push_auth(&rep->data, call->mem_ctx, &pkt, NULL); if (!NT_STATUS_IS_OK(status)) { return status; } - SSVAL(rep->data.data, DCERPC_FRAG_LEN_OFFSET, rep->data.length); + dcerpc_set_frag_length(&rep->data, rep->data.length); DLIST_ADD_END(call->replies, rep, struct dcesrv_call_reply *); @@ -247,12 +256,7 @@ static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32 reason) NTSTATUS status; /* setup a bind_ack */ - pkt.rpc_vers = 5; - pkt.rpc_vers_minor = 0; - pkt.drep[0] = 0x10; /* Little endian */ - pkt.drep[1] = 0; - pkt.drep[2] = 0; - pkt.drep[3] = 0; + dcesrv_init_hdr(&pkt); pkt.auth_length = 0; pkt.call_id = call->pkt.call_id; pkt.ptype = DCERPC_PKT_BIND_NAK; @@ -265,12 +269,12 @@ static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32 reason) return NT_STATUS_NO_MEMORY; } - status = dcerpc_push_auth(&rep->data, call->mem_ctx, &pkt, NULL, 0); + status = dcerpc_push_auth(&rep->data, call->mem_ctx, &pkt, NULL); if (!NT_STATUS_IS_OK(status)) { return status; } - SSVAL(rep->data.data, DCERPC_FRAG_LEN_OFFSET, rep->data.length); + dcerpc_set_frag_length(&rep->data, rep->data.length); DLIST_ADD_END(call->replies, rep, struct dcesrv_call_reply *); @@ -328,12 +332,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call) } /* setup a bind_ack */ - pkt.rpc_vers = 5; - pkt.rpc_vers_minor = 0; - pkt.drep[0] = 0x10; /* Little endian */ - pkt.drep[1] = 0; - pkt.drep[2] = 0; - pkt.drep[3] = 0; + dcesrv_init_hdr(&pkt); pkt.auth_length = 0; pkt.call_id = call->pkt.call_id; pkt.ptype = DCERPC_PKT_BIND_ACK; @@ -368,12 +367,12 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call) } status = dcerpc_push_auth(&rep->data, call->mem_ctx, &pkt, - call->dce->auth_state.auth_info, 0); + call->dce->auth_state.auth_info); if (!NT_STATUS_IS_OK(status)) { return status; } - SSVAL(rep->data.data, DCERPC_FRAG_LEN_OFFSET, rep->data.length); + dcerpc_set_frag_length(&rep->data, rep->data.length); DLIST_ADD_END(call->replies, rep, struct dcesrv_call_reply *); DLIST_ADD_END(call->dce->call_list, call, struct dcesrv_call_state *); @@ -428,6 +427,10 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call) return NT_STATUS_NO_MEMORY; } + if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) { + pull->flags |= LIBNDR_FLAG_BIGENDIAN; + } + /* unravel the NDR for the packet */ status = call->dce->ndr->calls[opnum].ndr_pull(pull, NDR_IN, r); if (!NT_STATUS_IS_OK(status)) { @@ -446,6 +449,10 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call) return NT_STATUS_NO_MEMORY; } + if (lp_rpc_big_endian()) { + push->flags |= LIBNDR_FLAG_BIGENDIAN; + } + status = call->dce->ndr->calls[opnum].ndr_push(push, NDR_OUT, r); if (!NT_STATUS_IS_OK(status)) { return dcesrv_fault(call, DCERPC_FAULT_NDR); @@ -471,12 +478,7 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call) } /* form the dcerpc response packet */ - pkt.rpc_vers = 5; - pkt.rpc_vers_minor = 0; - pkt.drep[0] = 0x10; /* Little endian */ - pkt.drep[1] = 0; - pkt.drep[2] = 0; - pkt.drep[3] = 0; + dcesrv_init_hdr(&pkt); pkt.auth_length = 0; pkt.call_id = call->pkt.call_id; pkt.ptype = DCERPC_PKT_RESPONSE; @@ -497,7 +499,7 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call) return dcesrv_fault(call, DCERPC_FAULT_OTHER); } - SSVAL(rep->data.data, DCERPC_FRAG_LEN_OFFSET, rep->data.length); + dcerpc_set_frag_length(&rep->data, rep->data.length); DLIST_ADD_END(call->replies, rep, struct dcesrv_call_reply *); @@ -519,7 +521,7 @@ static BOOL dce_full_packet(const DATA_BLOB *data) if (data->length < DCERPC_FRAG_LEN_OFFSET+2) { return False; } - if (SVAL(data->data, DCERPC_FRAG_LEN_OFFSET) > data->length) { + if (dcerpc_get_frag_length(data) > data->length) { return False; } return True; @@ -570,7 +572,7 @@ NTSTATUS dcesrv_input_process(struct dcesrv_state *dce) call->replies = NULL; blob = dce->partial_input; - blob.length = SVAL(blob.data, DCERPC_FRAG_LEN_OFFSET); + blob.length = dcerpc_get_frag_length(&blob); ndr = ndr_pull_init_blob(&blob, mem_ctx); if (!ndr) { @@ -579,6 +581,10 @@ NTSTATUS dcesrv_input_process(struct dcesrv_state *dce) return NT_STATUS_NO_MEMORY; } + if (!(CVAL(blob.data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) { + ndr->flags |= LIBNDR_FLAG_BIGENDIAN; + } + status = ndr_pull_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, &call->pkt); if (!NT_STATUS_IS_OK(status)) { talloc_free(dce->mem_ctx, dce->partial_input.data); diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c index 0f4b22ee3d..776d394e99 100644 --- a/source4/rpc_server/dcesrv_auth.c +++ b/source4/rpc_server/dcesrv_auth.c @@ -184,6 +184,10 @@ BOOL dcesrv_auth_request(struct dcesrv_call_state *call) return False; } + if (!(pkt->drep[0] & DCERPC_DREP_LE)) { + ndr->flags |= LIBNDR_FLAG_BIGENDIAN; + } + status = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, &auth); if (!NT_STATUS_IS_OK(status)) { return False; @@ -232,7 +236,7 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call, /* non-signed packets are simple */ if (!dce->auth_state.auth_info || !dce->auth_state.ntlmssp_state) { - status = dcerpc_push_auth(blob, call->mem_ctx, pkt, NULL, 0); + status = dcerpc_push_auth(blob, call->mem_ctx, pkt, NULL); return NT_STATUS_IS_OK(status); } @@ -241,6 +245,10 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call, return False; } + if (pkt->drep[0] & DCERPC_DREP_LE) { + ndr->flags |= LIBNDR_FLAG_BIGENDIAN; + } + status = ndr_push_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt); if (!NT_STATUS_IS_OK(status)) { return False; @@ -286,8 +294,8 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call, /* 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, dce->auth_state.auth_info->credentials.length); + dcerpc_set_frag_length(blob, blob->length); + dcerpc_set_auth_length(blob, dce->auth_state.auth_info->credentials.length); data_blob_free(&dce->auth_state.auth_info->credentials); |