From e4773b184cd6ccf1e46ec151afbfd9fb9ad3ede8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 24 Nov 2003 03:21:49 +0000 Subject: added tests for the remaining calls on the rpc management interface (This used to be commit 00f9b0e12061c175334f96805ca8333f28f74d91) --- source4/build/pidl/parser.pm | 48 +++++++++++------ source4/build/pidl/util.pm | 3 ++ source4/librpc/idl/mgmt.idl | 20 +++++-- source4/librpc/ndr/ndr_basic.c | 32 ++++++++++++ source4/librpc/rpc/dcerpc.c | 35 +------------ source4/torture/rpc/mgmt.c | 115 ++++++++++++++++++++++++++++++++++++++++- 6 files changed, 201 insertions(+), 52 deletions(-) diff --git a/source4/build/pidl/parser.pm b/source4/build/pidl/parser.pm index b92729a80a..788660c198 100644 --- a/source4/build/pidl/parser.pm +++ b/source4/build/pidl/parser.pm @@ -64,10 +64,12 @@ sub find_sibling($$) #################################################################### # work out the name of a size_is() variable -sub find_size_var($$) +sub find_size_var($$$) { my($e) = shift; my($size) = shift; + my($var_prefix) = shift; + my($fn) = $e->{PARENT}; if (util::is_constant($size)) { @@ -91,6 +93,9 @@ sub find_size_var($$) my $e2 = find_sibling($e, $size); + if (util::has_property($e2, "in") && util::has_property($e2, "out")) { + return $prefix . "$var_prefix$size"; + } if (util::has_property($e2, "in")) { return $prefix . "r->in.$size"; } @@ -212,7 +217,7 @@ sub ParseArrayPush($$$) my $var_prefix = shift; my $ndr_flags = shift; - my $size = find_size_var($e, util::array_size($e)); + my $size = find_size_var($e, util::array_size($e), $var_prefix); if (defined $e->{CONFORMANT_SIZE}) { # the conformant size has already been pushed @@ -222,7 +227,7 @@ sub ParseArrayPush($$$) } if (my $length = util::has_property($e, "length_is")) { - $length = find_size_var($e, $length); + $length = find_size_var($e, $length, $var_prefix); pidl "\t\tNDR_CHECK(ndr_push_uint32(ndr, 0));\n"; pidl "\t\tNDR_CHECK(ndr_push_uint32(ndr, $length));\n"; $size = $length; @@ -241,11 +246,11 @@ sub ParseArrayPrint($$) { my $e = shift; my $var_prefix = shift; - my $size = find_size_var($e, util::array_size($e)); + my $size = find_size_var($e, util::array_size($e), $var_prefix); my $length = util::has_property($e, "length_is"); if (defined $length) { - $size = find_size_var($e, $length); + $size = find_size_var($e, $length, $var_prefix); } if (util::is_scalar_type($e->{TYPE})) { @@ -263,7 +268,7 @@ sub ParseArrayPull($$$) my $var_prefix = shift; my $ndr_flags = shift; - my $size = find_size_var($e, util::array_size($e)); + my $size = find_size_var($e, util::array_size($e), $var_prefix); my $alloc_size = $size; # if this is a conformant array then we use that size to allocate, and make sure @@ -275,13 +280,22 @@ sub ParseArrayPull($$$) pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);\n"; pidl "\t}\n"; } elsif (!util::is_inline_array($e)) { + if ($var_prefix =~ /^r->out/ && $size =~ /^\*r->in/) { + my $size2 = substr($size, 1); + pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC(ndr, $size2); }\n"; + } + # non fixed arrays encode the size just before the array pidl "\t{\n"; pidl "\t\tuint32 _array_size;\n"; pidl "\t\tNDR_CHECK(ndr_pull_uint32(ndr, &_array_size));\n"; - pidl "\t\tif ($size > _array_size) {\n"; + if ($size =~ /r->in/) { + pidl "\t\tif (!(ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _array_size != $size) {\n"; + } else { + pidl "\t\tif ($size != _array_size) {\n"; + } pidl "\t\t\treturn ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should be %u\", _array_size, $size);\n"; - pidl "\t\t}\n"; + pidl "\t\t} else { $size = _array_size; }\n"; pidl "\t}\n"; } @@ -303,7 +317,7 @@ sub ParseArrayPull($$$) pidl "\t{\n"; if (my $length = util::has_property($e, "length_is")) { - $length = find_size_var($e, $length); + $length = find_size_var($e, $length, $var_prefix); pidl "\t\tuint32 _offset, _length;\n"; pidl "\t\tNDR_CHECK(ndr_pull_uint32(ndr, &_offset));\n"; pidl "\t\tNDR_CHECK(ndr_pull_uint32(ndr, &_length));\n"; @@ -395,7 +409,7 @@ sub ParseElementPullSwitch($$$$) my($var_prefix) = shift; my($ndr_flags) = shift; my $switch = shift; - my $switch_var = find_size_var($e, $switch); + my $switch_var = find_size_var($e, $switch, $var_prefix); my $cprefix = util::c_pull_prefix($e); @@ -433,7 +447,7 @@ sub ParseElementPushSwitch($$$$) my($var_prefix) = shift; my($ndr_flags) = shift; my $switch = shift; - my $switch_var = find_size_var($e, $switch); + my $switch_var = find_size_var($e, $switch, $var_prefix); my $cprefix = util::c_push_prefix($e); my $utype = $structs{$e->{TYPE}}; @@ -460,7 +474,7 @@ sub ParseElementPrintSwitch($$$) my($e) = shift; my($var_prefix) = shift; my $switch = shift; - my $switch_var = find_size_var($e, $switch); + my $switch_var = find_size_var($e, $switch, $var_prefix); my $cprefix = util::c_push_prefix($e); pidl "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});\n"; @@ -667,7 +681,7 @@ sub ParseStructPush($) # alignment) my $e = $struct->{ELEMENTS}[-1]; if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") { - my $size = find_size_var($e, util::array_size($e)); + my $size = find_size_var($e, util::array_size($e), "r->"); $e->{CONFORMANT_SIZE} = $size; $conform_e = $e; pidl "\tNDR_CHECK(ndr_push_uint32(ndr, $size));\n"; @@ -1078,7 +1092,11 @@ sub ParseFunctionPrint($) } } if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { - pidl "\tndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", &r->out.result);\n"; + if (util::is_scalar_type($fn->{RETURN_TYPE})) { + pidl "\tndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", r->out.result);\n"; + } else { + pidl "\tndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", &r->out.result);\n"; + } } pidl "\tndr->depth--;\n"; pidl "\t}\n"; @@ -1150,7 +1168,7 @@ sub ParseFunctionElementPull($$) if (util::array_size($e)) { if (util::need_wire_pointer($e)) { - pidl "\tNDR_CHECK(ndr_pull_uint32(ndr, _ptr_$e->{NAME}));\n"; + pidl "\tNDR_CHECK(ndr_pull_uint32(ndr, &_ptr_$e->{NAME}));\n"; pidl "\tif (_ptr_$e->{NAME}) {\n"; } elsif ($inout eq "in" && util::has_property($e, "ref")) { pidl "\t{\n"; diff --git a/source4/build/pidl/util.pm b/source4/build/pidl/util.pm index 2f94d80012..e99942f0ea 100644 --- a/source4/build/pidl/util.pm +++ b/source4/build/pidl/util.pm @@ -183,6 +183,9 @@ sub is_scalar_type($) return 1, if ($type eq "uint8"); return 1, if ($type eq "uint16"); return 1, if ($type eq "NTTIME"); + return 1, if ($type eq "error_status_t"); + return 1, if ($type eq "boolean32"); + return 1, if ($type eq "unsigned32"); return 1, if ($type eq "HYPER_T"); return 1, if ($type eq "wchar_t"); return 1, if ($type eq "DATA_BLOB"); diff --git a/source4/librpc/idl/mgmt.idl b/source4/librpc/idl/mgmt.idl index 94439bdea3..2bc752da3d 100644 --- a/source4/librpc/idl/mgmt.idl +++ b/source4/librpc/idl/mgmt.idl @@ -32,12 +32,26 @@ interface mgmt /***********************/ /* Function 0x01 */ + + const int mgmt_stats_calls_in = 0; + const int mgmt_stats_calls_out = 1; + const int mgmt_stats_pkts_in = 2; + const int mgmt_stats_pkts_out = 3; + const int mgmt_stats_array_max_size = 4; + + typedef struct { + uint32 count; + [size_is(count)] uint32 statistics[*]; + } mgmt_statistics; + void mgmt_inq_stats ( - [in, out] unsigned32 *count, - [out, size_is(*count)] unsigned32 *statistics, - [out] error_status_t *status + [in] uint32 max_count, + [in] uint32 unknown, + [out] mgmt_statistics statistics, + [out] error_status_t status ); + /***********************/ /* Function 0x02 */ boolean32 mgmt_is_server_listening ( diff --git a/source4/librpc/ndr/ndr_basic.c b/source4/librpc/ndr/ndr_basic.c index 5f59899133..a45771ef28 100644 --- a/source4/librpc/ndr/ndr_basic.c +++ b/source4/librpc/ndr/ndr_basic.c @@ -730,6 +730,38 @@ void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, ndr->depth--; } +/* + build a GUID from a string +*/ +NTSTATUS GUID_from_string(const char *s, struct GUID *guid) +{ + uint32 time_low; + uint32 time_mid, time_hi_and_version; + uint32 clock_seq_hi_and_reserved; + uint32 clock_seq_low; + uint32 node[6]; + int i; + + if (11 != sscanf(s, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + &time_low, &time_mid, &time_hi_and_version, + &clock_seq_hi_and_reserved, &clock_seq_low, + &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) { + return NT_STATUS_INVALID_PARAMETER; + } + + SIVAL(guid->info, 0, time_low); + SSVAL(guid->info, 4, time_mid); + SSVAL(guid->info, 6, time_hi_and_version); + SCVAL(guid->info, 8, clock_seq_hi_and_reserved); + SCVAL(guid->info, 9, clock_seq_low); + for (i=0;i<6;i++) { + SCVAL(guid->info, 10 + i, node[i]); + } + + return NT_STATUS_OK; +} + + const char *GUID_string(TALLOC_CTX *mem_ctx, const struct GUID *guid) { return talloc_asprintf(mem_ctx, diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index 6322123279..276b3c9ef4 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -60,37 +60,6 @@ void dcerpc_pipe_close(struct dcerpc_pipe *p) } -/* - build a GUID from a string -*/ -static NTSTATUS guid_from_string(const char *s, struct GUID *guid) -{ - uint32 time_low; - uint32 time_mid, time_hi_and_version; - uint32 clock_seq_hi_and_reserved; - uint32 clock_seq_low; - uint32 node[6]; - int i; - - if (11 != sscanf(s, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", - &time_low, &time_mid, &time_hi_and_version, - &clock_seq_hi_and_reserved, &clock_seq_low, - &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) { - return NT_STATUS_INVALID_PARAMETER; - } - - SIVAL(guid->info, 0, time_low); - SSVAL(guid->info, 4, time_mid); - SSVAL(guid->info, 6, time_hi_and_version); - SCVAL(guid->info, 8, clock_seq_hi_and_reserved); - SCVAL(guid->info, 9, clock_seq_low); - for (i=0;i<6;i++) { - SCVAL(guid->info, 10 + i, node[i]); - } - - return NT_STATUS_OK; -} - /* parse a data blob into a dcerpc_packet structure. This handles both input and output packets @@ -232,7 +201,7 @@ NTSTATUS dcerpc_bind_byuuid(struct dcerpc_pipe *p, struct dcerpc_syntax_id transfer_syntax; NTSTATUS status; - status = guid_from_string(uuid, &syntax.uuid); + status = GUID_from_string(uuid, &syntax.uuid); if (!NT_STATUS_IS_OK(status)) { DEBUG(2,("Invalid uuid string in dcerpc_bind_byuuid\n")); return status; @@ -240,7 +209,7 @@ NTSTATUS dcerpc_bind_byuuid(struct dcerpc_pipe *p, syntax.major_version = version; syntax.minor_version = 0; - status = guid_from_string("8a885d04-1ceb-11c9-9fe8-08002b104860", + status = GUID_from_string("8a885d04-1ceb-11c9-9fe8-08002b104860", &transfer_syntax.uuid); if (!NT_STATUS_IS_OK(status)) { return status; diff --git a/source4/torture/rpc/mgmt.c b/source4/torture/rpc/mgmt.c index 5eb0a56a7d..693703eb82 100644 --- a/source4/torture/rpc/mgmt.c +++ b/source4/torture/rpc/mgmt.c @@ -28,7 +28,7 @@ static BOOL test_inq_if_ids(struct dcerpc_pipe *p, NTSTATUS status; struct mgmt_inq_if_ids r; int i; - + status = dcerpc_mgmt_inq_if_ids(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { printf("inq_if_ids failed - %s\n", nt_errstr(status)); @@ -56,6 +56,103 @@ static BOOL test_inq_if_ids(struct dcerpc_pipe *p, return True; } +static BOOL test_inq_stats(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx) +{ + NTSTATUS status; + struct mgmt_inq_stats r; + + r.in.max_count = mgmt_stats_array_max_size; + r.in.unknown = 0; + + status = dcerpc_mgmt_inq_stats(p, mem_ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("inq_stats failed - %s\n", nt_errstr(status)); + return False; + } + + if (r.out.statistics.count != mgmt_stats_array_max_size) { + printf("Unexpected array size %d\n", r.out.statistics.count); + return False; + } + + printf("\tcalls_in %6d calls_out %6d\n\tpkts_in %6d pkts_out %6d\n", + r.out.statistics.statistics[mgmt_stats_calls_in], + r.out.statistics.statistics[mgmt_stats_calls_out], + r.out.statistics.statistics[mgmt_stats_pkts_in], + r.out.statistics.statistics[mgmt_stats_pkts_out]); + + return True; +} + +static BOOL test_inq_princ_name(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx) +{ +#if 0 + NTSTATUS status; + struct mgmt_inq_princ_name r; + + r.in.authn_proto = 1; + r.in.princ_name_size = 1000; + + status = dcerpc_mgmt_inq_princ_name(p, mem_ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("inq_princ_name failed - %s\n", nt_errstr(status)); + return False; + } + + return True; +#else + /* this is broken */ + printf("\tnot doing inq_princ_name\n"); + return True; +#endif +} + +static BOOL test_is_server_listening(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx) +{ + NTSTATUS status; + struct mgmt_is_server_listening r; + + status = dcerpc_mgmt_is_server_listening(p, mem_ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("is_server_listening failed - %s\n", nt_errstr(status)); + return False; + } + + if (r.out.status != 0 || r.out.result == 0) { + printf("\tserver is NOT listening\n"); + } else { + printf("\tserver is listening\n"); + } + + return True; +} + +static BOOL test_stop_server_listening(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx) +{ + NTSTATUS status; + struct mgmt_stop_server_listening r; + + status = dcerpc_mgmt_stop_server_listening(p, mem_ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("stop_server_listening failed - %s\n", nt_errstr(status)); + return False; + } + + if (r.out.status != 0) { + printf("\tserver refused to stop listening\n"); + } else { + printf("\tserver allowed a stop_server_listening request\n"); + return False; + } + + return True; +} + + BOOL torture_rpc_mgmt(int dummy) { NTSTATUS status; @@ -87,6 +184,22 @@ BOOL torture_rpc_mgmt(int dummy) p->flags |= DCERPC_DEBUG_PRINT_BOTH; + if (!test_is_server_listening(p, mem_ctx)) { + ret = False; + } + + if (!test_stop_server_listening(p, mem_ctx)) { + ret = False; + } + + if (!test_inq_stats(p, mem_ctx)) { + ret = False; + } + + if (!test_inq_princ_name(p, mem_ctx)) { + ret = False; + } + if (!test_inq_if_ids(p, mem_ctx)) { ret = False; } -- cgit