r23231: Fix make test on build farm for 64-bit hosts. There's no reason this should
[kai/samba.git] / source / torture / rpc / samba3rpc.c
index 94613185dcb0f95568f7b3cf791b7e2ac02dbf98..d5a00557cf5df6ca0d5e0d12dc23520bf1c666d5 100644 (file)
 
 #include "includes.h"
 #include "libcli/raw/libcliraw.h"
+#include "libcli/rap/rap.h"
 #include "torture/torture.h"
 #include "torture/util.h"
+#include "torture/rap/proto.h"
 #include "librpc/gen_ndr/ndr_lsa.h"
 #include "librpc/gen_ndr/ndr_lsa_c.h"
 #include "librpc/gen_ndr/ndr_samr.h"
 #include "librpc/gen_ndr/ndr_srvsvc_c.h"
 #include "librpc/gen_ndr/ndr_spoolss.h"
 #include "librpc/gen_ndr/ndr_spoolss_c.h"
+#include "librpc/gen_ndr/ndr_winreg.h"
+#include "librpc/gen_ndr/ndr_winreg_c.h"
+#include "librpc/gen_ndr/ndr_wkssvc.h"
+#include "librpc/gen_ndr/ndr_wkssvc_c.h"
 #include "lib/cmdline/popt_common.h"
 #include "librpc/rpc/dcerpc.h"
 #include "torture/rpc/rpc.h"
@@ -41,7 +47,6 @@
 #include "libcli/composite/composite.h"
 #include "libcli/smb_composite/smb_composite.h"
 #include "libcli/auth/libcli_auth.h"
-#include "libcli/auth/credentials.h"
 #include "lib/crypto/crypto.h"
 #include "libcli/security/proto.h"
 
@@ -87,7 +92,7 @@ BOOL torture_bind_authcontext(struct torture_context *torture)
        }
 
        status = smbcli_full_connection(mem_ctx, &cli,
-                                       lp_parm_string(-1, "torture", "host"),
+                                       torture_setting_string(torture, "host", NULL),
                                        "IPC$", NULL, cmdline_credentials,
                                        NULL);
        if (!NT_STATUS_IS_OK(status)) {
@@ -102,7 +107,7 @@ BOOL torture_bind_authcontext(struct torture_context *torture)
                goto done;
        }
 
-       status = dcerpc_pipe_open_smb(lsa_pipe->conn, cli->tree, "\\lsarpc");
+       status = dcerpc_pipe_open_smb(lsa_pipe, cli->tree, "\\lsarpc");
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("dcerpc_pipe_open_smb failed: %s\n",
                         nt_errstr(status));
@@ -163,6 +168,7 @@ BOOL torture_bind_authcontext(struct torture_context *torture)
                         nt_errstr(status));
                goto done;
        }
+       session2->vuid = setup.out.vuid;
 
        tmp = cli->tree->session;
        cli->tree->session = session2;
@@ -217,7 +223,7 @@ static BOOL bindtest(struct smbcli_state *cli,
                goto done;
        }
 
-       status = dcerpc_pipe_open_smb(lsa_pipe->conn, cli->tree, "\\lsarpc");
+       status = dcerpc_pipe_open_smb(lsa_pipe, cli->tree, "\\lsarpc");
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("dcerpc_pipe_open_smb failed: %s\n",
                         nt_errstr(status));
