/*
Unix SMB/CIFS implementation.
SMB torture tester
- Copyright (C) Guenther Deschner 2009
+ Copyright (C) Guenther Deschner 2009-2010
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
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "includes.h"
+#include "lib/replace/replace.h"
+#include "libcli/util/ntstatus.h"
+#include "libcli/util/werror.h"
+#include "lib/util/data_blob.h"
+#include "lib/util/time.h"
#include "nsswitch/libwbclient/wbclient.h"
#include "torture/smbtorture.h"
#include "torture/winbind/proto.h"
+#include "lib/util/util_net.h"
+#include "lib/util/charset/charset.h"
+#include "libcli/auth/libcli_auth.h"
+#include "source4/param/param.h"
+#include "lib/util/samba_util.h"
+#include "lib/crypto/arcfour.h"
#define WBC_ERROR_EQUAL(x,y) (x == y)
return true;
}
+static bool test_wbc_pingdc(struct torture_context *tctx)
+{
+ torture_assert_wbc_equal(tctx, wbcPingDc("random_string", NULL), WBC_ERR_NOT_IMPLEMENTED,
+ "wbcPingDc failed");
+ torture_assert_wbc_ok(tctx, wbcPingDc(NULL, NULL),
+ "wbcPingDc failed");
+
+ return true;
+}
+
static bool test_wbc_library_details(struct torture_context *tctx)
{
struct wbcLibraryDetails *details;
"wbcSidToString failed");
torture_assert_str_equal(tctx, sid_string, sid_string2,
"sid strings differ");
+ wbcFreeMemory(sid_string2);
return true;
}
"wbcGuidToString failed");
torture_assert_str_equal(tctx, guid_string, guid_string2,
"guid strings differ");
+ wbcFreeMemory(guid_string2);
return true;
}
static bool test_wbc_domain_info(struct torture_context *tctx)
{
- const char *domain_name = NULL;
struct wbcDomainInfo *info;
struct wbcInterfaceDetails *details;
torture_assert_wbc_ok(tctx, wbcInterfaceDetails(&details),
"wbcInterfaceDetails failed");
-
- domain_name = talloc_strdup(tctx, details->netbios_domain);
+ torture_assert_wbc_ok(
+ tctx, wbcDomainInfo(details->netbios_domain, &info),
+ "wbcDomainInfo failed");
wbcFreeMemory(details);
- torture_assert_wbc_ok(tctx, wbcDomainInfo(domain_name, &info),
- "wbcDomainInfo failed");
torture_assert(tctx, info,
"wbcDomainInfo returned NULL pointer");
+ wbcFreeMemory(info);
return true;
}
"wbcLookupSid expected WBC_SID_NAME_USER");
torture_assert(tctx, name,
"wbcLookupSid returned no name");
+ wbcFreeMemory(domain);
+ wbcFreeMemory(name);
torture_assert_wbc_ok(tctx, wbcLookupUserSids(&sid, true, &num_sids, &sids),
"wbcLookupUserSids failed");
+ torture_assert_wbc_ok(
+ tctx, wbcGetDisplayName(&sid, &domain, &name,
+ &name_type),
+ "wbcGetDisplayName failed");
+ wbcFreeMemory(domain);
+ wbcFreeMemory(name);
+ wbcFreeMemory(sids);
}
+ wbcFreeMemory(users);
return true;
}
torture_assert(tctx, name,
"wbcLookupSid returned no name");
}
+ wbcFreeMemory(groups);
return true;
}
"wbcLookupSid returned no name");
*/
}
+ wbcFreeMemory(domains);
+
+ return true;
+}
+
+static bool test_wbc_lookupdc(struct torture_context *tctx)
+{
+ const char *domain_name = NULL;
+ struct wbcInterfaceDetails *details;
+ struct wbcDomainControllerInfo *dc_info;
+
+ torture_assert_wbc_ok(tctx, wbcInterfaceDetails(&details),
+ "wbcInterfaceDetails failed");
+
+ domain_name = talloc_strdup(tctx, details->netbios_domain);
+ wbcFreeMemory(details);
+
+ torture_assert_wbc_ok(tctx, wbcLookupDomainController(domain_name, 0, &dc_info),
+ "wbcLookupDomainController failed");
+ wbcFreeMemory(dc_info);
+
+ return true;
+}
+
+static bool test_wbc_lookupdcex(struct torture_context *tctx)
+{
+ const char *domain_name = NULL;
+ struct wbcInterfaceDetails *details;
+ struct wbcDomainControllerInfoEx *dc_info;
+
+ torture_assert_wbc_ok(tctx, wbcInterfaceDetails(&details),
+ "wbcInterfaceDetails failed");
+
+ domain_name = talloc_strdup(tctx, details->netbios_domain);
+ wbcFreeMemory(details);
+
+ torture_assert_wbc_ok(tctx, wbcLookupDomainControllerEx(domain_name, NULL, NULL, 0, &dc_info),
+ "wbcLookupDomainControllerEx failed");
+ wbcFreeMemory(dc_info);
+
+ return true;
+}
+
+static bool test_wbc_resolve_winsbyname(struct torture_context *tctx)
+{
+ const char *name;
+ char *ip;
+ wbcErr ret;
+
+ name = torture_setting_string(tctx, "host", NULL);
+
+ ret = wbcResolveWinsByName(name, &ip);
+
+ if (is_ipaddress(name)) {
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_DOMAIN_NOT_FOUND, "wbcResolveWinsByName failed");
+ } else {
+ torture_assert_wbc_ok(tctx, ret, "wbcResolveWinsByName failed");
+ }
return true;
}
+static bool test_wbc_resolve_winsbyip(struct torture_context *tctx)
+{
+ const char *ip;
+ char *name;
+ wbcErr ret;
+
+ ip = torture_setting_string(tctx, "host", NULL);
+
+ ret = wbcResolveWinsByIP(ip, &name);
+
+ torture_assert_wbc_ok(tctx, ret, "wbcResolveWinsByIP failed");
+
+ wbcFreeMemory(name);
+
+ return true;
+}
+
+static bool test_wbc_lookup_rids(struct torture_context *tctx)
+{
+ struct wbcDomainSid builtin;
+ uint32_t rids[2] = { 544, 545 };
+ const char *domain_name, **names;
+ enum wbcSidType *types;
+ wbcErr ret;
+
+ wbcStringToSid("S-1-5-32", &builtin);
+
+ ret = wbcLookupRids(&builtin, 2, rids, &domain_name, &names,
+ &types);
+ torture_assert_wbc_ok(tctx, ret, "wbcLookupRids failed");
+
+ torture_assert_str_equal(
+ tctx, names[0], "Administrators",
+ "S-1-5-32-544 not mapped to 'Administrators'");
+ torture_assert_str_equal(
+ tctx, names[1], "Users", "S-1-5-32-545 not mapped to 'Users'");
+ wbcFreeMemory(discard_const_p(char ,domain_name));
+ wbcFreeMemory(names);
+ wbcFreeMemory(types);
+
+ return true;
+}
+
+static bool test_wbc_get_sidaliases(struct torture_context *tctx)
+{
+ struct wbcDomainSid builtin;
+ struct wbcDomainInfo *info;
+ struct wbcInterfaceDetails *details;
+ struct wbcDomainSid sids[2];
+ uint32_t *rids;
+ uint32_t num_rids;
+ wbcErr ret;
+
+ torture_assert_wbc_ok(tctx, wbcInterfaceDetails(&details),
+ "wbcInterfaceDetails failed");
+ torture_assert_wbc_ok(
+ tctx, wbcDomainInfo(details->netbios_domain, &info),
+ "wbcDomainInfo failed");
+ wbcFreeMemory(details);
+
+ sids[0] = info->sid;
+ sids[0].sub_auths[sids[0].num_auths++] = 500;
+ sids[1] = info->sid;
+ sids[1].sub_auths[sids[1].num_auths++] = 512;
+ wbcFreeMemory(info);
+
+ torture_assert_wbc_ok(
+ tctx, wbcStringToSid("S-1-5-32", &builtin),
+ "wbcStringToSid failed");
+
+ ret = wbcGetSidAliases(&builtin, sids, 2, &rids, &num_rids);
+ torture_assert_wbc_ok(tctx, ret, "wbcGetSidAliases failed");
+
+ wbcFreeMemory(rids);
+
+ return true;
+}
+
+static bool test_wbc_authenticate_user_int(struct torture_context *tctx,
+ const char *correct_password)
+{
+ struct wbcAuthUserParams params;
+ struct wbcAuthUserInfo *info = NULL;
+ struct wbcAuthErrorInfo *error = NULL;
+ wbcErr ret;
+
+ ret = wbcAuthenticateUser(getenv("USERNAME"), correct_password);
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
+ "wbcAuthenticateUser failed");
+
+ ZERO_STRUCT(params);
+ params.account_name = getenv("USERNAME");
+ params.level = WBC_AUTH_USER_LEVEL_PLAIN;
+ params.password.plaintext = correct_password;
+
+ ret = wbcAuthenticateUserEx(¶ms, &info, &error);
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
+ "wbcAuthenticateUserEx failed");
+ wbcFreeMemory(info);
+ info = NULL;
+
+ wbcFreeMemory(error);
+ error = NULL;
+
+ params.password.plaintext = "wrong";
+ ret = wbcAuthenticateUserEx(¶ms, &info, &error);
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_AUTH_ERROR,
+ "wbcAuthenticateUserEx succeeded where it "
+ "should have failed");
+ wbcFreeMemory(info);
+ info = NULL;
+
+ wbcFreeMemory(error);
+ error = NULL;
+
+ return true;
+}
+
+static bool test_wbc_authenticate_user(struct torture_context *tctx)
+{
+ return test_wbc_authenticate_user_int(tctx, getenv("PASSWORD"));
+}
+
+static bool test_wbc_change_password(struct torture_context *tctx)
+{
+ wbcErr ret;
+ const char *oldpass = getenv("PASSWORD");
+ const char *newpass = "Koo8irei";
+
+ struct samr_CryptPassword new_nt_password;
+ struct samr_CryptPassword new_lm_password;
+ struct samr_Password old_nt_hash_enc;
+ struct samr_Password old_lanman_hash_enc;
+
+ uint8_t old_nt_hash[16];
+ uint8_t old_lanman_hash[16];
+ uint8_t new_nt_hash[16];
+ uint8_t new_lanman_hash[16];
+
+ struct wbcChangePasswordParams params;
+
+ if (oldpass == NULL) {
+ torture_skip(tctx,
+ "skipping wbcChangeUserPassword test as old password cannot be retrieved\n");
+ }
+
+ ZERO_STRUCT(params);
+
+ E_md4hash(oldpass, old_nt_hash);
+ E_md4hash(newpass, new_nt_hash);
+
+ if (lpcfg_client_lanman_auth(tctx->lp_ctx) &&
+ E_deshash(newpass, new_lanman_hash) &&
+ E_deshash(oldpass, old_lanman_hash)) {
+
+ /* E_deshash returns false for 'long' passwords (> 14
+ DOS chars). This allows us to match Win2k, which
+ does not store a LM hash for these passwords (which
+ would reduce the effective password length to 14) */
+
+ encode_pw_buffer(new_lm_password.data, newpass, STR_UNICODE);
+ arcfour_crypt(new_lm_password.data, old_nt_hash, 516);
+ E_old_pw_hash(new_nt_hash, old_lanman_hash,
+ old_lanman_hash_enc.hash);
+
+ params.old_password.response.old_lm_hash_enc_length =
+ sizeof(old_lanman_hash_enc.hash);
+ params.old_password.response.old_lm_hash_enc_data =
+ old_lanman_hash_enc.hash;
+ params.new_password.response.lm_length =
+ sizeof(new_lm_password.data);
+ params.new_password.response.lm_data =
+ new_lm_password.data;
+ } else {
+ ZERO_STRUCT(new_lm_password);
+ ZERO_STRUCT(old_lanman_hash_enc);
+ }
+
+ encode_pw_buffer(new_nt_password.data, newpass, STR_UNICODE);
+
+ arcfour_crypt(new_nt_password.data, old_nt_hash, 516);
+ E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);
+
+ params.old_password.response.old_nt_hash_enc_length =
+ sizeof(old_nt_hash_enc.hash);
+ params.old_password.response.old_nt_hash_enc_data =
+ old_nt_hash_enc.hash;
+ params.new_password.response.nt_length = sizeof(new_nt_password.data);
+ params.new_password.response.nt_data = new_nt_password.data;
+
+ params.level = WBC_CHANGE_PASSWORD_LEVEL_RESPONSE;
+ params.account_name = getenv("USERNAME");
+ params.domain_name = "SAMBA-TEST";
+
+ ret = wbcChangeUserPasswordEx(¶ms, NULL, NULL, NULL);
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
+ "wbcChangeUserPassword failed");
+
+ if (!test_wbc_authenticate_user_int(tctx, "Koo8irei")) {
+ return false;
+ }
+
+ ret = wbcChangeUserPassword(getenv("USERNAME"), "Koo8irei",
+ getenv("PASSWORD"));
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
+ "wbcChangeUserPassword failed");
+
+ return test_wbc_authenticate_user_int(tctx, getenv("PASSWORD"));
+}
+
+static bool test_wbc_logon_user(struct torture_context *tctx)
+{
+ struct wbcLogonUserParams params;
+ struct wbcLogonUserInfo *info = NULL;
+ struct wbcAuthErrorInfo *error = NULL;
+ struct wbcUserPasswordPolicyInfo *policy = NULL;
+ struct wbcInterfaceDetails *iface;
+ struct wbcDomainSid sid;
+ enum wbcSidType sidtype;
+ char *sidstr;
+ wbcErr ret;
+
+ ZERO_STRUCT(params);
+
+ ret = wbcLogonUser(¶ms, &info, &error, &policy);
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_INVALID_PARAM,
+ "wbcLogonUser succeeded where it should "
+ "have failed");
+
+ params.username = getenv("USERNAME");
+ params.password = getenv("PASSWORD");
+
+ ret = wbcAddNamedBlob(¶ms.num_blobs, ¶ms.blobs,
+ "foo", 0, discard_const_p(uint8_t, "bar"), 4);
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
+ "wbcAddNamedBlob failed");
+
+ ret = wbcLogonUser(¶ms, &info, &error, &policy);
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
+ "wbcLogonUser failed");
+ wbcFreeMemory(info); info = NULL;
+ wbcFreeMemory(error); error = NULL;
+ wbcFreeMemory(policy); policy = NULL;
+
+ params.password = "wrong";
+
+ ret = wbcLogonUser(¶ms, &info, &error, &policy);
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_AUTH_ERROR,
+ "wbcLogonUser should have failed with "
+ "WBC_ERR_AUTH_ERROR");
+ wbcFreeMemory(info); info = NULL;
+ wbcFreeMemory(error); error = NULL;
+ wbcFreeMemory(policy); policy = NULL;
+
+ ret = wbcAddNamedBlob(¶ms.num_blobs, ¶ms.blobs,
+ "membership_of", 0,
+ discard_const_p(uint8_t, "S-1-2-3-4"),
+ strlen("S-1-2-3-4")+1);
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
+ "wbcAddNamedBlob failed");
+ params.password = getenv("PASSWORD");
+ ret = wbcLogonUser(¶ms, &info, &error, &policy);
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_AUTH_ERROR,
+ "wbcLogonUser should have failed with "
+ "WBC_ERR_AUTH_ERROR");
+ wbcFreeMemory(info); info = NULL;
+ wbcFreeMemory(error); error = NULL;
+ wbcFreeMemory(policy); policy = NULL;
+ wbcFreeMemory(params.blobs);
+ params.blobs = NULL; params.num_blobs = 0;
+
+ ret = wbcInterfaceDetails(&iface);
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
+ "wbcInterfaceDetails failed");
+
+ ret = wbcLookupName(iface->netbios_domain, getenv("USERNAME"), &sid,
+ &sidtype);
+ wbcFreeMemory(iface);
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
+ "wbcLookupName failed");
+
+ ret = wbcSidToString(&sid, &sidstr);
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
+ "wbcSidToString failed");
+
+ ret = wbcAddNamedBlob(¶ms.num_blobs, ¶ms.blobs,
+ "membership_of", 0,
+ (uint8_t *)sidstr, strlen(sidstr)+1);
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
+ "wbcAddNamedBlob failed");
+ wbcFreeMemory(sidstr);
+ params.password = getenv("PASSWORD");
+ ret = wbcLogonUser(¶ms, &info, &error, &policy);
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
+ "wbcLogonUser failed");
+ wbcFreeMemory(info); info = NULL;
+ wbcFreeMemory(error); error = NULL;
+ wbcFreeMemory(policy); policy = NULL;
+ wbcFreeMemory(params.blobs);
+ params.blobs = NULL; params.num_blobs = 0;
+
+ return true;
+}
+
+static bool test_wbc_getgroups(struct torture_context *tctx)
+{
+ wbcErr ret;
+ uint32_t num_groups;
+ gid_t *groups;
+
+ ret = wbcGetGroups(getenv("USERNAME"), &num_groups, &groups);
+ torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
+ "wbcGetGroups failed");
+ wbcFreeMemory(groups);
+ return true;
+}
struct torture_suite *torture_wbclient(void)
{
- struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "WBCLIENT");
+ struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "wbclient");
torture_suite_add_simple_test(suite, "wbcPing", test_wbc_ping);
+ torture_suite_add_simple_test(suite, "wbcPingDc", test_wbc_pingdc);
torture_suite_add_simple_test(suite, "wbcLibraryDetails", test_wbc_library_details);
torture_suite_add_simple_test(suite, "wbcInterfaceDetails", test_wbc_interface_details);
torture_suite_add_simple_test(suite, "wbcSidTypeString", test_wbc_sidtypestring);
torture_suite_add_simple_test(suite, "wbcListUsers", test_wbc_users);
torture_suite_add_simple_test(suite, "wbcListGroups", test_wbc_groups);
torture_suite_add_simple_test(suite, "wbcListTrusts", test_wbc_trusts);
+ torture_suite_add_simple_test(suite, "wbcLookupDomainController", test_wbc_lookupdc);
+ torture_suite_add_simple_test(suite, "wbcLookupDomainControllerEx", test_wbc_lookupdcex);
+ torture_suite_add_simple_test(suite, "wbcResolveWinsByName", test_wbc_resolve_winsbyname);
+ torture_suite_add_simple_test(suite, "wbcResolveWinsByIP", test_wbc_resolve_winsbyip);
+ torture_suite_add_simple_test(suite, "wbcLookupRids",
+ test_wbc_lookup_rids);
+ torture_suite_add_simple_test(suite, "wbcGetSidAliases",
+ test_wbc_get_sidaliases);
+ torture_suite_add_simple_test(suite, "wbcAuthenticateUser",
+ test_wbc_authenticate_user);
+ torture_suite_add_simple_test(suite, "wbcLogonUser",
+ test_wbc_logon_user);
+ torture_suite_add_simple_test(suite, "wbcChangeUserPassword",
+ test_wbc_change_password);
+ torture_suite_add_simple_test(suite, "wbcGetGroups",
+ test_wbc_getgroups);
return suite;
}