summaryrefslogtreecommitdiff
path: root/source4/torture/rpc
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2004-11-13 03:57:54 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:05:46 -0500
commit1158268287f07310e79e9d470971dc021a334f9e (patch)
treec8b79f8075c451ef5129c0e38e781a98d6b5026a /source4/torture/rpc
parent62979b84cb52465e6264ecb31fb3ff4db72313e4 (diff)
downloadsamba-1158268287f07310e79e9d470971dc021a334f9e.tar.gz
samba-1158268287f07310e79e9d470971dc021a334f9e.tar.bz2
samba-1158268287f07310e79e9d470971dc021a334f9e.zip
r3716: Improvements in the RPC-SAMSYNC tests:
We now (for the first time) start to parse the 'user sensitive info' field, which reveals the user's NT and LM passwords from Win2k3. Using this, the 'validate samsync against netlogon' portion of the tests works for accounts. Trusted domains and secrets are now retreived, but like users, require further cross-validation work. Andrew Bartlett (This used to be commit c1d3794cad8b001661b48ecb05df5c38a69be92c)
Diffstat (limited to 'source4/torture/rpc')
-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;