*/
#include "includes.h"
-#include "librpc/gen_ndr/ndr_lsa.h"
+#include "torture/torture.h"
+#include "librpc/gen_ndr/lsa.h"
#include "librpc/gen_ndr/ndr_samr.h"
+#include "librpc/gen_ndr/ndr_samr_c.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#include "smb.h"
#include "lib/crypto/crypto.h"
+#include "libcli/auth/libcli_auth.h"
+#include "libcli/security/proto.h"
+#include "torture/rpc/rpc.h"
#define TEST_ACCOUNT_NAME "samrtorturetest"
#define TEST_ALIASNAME "samrtorturetestalias"
static BOOL test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
struct policy_handle *handle);
-static void init_samr_String(struct samr_String *string, const char *s)
+static void init_lsa_String(struct lsa_String *string, const char *s)
{
string->string = s;
}
{
NTSTATUS status;
struct samr_SetDsrmPassword r;
- struct samr_String string;
+ struct lsa_String string;
struct samr_Password hash;
if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
E_md4hash("TeSTDSRM123", hash.hash);
- init_samr_String(&string, "Administrator");
+ init_lsa_String(&string, "Administrator");
r.in.name = &string;
r.in.unknown = 0;
uint32_t user_extra_flags = 0;
if (base_acct_flags == ACB_NORMAL) {
- /* Don't know what this is, but it is always here for users - you can't get rid of it */
- user_extra_flags = 0x20000;
+ /* When created, accounts are expired by default */
+ user_extra_flags = ACB_PW_EXPIRED;
}
s.in.user_handle = handle;
ZERO_STRUCT(u.info21); \
u.info21.fields_present = fpval; \
} \
- init_samr_String(&u.info ## lvl1.field1, value); \
+ init_lsa_String(&u.info ## lvl1.field1, value); \
TESTCALL(SetUserInfo, s) \
TESTCALL(SetUserInfo2, s2) \
- init_samr_String(&u.info ## lvl1.field1, ""); \
+ init_lsa_String(&u.info ## lvl1.field1, ""); \
TESTCALL(QueryUserInfo, q); \
u = *q.out.info; \
STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
(base_acct_flags | ACB_DISABLED | user_extra_flags),
0);
- /* Setting PWNOEXP clears the magic 0x20000 flag */
+ /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
(base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
(base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
r.in.level = levels[i];
r.in.info = talloc(mem_ctx, union samr_AliasInfo);
switch (r.in.level) {
- case 2 : init_samr_String(&r.in.info->name,TEST_ALIASNAME); break;
- case 3 : init_samr_String(&r.in.info->description,
+ case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
+ case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
"Test Description, should test I18N as well"); break;
}
}
static BOOL test_GetDomPwInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
- struct samr_String *domain_name)
+ struct lsa_String *domain_name)
{
NTSTATUS status;
struct samr_GetDomPwInfo r;
{
NTSTATUS status;
struct samr_LookupNames n;
- struct samr_String sname[2];
+ struct lsa_String sname[2];
- init_samr_String(&sname[0], name);
+ init_lsa_String(&sname[0], name);
n.in.domain_handle = domain_handle;
n.in.num_names = 1;
return status;
}
- init_samr_String(&sname[1], "xxNONAMExx");
+ init_lsa_String(&sname[1], "xxNONAMExx");
n.in.num_names = 2;
status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
return status;
}
- init_samr_String(&sname[1], "xxNONAMExx");
+ init_lsa_String(&sname[1], "xxNONAMExx");
n.in.num_names = 0;
status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
if (!NT_STATUS_IS_OK(status)) {
r.in.lm_cross = &hash6;
status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
- if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
+ printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
+ } else if (!NT_STATUS_IS_OK(status)) {
printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
ret = False;
} else {
BOOL ret = True;
struct samr_Password lm_verifier;
struct samr_CryptPassword lm_pass;
- struct samr_AsciiName server, account;
+ struct lsa_AsciiString server, account, account_bad;
char *oldpass = *password;
char *newpass;
uint8_t old_lm_hash[16], new_lm_hash[16];
struct samr_GetDomPwInfo dom_pw_info;
int policy_min_pw_len = 0;
- struct samr_String domain_name;
+ struct lsa_String domain_name;
domain_name.string = "";
dom_pw_info.in.domain_name = &domain_name;
r.in.password = &lm_pass;
r.in.hash = &lm_verifier;
+ /* Break the verification */
+ lm_verifier.hash[0]++;
+
status = dcerpc_samr_OemChangePasswordUser2(p, mem_ctx, &r);
- if (!NT_STATUS_IS_OK(status)) {
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
+ && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
+ printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
+ nt_errstr(status));
+ ret = False;
+ }
+
+ /* This shouldn't be a valid name */
+ account_bad.string = TEST_ACCOUNT_NAME "XX";
+ r.in.account = &account_bad;
+
+ status = dcerpc_samr_OemChangePasswordUser2(p, mem_ctx, &r);
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
+ printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
+ nt_errstr(status));
+ ret = False;
+ }
+
+ E_deshash(oldpass, old_lm_hash);
+ E_deshash(newpass, new_lm_hash);
+
+ encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
+ arcfour_crypt(lm_pass.data, old_lm_hash, 516);
+ E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
+
+ r.in.server = &server;
+ r.in.account = &account;
+ r.in.password = &lm_pass;
+ r.in.hash = &lm_verifier;
+
+ status = dcerpc_samr_OemChangePasswordUser2(p, mem_ctx, &r);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
+ printf("OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
+ } else if (!NT_STATUS_IS_OK(status)) {
printf("OemChangePasswordUser2 failed - %s\n", nt_errstr(status));
ret = False;
} else {
NTSTATUS status;
struct samr_ChangePasswordUser2 r;
BOOL ret = True;
- struct samr_String server, account;
+ struct lsa_String server, account;
struct samr_CryptPassword nt_pass, lm_pass;
struct samr_Password nt_verifier, lm_verifier;
char *oldpass = *password;
struct samr_GetDomPwInfo dom_pw_info;
int policy_min_pw_len = 0;
- struct samr_String domain_name;
+ struct lsa_String domain_name;
domain_name.string = "";
dom_pw_info.in.domain_name = &domain_name;
newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);
server.string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
- init_samr_String(&account, TEST_ACCOUNT_NAME);
+ init_lsa_String(&account, TEST_ACCOUNT_NAME);
E_md4hash(oldpass, old_nt_hash);
E_md4hash(newpass, new_nt_hash);
r.in.lm_verifier = &lm_verifier;
status = dcerpc_samr_ChangePasswordUser2(p, mem_ctx, &r);
- if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
+ printf("ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
+ } else if (!NT_STATUS_IS_OK(status)) {
printf("ChangePasswordUser2 failed - %s\n", nt_errstr(status));
ret = False;
} else {
}
-static BOOL test_ChangePasswordUser3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
- struct policy_handle *handle,
- int policy_min_pw_len,
- char **password)
+BOOL test_ChangePasswordUser3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+ const char *account_string,
+ int policy_min_pw_len,
+ char **password)
{
NTSTATUS status;
struct samr_ChangePasswordUser3 r;
BOOL ret = True;
- struct samr_String server, account;
+ struct lsa_String server, account, account_bad;
struct samr_CryptPassword nt_pass, lm_pass;
struct samr_Password nt_verifier, lm_verifier;
char *oldpass = *password;
printf("Testing ChangePasswordUser3\n");
server.string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
- init_samr_String(&account, TEST_ACCOUNT_NAME);
+ init_lsa_String(&account, account_string);
+
+ E_md4hash(oldpass, old_nt_hash);
+ E_md4hash(newpass, new_nt_hash);
+
+ E_deshash(oldpass, old_lm_hash);
+ E_deshash(newpass, new_lm_hash);
+
+ encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
+ arcfour_crypt(lm_pass.data, old_nt_hash, 516);
+ E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
+
+ encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
+ arcfour_crypt(nt_pass.data, old_nt_hash, 516);
+ E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
+
+ /* Break the verification */
+ nt_verifier.hash[0]++;
+
+ r.in.server = &server;
+ r.in.account = &account;
+ r.in.nt_password = &nt_pass;
+ r.in.nt_verifier = &nt_verifier;
+ r.in.lm_change = 1;
+ r.in.lm_password = &lm_pass;
+ r.in.lm_verifier = &lm_verifier;
+ r.in.password3 = NULL;
+
+ status = dcerpc_samr_ChangePasswordUser3(p, mem_ctx, &r);
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
+ (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
+ printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
+ nt_errstr(status));
+ ret = False;
+ }
+
+ /* This shouldn't be a valid name */
+ init_lsa_String(&account_bad, talloc_asprintf(mem_ctx, "%sXX", account_string));
+
+ r.in.account = &account_bad;
+ status = dcerpc_samr_ChangePasswordUser3(p, mem_ctx, &r);
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
+ printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
+ nt_errstr(status));
+ ret = False;
+ }
E_md4hash(oldpass, old_nt_hash);
E_md4hash(newpass, new_nt_hash);
policy_min_pw_len = r.out.dominfo->min_password_length;
}
if (policy_min_pw_len) /* try again with the right min password length */ {
- ret = test_ChangePasswordUser3(p, mem_ctx, handle, policy_min_pw_len, password);
+ ret = test_ChangePasswordUser3(p, mem_ctx, account_string, policy_min_pw_len, password);
} else {
- printf("ChangePasswordUser3 failed - %s\n", nt_errstr(status));
+ printf("ChangePasswordUser3 failed (no min length known) - %s\n", nt_errstr(status));
ret = False;
}
+ } else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
+ printf("ChangePasswordUser3 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
} else if (!NT_STATUS_IS_OK(status)) {
printf("ChangePasswordUser3 failed - %s\n", nt_errstr(status));
ret = False;
{
NTSTATUS status;
struct samr_CreateDomAlias r;
- struct samr_String name;
+ struct lsa_String name;
uint32_t rid;
BOOL ret = True;
- init_samr_String(&name, TEST_ALIASNAME);
+ init_lsa_String(&name, TEST_ALIASNAME);
r.in.domain_handle = domain_handle;
r.in.alias_name = &name;
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
/* we change passwords twice - this has the effect of verifying
they were changed correctly for the final call */
- if (!test_ChangePasswordUser3(p, mem_ctx, domain_handle, 0, password)) {
+ if (!test_ChangePasswordUser3(p, mem_ctx, TEST_ACCOUNT_NAME, 0, password)) {
ret = False;
}
- if (!test_ChangePasswordUser3(p, mem_ctx, domain_handle, 0, password)) {
+ if (!test_ChangePasswordUser3(p, mem_ctx, TEST_ACCOUNT_NAME, 0, password)) {
ret = False;
}
/* This call creates a 'normal' account - check that it really does */
const uint32_t acct_flags = ACB_NORMAL;
- struct samr_String name;
+ struct lsa_String name;
BOOL ret = True;
user_ctx = talloc_named(mem_ctx, 0, "test_CreateUser2 per-user context");
- init_samr_String(&name, TEST_ACCOUNT_NAME);
+ init_lsa_String(&name, TEST_ACCOUNT_NAME);
r.in.domain_handle = domain_handle;
r.in.account_name = &name;
}
/* check it was set right */
- if (!test_ChangePasswordUser3(p, user_ctx, domain_handle, 0, &password)) {
+ if (!test_ChangePasswordUser3(p, user_ctx, TEST_ACCOUNT_NAME, 0, &password)) {
ret = False;
}
}
}
/* check it was set right */
- if (!test_ChangePasswordUser3(p, user_ctx, domain_handle, 0, &password)) {
+ if (!test_ChangePasswordUser3(p, user_ctx, TEST_ACCOUNT_NAME, 0, &password)) {
ret = False;
}
}
struct samr_DeleteUser d;
struct policy_handle user_handle;
uint32_t rid;
- struct samr_String name;
+ struct lsa_String name;
BOOL ret = True;
int i;
uint32_t acct_flags = account_types[i].acct_flags;
uint32_t access_granted;
user_ctx = talloc_named(mem_ctx, 0, "test_CreateUser2 per-user context");
- init_samr_String(&name, account_types[i].account_name);
+ init_lsa_String(&name, account_types[i].account_name);
r.in.domain_handle = handle;
r.in.account_name = &name;
the name is still reserved, so creating the old name fails, but deleting by the old name
also fails */
if (s.in.level == 2) {
- init_samr_String(&s.in.info->string, "NewName");
+ init_lsa_String(&s.in.info->string, "NewName");
}
#endif
if (s.in.level == 4) {
- init_samr_String(&s.in.info->description, "test description");
+ init_lsa_String(&s.in.info->description, "test description");
}
status = dcerpc_samr_SetGroupInfo(p, mem_ctx, &s);
printf("Testing LookupNames\n");
n.in.domain_handle = handle;
n.in.num_names = r.out.sam->count;
- n.in.names = talloc_array(mem_ctx, struct samr_String, r.out.sam->count);
+ n.in.names = talloc_array(mem_ctx, struct lsa_String, r.out.sam->count);
for (i=0;i<r.out.sam->count;i++) {
- n.in.names[i] = r.out.sam->entries[i].name;
+ n.in.names[i].string = r.out.sam->entries[i].name.string;
}
status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
if (!NT_STATUS_IS_OK(status)) {
r.in.domain_handle = handle;
r.in.level = levels[i];
- init_samr_String(&r.in.name, TEST_ACCOUNT_NAME);
+ init_lsa_String(&r.in.name, TEST_ACCOUNT_NAME);
status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
ret = False;
}
- init_samr_String(&r.in.name, "zzzzzzzz");
+ init_lsa_String(&r.in.name, "zzzzzzzz");
status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
r.in.domain_handle = handle;
r.in.level = levels[i];
- init_samr_String(&r.in.name, TEST_ACCOUNT_NAME);
+ init_lsa_String(&r.in.name, TEST_ACCOUNT_NAME);
status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
if (ok_lvl[i] &&
ret = False;
}
- init_samr_String(&r.in.name, "zzzzzzzz");
+ init_lsa_String(&r.in.name, "zzzzzzzz");
status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
}
static BOOL test_RidToSid(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+ struct dom_sid *domain_sid,
struct policy_handle *domain_handle)
{
struct samr_RidToSid r;
NTSTATUS status;
BOOL ret = True;
+ struct dom_sid *calc_sid;
+ int rids[] = { 0, 42, 512, 10200 };
+ int i;
- printf("Testing RidToSid\n");
-
- r.in.domain_handle = domain_handle;
- r.in.rid = 512;
+ for (i=0;i<ARRAY_SIZE(rids);i++) {
+
+ printf("Testing RidToSid\n");
+
+ calc_sid = dom_sid_dup(mem_ctx, domain_sid);
+ r.in.domain_handle = domain_handle;
+ r.in.rid = rids[i];
+
+ status = dcerpc_samr_RidToSid(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
+ ret = False;
+ } else {
+ calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
- status = dcerpc_samr_RidToSid(p, mem_ctx, &r);
- if (!NT_STATUS_IS_OK(status)) {
- printf("RidToSid failed - %s\n", nt_errstr(status));
- ret = False;
+ if (!dom_sid_equal(calc_sid, r.out.sid)) {
+ printf("RidToSid for %d failed - got %s, expected %s\n", rids[i],
+ dom_sid_string(mem_ctx, r.out.sid),
+ dom_sid_string(mem_ctx, calc_sid));
+ ret = False;
+ }
+ }
}
return ret;
NTSTATUS status;
struct samr_CreateDomainGroup r;
uint32_t rid;
- struct samr_String name;
+ struct lsa_String name;
BOOL ret = True;
- init_samr_String(&name, TEST_GROUPNAME);
+ init_lsa_String(&name, TEST_GROUPNAME);
r.in.domain_handle = domain_handle;
r.in.name = &name;
ret &= test_GetDisplayEnumerationIndex2(p, mem_ctx, &domain_handle);
ret &= test_GroupList(p, mem_ctx, &domain_handle);
ret &= test_TestPrivateFunctionsDomain(p, mem_ctx, &domain_handle);
- ret &= test_RidToSid(p, mem_ctx, &domain_handle);
+ ret &= test_RidToSid(p, mem_ctx, sid, &domain_handle);
ret &= test_GetBootKeyInformation(p, mem_ctx, &domain_handle);
if (!policy_handle_empty(&user_handle) &&
}
static BOOL test_LookupDomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
- struct policy_handle *handle, struct samr_String *domain)
+ struct policy_handle *handle, struct lsa_String *domain)
{
NTSTATUS status;
struct samr_LookupDomain r;
- struct samr_String n2;
+ struct lsa_String n2;
BOOL ret = True;
printf("Testing LookupDomain(%s)\n", domain->string);
mem_ctx = talloc_init("torture_rpc_samr");
- status = torture_rpc_connection(mem_ctx,
- &p,
- DCERPC_SAMR_NAME,
- DCERPC_SAMR_UUID,
- DCERPC_SAMR_VERSION);
+ status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_samr);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(mem_ctx);
return False;