summaryrefslogtreecommitdiff
path: root/source4/torture/rpc/samsync.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/torture/rpc/samsync.c')
-rw-r--r--source4/torture/rpc/samsync.c169
1 files changed, 162 insertions, 7 deletions
diff --git a/source4/torture/rpc/samsync.c b/source4/torture/rpc/samsync.c
index 8bb6ec2ec6..aaab3ef988 100644
--- a/source4/torture/rpc/samsync.c
+++ b/source4/torture/rpc/samsync.c
@@ -25,6 +25,8 @@
#include "includes.h"
#include "librpc/gen_ndr/ndr_netlogon.h"
#include "auth/auth.h"
+#include "dlinklist.h"
+#include "lib/crypto/crypto.h"
#define TEST_MACHINE_NAME "samsynctest"
@@ -55,12 +57,18 @@ static NTSTATUS test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
ninfo.nt.length = 24;
ninfo.nt.data = talloc(mem_ctx, 24);
SMBOWFencrypt(nt_hash->hash, ninfo.challenge, ninfo.nt.data);
+ } else {
+ ninfo.nt.length = 0;
+ ninfo.nt.data = NULL;
}
if (lm_hash) {
ninfo.lm.length = 24;
ninfo.lm.data = talloc(mem_ctx, 24);
SMBOWFencrypt(lm_hash->hash, ninfo.challenge, ninfo.lm.data);
+ } else {
+ ninfo.lm.length = 0;
+ ninfo.lm.data = NULL;
}
r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
@@ -81,7 +89,9 @@ static NTSTATUS test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
printf("Credential chaining failed\n");
}
- *info3 = r.out.validation.sam3;
+ if (info3) {
+ *info3 = r.out.validation.sam3;
+ }
return status;
}
@@ -89,6 +99,20 @@ static NTSTATUS test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
struct samsync_state {
uint64_t seq_num;
char *domain_name;
+ struct samsync_secret *secrets;
+ struct samsync_trusted_domain *trusted_domains;
+};
+
+struct samsync_secret {
+ struct samsync_secret *prev, *next;
+ DATA_BLOB secret;
+ char *name;
+};
+
+struct samsync_trusted_domain {
+ struct samsync_trusted_domain *prev, *next;
+ struct dom_sid *sid;
+ char *name;
};
static struct samsync_state *samsync_state;
@@ -103,7 +127,7 @@ static BOOL samsync_handle_domain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
domain->sequence_num;
samsync_state[database_id].domain_name =
- talloc_reference(samsync_state, domain->DomainName.string);
+ talloc_reference(samsync_state, domain->domain_name.string);
printf("\tsequence_nums[%d/%s]=%llu\n",
database_id, samsync_state[database_id].domain_name,
@@ -120,6 +144,8 @@ static BOOL samsync_handle_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
struct netr_SamInfo3 *info3;
struct samr_Password lm_hash;
struct samr_Password nt_hash;
+ struct samr_Password *lm_hash_p = NULL;
+ struct samr_Password *nt_hash_p = NULL;
const char *domain = samsync_state[database_id].domain_name
? samsync_state[database_id].domain_name
: lp_workgroup();
@@ -130,22 +156,53 @@ static BOOL samsync_handle_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
if (user->lmpassword_present) {
sam_rid_crypt(rid, user->lmpassword.hash, lm_hash.hash, 0);
+ lm_hash_p = &lm_hash;
}
if (user->ntpassword_present) {
sam_rid_crypt(rid, user->ntpassword.hash, nt_hash.hash, 0);
+ nt_hash_p = &nt_hash;
}
- if (!user->lmpassword_present && !user->lmpassword_present) {
+ if (user->user_private_info.SensitiveData) {
+ DATA_BLOB data;
+ struct netr_USER_KEYS keys;
+ data.data = user->user_private_info.SensitiveData;
+ data.length = user->user_private_info.DataLength;
+ creds_arcfour_crypt(creds, data.data, data.length);
+#if 0
+ printf("Sensitive Data for %s:\n", username);
+ dump_data(0, data.data, data.length);
+#endif
+ nt_status = ndr_pull_struct_blob(&data, mem_ctx, &keys, (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return False;
+ }
+ if (keys.keys.keys2.lmpassword.length == 16) {
+ sam_rid_crypt(rid, keys.keys.keys2.lmpassword.pwd.hash, lm_hash.hash, 0);
+ dump_data(0, keys.keys.keys2.lmpassword.pwd.hash,
+ sizeof(keys.keys.keys2.lmpassword.pwd.hash));
+
+ lm_hash_p = &lm_hash;
+ }
+ if (keys.keys.keys2.ntpassword.length == 16) {
+ sam_rid_crypt(rid, keys.keys.keys2.ntpassword.pwd.hash, nt_hash.hash, 0);
+ dump_data(0, keys.keys.keys2.ntpassword.pwd.hash,
+ sizeof(keys.keys.keys2.ntpassword.pwd.hash));
+ nt_hash_p = &nt_hash;
+ }
+
+ }
+ if (!lm_hash_p && !nt_hash_p) {
printf("NO password set for %s\n",
user->account_name.string);
return True;
}
-
+
nt_status = test_SamLogon(p, mem_ctx, creds,
domain,
username,
- user->lmpassword_present ? &lm_hash : NULL,
- user->ntpassword_present ? &nt_hash : NULL,
+ lm_hash_p,
+ nt_hash_p,
&info3);
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
@@ -178,7 +235,7 @@ static BOOL samsync_handle_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
user->acct_flags, info3->base.acct_flags);
return False;
}
- if (strcmp(user->full_name.string, info3->base.full_name.string) != 0) {
+ if (strcmp_safe(user->full_name.string, info3->base.full_name.string) != 0) {
printf("Full name mismatch: %s != %s\n",
user->full_name.string, info3->base.full_name.string);
return False;
@@ -192,6 +249,44 @@ static BOOL samsync_handle_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
return False;
}
+static BOOL samsync_handle_secret(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+ struct creds_CredentialState *creds,
+ int database_id, struct netr_DELTA_ENUM *delta)
+{
+ struct netr_DELTA_SECRET *secret = delta->delta_union.secret;
+ const char *name = delta->delta_id_union.name;
+ struct samsync_secret *new = talloc_p(samsync_state, struct samsync_secret);
+
+ creds_arcfour_crypt(creds, secret->current_cipher.cipher_data,
+ secret->current_cipher.maxlen);
+
+ creds_arcfour_crypt(creds, secret->old_cipher.cipher_data,
+ secret->old_cipher.maxlen);
+
+ new->name = talloc_reference(new, name);
+ new->secret = data_blob_talloc(new, secret->current_cipher.cipher_data, secret->current_cipher.maxlen);
+
+ DLIST_ADD(samsync_state[database_id].secrets, new);
+
+ return True;
+}
+
+static BOOL samsync_handle_trusted_domain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+ struct creds_CredentialState *creds,
+ int database_id, struct netr_DELTA_ENUM *delta)
+{
+ struct netr_DELTA_TRUSTED_DOMAIN *trusted_domain = delta->delta_union.trusted_domain;
+ struct dom_sid *dom_sid = delta->delta_id_union.sid;
+
+ struct samsync_trusted_domain *new = talloc_p(samsync_state, struct samsync_trusted_domain);
+ new->name = talloc_reference(new, trusted_domain->domain_name.string);
+ new->sid = talloc_reference(new, dom_sid);
+
+ DLIST_ADD(samsync_state[database_id].trusted_domains, new);
+
+ return True;
+}
+
/* we remember the sequence numbers so we can easily do a DatabaseDelta */
static uint64_t sequence_nums[3];
@@ -206,6 +301,8 @@ static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
const uint32_t database_ids[] = {SAM_DATABASE_DOMAIN, SAM_DATABASE_BUILTIN, SAM_DATABASE_PRIVS};
int i, d;
BOOL ret = True;
+ struct samsync_trusted_domain *t;
+ struct samsync_secret *s;
samsync_state = talloc_zero_array_p(mem_ctx, struct samsync_state, 3);
@@ -247,9 +344,67 @@ static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
ret &= samsync_handle_user(p, mem_ctx, creds,
r.in.database_id, &r.out.delta_enum_array->delta_enum[d]);
break;
+ case NETR_DELTA_TRUSTED_DOMAIN:
+ ret &= samsync_handle_trusted_domain(p, mem_ctx, creds,
+ r.in.database_id, &r.out.delta_enum_array->delta_enum[d]);
+ break;
+ case NETR_DELTA_SECRET:
+ ret &= samsync_handle_secret(p, mem_ctx, creds,
+ r.in.database_id, &r.out.delta_enum_array->delta_enum[d]);
+ break;
}
}
} while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
+
+ for (t=samsync_state[r.in.database_id].trusted_domains; t; t=t->next) {
+ const char *domain = samsync_state[r.in.database_id].domain_name
+ ? samsync_state[r.in.database_id].domain_name
+ : lp_workgroup();
+ char *username = talloc_asprintf(mem_ctx, "%s$", domain);
+ char *secret_name = talloc_asprintf(mem_ctx, "G$$%s", t->name);
+ for (s=samsync_state[r.in.database_id].secrets; s; s=s->next) {
+ printf("Checking secret %s against %s\n",
+ s->name, secret_name);
+ if (StrCaseCmp(s->name, secret_name) == 0) {
+ NTSTATUS nt_status;
+ struct samr_Password nt_hash;
+ mdfour(nt_hash.hash, s->secret.data, s->secret.length);
+
+ printf("Checking password for %s\\%s\n", t->name, username);
+ nt_status = test_SamLogon(p, mem_ctx, creds,
+ t->name,
+ username,
+ NULL,
+ &nt_hash,
+ NULL);
+ if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
+ printf("Could not verify trust password to %s: %s\n",
+ t->name, nt_errstr(nt_status));
+ ret = False;
+ }
+
+ /* break it */
+ nt_hash.hash[0]++;
+ nt_status = test_SamLogon(p, mem_ctx, creds,
+ t->name,
+ username,
+ NULL,
+ &nt_hash,
+ NULL);
+
+ if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
+ printf("Verifiction of trust password to %s: should have failed (wrong password), instead: %s\n",
+ t->name, nt_errstr(nt_status));
+ ret = False;
+ ret = False;
+ }
+
+ break;
+ }
+ }
+ talloc_free(secret_name);
+ talloc_free(username);
+ }
}
return ret;