s4:torture/netlogon: add/use test_SetupCredentialsPipe() helper function
[samba.git] / source4 / torture / rpc / scanner.c
index 814b28a01d71f9fa8f320ef6d535c528917c61ac..261c3b91d0983b8c00279733032f7e65b12c7924 100644 (file)
@@ -7,7 +7,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"
-
-/*
-  find the number of calls defined by local IDL
-*/
-static const char *find_idl_name(const char *uuid, uint32 if_version)
-{
-       int i;
-       for (i=0;dcerpc_pipes[i];i++) {
-               if (strcasecmp(dcerpc_pipes[i]->uuid, uuid) == 0 &&
-                   dcerpc_pipes[i]->if_version == if_version) {
-                       return dcerpc_pipes[i]->name;
-               }
-       }
-       return "UNKNOWN";
-}
-
-/*
-  find the number of calls defined by local IDL
-*/
-static int num_idl_calls(const char *uuid, uint32 if_version)
-{
-       int i;
-       for (i=0;dcerpc_pipes[i];i++) {
-               if (strcasecmp(dcerpc_pipes[i]->uuid, uuid) == 0 &&
-                   dcerpc_pipes[i]->if_version == if_version) {
-                       return dcerpc_pipes[i]->num_calls;
-               }
-       }
-       return -1;
-}
+#include "librpc/gen_ndr/ndr_mgmt_c.h"
+#include "librpc/ndr/ndr_table.h"
+#include "torture/rpc/torture_rpc.h"
+#include "param/param.h"
 
 /*
   work out how many calls there are for an interface
  */
-static BOOL test_num_calls(const struct dcerpc_interface_table *iface,
+static bool test_num_calls(struct torture_context *tctx, 
+                          const struct ndr_interface_table *iface,
                           TALLOC_CTX *mem_ctx,
-                          struct dcerpc_syntax_id *id)
+                          struct ndr_syntax_id *id)
 {
        struct dcerpc_pipe *p;
        NTSTATUS status;
-       const char *uuid;
-       int i;
+       unsigned int i;
        DATA_BLOB stub_in, stub_out;
-       int idl_calls;
-
-       uuid = GUID_string(mem_ctx, &id->uuid);
+       struct ndr_interface_table _tbl;
+       const struct ndr_interface_table *tbl;
+
+       /* FIXME: This should be fixed when torture_rpc_connection 
+        * takes a ndr_syntax_id */
+       tbl = ndr_table_by_syntax(id);
+       if (tbl == NULL) {
+               _tbl = *iface;
+               _tbl.name = "__unknown__";
+               _tbl.syntax_id = *id;
+               _tbl.num_calls = UINT32_MAX;
+               tbl = &_tbl;
+       }
 
-       status = torture_rpc_connection(&p, iface->name,
-                                       uuid, id->major_version);
+       status = torture_rpc_connection(tctx, &p, tbl);
        if (!NT_STATUS_IS_OK(status)) {
+               char *uuid_str = GUID_string(mem_ctx, &id->uuid);
                printf("Failed to connect to '%s' on '%s' - %s\n", 
-                      uuid, iface->name, nt_errstr(status));
-               return False;
+                      uuid_str, iface->name, nt_errstr(status));
+               talloc_free(uuid_str);
+               return true;
        }
 
        /* make null calls */
-       stub_in = data_blob(NULL, 0);
-
-       status = dcerpc_request(p, 10000, mem_ctx, &stub_in, &stub_out);
-       if (NT_STATUS_IS_OK(status) ||
-           p->last_fault_code != DCERPC_FAULT_OP_RNG_ERROR) {
-               printf("unable to determine call count - %s %08x\n",
-                      nt_errstr(status), p->last_fault_code);
-               goto done;
-       }
+       stub_in = data_blob_talloc(mem_ctx, NULL, 1000);
+       memset(stub_in.data, 0xFF, stub_in.length);
+
+       for (i=0;i<200;i++) {
+               bool ok;
+               uint32_t out_flags = 0;
+
+               status = dcerpc_binding_handle_raw_call(p->binding_handle,
+                                                       NULL, i,
+                                                       0, /* in_flags */
+                                                       stub_in.data,
+                                                       stub_in.length,
+                                                       mem_ctx,
+                                                       &stub_out.data,
+                                                       &stub_out.length,
+                                                       &out_flags);
+               ok = dcerpc_binding_handle_is_connected(p->binding_handle);
+               if (!ok) {
+                       printf("\tpipe disconnected at %u\n", i);
+                       goto done;
+               }
 
-       for (i=128;i>=0;i--) {
-               status = dcerpc_request(p, i, mem_ctx, &stub_in, &stub_out);
-               if (NT_STATUS_IS_OK(status) ||
-                   p->last_fault_code != DCERPC_FAULT_OP_RNG_ERROR) break;
+               if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
+                       break;
+               }
+
+               if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+                       printf("\taccess denied at %u\n", i);
+                       goto done;
+               }
+
+               if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
+                       printf("\tprotocol error at %u\n", i);
+               }
        }
 
-       printf("\t%d calls available\n", i+1);
-       idl_calls = num_idl_calls(uuid, id->major_version);
-       if (idl_calls == -1) {
+       printf("\t%d calls available\n", i);
+       if (tbl->num_calls == UINT32_MAX) {
                printf("\tinterface not known in local IDL\n");
-       } else if (i+1 != idl_calls) {
-               printf("\tWARNING: local IDL defines %u calls\n", idl_calls);
+       } else if (tbl->num_calls != i) {
+               printf("\tWARNING: local IDL defines %u calls\n",
+                       (unsigned int)tbl->num_calls);
        } else {
                printf("\tOK: matches num_calls in local IDL\n");
        }
 
 done:
-       torture_rpc_close(p);
-       return True;
+       talloc_free(p);
+       return true;
 }
 
