📄 samsync.c
字号:
new = talloc_reference(samsync_state, new); 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; o.out.sec_handle = &sec_handle; status = dcerpc_lsa_OpenSecret(samsync_state->p_lsa, mem_ctx, &o); if (!NT_STATUS_IS_OK(status)) { printf("OpenSecret failed - %s\n", nt_errstr(status)); return false; }/* We would like to do this, but it is NOT_SUPPORTED on win2k3 TEST_SEC_DESC_EQUAL(secret->sdbuf, lsa, &sec_handle);*/ status = dcerpc_fetch_session_key(samsync_state->p_lsa, &session_key); if (!NT_STATUS_IS_OK(status)) { printf("dcerpc_fetch_session_key failed - %s\n", nt_errstr(status)); return false; } ZERO_STRUCT(new_mtime); ZERO_STRUCT(old_mtime); /* fetch the secret back again */ q.in.sec_handle = &sec_handle; q.in.new_val = &bufp1; q.in.new_mtime = &new_mtime; 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_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; status = sess_decrypt_blob(mem_ctx, &lsa_blob1, &session_key, &lsa_blob_out); if (!NT_STATUS_IS_OK(status)) { printf("Failed to decrypt secrets OLD blob: %s\n", nt_errstr(status)); return false; } 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, (int)old->secret.length, (int)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 { lsa_blob1.data = q.out.new_val->buf->data; lsa_blob1.length = q.out.new_val->buf->length; status = sess_decrypt_blob(mem_ctx, &lsa_blob1, &session_key, &lsa_blob_out); if (!NT_STATUS_IS_OK(status)) { printf("Failed to decrypt secrets OLD blob\n"); return false; } 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, (int)new->secret.length, (int)lsa_blob_out.length); ret = false; } else if (memcmp(lsa_blob_out.data, new->secret.data, new->secret.length) != 0) { printf("Returned secret %s doesn't match: \n", new->name); DEBUG(1, ("SamSync Secret:\n")); dump_data(1, new->secret.data, new->secret.length); DEBUG(1, ("LSA Secret:\n")); dump_data(1, lsa_blob_out.data, lsa_blob_out.length); ret = false; } } return ret;}static bool samsync_handle_trusted_domain(TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state, int database_id, struct netr_DELTA_ENUM *delta) { NTSTATUS status; bool ret = true; 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(samsync_state, struct samsync_trusted_domain); struct lsa_OpenTrustedDomain t; struct policy_handle trustdom_handle; struct lsa_QueryTrustedDomainInfo q; union lsa_TrustedDomainInfo *info[9]; int levels [] = {1, 3, 8}; int i; new->name = talloc_reference(new, trusted_domain->domain_name.string); new->sid = talloc_reference(new, dom_sid); t.in.handle = samsync_state->lsa_handle; t.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; t.in.sid = dom_sid; t.out.trustdom_handle = &trustdom_handle; status = dcerpc_lsa_OpenTrustedDomain(samsync_state->p_lsa, mem_ctx, &t); if (!NT_STATUS_IS_OK(status)) { printf("OpenTrustedDomain failed - %s\n", nt_errstr(status)); return false; } for (i=0; i< ARRAY_SIZE(levels); i++) { q.in.trustdom_handle = &trustdom_handle; q.in.level = levels[i]; status = dcerpc_lsa_QueryTrustedDomainInfo(samsync_state->p_lsa, mem_ctx, &q); if (!NT_STATUS_IS_OK(status)) { if (q.in.level == 8 && NT_STATUS_EQUAL(status,NT_STATUS_INVALID_PARAMETER)) { info[levels[i]] = NULL; continue; } printf("QueryInfoTrustedDomain level %d failed - %s\n", levels[i], nt_errstr(status)); return false; } info[levels[i]] = q.out.info; } if (info[8]) { TEST_SID_EQUAL(info[8]->full_info.info_ex.sid, dom_sid); TEST_STRING_EQUAL(info[8]->full_info.info_ex.netbios_name, trusted_domain->domain_name); } TEST_STRING_EQUAL(info[1]->name.netbios_name, trusted_domain->domain_name); TEST_INT_EQUAL(info[3]->posix_offset.posix_offset, trusted_domain->posix_offset);/* We would like to do this, but it is NOT_SUPPORTED on win2k3 TEST_SEC_DESC_EQUAL(trusted_domain->sdbuf, lsa, &trustdom_handle);*/ new = talloc_reference(samsync_state, new); DLIST_ADD(samsync_state->trusted_domains, new); return ret;}static bool samsync_handle_account(TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state, int database_id, struct netr_DELTA_ENUM *delta) { NTSTATUS status; bool ret = true; struct netr_DELTA_ACCOUNT *account = delta->delta_union.account; struct dom_sid *dom_sid = delta->delta_id_union.sid; struct lsa_OpenAccount a; struct policy_handle acct_handle; struct lsa_EnumPrivsAccount e; struct lsa_LookupPrivName r; int i, j; bool *found_priv_in_lsa; a.in.handle = samsync_state->lsa_handle; a.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; a.in.sid = dom_sid; a.out.acct_handle = &acct_handle; status = dcerpc_lsa_OpenAccount(samsync_state->p_lsa, mem_ctx, &a); if (!NT_STATUS_IS_OK(status)) { printf("OpenTrustedDomain failed - %s\n", nt_errstr(status)); return false; } TEST_SEC_DESC_EQUAL(account->sdbuf, lsa, &acct_handle); found_priv_in_lsa = talloc_zero_array(mem_ctx, bool, account->privilege_entries); e.in.handle = &acct_handle; status = dcerpc_lsa_EnumPrivsAccount(samsync_state->p_lsa, mem_ctx, &e); if (!NT_STATUS_IS_OK(status)) { printf("EnumPrivsAccount failed - %s\n", nt_errstr(status)); return false; } if ((account->privilege_entries && !e.out.privs)) { printf("Account %s has privileges in SamSync, but not LSA\n", dom_sid_string(mem_ctx, dom_sid)); return false; } if (!account->privilege_entries && e.out.privs && e.out.privs->count) { printf("Account %s has privileges in LSA, but not SamSync\n", dom_sid_string(mem_ctx, dom_sid)); return false; } TEST_INT_EQUAL(account->privilege_entries, e.out.privs->count); for (i=0;i< e.out.privs->count; i++) { r.in.handle = samsync_state->lsa_handle; r.in.luid = &e.out.privs->set[i].luid; status = dcerpc_lsa_LookupPrivName(samsync_state->p_lsa, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { printf("\nLookupPrivName failed - %s\n", nt_errstr(status)); return false; } if (!r.out.name) { printf("\nLookupPrivName failed to return a name\n"); return false; } for (j=0;j<account->privilege_entries; j++) { if (strcmp(r.out.name->string, account->privilege_name[j].string) == 0) { found_priv_in_lsa[j] = true; break; } } } for (j=0;j<account->privilege_entries; j++) { if (!found_priv_in_lsa[j]) { printf("Privilage %s on account %s not found in LSA\n", account->privilege_name[j].string, dom_sid_string(mem_ctx, dom_sid)); ret = false; } } return ret;}/* try a netlogon DatabaseSync*/static bool test_DatabaseSync(struct torture_context *tctx, struct samsync_state *samsync_state, TALLOC_CTX *mem_ctx){ NTSTATUS status; TALLOC_CTX *loop_ctx, *delta_ctx, *trustdom_ctx; struct netr_DatabaseSync r; const enum netr_SamDatabaseID 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; const char *domain, *username; r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(samsync_state->p)); r.in.computername = TEST_MACHINE_NAME; r.in.preferredmaximumlength = (uint32_t)-1; ZERO_STRUCT(r.in.return_authenticator); for (i=0;i<ARRAY_SIZE(database_ids);i++) { r.in.sync_context = 0; r.in.database_id = database_ids[i]; printf("Testing DatabaseSync of id %d\n", r.in.database_id); do { loop_ctx = talloc_named(mem_ctx, 0, "DatabaseSync loop context"); creds_client_authenticator(samsync_state->creds, &r.in.credential); status = dcerpc_netr_DatabaseSync(samsync_state->p, loop_ctx, &r); if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { printf("DatabaseSync - %s\n", nt_errstr(status)); ret = false; break; } if (!creds_client_check(samsync_state->creds, &r.out.return_authenticator.cred)) { printf("Credential chaining failed\n"); } r.in.sync_context = r.out.sync_context; for (d=0; d < r.out.delta_enum_array->num_deltas; d++) { delta_ctx = talloc_named(loop_ctx, 0, "DatabaseSync delta context"); switch (r.out.delta_enum_array->delta_enum[d].delta_type) { case NETR_DELTA_DOMAIN: if (!samsync_handle_domain(delta_ctx, samsync_state, r.in.database_id, &r.out.delta_enum_array->delta_enum[d])) { printf("Failed to handle DELTA_DOMAIN\n"); ret = false; } break; case NETR_DELTA_GROUP: if (!samsync_handle_group(delta_ctx, samsync_state, r.in.database_id, &r.out.delta_enum_array->delta_enum[d])) { printf("Failed to handle DELTA_USER\n"); ret = false; } break; case NETR_DELTA_USER: if (!samsync_handle_user(tctx, delta_ctx, samsync_state, r.in.database_id, &r.out.delta_enum_array->delta_enum[d])) { printf("Failed to handle DELTA_USER\n"); ret = false; } break; case NETR_DELTA_ALIAS: if (!samsync_handle_alias(delta_ctx, samsync_state, r.in.database_id, &r.out.delta_enum_array->delta_enum[d])) { printf("Failed to handle DELTA_ALIAS\n"); ret = false; } break; case NETR_DELTA_POLICY: if (!samsync_handle_policy(delta_ctx, samsync_state, r.in.database_id, &r.out.delta_enum_array->delta_enum[d])) { printf("Failed to handle DELTA_POLICY\n"); ret = false; } break; case NETR_DELTA_TRUSTED_DOMAIN: if (!samsync_handle_trusted_domain(delta_ctx, samsync_state, r.in.database_id, &r.out.delta_enum_array->delta_enum[d])) { printf("Failed to handle DELTA_TRUSTED_DOMAIN\n"); ret = false; } break; case NETR_DELTA_ACCOUNT: if (!samsync_handle_account(delta_ctx, samsync_state, r.in.database_id, &r.out.delta_enum_array->delta_enum[d])) { printf("Failed to handle DELTA_ACCOUNT\n"); ret = false; } break; case NETR_DELTA_SECRET: if (!samsync_handle_secret(delta_ctx, samsync_state, r.in.database_id, &r.out.delta_enum_array->delta_enum[d])) { printf("Failed to handle DELTA_SECRET\n"); ret = false; } break; case NETR_DELTA_GROUP_MEMBER: case NETR_DELTA_ALIAS_MEMBER: /* These are harder to cross-check, and we expect them */ break; case NETR_DELTA_DELETE_GROUP: case NETR_DELTA_RENAME_GROUP: case NETR_DELTA_DELETE_USER: case NETR_DELTA_RENAME_USER: case NETR_DELTA_DELETE_ALIAS: case NETR_DELTA_RENAME_ALIAS: case NETR_DELTA_DELETE_TRUST: case NETR_DELTA_DELETE_ACCOUNT: case NETR_DELTA_DELETE_SECRET: case NETR_DELTA_DELETE_GROUP2: case NETR_DELTA_DELETE_USER2: case NETR_DELTA_MODIFY_COUNT: default: printf("Uxpected delta type %d\n", r.out.delta_enum_array->delta_enum[d].delta_type); ret = false; break; } talloc_free(delta_ctx); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -