📄 samsync.c
字号:
struct samr_Password *nt_hash_p = NULL; const char *domain = samsync_state->domain_name[database_id]; const char *username = user->account_name.string; NTSTATUS nt_status; bool ret = true; struct samr_OpenUser r; struct samr_QueryUserInfo q; struct policy_handle user_handle; struct samr_GetGroupsForUser getgroups; if (!samsync_state->domain_name || !samsync_state->domain_handle[database_id]) { printf("SamSync needs domain information before the users\n"); return false; } r.in.domain_handle = samsync_state->domain_handle[database_id]; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.in.rid = rid; r.out.user_handle = &user_handle; nt_status = dcerpc_samr_OpenUser(samsync_state->p_samr, mem_ctx, &r); if (!NT_STATUS_IS_OK(nt_status)) { printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(nt_status)); return false; } q.in.user_handle = &user_handle; q.in.level = 21; TEST_SEC_DESC_EQUAL(user->sdbuf, samr, &user_handle); nt_status = dcerpc_samr_QueryUserInfo(samsync_state->p_samr, mem_ctx, &q); if (!NT_STATUS_IS_OK(nt_status)) { printf("QueryUserInfo level %u failed - %s\n", q.in.level, nt_errstr(nt_status)); ret = false; } getgroups.in.user_handle = &user_handle; nt_status = dcerpc_samr_GetGroupsForUser(samsync_state->p_samr, mem_ctx, &getgroups); if (!NT_STATUS_IS_OK(nt_status)) { printf("GetGroupsForUser failed - %s\n", nt_errstr(nt_status)); ret = false; } if (!test_samr_handle_Close(samsync_state->p_samr, mem_ctx, &user_handle)) { printf("samr_handle_Close failed - %s\n", nt_errstr(nt_status)); ret = false; } if (!ret) { return false; } if (!NT_STATUS_IS_OK(nt_status)) { printf("QueryUserInfo level %u failed - %s\n", q.in.level, nt_errstr(nt_status)); return false; } TEST_STRING_EQUAL(q.out.info->info21.account_name, user->account_name); TEST_STRING_EQUAL(q.out.info->info21.full_name, user->full_name); TEST_INT_EQUAL(q.out.info->info21.rid, user->rid); TEST_INT_EQUAL(q.out.info->info21.primary_gid, user->primary_gid); TEST_STRING_EQUAL(q.out.info->info21.home_directory, user->home_directory); TEST_STRING_EQUAL(q.out.info->info21.home_drive, user->home_drive); TEST_STRING_EQUAL(q.out.info->info21.logon_script, user->logon_script); TEST_STRING_EQUAL(q.out.info->info21.description, user->description); TEST_STRING_EQUAL(q.out.info->info21.workstations, user->workstations); TEST_TIME_EQUAL(q.out.info->info21.last_logon, user->last_logon); TEST_TIME_EQUAL(q.out.info->info21.last_logoff, user->last_logoff); TEST_INT_EQUAL(q.out.info->info21.logon_hours.units_per_week, user->logon_hours.units_per_week); if (ret) { if (memcmp(q.out.info->info21.logon_hours.bits, user->logon_hours.bits, q.out.info->info21.logon_hours.units_per_week/8) != 0) { printf("Logon hours mismatch\n"); ret = false; } } TEST_INT_EQUAL(q.out.info->info21.bad_password_count, user->bad_password_count); TEST_INT_EQUAL(q.out.info->info21.logon_count, user->logon_count); TEST_TIME_EQUAL(q.out.info->info21.last_password_change, user->last_password_change); TEST_TIME_EQUAL(q.out.info->info21.acct_expiry, user->acct_expiry); TEST_INT_EQUAL((q.out.info->info21.acct_flags & ~ACB_PW_EXPIRED), user->acct_flags); if (user->acct_flags & ACB_PWNOEXP) { if (q.out.info->info21.acct_flags & ACB_PW_EXPIRED) { printf("ACB flags mismatch: both expired and no expiry!\n"); ret = false; } if (q.out.info->info21.force_password_change != (NTTIME)0x7FFFFFFFFFFFFFFFULL) { printf("ACB flags mismatch: no password expiry, but force password change 0x%016llx (%lld) != 0x%016llx (%lld)\n", (unsigned long long)q.out.info->info21.force_password_change, (unsigned long long)q.out.info->info21.force_password_change, (unsigned long long)0x7FFFFFFFFFFFFFFFULL, (unsigned long long)0x7FFFFFFFFFFFFFFFULL ); ret = false; } } TEST_INT_EQUAL(q.out.info->info21.nt_password_set, user->nt_password_present); TEST_INT_EQUAL(q.out.info->info21.lm_password_set, user->lm_password_present); TEST_INT_EQUAL(q.out.info->info21.password_expired, user->password_expired); TEST_STRING_EQUAL(q.out.info->info21.comment, user->comment); TEST_STRING_EQUAL(q.out.info->info21.parameters, user->parameters); TEST_INT_EQUAL(q.out.info->info21.country_code, user->country_code); TEST_INT_EQUAL(q.out.info->info21.code_page, user->code_page); TEST_STRING_EQUAL(q.out.info->info21.profile_path, user->profile_path); if (user->lm_password_present) { sam_rid_crypt(rid, user->lmpassword.hash, lm_hash.hash, 0); lm_hash_p = &lm_hash; } if (user->nt_password_present) { sam_rid_crypt(rid, user->ntpassword.hash, nt_hash.hash, 0); nt_hash_p = &nt_hash; } if (user->user_private_info.SensitiveData) { DATA_BLOB data; struct netr_USER_KEYS keys; enum ndr_err_code ndr_err; data.data = user->user_private_info.SensitiveData; data.length = user->user_private_info.DataLength; creds_arcfour_crypt(samsync_state->creds, data.data, data.length); ndr_err = ndr_pull_struct_blob(&data, mem_ctx, lp_iconv_convenience(tctx->lp_ctx), &keys, (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS); if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { if (keys.keys.keys2.lmpassword.length == 16) { sam_rid_crypt(rid, keys.keys.keys2.lmpassword.pwd.hash, lm_hash.hash, 0); lm_hash_p = &lm_hash; } if (keys.keys.keys2.ntpassword.length == 16) { sam_rid_crypt(rid, keys.keys.keys2.ntpassword.pwd.hash, nt_hash.hash, 0); nt_hash_p = &nt_hash; } } else { printf("Failed to parse Sensitive Data for %s:\n", username);#if 0 dump_data(0, data.data, data.length);#endif return false; } } if (nt_hash_p) { DATA_BLOB nt_hash_blob = data_blob_const(nt_hash_p, 16); DEBUG(100,("ACCOUNT [%s\\%-25s] NTHASH %s\n", samsync_state->domain_name[0], username, data_blob_hex_string(mem_ctx, &nt_hash_blob))); } if (lm_hash_p) { DATA_BLOB lm_hash_blob = data_blob_const(lm_hash_p, 16); DEBUG(100,("ACCOUNT [%s\\%-25s] LMHASH %s\n", samsync_state->domain_name[0], username, data_blob_hex_string(mem_ctx, &lm_hash_blob))); } nt_status = test_SamLogon(samsync_state->p_netlogon_wksta, mem_ctx, samsync_state->creds_netlogon_wksta, domain, username, TEST_WKSTA_MACHINE_NAME, lm_hash_p, nt_hash_p, &info3); if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) { if (user->acct_flags & ACB_DISABLED) { return true; } } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)) { if (user->acct_flags & ACB_WSTRUST) { return true; } } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT)) { if (user->acct_flags & ACB_SVRTRUST) { return true; } } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) { if (user->acct_flags & ACB_DOMTRUST) { return true; } } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) { if (user->acct_flags & ACB_DOMTRUST) { return true; } } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_LOCKED_OUT)) { if (user->acct_flags & ACB_AUTOLOCK) { return true; } } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_EXPIRED)) { if (q.out.info->info21.acct_flags & ACB_PW_EXPIRED) { return true; } } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) { if (!lm_hash_p && !nt_hash_p) { return true; } } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_MUST_CHANGE)) { /* We would need to know the server's current time to test this properly */ return true; } else if (NT_STATUS_IS_OK(nt_status)) { TEST_INT_EQUAL(user->rid, info3->base.rid); TEST_INT_EQUAL(user->primary_gid, info3->base.primary_gid); /* this is 0x0 from NT4 sp6 */ if (info3->base.acct_flags) { TEST_INT_EQUAL(user->acct_flags, info3->base.acct_flags); } /* this is NULL from NT4 sp6 */ if (info3->base.account_name.string) { TEST_STRING_EQUAL(user->account_name, info3->base.account_name); } /* this is NULL from Win2k3 */ if (info3->base.full_name.string) { TEST_STRING_EQUAL(user->full_name, info3->base.full_name); } TEST_STRING_EQUAL(user->logon_script, info3->base.logon_script); TEST_STRING_EQUAL(user->profile_path, info3->base.profile_path); TEST_STRING_EQUAL(user->home_directory, info3->base.home_directory); TEST_STRING_EQUAL(user->home_drive, info3->base.home_drive); TEST_STRING_EQUAL(user->logon_script, info3->base.logon_script); TEST_TIME_EQUAL(user->last_logon, info3->base.last_logon); TEST_TIME_EQUAL(user->acct_expiry, info3->base.acct_expiry); TEST_TIME_EQUAL(user->last_password_change, info3->base.last_password_change); TEST_TIME_EQUAL(q.out.info->info21.force_password_change, info3->base.force_password_change); /* Does the concept of a logoff time ever really * exist? (not in any sensible way, according to the * doco I read -- abartlet) */ /* This copes with the two different versions of 0 I see */ /* with NT4 sp6 we have the || case */ if (!((user->last_logoff == 0) || (info3->base.last_logoff == 0x7fffffffffffffffLL))) { TEST_TIME_EQUAL(user->last_logoff, info3->base.last_logoff); } TEST_INT_EQUAL(getgroups.out.rids->count, info3->base.groups.count); if (getgroups.out.rids->count == info3->base.groups.count) { int i, j; int count = getgroups.out.rids->count; bool *matched = talloc_zero_array(mem_ctx, bool, getgroups.out.rids->count); for (i = 0; i < count; i++) { for (j = 0; j < count; j++) { if ((getgroups.out.rids->rids[i].rid == info3->base.groups.rids[j].rid) && (getgroups.out.rids->rids[i].attributes == info3->base.groups.rids[j].attributes)) { matched[i] = true; } } } for (i = 0; i < getgroups.out.rids->count; i++) { if (matched[i] == false) { ret = false; printf("Could not find group RID %u found in getgroups in NETLOGON reply\n", getgroups.out.rids->rids[i].rid); } } } return ret; } else { printf("Could not validate password for user %s\\%s: %s\n", domain, username, nt_errstr(nt_status)); return false; } return false;}static bool samsync_handle_alias(TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state, int database_id, struct netr_DELTA_ENUM *delta) { uint32_t rid = delta->delta_id_union.rid; struct netr_DELTA_ALIAS *alias = delta->delta_union.alias; NTSTATUS nt_status; bool ret = true; struct samr_OpenAlias r; struct samr_QueryAliasInfo q; struct policy_handle alias_handle; if (!samsync_state->domain_name || !samsync_state->domain_handle[database_id]) { printf("SamSync needs domain information before the users\n"); return false; } r.in.domain_handle = samsync_state->domain_handle[database_id]; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.in.rid = rid; r.out.alias_handle = &alias_handle; nt_status = dcerpc_samr_OpenAlias(samsync_state->p_samr, mem_ctx, &r); if (!NT_STATUS_IS_OK(nt_status)) { printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(nt_status)); return false; } q.in.alias_handle = &alias_handle; q.in.level = 1; TEST_SEC_DESC_EQUAL(alias->sdbuf, samr, &alias_handle); nt_status = dcerpc_samr_QueryAliasInfo(samsync_state->p_samr, mem_ctx, &q); if (!test_samr_handle_Close(samsync_state->p_samr, mem_ctx, &alias_handle)) { return false; } if (!NT_STATUS_IS_OK(nt_status)) { printf("QueryAliasInfo level %u failed - %s\n", q.in.level, nt_errstr(nt_status)); return false; } TEST_STRING_EQUAL(q.out.info->all.name, alias->alias_name); TEST_STRING_EQUAL(q.out.info->all.description, alias->description); return ret;}static bool samsync_handle_group(TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state, int database_id, struct netr_DELTA_ENUM *delta) { uint32_t rid = delta->delta_id_union.rid; struct netr_DELTA_GROUP *group = delta->delta_union.group; NTSTATUS nt_status; bool ret = true; struct samr_OpenGroup r; struct samr_QueryGroupInfo q; struct policy_handle group_handle; if (!samsync_state->domain_name || !samsync_state->domain_handle[database_id]) { printf("SamSync needs domain information before the users\n"); return false; } r.in.domain_handle = samsync_state->domain_handle[database_id]; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.in.rid = rid; r.out.group_handle = &group_handle; nt_status = dcerpc_samr_OpenGroup(samsync_state->p_samr, mem_ctx, &r); if (!NT_STATUS_IS_OK(nt_status)) { printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(nt_status)); return false; } q.in.group_handle = &group_handle; q.in.level = 1; TEST_SEC_DESC_EQUAL(group->sdbuf, samr, &group_handle); nt_status = dcerpc_samr_QueryGroupInfo(samsync_state->p_samr, mem_ctx, &q); if (!test_samr_handle_Close(samsync_state->p_samr, mem_ctx, &group_handle)) { return false; } if (!NT_STATUS_IS_OK(nt_status)) { printf("QueryGroupInfo level %u failed - %s\n", q.in.level, nt_errstr(nt_status)); return false; } TEST_STRING_EQUAL(q.out.info->all.name, group->group_name); TEST_INT_EQUAL(q.out.info->all.attributes, group->attributes); TEST_STRING_EQUAL(q.out.info->all.description, group->description); return ret;}static bool samsync_handle_secret(TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state, int database_id, struct netr_DELTA_ENUM *delta) { struct netr_DELTA_SECRET *secret = delta->delta_union.secret; const char *name = delta->delta_id_union.name; struct samsync_secret *new = talloc(samsync_state, struct samsync_secret); struct samsync_secret *old = talloc(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; creds_arcfour_crypt(samsync_state->creds, secret->current_cipher.cipher_data, secret->current_cipher.maxlen); creds_arcfour_crypt(samsync_state->creds, secret->old_cipher.cipher_data, secret->old_cipher.maxlen); 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -