diff options
-rw-r--r-- | source4/libcli/ndr/ndr_echo.c | 42 | ||||
-rw-r--r-- | source4/libcli/ndr/ndr_echo.h | 19 | ||||
-rw-r--r-- | source4/libcli/rpc/dcerpc.c | 2 | ||||
-rw-r--r-- | source4/libcli/rpc/rpc_echo.c | 52 | ||||
-rw-r--r-- | source4/torture/rpc/echo.c | 72 |
5 files changed, 185 insertions, 2 deletions
diff --git a/source4/libcli/ndr/ndr_echo.c b/source4/libcli/ndr/ndr_echo.c index 456b254f3a..a085a6534d 100644 --- a/source4/libcli/ndr/ndr_echo.c +++ b/source4/libcli/ndr/ndr_echo.c @@ -68,3 +68,45 @@ NTSTATUS ndr_push_rpcecho_echodata(struct ndr_push *ndr, NDR_CHECK(ndr_push_bytes(ndr, r->in.data, r->in.len)); return NT_STATUS_OK; } + +/* + parse a sinkdata +*/ +NTSTATUS ndr_pull_rpcecho_sinkdata(struct ndr_pull *ndr, + struct rpcecho_sinkdata *r) +{ + return NT_STATUS_OK; +} + +/* + push a sinkdata +*/ +NTSTATUS ndr_push_rpcecho_sinkdata(struct ndr_push *ndr, + struct rpcecho_sinkdata *r) +{ + NDR_CHECK(ndr_push_u32(ndr, r->in.len)); + NDR_CHECK(ndr_push_u32(ndr, r->in.len)); + NDR_CHECK(ndr_push_bytes(ndr, r->in.data, r->in.len)); + return NT_STATUS_OK; +} + +/* + parse a sourcedata +*/ +NTSTATUS ndr_pull_rpcecho_sourcedata(struct ndr_pull *ndr, + struct rpcecho_sourcedata *r) +{ + NDR_CHECK(ndr_pull_u32(ndr, &r->out.len)); + NDR_CHECK(ndr_pull_bytes(ndr, &r->out.data, r->out.len)); + return NT_STATUS_OK; +} + +/* + push a sourcedata +*/ +NTSTATUS ndr_push_rpcecho_sourcedata(struct ndr_push *ndr, + struct rpcecho_sourcedata *r) +{ + NDR_CHECK(ndr_push_u32(ndr, r->in.len)); + return NT_STATUS_OK; +} diff --git a/source4/libcli/ndr/ndr_echo.h b/source4/libcli/ndr/ndr_echo.h index 4a8a4f5ab5..aecf68c4c0 100644 --- a/source4/libcli/ndr/ndr_echo.h +++ b/source4/libcli/ndr/ndr_echo.h @@ -47,6 +47,25 @@ struct rpcecho_echodata { } out; }; +/* SinkData interface */ +struct rpcecho_sinkdata { + struct { + int len; + char *data; + } in; +}; + +/* SourceData interface */ +struct rpcecho_sourcedata { + struct { + int len; + } in; + struct { + int len; + char *data; + } out; +}; + /* define the command codes */ enum { RPCECHO_CALL_ADDONE=0, diff --git a/source4/libcli/rpc/dcerpc.c b/source4/libcli/rpc/dcerpc.c index 96a355c9e1..b620718755 100644 --- a/source4/libcli/rpc/dcerpc.c +++ b/source4/libcli/rpc/dcerpc.c @@ -199,7 +199,7 @@ static NTSTATUS dcerpc_pull_response(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, stub_len = blob->length - ((*offset) + hdr->auth_length); BLOB_CHECK_BOUNDS(blob, *offset, stub_len); pkt->stub_data = data_blob_talloc(mem_ctx, blob->data + (*offset), stub_len); - if (!pkt->stub_data.data) { + if (stub_len != 0 && !pkt->stub_data.data) { return NT_STATUS_NO_MEMORY; } (*offset) += stub_len; diff --git a/source4/libcli/rpc/rpc_echo.c b/source4/libcli/rpc/rpc_echo.c index ab793a1ffa..d73f9bda9c 100644 --- a/source4/libcli/rpc/rpc_echo.c +++ b/source4/libcli/rpc/rpc_echo.c @@ -83,3 +83,55 @@ NTSTATUS dcerpc_rpcecho_echodata(struct dcerpc_pipe *p, return status; } + +/* + sourcedata interface +*/ +NTSTATUS dcerpc_rpcecho_sourcedata(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx, + int len, + int *out_len, + char **out_data) +{ + struct rpcecho_sourcedata r; + NTSTATUS status; + + /* fill the .in side of the call */ + r.in.len = len; + + /* make the call */ + status = dcerpc_ndr_request(p, RPCECHO_CALL_SOURCEDATA, mem_ctx, + (ndr_push_fn_t) ndr_push_rpcecho_sourcedata, + (ndr_pull_fn_t) ndr_pull_rpcecho_sourcedata, + &r); + + /* and extract the .out parameters */ + *out_len = r.out.len; + *out_data = r.out.data; + + return status; +} + +/* + sinkdata interface +*/ +NTSTATUS dcerpc_rpcecho_sinkdata(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx, + int len, + char *data) +{ + struct rpcecho_sinkdata r; + NTSTATUS status; + + /* fill the .in side of the call */ + r.in.len = len; + r.in.data = data; + + /* make the call */ + status = dcerpc_ndr_request(p, RPCECHO_CALL_SINKDATA, mem_ctx, + (ndr_push_fn_t) ndr_push_rpcecho_sinkdata, + (ndr_pull_fn_t) ndr_pull_rpcecho_sinkdata, + &r); + + return status; +} diff --git a/source4/torture/rpc/echo.c b/source4/torture/rpc/echo.c index 754d0c16d3..48b004782c 100644 --- a/source4/torture/rpc/echo.c +++ b/source4/torture/rpc/echo.c @@ -53,7 +53,7 @@ static BOOL test_echodata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) int i; NTSTATUS status; char *data_in, *data_out; - int len = 10; + int len = 17; int len_out; printf("\nTesting EchoData\n"); @@ -83,6 +83,68 @@ static BOOL test_echodata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) return True; } + +/* + test the SourceData interface +*/ +static BOOL test_sourcedata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) +{ + int i; + NTSTATUS status; + char *data_out; + int len = 100; + int len_out; + + printf("\nTesting SourceData\n"); + + status = dcerpc_rpcecho_sourcedata(p, mem_ctx, + len, + &len_out, + &data_out); + if (!NT_STATUS_IS_OK(status)) { + printf("SourceData(%d) failed\n", len); + return False; + } + printf("SourceData(%d) returned %d bytes\n", len, len_out); + + for (i=0;i<len;i++) { + if (data_out[i] != (i & 0xFF)) { + printf("bad data 0x%x at %d\n", data_out[i], i); + return False; + } + } + + return True; +} + +/* + test the SinkData interface +*/ +static BOOL test_sinkdata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) +{ + int i; + NTSTATUS status; + char *data_in; + int len = 100; + + printf("\nTesting SinkData\n"); + + data_in = talloc(mem_ctx, len); + for (i=0;i<len;i++) { + data_in[i] = i+1; + } + + status = dcerpc_rpcecho_sinkdata(p, mem_ctx, + len, + data_in); + if (!NT_STATUS_IS_OK(status)) { + printf("SinkData(%d) failed\n", len); + return False; + } + + return True; +} + BOOL torture_rpc_echo(int dummy) { NTSTATUS status; @@ -105,6 +167,14 @@ BOOL torture_rpc_echo(int dummy) ret = False; } + if (!test_sourcedata(p, mem_ctx)) { + ret = False; + } + + if (!test_sinkdata(p, mem_ctx)) { + ret = False; + } + printf("\n"); torture_rpc_close(p); |