@@ -292,7 +298,7 @@ BOOL torture_bind_samba3(struct torture_context *torture)
        }
 
        status = smbcli_full_connection(mem_ctx, &cli,
-                                       lp_parm_string(-1, "torture", "host"),
+                                       torture_setting_string(torture, "host", NULL),
                                        "IPC$", NULL, cmdline_credentials,
                                        NULL);
        if (!NT_STATUS_IS_OK(status)) {
@@ -356,7 +362,7 @@ static NTSTATUS get_usr_handle(struct smbcli_state *cli,
                goto fail;
        }
 
-       status = dcerpc_pipe_open_smb(samr_pipe->conn, cli->tree, "\\samr");
+       status = dcerpc_pipe_open_smb(samr_pipe, cli->tree, "\\samr");
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("dcerpc_pipe_open_smb failed: %s\n",
                         nt_errstr(status));
@@ -576,6 +582,7 @@ static BOOL create_user(TALLOC_CTX *mem_ctx, struct smbcli_state *cli,
                qui.out.info->info21.force_password_change = 0;
                qui.out.info->info21.account_name.string = NULL;
                qui.out.info->info21.rid = 0;
+               qui.out.info->info21.acct_expiry = 0;
                qui.out.info->info21.fields_present = 0x81827fa; /* copy usrmgr.exe */
 
                u_info.info21 = qui.out.info->info21;
@@ -816,7 +823,7 @@ static BOOL auth2(struct smbcli_state *cli,
                goto done;
        }
 
-       status = dcerpc_pipe_open_smb(net_pipe->conn, cli->tree, "\\netlogon");
+       status = dcerpc_pipe_open_smb(net_pipe, cli->tree, "\\netlogon");
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("dcerpc_pipe_open_smb failed: %s\n",
                         nt_errstr(status));
@@ -917,7 +924,7 @@ static BOOL schan(struct smbcli_state *cli,
                goto done;
        }
 
-       status = dcerpc_pipe_open_smb(net_pipe->conn, cli->tree, "\\netlogon");
+       status = dcerpc_pipe_open_smb(net_pipe, cli->tree, "\\netlogon");
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("dcerpc_pipe_open_smb failed: %s\n",
                         nt_errstr(status));
@@ -1119,12 +1126,12 @@ BOOL torture_netlogon_samba3(struct torture_context *torture)
        const char *wks_name;
        int i;
 
-       wks_name = lp_parm_string(-1, "torture", "wksname");
+       wks_name = torture_setting_string(torture, "wksname", NULL);
        if (wks_name == NULL) {
                wks_name = get_myname();
        }
 
-       mem_ctx = talloc_init("torture_bind_authcontext");
+       mem_ctx = talloc_init("torture_netlogon_samba3");
 
        if (mem_ctx == NULL) {
                d_printf("talloc_init failed\n");
@@ -1137,7 +1144,7 @@ BOOL torture_netlogon_samba3(struct torture_context *torture)
        }
 
        status = smbcli_full_connection(mem_ctx, &cli,
-                                       lp_parm_string(-1, "torture", "host"),
+                                       torture_setting_string(torture, "host", NULL),
                                        "IPC$", NULL, anon_creds, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("smbcli_full_connection failed: %s\n",
@@ -1279,10 +1286,7 @@ BOOL torture_samba3_sessionkey(struct torture_context *torture)
        struct cli_credentials *anon_creds;
        const char *wks_name;
 
-       wks_name = lp_parm_string(-1, "torture", "wksname");
-       if (wks_name == NULL) {
-               wks_name = get_myname();
-       }
+       wks_name = torture_setting_string(torture, "wksname", get_myname());
 
        mem_ctx = talloc_init("torture_samba3_sessionkey");
 
@@ -1298,7 +1302,7 @@ BOOL torture_samba3_sessionkey(struct torture_context *torture)
 
        ret = True;
 
-       if (!lp_parm_bool(-1, "target", "samba3", False)) {
+       if (!torture_setting_bool(torture, "samba3", False)) {
 
                /* Samba3 in the build farm right now does this happily. Need
                 * to fix :-) */
@@ -1371,7 +1375,7 @@ static NTSTATUS pipe_bind_smb(TALLOC_CTX *mem_ctx,
                return NT_STATUS_NO_MEMORY;
        }
 
-       status = dcerpc_pipe_open_smb(result->conn, tree, pipe_name);
+       status = dcerpc_pipe_open_smb(result, tree, pipe_name);
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("dcerpc_pipe_open_smb failed: %s\n",
                         nt_errstr(status));
@@ -1456,9 +1460,10 @@ static struct dom_sid *name2sid(TALLOC_CTX *mem_ctx,
 
        status = dcerpc_lsa_LookupNames(p, tmp_ctx, &l);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("LookupNames failed - %s\n", nt_errstr(status));
+               printf("LookupNames of %s failed - %s\n", lsa_name.string, 
+                      nt_errstr(status));
                talloc_free(tmp_ctx);
-               return False;
+               return NULL;
        }
 
        result = dom_sid_add_rid(mem_ctx, l.out.domains->domains[0].sid,
@@ -1506,7 +1511,8 @@ static struct dom_sid *whoami(TALLOC_CTX *mem_ctx, struct smbcli_tree *tree)
        status = dcerpc_lsa_GetUserName(lsa, mem_ctx, &r);
 
        if (!NT_STATUS_IS_OK(status)) {
-               printf("GetUserName failed - %s\n", nt_errstr(status));
+               printf("(%s) GetUserName failed - %s\n",
+                      __location__, nt_errstr(status));
                talloc_free(lsa);
                return NULL;
        }
@@ -1549,7 +1555,8 @@ NTSTATUS secondary_tcon(TALLOC_CTX *mem_ctx,
 
        status = smb_raw_tcon(result, tmp_ctx, &tcon);
        if (!NT_STATUS_IS_OK(status)) {
-               d_printf("smb_raw_tcon failed: %s\n", nt_errstr(status));
+               d_printf("(%s) smb_raw_tcon failed: %s\n", __location__,
+                        nt_errstr(status));
                talloc_free(tmp_ctx);
                return status;
        }
@@ -1582,53 +1589,56 @@ BOOL torture_samba3_rpc_getusername(struct torture_context *torture)
        }
 
        status = smbcli_full_connection(
-               mem_ctx, &cli, lp_parm_string(-1, "torture", "host"),
+               mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
                "IPC$", NULL, cmdline_credentials, NULL);
        if (!NT_STATUS_IS_OK(status)) {
-               d_printf("smbcli_full_connection failed: %s\n",
-                        nt_errstr(status));
+               d_printf("(%s) smbcli_full_connection failed: %s\n",
+                        __location__, nt_errstr(status));
                ret = False;
                goto done;
        }
 
        if (!(user_sid = whoami(mem_ctx, cli->tree))) {
-               d_printf("whoami on auth'ed connection failed\n");
+               d_printf("(%s) whoami on auth'ed connection failed\n",
+                        __location__);
                ret = False;
        }
 
        talloc_free(cli);
 
        if (!(anon_creds = create_anon_creds(mem_ctx))) {
-               d_printf("create_anon_creds failed\n");
+               d_printf("(%s) create_anon_creds failed\n", __location__);
                ret = False;
                goto done;
        }
 
        status = smbcli_full_connection(
-               mem_ctx, &cli, lp_parm_string(-1, "torture", "host"),
+               mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
                "IPC$", NULL, anon_creds, NULL);
        if (!NT_STATUS_IS_OK(status)) {
-               d_printf("anon smbcli_full_connection failed: %s\n",
-                        nt_errstr(status));
+               d_printf("(%s) anon smbcli_full_connection failed: %s\n",
+                        __location__, nt_errstr(status));
                ret = False;
                goto done;
        }
 
        if (!(user_sid = whoami(mem_ctx, cli->tree))) {
-               d_printf("whoami on anon connection failed\n");
+               d_printf("(%s) whoami on anon connection failed\n",
+                        __location__);
                ret = False;
                goto done;
        }
 
        if (!dom_sid_equal(user_sid,
                           dom_sid_parse_talloc(mem_ctx, "s-1-5-7"))) {
-               d_printf("Anon lsa_GetUserName returned %s, expected S-1-5-7",
+               d_printf("(%s) Anon lsa_GetUserName returned %s, expected "
+                        "S-1-5-7", __location__,
                         dom_sid_string(mem_ctx, user_sid));
                ret = False;
        }
 
        if (!(user_creds = cli_credentials_init(mem_ctx))) {
-               d_printf("cli_credentials_init failed\n");
+               d_printf("(%s) cli_credentials_init failed\n", __location__);
                ret = False;
                goto done;
        }
@@ -1644,7 +1654,7 @@ BOOL torture_samba3_rpc_getusername(struct torture_context *torture)
                         cli_credentials_get_username(user_creds),
                         cli_credentials_get_password(user_creds),
                         &domain_name, &created_sid)) {
-               d_printf("create_user failed\n");
+               d_printf("(%s) create_user failed\n", __location__);
                ret = False;
                goto done;
        }
@@ -1659,7 +1669,8 @@ BOOL torture_samba3_rpc_getusername(struct torture_context *torture)
 
                session2 = smbcli_session_init(cli->transport, mem_ctx, False);
                if (session2 == NULL) {
-                       d_printf("smbcli_session_init failed\n");
+                       d_printf("(%s) smbcli_session_init failed\n",
+                                __location__);
                        goto done;
                }
 
@@ -1670,21 +1681,24 @@ BOOL torture_samba3_rpc_getusername(struct torture_context *torture)
 
                status = smb_composite_sesssetup(session2, &setup);
                if (!NT_STATUS_IS_OK(status)) {
-                       d_printf("anon session setup failed: %s\n",
-                                nt_errstr(status));
+                       d_printf("(%s) session setup with new user failed: "
+                                "%s\n", __location__, nt_errstr(status));
                        ret = False;
                        goto done;
                }
+               session2->vuid = setup.out.vuid;
 
                if (!NT_STATUS_IS_OK(secondary_tcon(mem_ctx, session2,
                                                    "IPC$", &tree))) {
-                       d_printf("secondary_tcon failed\n");
+                       d_printf("(%s) secondary_tcon failed\n",
+                                __location__);
                        ret = False;
                        goto done;
                }
 
                if (!(user_sid = whoami(mem_ctx, tree))) {
-                       d_printf("whoami on user connection failed\n");
+                       d_printf("(%s) whoami on user connection failed\n",
+                                __location__);
                        ret = False;
                        goto delete;
                }
@@ -1703,7 +1717,7 @@ BOOL torture_samba3_rpc_getusername(struct torture_context *torture)
  delete:
        if (!delete_user(cli, cmdline_credentials,
                         cli_credentials_get_username(user_creds))) {
-               d_printf("delete_user failed\n");
+               d_printf("(%s) delete_user failed\n", __location__);
                ret = False;
        }
 
@@ -1813,7 +1827,7 @@ BOOL torture_samba3_rpc_srvsvc(struct torture_context *torture)
        }
 
        if (!(torture_open_connection_share(
-                     mem_ctx, &cli, lp_parm_string(-1, "torture", "host"),
+                     mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
                      "IPC$", NULL))) {
                talloc_free(mem_ctx);
                return False;
@@ -2019,8 +2033,8 @@ BOOL try_tcon(TALLOC_CTX *mem_ctx,
 
        status = smbcli_mkdir(tree, "sharesec_testdir");
        if (!NT_STATUS_EQUAL(status, expected_mkdir)) {
-               d_printf("Expected %s, got %s\n", nt_errstr(expected_mkdir),
-                        nt_errstr(status));
+               d_printf("(%s) Expected %s, got %s\n", __location__,
+                        nt_errstr(expected_mkdir), nt_errstr(status));
                ret = False;
        }
 
@@ -2052,7 +2066,7 @@ BOOL torture_samba3_rpc_sharesec(struct torture_context *torture)
        }
 
        if (!(torture_open_connection_share(
-                     mem_ctx, &cli, lp_parm_string(-1, "torture", "host"),
+                     mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
                      "IPC$", NULL))) {
                d_printf("IPC$ connection failed\n");
                talloc_free(mem_ctx);
@@ -2065,20 +2079,20 @@ BOOL torture_samba3_rpc_sharesec(struct torture_context *torture)
                return False;
        }
 
-       sd = get_sharesec(mem_ctx, cli->session, lp_parm_string(-1, "torture",
-                                                               "share"));
+       sd = get_sharesec(mem_ctx, cli->session, torture_setting_string(torture,
+                                                               "share", NULL));
 
        ret &= try_tcon(mem_ctx, sd, cli->session,
-                       lp_parm_string(-1, "torture", "share"),
+                       torture_setting_string(torture, "share", NULL),
                        user_sid, 0, NT_STATUS_ACCESS_DENIED, NT_STATUS_OK);
 
        ret &= try_tcon(mem_ctx, sd, cli->session,
-                       lp_parm_string(-1, "torture", "share"),
+                       torture_setting_string(torture, "share", NULL),
                        user_sid, SEC_FILE_READ_DATA, NT_STATUS_OK,
-                       NT_STATUS_NETWORK_ACCESS_DENIED);
+                       NT_STATUS_MEDIA_WRITE_PROTECTED);
 
        ret &= try_tcon(mem_ctx, sd, cli->session,
-                       lp_parm_string(-1, "torture", "share"),
+                       torture_setting_string(torture, "share", NULL),
                        user_sid, SEC_FILE_ALL, NT_STATUS_OK, NT_STATUS_OK);
 
        talloc_free(mem_ctx);
@@ -2100,7 +2114,7 @@ BOOL torture_samba3_rpc_lsa(struct torture_context *torture)
        }
 
        if (!(torture_open_connection_share(
-                     mem_ctx, &cli, lp_parm_string(-1, "torture", "host"),
+                     mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
                      "IPC$", NULL))) {
                d_printf("IPC$ connection failed\n");
                talloc_free(mem_ctx);
@@ -2163,6 +2177,32 @@ BOOL torture_samba3_rpc_lsa(struct torture_context *torture)
        return ret;
 }
 
+static NTSTATUS get_servername(TALLOC_CTX *mem_ctx, struct smbcli_tree *tree,
+                              char **name)
+{
+       struct rap_WserverGetInfo r;
+       NTSTATUS status;
+       char servername[17];
+
+       r.in.level = 0;
+       r.in.bufsize = 0xffff;
+
+       status = smbcli_rap_netservergetinfo(tree, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       memcpy(servername, r.out.info.info0.name, 16);
+       servername[16] = '\0';
+
+       if (pull_ascii_talloc(mem_ctx, name, servername) < 0) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       return NT_STATUS_OK;
+}
+
+
 static NTSTATUS find_printers(TALLOC_CTX *ctx, struct smbcli_tree *tree,
                              const char ***printers, int *num_printers)
 {
@@ -2221,6 +2261,55 @@ static NTSTATUS find_printers(TALLOC_CTX *ctx, struct smbcli_tree *tree,
        return NT_STATUS_OK;
 }
 
+static BOOL enumprinters(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *pipe,
+                        const char *servername, int level, int *num_printers)
+{
+       struct spoolss_EnumPrinters r;
+       NTSTATUS status;
+       DATA_BLOB blob;
+
+       r.in.flags = PRINTER_ENUM_LOCAL;
+       r.in.server = talloc_asprintf(mem_ctx, "\\\\%s", servername);
+       r.in.level = level;
+       r.in.buffer = NULL;
+       r.in.offered = 0;
+
+       status = dcerpc_spoolss_EnumPrinters(pipe, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("(%s) dcerpc_spoolss_EnumPrinters failed: %s\n",
+                        __location__, nt_errstr(status));
+               return False;
+       }
+
+       if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
+               d_printf("(%s) EnumPrinters unexpected return code %s, should "
+                        "be WERR_INSUFFICIENT_BUFFER\n", __location__,
+                        win_errstr(r.out.result));
+               return False;
+       }
+
+       blob = data_blob_talloc_zero(mem_ctx, r.out.needed);
+       if (blob.data == NULL) {
+               d_printf("(%s) data_blob_talloc failed\n", __location__);
+               return False;
+       }
+
+       r.in.buffer = &blob;
+       r.in.offered = r.out.needed;
+
+       status = dcerpc_spoolss_EnumPrinters(pipe, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
+               d_printf("(%s) dcerpc_spoolss_EnumPrinters failed: %s, "
+                        "%s\n", __location__, nt_errstr(status),
+                        win_errstr(r.out.result));
+               return False;
+       }
+
+       *num_printers = r.out.count;
+
+       return True;
+}
+
 static NTSTATUS getprinterinfo(TALLOC_CTX *ctx, struct dcerpc_pipe *pipe,
                               struct policy_handle *handle, int level,
                               union spoolss_PrinterInfo **res)
@@ -2284,7 +2373,6 @@ static NTSTATUS getprinterinfo(TALLOC_CTX *ctx, struct dcerpc_pipe *pipe,
        talloc_free(mem_ctx);
        return NT_STATUS_OK;
 }
-       
 
 BOOL torture_samba3_rpc_spoolss(struct torture_context *torture)
 {
@@ -2297,19 +2385,28 @@ BOOL torture_samba3_rpc_spoolss(struct torture_context *torture)
        const char **printers;
        int num_printers;
        struct spoolss_UserLevel1 userlevel1;
+       char *servername;
 
        if (!(mem_ctx = talloc_new(torture))) {
                return False;
        }
 
        if (!(torture_open_connection_share(
-                     mem_ctx, &cli, lp_parm_string(-1, "torture", "host"),
+                     mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
                      "IPC$", NULL))) {
                d_printf("IPC$ connection failed\n");
                talloc_free(mem_ctx);
                return False;
        }
 
+       status = get_servername(mem_ctx, cli->tree, &servername);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "(%s) get_servername returned %s\n",
+                         __location__, nt_errstr(status));
+               talloc_free(mem_ctx);
+               return False;
+       }
+
        if (!NT_STATUS_IS_OK(find_printers(mem_ctx, cli->tree,
                                           &printers, &num_printers))) {
                talloc_free(mem_ctx);
@@ -2344,8 +2441,8 @@ BOOL torture_samba3_rpc_spoolss(struct torture_context *torture)
                struct spoolss_OpenPrinterEx r;
 
                ZERO_STRUCT(r);
-               r.in.printername = talloc_asprintf(
-                       mem_ctx, "\\\\%s", dcerpc_server_name(p));
+               r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s",
+                                                  servername);
                r.in.datatype = NULL;
                r.in.access_mask = 0;
                r.in.level = 1;
@@ -2353,9 +2450,10 @@ BOOL torture_samba3_rpc_spoolss(struct torture_context *torture)
                r.out.handle = &server_handle;
 
                status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
+               if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
                        d_printf("(%s) dcerpc_spoolss_OpenPrinterEx failed: "
-                                "%s\n", __location__, nt_errstr(status));
+                                "%s, %s\n", __location__, nt_errstr(status),
+                                win_errstr(r.out.result));
                        talloc_free(mem_ctx);
                        return False;
                }
@@ -2368,9 +2466,10 @@ BOOL torture_samba3_rpc_spoolss(struct torture_context *torture)
                r.out.handle = &server_handle;
 
                status = dcerpc_spoolss_ClosePrinter(p, mem_ctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
+               if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
                        d_printf("(%s) dcerpc_spoolss_ClosePrinter failed: "
-                                "%s\n", __location__, nt_errstr(status));
+                                "%s, %s\n", __location__, nt_errstr(status),
+                                win_errstr(r.out.result));
                        talloc_free(mem_ctx);
                        return False;
                }
@@ -2381,8 +2480,7 @@ BOOL torture_samba3_rpc_spoolss(struct torture_context *torture)
 
                ZERO_STRUCT(r);
                r.in.printername = talloc_asprintf(
-                       mem_ctx, "\\\\%s\\%s", dcerpc_server_name(p),
-                       printers[0]);
+                       mem_ctx, "\\\\%s\\%s", servername, printers[0]);
                r.in.datatype = NULL;
                r.in.access_mask = 0;
                r.in.level = 1;
