r23792: convert Samba4 to GPLv3
[tprouty/samba.git] / source4 / torture / rpc / samba3rpc.c
index 8bfbad22e538314bb2150fe12494f9a0e51274a7..9e5eedab3a54a1325fa0fcec98c9bea952b8f51a 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"
 #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 +46,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 +91,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 +106,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 +167,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 +222,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 +297,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 +361,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));
@@ -530,24 +535,29 @@ static BOOL create_user(TALLOC_CTX *mem_ctx, struct smbcli_state *cli,
                union samr_UserInfo u_info;
                DATA_BLOB session_key;
 
-               encode_pw_buffer(u_info.info24.password.data, password,
+
+               ZERO_STRUCT(u_info);
+               encode_pw_buffer(u_info.info23.password.data, password,
                                 STR_UNICODE);
-               u_info.info24.pw_len =  strlen_m(password)*2;
 
                status = dcerpc_fetch_session_key(samr_pipe, &session_key);
                if (!NT_STATUS_IS_OK(status)) {
                        d_printf("dcerpc_fetch_session_key failed\n");
                        goto done;
                }
-               arcfour_crypt_blob(u_info.info24.password.data, 516,
+               arcfour_crypt_blob(u_info.info23.password.data, 516,
                                   &session_key);
+               u_info.info23.info.password_expired = 0;
+               u_info.info23.info.fields_present = SAMR_FIELD_PASSWORD | 
+                                                   SAMR_FIELD_PASSWORD2 |
+                                                   SAMR_FIELD_EXPIRED_FLAG;
                sui2.in.user_handle = wks_handle;
                sui2.in.info = &u_info;
-               sui2.in.level = 24;
+               sui2.in.level = 23;
 
                status = dcerpc_samr_SetUserInfo2(samr_pipe, tmp_ctx, &sui2);
                if (!NT_STATUS_IS_OK(status)) {
-                       d_printf("samr_SetUserInfo(24) failed: %s\n",
+                       d_printf("samr_SetUserInfo(23) failed: %s\n",
                                 nt_errstr(status));
                        goto done;
                }
@@ -576,6 +586,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 +827,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 +928,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 +1130,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 +1148,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 +1290,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 +1306,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 +1379,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,7 +1464,8 @@ 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 NULL;
        }
@@ -1584,7 +1593,7 @@ 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("(%s) smbcli_full_connection failed: %s\n",
@@ -1608,7 +1617,7 @@ 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, anon_creds, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("(%s) anon smbcli_full_connection failed: %s\n",
@@ -1681,6 +1690,7 @@ BOOL torture_samba3_rpc_getusername(struct torture_context *torture)
                        ret = False;
                        goto done;
                }
+               session2->vuid = setup.out.vuid;
 
                if (!NT_STATUS_IS_OK(secondary_tcon(mem_ctx, session2,
                                                    "IPC$", &tree))) {
@@ -1821,7 +1831,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;
@@ -2027,8 +2037,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;
        }
 
@@ -2060,7 +2070,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);
@@ -2073,20 +2083,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);
@@ -2108,7 +2118,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);
@@ -2171,6 +2181,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)
 {
@@ -2230,15 +2266,15 @@ static NTSTATUS find_printers(TALLOC_CTX *ctx, struct smbcli_tree *tree,
 }
 
 static BOOL enumprinters(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *pipe,
-                        int level, int *num_printers)
+                        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 = "\\\\localhost";
-       r.in.level = 1;
+       r.in.server = talloc_asprintf(mem_ctx, "\\\\%s", servername);
+       r.in.level = level;
        r.in.buffer = NULL;
        r.in.offered = 0;
 
@@ -2256,7 +2292,7 @@ static BOOL enumprinters(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *pipe,
                return False;
        }
 
-       blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
+       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;
@@ -2341,7 +2377,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)
 {
@@ -2354,19 +2389,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);
@@ -2401,7 +2445,8 @@ BOOL torture_samba3_rpc_spoolss(struct torture_context *torture)
                struct spoolss_OpenPrinterEx r;
 
                ZERO_STRUCT(r);
-               r.in.printername = "\\\\localhost";
+               r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s",
+                                                  servername);
                r.in.datatype = NULL;
                r.in.access_mask = 0;
                r.in.level = 1;
@@ -2409,15 +2454,9 @@ 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));
-                       talloc_free(mem_ctx);
-                       return False;
-               }
-               if (!W_ERROR_IS_OK(r.out.result)) {
-                       d_printf("(%s) dcerpc_spoolss_OpenPrinterEx failed: "
-                                "%s\n", __location__,
+                                "%s, %s\n", __location__, nt_errstr(status),
                                 win_errstr(r.out.result));
                        talloc_free(mem_ctx);
                        return False;
@@ -2431,15 +2470,9 @@ 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));
-                       talloc_free(mem_ctx);
-                       return False;
-               }
-               if (!W_ERROR_IS_OK(r.out.result)) {
-                       d_printf("(%s) dcerpc_spoolss_ClosePrinter failed: "
-                                "%s\n", __location__,
+                                "%s, %s\n", __location__, nt_errstr(status),
                                 win_errstr(r.out.result));
                        talloc_free(mem_ctx);
                        return False;
@@ -2451,7 +2484,7 @@ BOOL torture_samba3_rpc_spoolss(struct torture_context *torture)
 
                ZERO_STRUCT(r);
                r.in.printername = talloc_asprintf(
-                       mem_ctx, "\\\\localhost\\%s", printers[0]);
+                       mem_ctx, "\\\\%s\\%s", servername, printers[0]);
                r.in.datatype = NULL;
                r.in.access_mask = 0;
                r.in.level = 1;
@@ -2459,15 +2492,9 @@ 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));
-                       talloc_free(mem_ctx);
-                       return False;
-               }
-               if (!W_ERROR_IS_OK(r.out.result)) {
-                       d_printf("(%s) dcerpc_spoolss_OpenPrinterEx failed: "
-                                "%s\n", __location__,
+                                "%s, %s\n", __location__, nt_errstr(status),
                                 win_errstr(r.out.result));
                        talloc_free(mem_ctx);
                        return False;
@@ -2478,11 +2505,6 @@ BOOL torture_samba3_rpc_spoolss(struct torture_context *torture)
                int i;
 
                for (i=0; i<8; i++) {
-                       if ((i == 6) &&
-                           (lp_parm_bool(-1, "target", "samba3", False))) {
-                               /* Samba3 does not yet do level 6 */
-                               continue;
-                       }
                        status = getprinterinfo(mem_ctx, p, &printer_handle,
                                                i, NULL);
                        if (!NT_STATUS_IS_OK(status)) {
@@ -2510,20 +2532,314 @@ BOOL torture_samba3_rpc_spoolss(struct torture_context *torture)
 
        {
                int num_enumerated;
-               if (!enumprinters(mem_ctx, p, 1, &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 gave %d\n", __location__,
+                                "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;