Port Samba4 to the new combined libcli/auth functions
[kai/samba.git] / source4 / torture / rpc / wkssvc.c
index bec2ec9f3ec5ae92c74020f93b79540694261693..06b1d05ee4dce2ee8063caf17485569c52e17727 100644 (file)
@@ -3,6 +3,7 @@
    test suite for wkssvc rpc operations
 
    Copyright (C) Andrew Tridgell 2003
+   Copyright (C) Günther Deschner 2007
 
    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
@@ -24,6 +25,8 @@
 #include "torture/rpc/rpc.h"
 #include "lib/cmdline/popt_common.h"
 #include "param/param.h"
+#include "../lib/crypto/crypto.h"
+#include "libcli/auth/libcli_auth.h"
 
 #define SMBTORTURE_MACHINE_NAME "smbtrt_name"
 #define SMBTORTURE_ALTERNATE_NAME "smbtrt_altname"
@@ -209,7 +212,7 @@ static bool test_NetrWkstaUserGetInfo(struct torture_context *tctx,
        NTSTATUS status;
        struct wkssvc_NetrWkstaUserGetInfo r;
        union wkssvc_NetrWkstaUserInfo info;
-       const char *dom = lp_workgroup(global_loadparm);
+       const char *dom = lp_workgroup(tctx->lp_ctx);
        struct cli_credentials *creds = cmdline_credentials;
        const char *user = cli_credentials_get_username(creds);
        int i;
@@ -480,7 +483,7 @@ static bool test_NetrLogonDomainNameAdd(struct torture_context *tctx,
        NTSTATUS status;
        struct wkssvc_NetrLogonDomainNameAdd r;
 
-       r.in.domain_name = lp_workgroup(global_loadparm);
+       r.in.domain_name = lp_workgroup(tctx->lp_ctx);
 
        torture_comment(tctx, "testing NetrLogonDomainNameAdd\n");
 
@@ -498,7 +501,7 @@ static bool test_NetrLogonDomainNameDel(struct torture_context *tctx,
        NTSTATUS status;
        struct wkssvc_NetrLogonDomainNameDel r;
 
-       r.in.domain_name = lp_workgroup(global_loadparm);
+       r.in.domain_name = lp_workgroup(tctx->lp_ctx);
 
        torture_comment(tctx, "testing NetrLogonDomainNameDel\n");
 
@@ -592,7 +595,7 @@ static bool test_NetrValidateName(struct torture_context *tctx,
        for (i=0; i<ARRAY_SIZE(levels); i++) {
 
                r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
-               r.in.name = lp_workgroup(global_loadparm);
+               r.in.name = lp_workgroup(tctx->lp_ctx);
                r.in.Account = NULL;
                r.in.Password = NULL;
                r.in.name_type = levels[i];
@@ -622,7 +625,7 @@ static bool test_NetrValidateName2(struct torture_context *tctx,
        for (i=0; i<ARRAY_SIZE(levels); i++) {
 
                r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
-               r.in.name = lp_workgroup(global_loadparm);
+               r.in.name = lp_workgroup(tctx->lp_ctx);
                r.in.Account = NULL;
                r.in.EncryptedPassword = NULL;
                r.in.name_type = levels[i];
@@ -963,7 +966,7 @@ static bool test_NetrMessageBufferSend(struct torture_context *tctx,
        size_t size;
        uint8_t *msg;
 
-       size = push_ucs2_talloc(tctx, (void **)&msg, message);
+       push_ucs2_talloc(tctx, (void **)&msg, message, &size);
 
        r.in.server_name = dcerpc_server_name(p);
        r.in.message_name = dcerpc_server_name(p);
@@ -1003,6 +1006,38 @@ static bool test_NetrGetJoinInformation(struct torture_context *tctx,
        return true;
 }
 
+static bool test_GetJoinInformation(struct torture_context *tctx,
+                                   struct dcerpc_pipe *p,
+                                   enum wkssvc_NetJoinStatus *join_status_p,
+                                   const char **name)
+{
+       NTSTATUS status;
+       struct wkssvc_NetrGetJoinInformation r;
+       enum wkssvc_NetJoinStatus join_status;
+       const char *name_buffer = "";
+
+       r.in.server_name = dcerpc_server_name(p);
+       r.in.name_buffer = r.out.name_buffer = &name_buffer;
+       r.out.name_type = &join_status;
+
+       status = dcerpc_wkssvc_NetrGetJoinInformation(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status,
+                                  "NetrGetJoinInformation failed");
+       torture_assert_werr_ok(tctx, r.out.result,
+                              "NetrGetJoinInformation failed");
+
+       if (join_status_p) {
+               *join_status_p = join_status;
+       }
+
+       if (*name) {
+               *name = talloc_strdup(tctx, name_buffer);
+       }
+
+       return true;
+
+}
+
 static bool test_NetrGetJoinableOus(struct torture_context *tctx,
                                    struct dcerpc_pipe *p)
 {
@@ -1012,7 +1047,7 @@ static bool test_NetrGetJoinableOus(struct torture_context *tctx,
        const char **ous = NULL;
 
        r.in.server_name = dcerpc_server_name(p);
-       r.in.domain_name = lp_workgroup(global_loadparm);
+       r.in.domain_name = lp_workgroup(tctx->lp_ctx);
        r.in.Account = NULL;
        r.in.unknown = NULL;
        r.in.num_ous = r.out.num_ous = &num_ous;
@@ -1038,7 +1073,7 @@ static bool test_NetrGetJoinableOus2(struct torture_context *tctx,
        const char **ous = NULL;
 
        r.in.server_name = dcerpc_server_name(p);
-       r.in.domain_name = lp_workgroup(global_loadparm);
+       r.in.domain_name = lp_workgroup(tctx->lp_ctx);
        r.in.Account = NULL;
        r.in.EncryptedPassword = NULL;
        r.in.num_ous = r.out.num_ous = &num_ous;
@@ -1054,6 +1089,244 @@ static bool test_NetrGetJoinableOus2(struct torture_context *tctx,
 
        return true;
 }
+
+static bool test_NetrUnjoinDomain(struct torture_context *tctx,
+                                 struct dcerpc_pipe *p)
+{
+       NTSTATUS status;
+       struct wkssvc_NetrUnjoinDomain r;
+       struct cli_credentials *creds = cmdline_credentials;
+       const char *user = cli_credentials_get_username(creds);
+       const char *admin_account = NULL;
+
+       admin_account = talloc_asprintf(tctx, "%s\\%s",
+                                       lp_workgroup(tctx->lp_ctx),
+                                       user);
+
+       r.in.server_name = dcerpc_server_name(p);
+       r.in.Account = admin_account;
+       r.in.password = NULL;
+       r.in.unjoin_flags = 0;
+
+       torture_comment(tctx, "testing NetrUnjoinDomain\n");
+
+       status = dcerpc_wkssvc_NetrUnjoinDomain(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status,
+                                  "NetrUnjoinDomain failed");
+       torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
+                                 "NetrUnjoinDomain failed");
+       return true;
+}
+
+static bool test_NetrJoinDomain(struct torture_context *tctx,
+                               struct dcerpc_pipe *p)
+{
+       NTSTATUS status;
+       struct wkssvc_NetrJoinDomain r;
+       struct cli_credentials *creds = cmdline_credentials;
+       const char *user = cli_credentials_get_username(creds);
+       const char *admin_account = NULL;
+
+       admin_account = talloc_asprintf(tctx, "%s\\%s",
+                                       lp_workgroup(tctx->lp_ctx),
+                                       user);
+
+       r.in.server_name = dcerpc_server_name(p);
+       r.in.domain_name = lp_realm(tctx->lp_ctx);
+       r.in.account_ou = NULL;
+       r.in.Account = admin_account;
+       r.in.password = NULL;
+       r.in.join_flags = 0;
+
+       torture_comment(tctx, "testing NetrJoinDomain\n");
+
+       status = dcerpc_wkssvc_NetrJoinDomain(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status,
+                                  "NetrJoinDomain failed");
+       torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
+                                 "NetrJoinDomain failed");
+       return true;
+}
+
+/*
+ * prerequisites for remotely joining an unjoined XP SP2 workstation:
+ * - firewall needs to be disabled (or open for ncacn_np access)
+ * - HKLM\System\CurrentControlSet\Control\Lsa\forceguest needs to 0
+ * see also:
+ * http://support.microsoft.com/kb/294355/EN-US/ and
+ * http://support.microsoft.com/kb/290403/EN-US/
+ */
+
+static bool test_NetrJoinDomain2(struct torture_context *tctx,
+                                struct dcerpc_pipe *p)
+{
+       NTSTATUS status;
+       struct wkssvc_NetrJoinDomain2 r;
+       const char *domain_admin_account = NULL;
+       const char *domain_admin_password = NULL;
+       const char *domain_name = NULL;
+       struct wkssvc_PasswordBuffer *pwd_buf;
+       enum wkssvc_NetJoinStatus join_status;
+       const char *join_name = NULL;
+       WERROR expected_err;
+       DATA_BLOB session_key;
+
+       /* FIXME: this test assumes to join workstations / servers and does not
+        * handle DCs (WERR_SETUP_DOMAIN_CONTROLLER) */
+
+       if (!test_GetJoinInformation(tctx, p, &join_status, &join_name))
+       {
+               return false;
+       }
+
+       switch (join_status) {
+               case NET_SETUP_DOMAIN_NAME:
+                       expected_err = WERR_SETUP_ALREADY_JOINED;
+                       break;
+               case NET_SETUP_UNKNOWN_STATUS:
+               case NET_SETUP_UNJOINED:
+               case NET_SETUP_WORKGROUP_NAME:
+               default:
+                       expected_err = WERR_OK;
+                       break;
+       }
+
+       domain_admin_account = torture_setting_string(tctx, "domain_admin_account", NULL);
+
+       domain_admin_password = torture_setting_string(tctx, "domain_admin_password", NULL);
+
+       domain_name = torture_setting_string(tctx, "domain_name", NULL);
+
+       if ((domain_admin_account == NULL) ||
+           (domain_admin_password == NULL) ||
+           (domain_name == NULL)) {
+               torture_comment(tctx, "not enough input parameter\n");
+               return false;
+       }
+
+       status = dcerpc_fetch_session_key(p, &session_key);
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+
+       encode_wkssvc_join_password_buffer(tctx, domain_admin_password,
+                                          &session_key, &pwd_buf);
+
+       r.in.server_name = dcerpc_server_name(p);
+       r.in.domain_name = domain_name;
+       r.in.account_ou = NULL;
+       r.in.admin_account = domain_admin_account;
+       r.in.encrypted_password = pwd_buf;
+       r.in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
+                         WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE;
+
+       torture_comment(tctx, "testing NetrJoinDomain2 (assuming non-DC)\n");
+
+       status = dcerpc_wkssvc_NetrJoinDomain2(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status,
+                                  "NetrJoinDomain2 failed");
+       torture_assert_werr_equal(tctx, r.out.result, expected_err,
+                                 "NetrJoinDomain2 failed");
+
+       if (!test_GetJoinInformation(tctx, p, &join_status, &join_name))
+       {
+               return false;
+       }
+
+       if (join_status != NET_SETUP_DOMAIN_NAME) {
+               torture_comment(tctx,
+                               "Join verify failed: got %d\n", join_status);
+               return false;
+       }
+
+       return true;
+}
+
+static bool test_NetrUnjoinDomain2(struct torture_context *tctx,
+                                  struct dcerpc_pipe *p)
+{
+       NTSTATUS status;
+       struct wkssvc_NetrUnjoinDomain2 r;
+       const char *domain_admin_account = NULL;
+       const char *domain_admin_password = NULL;
+       struct wkssvc_PasswordBuffer *pwd_buf;
+       enum wkssvc_NetJoinStatus join_status;
+       const char *join_name = NULL;
+       WERROR expected_err;
+       DATA_BLOB session_key;
+
+       /* FIXME: this test assumes to join workstations / servers and does not
+        * handle DCs (WERR_SETUP_DOMAIN_CONTROLLER) */
+
+       if (!test_GetJoinInformation(tctx, p, &join_status, &join_name))
+       {
+               return false;
+       }
+
+       switch (join_status) {
+               case NET_SETUP_UNJOINED:
+                       expected_err = WERR_SETUP_NOT_JOINED;
+                       break;
+               case NET_SETUP_DOMAIN_NAME:
+               case NET_SETUP_UNKNOWN_STATUS:
+               case NET_SETUP_WORKGROUP_NAME:
+               default:
+                       expected_err = WERR_OK;
+                       break;
+       }
+
+       domain_admin_account = torture_setting_string(tctx, "domain_admin_account", NULL);
+
+       domain_admin_password = torture_setting_string(tctx, "domain_admin_password", NULL);
+
+       if ((domain_admin_account == NULL) ||
+           (domain_admin_password == NULL)) {
+               torture_comment(tctx, "not enough input parameter\n");
+               return false;
+       }
+
+       status = dcerpc_fetch_session_key(p, &session_key);
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+
+       encode_wkssvc_join_password_buffer(tctx, domain_admin_password,
+                                          &session_key, &pwd_buf);
+
+       r.in.server_name = dcerpc_server_name(p);
+       r.in.account = domain_admin_account;
+       r.in.encrypted_password = pwd_buf;
+       r.in.unjoin_flags = 0;
+
+       torture_comment(tctx, "testing NetrUnjoinDomain2 (assuming non-DC)\n");
+
+       status = dcerpc_wkssvc_NetrUnjoinDomain2(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status,
+                                  "NetrUnjoinDomain2 failed");
+       torture_assert_werr_equal(tctx, r.out.result, expected_err,
+                                 "NetrUnjoinDomain2 failed");
+
+       if (!test_GetJoinInformation(tctx, p, &join_status, &join_name))
+       {
+               return false;
+       }
+
+       switch (join_status) {
+               case NET_SETUP_UNJOINED:
+               case NET_SETUP_WORKGROUP_NAME:
+                       break;
+               case NET_SETUP_UNKNOWN_STATUS:
+               case NET_SETUP_DOMAIN_NAME:
+               default:
+                       torture_comment(tctx,
+                               "Unjoin verify failed: got %d\n", join_status);
+                       return false;
+       }
+
+       return true;
+}
+
+
 struct torture_suite *torture_rpc_wkssvc(TALLOC_CTX *mem_ctx)
 {
        struct torture_suite *suite;
@@ -1112,6 +1385,19 @@ struct torture_suite *torture_rpc_wkssvc(TALLOC_CTX *mem_ctx)
        torture_rpc_tcase_add_test(tcase, "NetrEnumerateComputerNames",
                                   test_NetrEnumerateComputerNames);
 
+       test = torture_rpc_tcase_add_test(tcase, "NetrJoinDomain2",
+                                         test_NetrJoinDomain2);
+       test->dangerous = true;
+       test = torture_rpc_tcase_add_test(tcase, "NetrUnjoinDomain2",
+                                         test_NetrUnjoinDomain2);
+       test->dangerous = true;
+
+       torture_rpc_tcase_add_test(tcase, "NetrJoinDomain",
+                                  test_NetrJoinDomain);
+       test->dangerous = true;
+       torture_rpc_tcase_add_test(tcase, "NetrUnjoinDomain",
+                                  test_NetrUnjoinDomain);
+       test->dangerous = true;
        torture_rpc_tcase_add_test(tcase, "NetrGetJoinInformation",
                                   test_NetrGetJoinInformation);
        torture_rpc_tcase_add_test(tcase, "NetrGetJoinableOus",