@@ -2390,9 +2488,10 @@ BOOL torture_samba3_rpc_spoolss(struct torture_context *torture)
                r.out.handle = &printer_handle;
 
                status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
+               if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
                        d_printf("(%s) dcerpc_spoolss_OpenPrinterEx failed: "
-                                "%s\n", __location__, nt_errstr(status));
+                                "%s, %s\n", __location__, nt_errstr(status),
+                                win_errstr(r.out.result));
                        talloc_free(mem_ctx);
                        return False;
                }
@@ -2427,6 +2526,316 @@ BOOL torture_samba3_rpc_spoolss(struct torture_context *torture)
                }
        }
 
+       {
+               int num_enumerated;
+               if (!enumprinters(mem_ctx, p, servername, 1,
+                                 &num_enumerated)) {
+                       d_printf("(%s) enumprinters failed\n", __location__);
+                       talloc_free(mem_ctx);
+                       return False;
+               }
+               if (num_printers != num_enumerated) {
+                       d_printf("(%s) netshareenum gave %d printers, "
+                                "enumprinters lvl 1 gave %d\n", __location__,
+                                num_printers, num_enumerated);
+                       talloc_free(mem_ctx);
+                       return False;
+               }
+       }
+
+       {
+               int num_enumerated;
+               if (!enumprinters(mem_ctx, p, servername, 2,
+                                 &num_enumerated)) {
+                       d_printf("(%s) enumprinters failed\n", __location__);
+                       talloc_free(mem_ctx);
+                       return False;
+               }
+               if (num_printers != num_enumerated) {
+                       d_printf("(%s) netshareenum gave %d printers, "
+                                "enumprinters lvl 2 gave %d\n", __location__,
+                                num_printers, num_enumerated);
+                       talloc_free(mem_ctx);
+                       return False;
+               }
+       }
+
+       talloc_free(mem_ctx);
+
+       return ret;
+}
+
+BOOL torture_samba3_rpc_wkssvc(struct torture_context *torture)
+{
+       TALLOC_CTX *mem_ctx;
+       struct smbcli_state *cli;
+       struct dcerpc_pipe *p;
+       NTSTATUS status;
+       char *servername;
+
+       if (!(mem_ctx = talloc_new(torture))) {
+               return False;
+       }
+
+       if (!(torture_open_connection_share(
+                     mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
+                     "IPC$", NULL))) {
+               d_printf("IPC$ connection failed\n");
+               talloc_free(mem_ctx);
+               return False;
+       }
+
+       status = get_servername(mem_ctx, cli->tree, &servername);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "(%s) get_servername returned %s\n",
+                         __location__, nt_errstr(status));
+               talloc_free(mem_ctx);
+               return False;
+       }
+
+       status = pipe_bind_smb(mem_ctx, cli->tree, "\\wkssvc",
+                              &dcerpc_table_wkssvc, &p);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("(%s) pipe_bind_smb failed: %s\n", __location__,
+                        nt_errstr(status));
+               talloc_free(mem_ctx);
+               return False;
+       }
+
+       {
+               struct wkssvc_NetWkstaInfo100 wks100;
+               union wkssvc_NetWkstaInfo info;
+               struct wkssvc_NetWkstaGetInfo r;
+
+               r.in.server_name = "\\foo";
+               r.in.level = 100;
+               info.info100 = &wks100;
+               r.out.info = &info;
+
+               status = dcerpc_wkssvc_NetWkstaGetInfo(p, mem_ctx, &r);
+               if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
+                       d_printf("(%s) dcerpc_wkssvc_NetWksGetInfo failed: "
+                                "%s, %s\n", __location__, nt_errstr(status),
+                                win_errstr(r.out.result));
+                       talloc_free(mem_ctx);
+                       return False;
+               }
+
+               if (strcmp(servername,
+                          r.out.info->info100->server_name) != 0) {
+                       d_printf("(%s) servername inconsistency: RAP=%s, "
+                                "dcerpc_wkssvc_NetWksGetInfo=%s",
+                                __location__, servername,
+                                r.out.info->info100->server_name);
+                       talloc_free(mem_ctx);
+                       return False;
+               }
+       }
+
+       talloc_free(mem_ctx);
+       return True;
+}
+
+static NTSTATUS winreg_close(struct dcerpc_pipe *p,
+                            struct policy_handle *handle)
+{
+       struct winreg_CloseKey c;
+       NTSTATUS status;
+       TALLOC_CTX *mem_ctx;
+
+       c.in.handle = c.out.handle = handle;
+
+       if (!(mem_ctx = talloc_new(p))) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       status = dcerpc_winreg_CloseKey(p, mem_ctx, &c);
+       talloc_free(mem_ctx);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (!W_ERROR_IS_OK(c.out.result)) {
+               return werror_to_ntstatus(c.out.result);
+       }
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS enumvalues(struct dcerpc_pipe *p, struct policy_handle *handle,
+                          TALLOC_CTX *mem_ctx)
+{
+       uint32_t enum_index = 0;
+
+       while (1) {
+               struct winreg_EnumValue r;
+               struct winreg_StringBuf name;
+               enum winreg_Type type = 0;
+               uint8_t buf8[1024];
+               NTSTATUS status;
+               uint32_t size, length;
+               
+               r.in.handle = handle;
+               r.in.enum_index = enum_index;
+               name.name = "";
+               name.size = 1024;
+               r.in.name = r.out.name = &name;
+               size = 1024;
+               length = 5;
+               r.in.type = &type;
+               r.in.value = buf8;
+               r.in.size = &size;
+               r.in.length = &length;
+
+               status = dcerpc_winreg_EnumValue(p, mem_ctx, &r);
+               if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
+                       return NT_STATUS_OK;
+               }
+               enum_index += 1;
+       }
+}
+
+static NTSTATUS enumkeys(struct dcerpc_pipe *p, struct policy_handle *handle, 
+                        TALLOC_CTX *mem_ctx, int depth)
+{
+       struct winreg_EnumKey r;
+       struct winreg_StringBuf class, name;
+       NTSTATUS status;
+       NTTIME t = 0;
+
+       if (depth <= 0) {
+               return NT_STATUS_OK;
+       }
+
+       class.name   = "";
+       class.size   = 1024;
+
+       r.in.handle = handle;
+       r.in.enum_index = 0;
+       r.in.name = &name;
+       r.in.keyclass = &class;
+       r.out.name = &name;
+       r.in.last_changed_time = &t;
+
+       do {
+               TALLOC_CTX *tmp_ctx;
+               struct winreg_OpenKey o;
+               struct policy_handle key_handle;
+               int i;
+
+               if (!(tmp_ctx = talloc_new(mem_ctx))) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               name.name = NULL;
+               name.size = 1024;
+
+               status = dcerpc_winreg_EnumKey(p, tmp_ctx, &r);
+               if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
+                       /* We're done enumerating */
+                       talloc_free(tmp_ctx);
+                       return NT_STATUS_OK;
+               }
+
+               for (i=0; i<10-depth; i++)
+                       printf(" ");
+               printf("%s\n", r.out.name->name);
+                       
+
+               o.in.parent_handle = handle;
+               o.in.keyname.name = r.out.name->name;
+               o.in.unknown = 0;
+               o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+               o.out.handle = &key_handle;
+
+               status = dcerpc_winreg_OpenKey(p, tmp_ctx, &o);
+               if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(o.out.result)) {
+                       enumkeys(p, &key_handle, tmp_ctx, depth-1);
+                       enumvalues(p, &key_handle, tmp_ctx);
+                       status = winreg_close(p, &key_handle);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
+               }
+
+               talloc_free(tmp_ctx);
+
+               r.in.enum_index += 1;
+       } while(True);
+
+       return NT_STATUS_OK;
+}
+
+typedef NTSTATUS (*winreg_open_fn)(struct dcerpc_pipe *, TALLOC_CTX *, void *);
+
+static BOOL test_Open3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                      const char *name, winreg_open_fn open_fn)
+{
+       struct policy_handle handle;
+       struct winreg_OpenHKLM r;
+       NTSTATUS status;
+
+       r.in.system_name = 0;
+       r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+       r.out.handle = &handle;
+       
+       status = open_fn(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
+               d_printf("(%s) %s failed: %s, %s\n", __location__, name,
+                        nt_errstr(status), win_errstr(r.out.result));
+               return False;
+       }
+
+       enumkeys(p, &handle, mem_ctx, 4);
+
+       status = winreg_close(p, &handle);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("(%s) dcerpc_CloseKey failed: %s\n",
+                        __location__, nt_errstr(status));
+               return False;
+       }
+
+       return True;
+}
+
+BOOL torture_samba3_rpc_winreg(struct torture_context *torture)
+{
+        NTSTATUS status;
+       struct dcerpc_pipe *p;
+       TALLOC_CTX *mem_ctx;
+       BOOL ret = True;
+       struct {
+               const char *name;
+               winreg_open_fn fn;
+       } open_fns[] = {
+               {"OpenHKLM", (winreg_open_fn)dcerpc_winreg_OpenHKLM },
+               {"OpenHKU",  (winreg_open_fn)dcerpc_winreg_OpenHKU },
+               {"OpenHKPD", (winreg_open_fn)dcerpc_winreg_OpenHKPD },
+               {"OpenHKPT", (winreg_open_fn)dcerpc_winreg_OpenHKPT },
+               {"OpenHKCR", (winreg_open_fn)dcerpc_winreg_OpenHKCR }};
+#if 0
+       int i;
+#endif
+
+       mem_ctx = talloc_init("torture_rpc_winreg");
+
+       status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_winreg);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               talloc_free(mem_ctx);
+               return False;
+       }
+
+#if 1
+       ret = test_Open3(p, mem_ctx, open_fns[0].name, open_fns[0].fn);
+#else
+       for (i = 0; i < ARRAY_SIZE(open_fns); i++) {
+               if (!test_Open3(p, mem_ctx, open_fns[i].name, open_fns[i].fn))
+                       ret = False;
+       }
+#endif
+
        talloc_free(mem_ctx);
 
        return ret;