diff options
author | Andrew Bartlett <abartlet@samba.org> | 2005-01-11 05:16:43 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:08:40 -0500 |
commit | 462ef44745d56dbb00b3e31d12d2ecdc9d309219 (patch) | |
tree | a68bd379a6054a753647cab6e2ec21a5f0b95e52 /source4 | |
parent | 70071c21143c96039b6ebfe5b9b3f4463905ca49 (diff) | |
download | samba-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)
Diffstat (limited to 'source4')
-rw-r--r-- | source4/build/pidl/util.pm | 3 | ||||
-rw-r--r-- | source4/include/smb.h | 11 | ||||
-rw-r--r-- | source4/librpc/idl/lsa.idl | 4 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_basic.c | 27 | ||||
-rw-r--r-- | source4/torture/rpc/lsa.c | 95 | ||||
-rw-r--r-- | source4/torture/rpc/samsync.c | 71 |
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); |