From 462ef44745d56dbb00b3e31d12d2ecdc9d309219 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 11 Jan 2005 05:16:43 +0000 Subject: 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) --- source4/build/pidl/util.pm | 3 +- source4/include/smb.h | 11 +++-- source4/librpc/idl/lsa.idl | 4 +- source4/librpc/ndr/ndr_basic.c | 27 +++++++++++- source4/torture/rpc/lsa.c | 95 ++++++++++++++++++++++++++---------------- source4/torture/rpc/samsync.c | 71 ++++++++++++++++++++++++++++--- 6 files changed, 161 insertions(+), 50 deletions(-) (limited to 'source4') 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) { @@ -974,6 +974,24 @@ NTSTATUS ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, NTTIME *t) return NT_STATUS_OK; } +/* + 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 */ @@ -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); -- cgit