-/*
-  ask the server what interface IDs are available on this endpoint
-*/
-static BOOL test_inq_if_ids(struct dcerpc_pipe *p, 
-                           TALLOC_CTX *mem_ctx,
-                           const struct dcerpc_interface_table *iface)
-{
-       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));
-               return False;
-       }
-
-       if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("inq_if_ids gave error code %s\n", win_errstr(r.out.result));
-               return False;
-       }
-
-       if (!r.out.if_id_vector) {
-               printf("inq_if_ids gave NULL if_id_vector\n");
-               return False;
-       }
-
-       for (i=0;i<r.out.if_id_vector->count;i++) {
-               const char *uuid;
-               struct dcerpc_syntax_id *id = r.out.if_id_vector->if_id[i].id;
-               if (!id) continue;
-
-               uuid = GUID_string(mem_ctx, &id->uuid),
-
-               printf("\n\tuuid %s  version 0x%04x:0x%04x  '%s'\n",
-                      uuid,
-                      id->major_version, id->minor_version,
-                      find_idl_name(uuid, id->major_version));
-               test_num_calls(iface, mem_ctx, id);
-       }
-
-       return True;
-}
 
 
-BOOL torture_rpc_scanner(int dummy)
+bool torture_rpc_scanner(struct torture_context *torture)
 {
         NTSTATUS status;
         struct dcerpc_pipe *p;
-       TALLOC_CTX *mem_ctx;
-       BOOL ret = True;
-       int i;
-       char *host = lp_parm_string(-1, "torture", "host");
-       uint32 port;
+       TALLOC_CTX *loop_ctx;
+       bool ret = true;
+       const struct ndr_interface_list *l;
+       struct dcerpc_binding *b;
+       enum dcerpc_transport_t transport;
 
-       mem_ctx = talloc_init("torture_rpc_scanner");
-
-       for (i=0;dcerpc_pipes[i];i++) {         
-               char *transport = lp_parm_string(-1, "torture", "transport");
+       status = torture_rpc_binding(torture, &b);
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+       transport = dcerpc_binding_get_transport(b);
 
+       for (l=ndr_table_list();l;l=l->next) {          
+               loop_ctx = talloc_named(torture, 0, "torture_rpc_scanner loop context");
                /* some interfaces are not mappable */
-               if (dcerpc_pipes[i]->num_calls == 0 ||
-                   strcmp(dcerpc_pipes[i]->name, "mgmt") == 0) {
+               if (l->table->num_calls == 0 ||
+                   strcmp(l->table->name, "mgmt") == 0) {
+                       talloc_free(loop_ctx);
                        continue;
                }
 
-               printf("\nTesting pipe '%s'\n", dcerpc_pipes[i]->name);
+               printf("\nTesting pipe '%s'\n", l->table->name);
 
-               /* on TCP we need to find the right endpoint */
-               if (strcasecmp(transport, "ncacn_ip_tcp") == 0) {
-                       status = dcerpc_epm_map_tcp_port(host, 
-                                                        dcerpc_pipes[i]->uuid, 
-                                                        dcerpc_pipes[i]->if_version, 
-                                                        &port);
+               if (transport == NCACN_IP_TCP) {
+                       status = dcerpc_epm_map_binding(torture, b, l->table,
+                                                       torture->ev,
+                                                       torture->lp_ctx);
                        if (!NT_STATUS_IS_OK(status)) {
-                               ret = False;
+                               printf("Failed to map port for uuid %s\n", 
+                                          GUID_string(loop_ctx, &l->table->syntax_id.uuid));
+                               talloc_free(loop_ctx);
+                               continue;
+                       }
+               } else {
+                       status = dcerpc_binding_set_string_option(b, "endpoint",
+                                                                 l->table->name);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               talloc_free(loop_ctx);
+                               ret = false;
+                               continue;
+                       }
+                       status = dcerpc_binding_set_abstract_syntax(b,
+                                                       &l->table->syntax_id);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               talloc_free(loop_ctx);
+                               ret = false;
                                continue;
                        }
-
-                       lp_set_cmdline("torture:share", 
-                                      talloc_asprintf(mem_ctx, "%u", port));
                }
 
-               status = torture_rpc_connection(&p, 
-                                               dcerpc_pipes[i]->name,
-                                               DCERPC_MGMT_UUID,
-                                               DCERPC_MGMT_VERSION);
+               lpcfg_set_cmdline(torture->lp_ctx, "torture:binding", dcerpc_binding_string(torture, b));
+
+               status = torture_rpc_connection(torture, &p, &ndr_table_mgmt);
                if (!NT_STATUS_IS_OK(status)) {
-                       ret = False;
+                       talloc_free(loop_ctx);
+                       ret = false;
                        continue;
                }
        
-               if (!test_inq_if_ids(p, mem_ctx, dcerpc_pipes[i])) {
-                       ret = False;
+               if (!test_inq_if_ids(torture, p->binding_handle, torture, test_num_calls, l->table)) {
+                       ret = false;
                }
-
-               torture_rpc_close(p);
        }
 
        return ret;
 }
+