Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into registry
[ira/wip.git] / source4 / torture / rpc / rpc.c
index 4fe35a5cf7de148a857860f4821bbfb5ddaac6b8..acc1220ccc94484fcef6b6748bb360434e6f9dc8 100644 (file)
@@ -6,7 +6,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "auth/credentials/credentials.h"
 #include "lib/cmdline/popt_common.h"
+#include "librpc/rpc/dcerpc.h"
 #include "torture/rpc/rpc.h"
-#include "torture/torture.h"
+#include "torture/smbtorture.h"
+#include "librpc/ndr/ndr_table.h"
+#include "lib/util/dlinklist.h"
 
-/* open a rpc connection to the chosen binding string */
-NTSTATUS torture_rpc_connection(TALLOC_CTX *parent_ctx, 
-                               struct dcerpc_pipe **p, 
-                               const struct dcerpc_interface_table *table)
+static bool torture_rpc_teardown (struct torture_context *tcase, 
+                                         void *data)
+{
+       struct torture_rpc_tcase_data *tcase_data = 
+               (struct torture_rpc_tcase_data *)data;
+       if (tcase_data->join_ctx != NULL)
+           torture_leave_domain(tcase_data->join_ctx);
+       talloc_free(tcase_data);
+       return true;
+}
+
+/**
+ * Obtain the DCE/RPC binding context associated with a torture context.
+ *
+ * @param tctx Torture context
+ * @param binding Pointer to store DCE/RPC binding
+ */
+NTSTATUS torture_rpc_binding(struct torture_context *tctx,
+                            struct dcerpc_binding **binding)
 {
-        NTSTATUS status;
-       const char *binding = lp_parm_string(-1, "torture", "binding");
+       NTSTATUS status;
+       const char *binding_string = torture_setting_string(tctx, "binding", 
+                                                           NULL);
 
-       if (!binding) {
-               printf("You must specify a ncacn binding string\n");
+       if (binding_string == NULL) {
+               torture_comment(tctx, 
+                               "You must specify a DCE/RPC binding string\n");
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       status = dcerpc_pipe_connect(parent_ctx, 
+       status = dcerpc_parse_binding(tctx, binding_string, binding);
+       if (NT_STATUS_IS_ERR(status)) {
+               DEBUG(0,("Failed to parse dcerpc binding '%s'\n", 
+                        binding_string));
+               return status;
+       }
+
+       return NT_STATUS_OK;    
+}
+
+/**
+ * open a rpc connection to the chosen binding string
+ */
+_PUBLIC_ NTSTATUS torture_rpc_connection(struct torture_context *tctx,
+                               struct dcerpc_pipe **p, 
+                               const struct ndr_interface_table *table)
+{
+       NTSTATUS status;
+       struct dcerpc_binding *binding;
+
+       status = torture_rpc_binding(tctx, &binding);
+       if (NT_STATUS_IS_ERR(status))
+               return status;
+
+       status = dcerpc_pipe_connect_b(tctx, 
                                     p, binding, table,
-                                    cmdline_credentials, NULL);
+                                    cmdline_credentials, tctx->ev, tctx->lp_ctx);
  
-        return status;
+       if (NT_STATUS_IS_ERR(status)) {
+               printf("Failed to connect to remote server: %s %s\n", 
+                          dcerpc_binding_string(tctx, binding), nt_errstr(status));
+       }
+
+       return status;
 }
 
-/* open a rpc connection to a specific transport */
-NTSTATUS torture_rpc_connection_transport(TALLOC_CTX *parent_ctx, 
+/**
+ * open a rpc connection to a specific transport
+ */
+NTSTATUS torture_rpc_connection_transport(struct torture_context *tctx, 
                                          struct dcerpc_pipe **p, 
-                                         const struct dcerpc_interface_table *table,
-                                         enum dcerpc_transport_t transport)
+                                         const struct ndr_interface_table *table,
+                                         enum dcerpc_transport_t transport,
+                                         uint32_t assoc_group_id)
 {
-        NTSTATUS status;
-       const char *binding = lp_parm_string(-1, "torture", "binding");
-       struct dcerpc_binding *b;
-       TALLOC_CTX *mem_ctx = talloc_named(parent_ctx, 0, "torture_rpc_connection_smb");
+       NTSTATUS status;
+       struct dcerpc_binding *binding;
 
-       if (!binding) {
-               printf("You must specify a ncacn binding string\n");
-               talloc_free(mem_ctx);
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       status = dcerpc_parse_binding(mem_ctx, binding, &b);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0,("Failed to parse dcerpc binding '%s'\n", binding));
-               talloc_free(mem_ctx);
+       status = torture_rpc_binding(tctx, &binding);
+       if (NT_STATUS_IS_ERR(status))
                return status;
-       }
 
-       b->transport = transport;
+       binding->transport = transport;
+       binding->assoc_group_id = assoc_group_id;
 
-       status = dcerpc_pipe_connect_b(mem_ctx, p, b, table,
-                                      cmdline_credentials, NULL);
+       status = dcerpc_pipe_connect_b(tctx, p, binding, table,
+                                      cmdline_credentials, tctx->ev, tctx->lp_ctx);
                                           
-       if (NT_STATUS_IS_OK(status)) {
-               *p = talloc_reference(parent_ctx, *p);
-       } else {
+       if (NT_STATUS_IS_ERR(status)) {
                *p = NULL;
        }
-       talloc_free(mem_ctx);
+
         return status;
 }
 
+static bool torture_rpc_setup_machine(struct torture_context *tctx,
+                                     void **data)
+{
+       NTSTATUS status;
+       struct dcerpc_binding *binding;
+       struct torture_rpc_tcase *tcase = talloc_get_type(tctx->active_tcase, 
+                                               struct torture_rpc_tcase);
+       struct torture_rpc_tcase_data *tcase_data;
+
+       status = torture_rpc_binding(tctx, &binding);
+       if (NT_STATUS_IS_ERR(status))
+               return false;
+
+       *data = tcase_data = talloc_zero(tctx, struct torture_rpc_tcase_data);
+       tcase_data->credentials = cmdline_credentials;
+       tcase_data->join_ctx = torture_join_domain(tctx, tcase->machine_name,
+                                                  ACB_SVRTRUST, 
+                                                  &tcase_data->credentials);
+       if (tcase_data->join_ctx == NULL)
+           torture_fail(tctx, "Failed to join as BDC");
+
+       status = dcerpc_pipe_connect_b(tctx, 
+                               &(tcase_data->pipe),
+                               binding,
+                               tcase->table,
+                               tcase_data->credentials, tctx->ev, tctx->lp_ctx);
+
+       torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
+
+       return true;
+}
+
+_PUBLIC_ struct torture_rpc_tcase *torture_suite_add_machine_rpc_iface_tcase(
+                               struct torture_suite *suite, 
+                               const char *name,
+                               const struct ndr_interface_table *table,
+                               const char *machine_name)
+{
+       struct torture_rpc_tcase *tcase = talloc(suite, 
+                                                struct torture_rpc_tcase);
+
+       torture_suite_init_rpc_tcase(suite, tcase, name, table);
+
+       tcase->machine_name = talloc_strdup(tcase, machine_name);
+       tcase->tcase.setup = torture_rpc_setup_machine;
+       tcase->tcase.teardown = torture_rpc_teardown;
+
+       return tcase;
+}
+
+_PUBLIC_ bool torture_suite_init_rpc_tcase(struct torture_suite *suite, 
+                                          struct torture_rpc_tcase *tcase, 
+                                          const char *name,
+                                          const struct ndr_interface_table *table)
+{
+       if (!torture_suite_init_tcase(suite, (struct torture_tcase *)tcase, name))
+               return false;
+
+       tcase->table = table;
+
+       return true;
+}
+
+static bool torture_rpc_setup_anonymous(struct torture_context *tctx, 
+                                       void **data)
+{
+       NTSTATUS status;
+       struct dcerpc_binding *binding;
+       struct torture_rpc_tcase_data *tcase_data;
+       struct torture_rpc_tcase *tcase = talloc_get_type(tctx->active_tcase, 
+                                                         struct torture_rpc_tcase);
+
+       status = torture_rpc_binding(tctx, &binding);
+       if (NT_STATUS_IS_ERR(status))
+               return false;
+
+       *data = tcase_data = talloc_zero(tctx, struct torture_rpc_tcase_data);
+       tcase_data->credentials = cli_credentials_init_anon(tctx);
+
+       status = dcerpc_pipe_connect_b(tctx, 
+                               &(tcase_data->pipe),
+                               binding,
+                               tcase->table,
+                               tcase_data->credentials, tctx->ev, tctx->lp_ctx);
+
+       torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
+
+       return true;
+}
+
+static bool torture_rpc_setup (struct torture_context *tctx, void **data)
+{
+       NTSTATUS status;
+       struct torture_rpc_tcase *tcase = talloc_get_type(
+                                               tctx->active_tcase, struct torture_rpc_tcase);
+       struct torture_rpc_tcase_data *tcase_data;
+
+       *data = tcase_data = talloc_zero(tctx, struct torture_rpc_tcase_data);
+       tcase_data->credentials = cmdline_credentials;
+       
+       status = torture_rpc_connection(tctx, 
+                               &(tcase_data->pipe),
+                               tcase->table);
+
+       torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
+
+       return true;
+}
+
+
+
+_PUBLIC_ struct torture_rpc_tcase *torture_suite_add_anon_rpc_iface_tcase(struct torture_suite *suite, 
+                                                               const char *name,
+                                                               const struct ndr_interface_table *table)
+{
+       struct torture_rpc_tcase *tcase = talloc(suite, struct torture_rpc_tcase);
+
+       torture_suite_init_rpc_tcase(suite, tcase, name, table);
+
+       tcase->tcase.setup = torture_rpc_setup_anonymous;
+       tcase->tcase.teardown = torture_rpc_teardown;
+
+       return tcase;
+}
+
+
+_PUBLIC_ struct torture_rpc_tcase *torture_suite_add_rpc_iface_tcase(struct torture_suite *suite, 
+                                                               const char *name,
+                                                               const struct ndr_interface_table *table)
+{
+       struct torture_rpc_tcase *tcase = talloc(suite, struct torture_rpc_tcase);
+
+       torture_suite_init_rpc_tcase(suite, tcase, name, table);
+
+       tcase->tcase.setup = torture_rpc_setup;
+       tcase->tcase.teardown = torture_rpc_teardown;
+
+       return tcase;
+}
+
+static bool torture_rpc_wrap_test(struct torture_context *tctx, 
+                                                                 struct torture_tcase *tcase,
+                                                                 struct torture_test *test)
+{
+       bool (*fn) (struct torture_context *, struct dcerpc_pipe *);
+       struct torture_rpc_tcase_data *tcase_data = 
+               (struct torture_rpc_tcase_data *)tcase->data;
+
+       fn = test->fn;
+
+       return fn(tctx, tcase_data->pipe);
+}
+
+static bool torture_rpc_wrap_test_ex(struct torture_context *tctx, 
+                                                                 struct torture_tcase *tcase,
+                                                                 struct torture_test *test)
+{
+       bool (*fn) (struct torture_context *, struct dcerpc_pipe *, const void *);
+       struct torture_rpc_tcase_data *tcase_data = 
+               (struct torture_rpc_tcase_data *)tcase->data;
+
+       fn = test->fn;
+
+       return fn(tctx, tcase_data->pipe, test->data);
+}
+
+
+static bool torture_rpc_wrap_test_creds(struct torture_context *tctx, 
+                                                                 struct torture_tcase *tcase,
+                                                                 struct torture_test *test)
+{
+       bool (*fn) (struct torture_context *, struct dcerpc_pipe *, struct cli_credentials *);
+       struct torture_rpc_tcase_data *tcase_data = 
+               (struct torture_rpc_tcase_data *)tcase->data;
+
+       fn = test->fn;
+
+       return fn(tctx, tcase_data->pipe, tcase_data->credentials);
+}
+
+_PUBLIC_ struct torture_test *torture_rpc_tcase_add_test(
+                                       struct torture_rpc_tcase *tcase, 
+                                       const char *name, 
+                                       bool (*fn) (struct torture_context *, struct dcerpc_pipe *))
+{
+       struct torture_test *test;
+
+       test = talloc(tcase, struct torture_test);
+
+       test->name = talloc_strdup(test, name);
+       test->description = NULL;
+       test->run = torture_rpc_wrap_test;
+       test->dangerous = false;
+       test->data = NULL;
+       test->fn = fn;
+
+       DLIST_ADD(tcase->tcase.tests, test);
+
+       return test;
+}
+
+_PUBLIC_ struct torture_test *torture_rpc_tcase_add_test_creds(
+                                       struct torture_rpc_tcase *tcase, 
+                                       const char *name, 
+                                       bool (*fn) (struct torture_context *, struct dcerpc_pipe *, struct cli_credentials *))
+{
+       struct torture_test *test;
+
+       test = talloc(tcase, struct torture_test);
+
+       test->name = talloc_strdup(test, name);
+       test->description = NULL;
+       test->run = torture_rpc_wrap_test_creds;
+       test->dangerous = false;
+       test->data = NULL;
+       test->fn = fn;
+
+       DLIST_ADD(tcase->tcase.tests, test);
+
+       return test;
+}
+
+_PUBLIC_ struct torture_test *torture_rpc_tcase_add_test_ex(
+                                       struct torture_rpc_tcase *tcase, 
+                                       const char *name, 
+                                       bool (*fn) (struct torture_context *, struct dcerpc_pipe *,
+                                                               void *),
+                                       void *userdata)
+{
+       struct torture_test *test;
+
+       test = talloc(tcase, struct torture_test);
+
+       test->name = talloc_strdup(test, name);
+       test->description = NULL;
+       test->run = torture_rpc_wrap_test_ex;
+       test->dangerous = false;
+       test->data = userdata;
+       test->fn = fn;
+
+       DLIST_ADD(tcase->tcase.tests, test);
+
+       return test;
+}
+
 NTSTATUS torture_rpc_init(void)
 {
-    register_torture_op("RPC-LSA", torture_rpc_lsa, 0);
-    register_torture_op("RPC-LSALOOKUP", torture_rpc_lsa_lookup, 0);
-    register_torture_op("RPC-SECRETS", torture_rpc_lsa_secrets, 0);
-    register_torture_op("RPC-ECHO", torture_rpc_echo, 0);
-    register_torture_op("RPC-DFS", torture_rpc_dfs, 0);
-    register_torture_op("RPC-SPOOLSS", torture_rpc_spoolss, 0);
-    register_torture_op("RPC-SAMR", torture_rpc_samr, 0);
-    register_torture_op("RPC-UNIXINFO", torture_rpc_unixinfo, 0);
-    register_torture_op("RPC-NETLOGON", torture_rpc_netlogon, 0);
-    register_torture_op("RPC-SAMLOGON", torture_rpc_samlogon, 0);
-    register_torture_op("RPC-SAMSYNC", torture_rpc_samsync, 0);
-    register_torture_op("RPC-SCHANNEL", torture_rpc_schannel, 0);
-    register_torture_op("RPC-WKSSVC", torture_rpc_wkssvc, 0);
-    register_torture_op("RPC-SRVSVC", torture_rpc_srvsvc, 0);
-    register_torture_op("RPC-SVCCTL", torture_rpc_svcctl, 0);
-    register_torture_op("RPC-ATSVC", torture_rpc_atsvc, 0);
-    register_torture_op("RPC-EVENTLOG", torture_rpc_eventlog, 0);
-    register_torture_op("RPC-EPMAPPER", torture_rpc_epmapper, 0);
-    register_torture_op("RPC-WINREG", torture_rpc_winreg, 0);
-    register_torture_op("RPC-INITSHUTDOWN", torture_rpc_initshutdown, 0);
-    register_torture_op("RPC-OXIDRESOLVE", torture_rpc_oxidresolve, 0);
-    register_torture_op("RPC-REMACT", torture_rpc_remact, 0);
-    register_torture_op("RPC-MGMT", torture_rpc_mgmt, 0);
-    register_torture_op("RPC-SCANNER", torture_rpc_scanner, 0);
-    register_torture_op("RPC-AUTOIDL", torture_rpc_autoidl, 0);
-    register_torture_op("RPC-COUNTCALLS", torture_rpc_countcalls, 0);
-       register_torture_op("RPC-MULTIBIND", torture_multi_bind, 0);
-       register_torture_op("RPC-DRSUAPI", torture_rpc_drsuapi, 0);
-       register_torture_op("RPC-CRACKNAMES", torture_rpc_drsuapi_cracknames, 0);
-       register_torture_op("RPC-ROT", torture_rpc_rot, 0);
-       register_torture_op("RPC-DSSETUP", torture_rpc_dssetup, 0);
-    register_torture_op("RPC-ALTERCONTEXT", torture_rpc_alter_context, 0);
-    register_torture_op("RPC-JOIN", torture_rpc_join, 0);
-    register_torture_op("RPC-DSSYNC", torture_rpc_dssync, 0);
-       register_torture_op("BENCH-RPC", torture_bench_rpc, 0);
+       struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "RPC");
+
+       dcerpc_init();
+
+       ndr_table_init();
+
+       torture_suite_add_simple_test(suite, "LSA", torture_rpc_lsa);
+       torture_suite_add_simple_test(suite, "LSALOOKUP", torture_rpc_lsa_lookup);
+       torture_suite_add_simple_test(suite, "LSA-GETUSER", torture_rpc_lsa_get_user);
+       torture_suite_add_suite(suite, torture_rpc_lsa_secrets(suite));
+       torture_suite_add_suite(suite, torture_rpc_echo(suite));
+       torture_suite_add_simple_test(suite, "DFS", torture_rpc_dfs);
+       torture_suite_add_suite(suite, torture_rpc_frsapi(suite));
+       torture_suite_add_suite(suite, torture_rpc_unixinfo(suite));
+       torture_suite_add_suite(suite, torture_rpc_eventlog(suite));
+       torture_suite_add_suite(suite, torture_rpc_atsvc(suite));
+       torture_suite_add_suite(suite, torture_rpc_wkssvc(suite));
+       torture_suite_add_suite(suite, torture_rpc_handles(suite));
+       torture_suite_add_suite(suite, torture_rpc_winreg(suite));
+       torture_suite_add_simple_test(suite, "SPOOLSS", torture_rpc_spoolss);
+       torture_suite_add_suite(suite, torture_rpc_spoolss_notify(suite));
+       torture_suite_add_suite(suite, torture_rpc_spoolss_win(suite));
+       torture_suite_add_simple_test(suite, "SAMR", torture_rpc_samr);
+       torture_suite_add_simple_test(suite, "SAMR-USERS", torture_rpc_samr_users);
+       torture_suite_add_simple_test(suite, "SAMR-PASSWORDS", torture_rpc_samr_passwords);
+       torture_suite_add_suite(suite, torture_rpc_netlogon(suite));
+       torture_suite_add_simple_test(suite, "SAMLOGON", torture_rpc_samlogon);
+       torture_suite_add_simple_test(suite, "SAMSYNC", torture_rpc_samsync);
+       torture_suite_add_simple_test(suite, "SCHANNEL", torture_rpc_schannel);
+       torture_suite_add_simple_test(suite, "SCHANNEL2", torture_rpc_schannel2);
+       torture_suite_add_simple_test(suite, "BENCH-SCHANNEL1", torture_rpc_schannel_bench1);
+       torture_suite_add_suite(suite, torture_rpc_srvsvc(suite));
+       torture_suite_add_suite(suite, torture_rpc_svcctl(suite));
+       torture_suite_add_suite(suite, torture_rpc_samr_accessmask(suite));
+       torture_suite_add_suite(suite, torture_rpc_epmapper(suite));
+       torture_suite_add_suite(suite, torture_rpc_initshutdown(suite));
+       torture_suite_add_suite(suite, torture_rpc_oxidresolve(suite));
+       torture_suite_add_suite(suite, torture_rpc_remact(suite));
+       torture_suite_add_simple_test(suite, "MGMT", torture_rpc_mgmt);
+       torture_suite_add_simple_test(suite, "SCANNER", torture_rpc_scanner);
+       torture_suite_add_simple_test(suite, "AUTOIDL", torture_rpc_autoidl);
+       torture_suite_add_simple_test(suite, "COUNTCALLS", torture_rpc_countcalls);
+       torture_suite_add_simple_test(suite, "MULTIBIND", torture_multi_bind);
+       torture_suite_add_simple_test(suite, "AUTHCONTEXT", torture_bind_authcontext);
+       torture_suite_add_simple_test(suite, "BINDSAMBA3", torture_bind_samba3);
+       torture_suite_add_simple_test(suite, "NETLOGSAMBA3", torture_netlogon_samba3);
+       torture_suite_add_simple_test(suite, "SAMBA3SESSIONKEY", torture_samba3_sessionkey);
+       torture_suite_add_simple_test(suite, "SAMBA3-SRVSVC", torture_samba3_rpc_srvsvc);
+       torture_suite_add_simple_test(suite, "SAMBA3-SHARESEC",
+                           torture_samba3_rpc_sharesec);
+       torture_suite_add_simple_test(suite, "SAMBA3-GETUSERNAME",
+                           torture_samba3_rpc_getusername);
+       torture_suite_add_simple_test(suite, "SAMBA3-RANDOMAUTH2",
+                                     torture_samba3_rpc_randomauth2);
+       torture_suite_add_simple_test(suite, "SAMBA3-LSA", torture_samba3_rpc_lsa);
+       torture_suite_add_simple_test(suite, "SAMBA3-SPOOLSS", torture_samba3_rpc_spoolss);
+       torture_suite_add_simple_test(suite, "SAMBA3-WKSSVC", torture_samba3_rpc_wkssvc);
+       torture_suite_add_simple_test(suite, "SAMBA3-WINREG", torture_samba3_rpc_winreg);
+       torture_suite_add_simple_test(suite, "DRSUAPI", torture_rpc_drsuapi);
+       torture_suite_add_simple_test(suite, "CRACKNAMES", torture_rpc_drsuapi_cracknames);
+       torture_suite_add_suite(suite, torture_rpc_dssetup(suite));
+       torture_suite_add_simple_test(suite, "SAMBA3-REGCONFIG", torture_samba3_regconfig);
+       torture_suite_add_simple_test(suite, "ALTERCONTEXT", torture_rpc_alter_context);
+       torture_suite_add_simple_test(suite, "JOIN", torture_rpc_join);
+       torture_suite_add_simple_test(suite, "DSSYNC", torture_rpc_dssync);
+       torture_suite_add_simple_test(suite, "BENCH-RPC", torture_bench_rpc);
+       torture_suite_add_simple_test(suite, "ASYNCBIND", torture_async_bind);
+
+       suite->description = talloc_strdup(suite, "DCE/RPC protocol and interface tests");
+
+       torture_register_suite(suite);
 
        return NT_STATUS_OK;
 }