summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2005-01-11 05:16:43 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:08:40 -0500
commit462ef44745d56dbb00b3e31d12d2ecdc9d309219 (patch)
treea68bd379a6054a753647cab6e2ec21a5f0b95e52
parent70071c21143c96039b6ebfe5b9b3f4463905ca49 (diff)
downloadsamba-462ef44745d56dbb00b3e31d12d2ecdc9d309219.tar.gz
samba-462ef44745d56dbb00b3e31d12d2ecdc9d309219.tar.bz2
samba-462ef44745d56dbb00b3e31d12d2ecdc9d309219.zip
r4673: Fix the IDL for the QuerySecret LSA call.
This call uses a new IDL type, NTTIME_hyper. This is 8-byte aligned, as the name suggests. Expand the QuerySecret LSA calls in RPC-SAMLOGON and RPC-LSA, to validate the behaviour of times, and of the old secrets. Thanks to tridge for spotting the use of HYPER! Andrew Bartlett (This used to be commit 1fed79cb0f2ae7940639d08ef99576559d4cd06e)
-rw-r--r--source4/build/pidl/util.pm3
-rw-r--r--source4/include/smb.h11
-rw-r--r--source4/librpc/idl/lsa.idl4
-rw-r--r--source4/librpc/ndr/ndr_basic.c27
-rw-r--r--source4/torture/rpc/lsa.c95
-rw-r--r--source4/torture/rpc/samsync.c71
6 files changed, 161 insertions, 50 deletions
diff --git a/source4/build/pidl/util.pm b/source4/build/pidl/util.pm
index 189f88de0f..bd87cf4317 100644
--- a/source4/build/pidl/util.pm
+++ b/source4/build/pidl/util.pm
@@ -301,7 +301,8 @@ my %type_alignments =
"WERROR" => 4,
"boolean32" => 4,
"unsigned32" => 4,
- "HYPER_T" => 8
+ "HYPER_T" => 8,
+ "NTTIME_hyper" => 8
);
sub is_scalar_type($)
diff --git a/source4/include/smb.h b/source4/include/smb.h
index f2e29f571a..f5115edc08 100644
--- a/source4/include/smb.h
+++ b/source4/include/smb.h
@@ -196,14 +196,17 @@ typedef struct data_blob {
size_t length;
} DATA_BLOB;
+/* 8 byte aligned 'hyper' type from MS IDL */
+typedef uint64_t HYPER_T;
+
/* 64 bit time (100 nanosec) 1601 - cifs6.txt, section 3.5, page 30 */
typedef uint64_t NTTIME;
-/* 64 bit time (1 sec) 1601 - in the NDR blob but mapped to NTTIME */
-#define NTTIME_1sec NTTIME
-/* 8 byte aligned 'hyper' type from MS IDL */
-typedef uint64_t HYPER_T;
+/* 64 bit time (100 nanosec) 1601, but 8 byte aligned 'hyper' type */
+#define NTTIME_hyper NTTIME
+/* 64 bit time (1 sec) 1601 - in the NDR blob but mapped to NTTIME */
+#define NTTIME_1sec NTTIME
/* the basic packet size, assuming no words or bytes. Does not include the NBT header */
#define MIN_SMB_SIZE 35
diff --git a/source4/librpc/idl/lsa.idl b/source4/librpc/idl/lsa.idl
index a1d14c82b9..850acdcd05 100644
--- a/source4/librpc/idl/lsa.idl
+++ b/source4/librpc/idl/lsa.idl
@@ -557,9 +557,9 @@
NTSTATUS lsa_QuerySecret (
[in,ref] policy_handle *handle,
[in,out] lsa_DATA_BUF_PTR *new_val,
- [in,out] NTTIME *new_mtime,
+ [in,out] NTTIME_hyper *new_mtime,
[in,out] lsa_DATA_BUF_PTR *old_val,
- [in,out] NTTIME *old_mtime
+ [in,out] NTTIME_hyper *old_mtime
);
/* Function: 0x1f */
diff --git a/source4/librpc/ndr/ndr_basic.c b/source4/librpc/ndr/ndr_basic.c
index 13ac087978..689483986e 100644
--- a/source4/librpc/ndr/ndr_basic.c
+++ b/source4/librpc/ndr/ndr_basic.c
@@ -965,7 +965,7 @@ NTSTATUS ndr_push_NTTIME_1sec(struct ndr_push *ndr, NTTIME t)
}
/*
- pull a NTTIME
+ pull a NTTIME_1sec
*/
NTSTATUS ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, NTTIME *t)
{
@@ -975,6 +975,24 @@ NTSTATUS ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, NTTIME *t)
}
/*
+ pull a NTTIME_hyper
+*/
+NTSTATUS ndr_pull_NTTIME_hyper(struct ndr_pull *ndr, NTTIME_hyper *t)
+{
+ NDR_CHECK(ndr_pull_HYPER_T(ndr, t));
+ return NT_STATUS_OK;
+}
+
+/*
+ push a NTTIME_hyper
+*/
+NTSTATUS ndr_push_NTTIME_hyper(struct ndr_push *ndr, NTTIME_hyper t)
+{
+ NDR_CHECK(ndr_push_HYPER_T(ndr, t));
+ return NT_STATUS_OK;
+}
+
+/*
push a time_t
*/
NTSTATUS ndr_push_time_t(struct ndr_push *ndr, time_t t)
@@ -1082,7 +1100,12 @@ void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t)
ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr, t));
}
-void ndr_print_NTTIME_1sec(struct ndr_print *ndr, const char *name, NTTIME t)
+void ndr_print_NTTIME_1sec(struct ndr_print *ndr, const char *name, NTTIME_1sec t)
+{
+ ndr_print_NTTIME(ndr, name, t * 10000000);
+}
+
+void ndr_print_NTTIME_hyper(struct ndr_print *ndr, const char *name, NTTIME_hyper t)
{
ndr_print_NTTIME(ndr, name, t);
}
diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c
index 79e82a25da..11b736d158 100644
--- a/source4/torture/rpc/lsa.c
+++ b/source4/torture/rpc/lsa.c
@@ -684,6 +684,7 @@ static BOOL test_CreateSecret(struct dcerpc_pipe *p,
struct lsa_Delete d;
struct lsa_DATA_BUF buf1;
struct lsa_DATA_BUF_PTR bufp1;
+ struct lsa_DATA_BUF_PTR bufp2;
DATA_BLOB enc_key;
BOOL ret = True;
DATA_BLOB session_key;
@@ -769,24 +770,24 @@ static BOOL test_CreateSecret(struct dcerpc_pipe *p,
if (!NT_STATUS_IS_OK(status)) {
printf("QuerySecret failed - %s\n", nt_errstr(status));
ret = False;
- }
-
- if (r4.out.new_val->buf == NULL) {
- printf("No secret buffer returned\n");
- ret = False;
} else {
- blob1.data = r4.out.new_val->buf->data;
- blob1.length = r4.out.new_val->buf->length;
-
- blob2 = data_blob(NULL, blob1.length);
-
- secret2 = sess_decrypt_string(&blob1, &session_key);
-
- printf("returned secret '%s'\n", secret2);
-
- if (strcmp(secret1, secret2) != 0) {
- printf("Returned secret doesn't match\n");
+ if (r4.out.new_val->buf == NULL) {
+ printf("No secret buffer returned\n");
ret = False;
+ } else {
+ blob1.data = r4.out.new_val->buf->data;
+ blob1.length = r4.out.new_val->buf->length;
+
+ blob2 = data_blob_talloc(mem_ctx, NULL, blob1.length);
+
+ secret2 = sess_decrypt_string(&blob1, &session_key);
+
+ printf("returned secret '%s'\n", secret2);
+
+ if (strcmp(secret1, secret2) != 0) {
+ printf("Returned secret doesn't match\n");
+ ret = False;
+ }
}
}
@@ -816,36 +817,60 @@ static BOOL test_CreateSecret(struct dcerpc_pipe *p,
r6.in.handle = &sec_handle;
r6.in.new_val = &bufp1;
r6.in.new_mtime = &new_mtime;
- r6.in.old_val = NULL;
- r6.in.old_mtime = NULL;
+ r6.in.old_val = &bufp2;
+ r6.in.old_mtime = &old_mtime;
bufp1.buf = NULL;
+ bufp2.buf = NULL;
status = dcerpc_lsa_QuerySecret(p, mem_ctx, &r6);
if (!NT_STATUS_IS_OK(status)) {
printf("QuerySecret failed - %s\n", nt_errstr(status));
ret = False;
- }
-
- if (r6.out.new_val->buf == NULL) {
- printf("No secret buffer returned\n");
- ret = False;
} else {
- blob1.data = r6.out.new_val->buf->data;
- blob1.length = r6.out.new_val->buf->length;
-
- blob2 = data_blob(NULL, blob1.length);
-
- secret4 = sess_decrypt_string(&blob1, &session_key);
-
- printf("returned secret '%s'\n", secret3);
-
- if (strcmp(secret3, secret4) != 0) {
- printf("Returned secret %s doesn't match %s\n", secret4, secret3);
+
+ if (r6.out.new_val->buf == NULL || r6.out.old_val->buf == NULL
+ || r6.out.new_mtime == NULL || r6.out.old_mtime == NULL) {
+ printf("Both secret buffers and both times not returned\n");
ret = False;
+ } else {
+ blob1.data = r6.out.new_val->buf->data;
+ blob1.length = r6.out.new_val->buf->length;
+
+ blob2 = data_blob_talloc(mem_ctx, NULL, blob1.length);
+
+ secret4 = sess_decrypt_string(&blob1, &session_key);
+
+ printf("returned secret '%s'\n", secret4);
+
+ if (strcmp(secret3, secret4) != 0) {
+ printf("Returned NEW secret %s doesn't match %s\n", secret4, secret3);
+ ret = False;
+ }
+
+ blob1.data = r6.out.new_val->buf->data;
+ blob1.length = r6.out.new_val->buf->length;
+
+ blob2 = data_blob_talloc(mem_ctx, NULL, blob1.length);
+
+ secret2 = sess_decrypt_string(&blob1, &session_key);
+
+ printf("returned OLD secret '%s'\n", secret2);
+
+ if (strcmp(secret3, secret4) != 0) {
+ printf("Returned secret %s doesn't match %s\n", secret2, secret1);
+ ret = False;
+ }
+
+ if (*r6.out.new_mtime == *r6.out.old_mtime) {
+ printf("Returned secret %s had same mtime for both secrets: %s\n",
+ secname[i],
+ nt_time_string(mem_ctx, *r6.out.new_mtime));
+ ret = False;
+ }
}
}
-
+
if (!test_Delete(p, mem_ctx, &sec_handle)) {
ret = False;
}
diff --git a/source4/torture/rpc/samsync.c b/source4/torture/rpc/samsync.c
index 4a71e90957..e393cd40fe 100644
--- a/source4/torture/rpc/samsync.c
+++ b/source4/torture/rpc/samsync.c
@@ -121,6 +121,7 @@ struct samsync_secret {
struct samsync_secret *prev, *next;
DATA_BLOB secret;
char *name;
+ NTTIME mtime;
};
struct samsync_trusted_domain {
@@ -699,11 +700,14 @@ static BOOL samsync_handle_secret(TALLOC_CTX *mem_ctx, struct samsync_state *sam
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);
+ struct samsync_secret *old = talloc_p(mem_ctx, struct samsync_secret);
struct lsa_QuerySecret q;
struct lsa_OpenSecret o;
struct policy_handle sec_handle;
struct lsa_DATA_BUF_PTR bufp1;
+ struct lsa_DATA_BUF_PTR bufp2;
NTTIME new_mtime;
+ NTTIME old_mtime;
BOOL ret = True;
DATA_BLOB lsa_blob1, lsa_blob_out, session_key;
NTSTATUS status;
@@ -716,9 +720,14 @@ static BOOL samsync_handle_secret(TALLOC_CTX *mem_ctx, struct samsync_state *sam
new->name = talloc_reference(new, name);
new->secret = data_blob_talloc(new, secret->current_cipher.cipher_data, secret->current_cipher.maxlen);
+ new->mtime = secret->current_cipher_set_time;
DLIST_ADD(samsync_state->secrets, new);
+ old->name = talloc_reference(old, name);
+ old->secret = data_blob_const(secret->old_cipher.cipher_data, secret->old_cipher.maxlen);
+ old->mtime = secret->old_cipher_set_time;
+
o.in.handle = samsync_state->lsa_handle;
o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
o.in.name.string = name;
@@ -742,22 +751,63 @@ static BOOL samsync_handle_secret(TALLOC_CTX *mem_ctx, struct samsync_state *sam
ZERO_STRUCT(new_mtime);
+ ZERO_STRUCT(old_mtime);
/* fetch the secret back again */
q.in.handle = &sec_handle;
q.in.new_val = &bufp1;
q.in.new_mtime = &new_mtime;
- q.in.old_val = NULL;
- q.in.old_mtime = NULL;
+ q.in.old_val = &bufp2;
+ q.in.old_mtime = &old_mtime;
bufp1.buf = NULL;
+ bufp2.buf = NULL;
status = dcerpc_lsa_QuerySecret(samsync_state->p_lsa, mem_ctx, &q);
- if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, status)) {
+ /* some things are just off limits */
+ return True;
+ } else if (!NT_STATUS_IS_OK(status)) {
printf("QuerySecret failed - %s\n", nt_errstr(status));
return False;
}
+ if (q.out.old_val->buf == NULL) {
+ /* probably just not available due to ACLs */
+ } else {
+ lsa_blob1.data = q.out.old_val->buf->data;
+ lsa_blob1.length = q.out.old_val->buf->length;
+
+ lsa_blob_out = sess_decrypt_blob(mem_ctx, &lsa_blob1, &session_key);
+
+ if (!q.out.old_mtime) {
+ printf("OLD mtime not available on LSA for secret %s\n", old->name);
+ ret = False;
+ }
+ if (old->mtime != *q.out.old_mtime) {
+ printf("OLD mtime on secret %s does not match between SAMSYNC (%s) and LSA (%s)\n",
+ old->name, nt_time_string(mem_ctx, old->mtime),
+ nt_time_string(mem_ctx, *q.out.old_mtime));
+ ret = False;
+ }
+
+ if (old->secret.length != lsa_blob_out.length) {
+ printf("Returned secret %s doesn't match: %d != %d\n",
+ old->name, old->secret.length, lsa_blob_out.length);
+ ret = False;
+ } else if (memcmp(lsa_blob_out.data,
+ old->secret.data, old->secret.length) != 0) {
+ printf("Returned secret %s doesn't match: \n",
+ old->name);
+ DEBUG(1, ("SamSync Secret:\n"));
+ dump_data(1, old->secret.data, old->secret.length);
+ DEBUG(1, ("LSA Secret:\n"));
+ dump_data(1, lsa_blob_out.data, lsa_blob_out.length);
+ ret = False;
+ }
+
+ }
+
if (q.out.new_val->buf == NULL) {
/* probably just not available due to ACLs */
} else {
@@ -766,13 +816,22 @@ static BOOL samsync_handle_secret(TALLOC_CTX *mem_ctx, struct samsync_state *sam
lsa_blob_out = sess_decrypt_blob(mem_ctx, &lsa_blob1, &session_key);
+ if (!q.out.new_mtime) {
+ printf("NEW mtime not available on LSA for secret %s\n", new->name);
+ ret = False;
+ }
+ if (new->mtime != *q.out.new_mtime) {
+ printf("NEW mtime on secret %s does not match between SAMSYNC (%s) and LSA (%s)\n",
+ new->name, nt_time_string(mem_ctx, new->mtime),
+ nt_time_string(mem_ctx, *q.out.new_mtime));
+ ret = False;
+ }
+
if (new->secret.length != lsa_blob_out.length) {
printf("Returned secret %s doesn't match: %d != %d\n",
new->name, new->secret.length, lsa_blob_out.length);
ret = False;
- }
-
- if (memcmp(lsa_blob_out.data,
+ } else if (memcmp(lsa_blob_out.data,
new->secret.data, new->secret.length) != 0) {
printf("Returned secret %s doesn't match: \n",
new->name);