mirror of
https://github.com/samba-team/samba.git
synced 2025-01-08 21:18:16 +03:00
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 1fed79cb0f
)
This commit is contained in:
parent
70071c2114
commit
462ef44745
@ -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($)
|
||||
|
@ -196,14 +196,17 @@ typedef struct data_blob {
|
||||
size_t length;
|
||||
} DATA_BLOB;
|
||||
|
||||
/* 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 - cifs6.txt, section 3.5, page 30 */
|
||||
typedef uint64_t NTTIME;
|
||||
|
||||
/* 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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user