dssync.c
来自「samba最新软件」· C语言 代码 · 共 835 行 · 第 1/2 页
C
835 行
/* Unix SMB/CIFS implementation. DsGetNCChanges replication test Copyright (C) Stefan (metze) Metzmacher 2005 Copyright (C) Brad Henry 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.*/#include "includes.h"#include "lib/cmdline/popt_common.h"#include "librpc/gen_ndr/ndr_drsuapi_c.h"#include "libcli/cldap/cldap.h"#include "libcli/ldap/ldap_client.h"#include "torture/torture.h"#include "torture/ldap/proto.h"#include "libcli/auth/libcli_auth.h"#include "lib/crypto/crypto.h"#include "auth/credentials/credentials.h"#include "libcli/auth/libcli_auth.h"#include "auth/gensec/gensec.h"#include "param/param.h"struct DsSyncBindInfo { struct dcerpc_pipe *pipe; struct drsuapi_DsBind req; struct GUID bind_guid; struct drsuapi_DsBindInfoCtr our_bind_info_ctr; struct drsuapi_DsBindInfo28 our_bind_info28; struct drsuapi_DsBindInfo28 peer_bind_info28; struct policy_handle bind_handle;};struct DsSyncLDAPInfo { struct ldap_connection *conn;};struct DsSyncTest { struct dcerpc_binding *drsuapi_binding; const char *ldap_url; const char *site_name; const char *domain_dn; /* what we need to do as 'Administrator' */ struct { struct cli_credentials *credentials; struct DsSyncBindInfo drsuapi; struct DsSyncLDAPInfo ldap; } admin; /* what we need to do as the new dc machine account */ struct { struct cli_credentials *credentials; struct DsSyncBindInfo drsuapi; struct drsuapi_DsGetDCInfo2 dc_info2; struct GUID invocation_id; struct GUID object_guid; } new_dc; /* info about the old dc */ struct { struct drsuapi_DsGetDomainControllerInfo dc_info; } old_dc;};static struct DsSyncTest *test_create_context(struct torture_context *tctx){ NTSTATUS status; struct DsSyncTest *ctx; struct drsuapi_DsBindInfo28 *our_bind_info28; struct drsuapi_DsBindInfoCtr *our_bind_info_ctr; const char *binding = torture_setting_string(tctx, "binding", NULL); ctx = talloc_zero(tctx, struct DsSyncTest); if (!ctx) return NULL; status = dcerpc_parse_binding(ctx, binding, &ctx->drsuapi_binding); if (!NT_STATUS_IS_OK(status)) { printf("Bad binding string %s\n", binding); return NULL; } ctx->drsuapi_binding->flags |= DCERPC_SIGN | DCERPC_SEAL; ctx->ldap_url = talloc_asprintf(ctx, "ldap://%s/", ctx->drsuapi_binding->host); /* ctx->admin ...*/ ctx->admin.credentials = cmdline_credentials; our_bind_info28 = &ctx->admin.drsuapi.our_bind_info28; our_bind_info28->supported_extensions = 0xFFFFFFFF; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3; our_bind_info28->site_guid = GUID_zero(); our_bind_info28->u1 = 0; our_bind_info28->repl_epoch = 1; our_bind_info_ctr = &ctx->admin.drsuapi.our_bind_info_ctr; our_bind_info_ctr->length = 28; our_bind_info_ctr->info.info28 = *our_bind_info28; GUID_from_string(DRSUAPI_DS_BIND_GUID, &ctx->admin.drsuapi.bind_guid); ctx->admin.drsuapi.req.in.bind_guid = &ctx->admin.drsuapi.bind_guid; ctx->admin.drsuapi.req.in.bind_info = our_bind_info_ctr; ctx->admin.drsuapi.req.out.bind_handle = &ctx->admin.drsuapi.bind_handle; /* ctx->new_dc ...*/ ctx->new_dc.credentials = cmdline_credentials; our_bind_info28 = &ctx->new_dc.drsuapi.our_bind_info28; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_BASE; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT; if (lp_parm_bool(tctx->lp_ctx, NULL, "dssync", "xpress", false)) { our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS; } our_bind_info28->site_guid = GUID_zero(); our_bind_info28->u1 = 508; our_bind_info28->repl_epoch = 0; our_bind_info_ctr = &ctx->new_dc.drsuapi.our_bind_info_ctr; our_bind_info_ctr->length = 28; our_bind_info_ctr->info.info28 = *our_bind_info28; GUID_from_string(DRSUAPI_DS_BIND_GUID_W2K3, &ctx->new_dc.drsuapi.bind_guid); ctx->new_dc.drsuapi.req.in.bind_guid = &ctx->new_dc.drsuapi.bind_guid; ctx->new_dc.drsuapi.req.in.bind_info = our_bind_info_ctr; ctx->new_dc.drsuapi.req.out.bind_handle = &ctx->new_dc.drsuapi.bind_handle; ctx->new_dc.invocation_id = ctx->new_dc.drsuapi.bind_guid; /* ctx->old_dc ...*/ return ctx;}static bool _test_DsBind(struct torture_context *tctx, struct DsSyncTest *ctx, struct cli_credentials *credentials, struct DsSyncBindInfo *b){ NTSTATUS status; bool ret = true; status = dcerpc_pipe_connect_b(ctx, &b->pipe, ctx->drsuapi_binding, &ndr_table_drsuapi, credentials, tctx->ev, tctx->lp_ctx); if (!NT_STATUS_IS_OK(status)) { printf("Failed to connect to server as a BDC: %s\n", nt_errstr(status)); return false; } status = dcerpc_drsuapi_DsBind(b->pipe, ctx, &b->req); if (!NT_STATUS_IS_OK(status)) { const char *errstr = nt_errstr(status); if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) { errstr = dcerpc_errstr(ctx, b->pipe->last_fault_code); } printf("dcerpc_drsuapi_DsBind failed - %s\n", errstr); ret = false; } else if (!W_ERROR_IS_OK(b->req.out.result)) { printf("DsBind failed - %s\n", win_errstr(b->req.out.result)); ret = false; } ZERO_STRUCT(b->peer_bind_info28); if (b->req.out.bind_info) { switch (b->req.out.bind_info->length) { case 24: { struct drsuapi_DsBindInfo24 *info24; info24 = &b->req.out.bind_info->info.info24; b->peer_bind_info28.supported_extensions= info24->supported_extensions; b->peer_bind_info28.site_guid = info24->site_guid; b->peer_bind_info28.u1 = info24->u1; b->peer_bind_info28.repl_epoch = 0; break; } case 28: b->peer_bind_info28 = b->req.out.bind_info->info.info28; break; } } return ret;}static bool test_LDAPBind(struct torture_context *tctx, struct DsSyncTest *ctx, struct cli_credentials *credentials, struct DsSyncLDAPInfo *l){ NTSTATUS status; bool ret = true; status = torture_ldap_connection(tctx, &l->conn, ctx->ldap_url); if (!NT_STATUS_IS_OK(status)) { printf("failed to connect to LDAP: %s\n", ctx->ldap_url); return false; } printf("connected to LDAP: %s\n", ctx->ldap_url); status = torture_ldap_bind_sasl(l->conn, credentials, tctx->lp_ctx); if (!NT_STATUS_IS_OK(status)) { printf("failed to bind to LDAP:\n"); return false; } printf("bound to LDAP.\n"); return ret;}static bool test_GetInfo(struct torture_context *tctx, struct DsSyncTest *ctx){ NTSTATUS status; struct drsuapi_DsCrackNames r; struct drsuapi_DsNameString names[1]; bool ret = true; struct cldap_socket *cldap; struct cldap_netlogon search; cldap = cldap_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx)); r.in.bind_handle = &ctx->admin.drsuapi.bind_handle; r.in.level = 1; r.in.req.req1.codepage = 1252; /* western european */ r.in.req.req1.language = 0x00000407; /* german */ r.in.req.req1.count = 1; r.in.req.req1.names = names; r.in.req.req1.format_flags = DRSUAPI_DS_NAME_FLAG_NO_FLAGS; r.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT; r.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779; names[0].str = talloc_asprintf(ctx, "%s\\", lp_workgroup(tctx->lp_ctx)); status = dcerpc_drsuapi_DsCrackNames(ctx->admin.drsuapi.pipe, ctx, &r); if (!NT_STATUS_IS_OK(status)) { const char *errstr = nt_errstr(status); if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) { errstr = dcerpc_errstr(ctx, ctx->admin.drsuapi.pipe->last_fault_code); } printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr); return false; } else if (!W_ERROR_IS_OK(r.out.result)) { printf("DsCrackNames failed - %s\n", win_errstr(r.out.result)); return false; } ctx->domain_dn = r.out.ctr.ctr1->array[0].result_name; ZERO_STRUCT(search); search.in.dest_address = ctx->drsuapi_binding->host; search.in.dest_port = lp_cldap_port(tctx->lp_ctx); search.in.acct_control = -1; search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; search.in.map_response = true; status = cldap_netlogon(cldap, ctx, &search); if (!NT_STATUS_IS_OK(status)) { const char *errstr = nt_errstr(status); ctx->site_name = talloc_asprintf(ctx, "%s", "Default-First-Site-Name"); printf("cldap_netlogon() returned %s. Defaulting to Site-Name: %s\n", errstr, ctx->site_name); } else { ctx->site_name = talloc_steal(ctx, search.out.netlogon.nt5_ex.client_site); printf("cldap_netlogon() returned Client Site-Name: %s.\n",ctx->site_name); printf("cldap_netlogon() returned Server Site-Name: %s.\n",search.out.netlogon.nt5_ex.server_site); } return ret;}static DATA_BLOB decrypt_blob(TALLOC_CTX *mem_ctx, const DATA_BLOB *gensec_skey, bool rcrypt, struct drsuapi_DsReplicaObjectIdentifier *id, uint32_t rid, const DATA_BLOB *buffer){ DATA_BLOB confounder; DATA_BLOB enc_buffer; struct MD5Context md5; uint8_t _enc_key[16]; DATA_BLOB enc_key; DATA_BLOB dec_buffer; uint32_t crc32_given; uint32_t crc32_calc; DATA_BLOB checked_buffer; DATA_BLOB plain_buffer; /* * the combination "c[3] s[1] e[1] d[0]..." * was successful!!!!!!!!!!!!!!!!!!!!!!!!!! */ /* * the first 16 bytes at the beginning are the confounder * followed by the 4 byte crc32 checksum */ if (buffer->length < 20) { return data_blob_const(NULL, 0); } confounder = data_blob_const(buffer->data, 16); enc_buffer = data_blob_const(buffer->data + 16, buffer->length - 16); /* * build the encryption key md5 over the session key followed * by the confounder * * here the gensec session key is used and * not the dcerpc ncacn_ip_tcp "SystemLibraryDTC" key! */ enc_key = data_blob_const(_enc_key, sizeof(_enc_key)); MD5Init(&md5); MD5Update(&md5, gensec_skey->data, gensec_skey->length); MD5Update(&md5, confounder.data, confounder.length); MD5Final(enc_key.data, &md5); /* * copy the encrypted buffer part and * decrypt it using the created encryption key using arcfour */ dec_buffer = data_blob_talloc(mem_ctx, enc_buffer.data, enc_buffer.length); if (!dec_buffer.data) { return data_blob_const(NULL, 0); } arcfour_crypt_blob(dec_buffer.data, dec_buffer.length, &enc_key); /* * the first 4 byte are the crc32 checksum * of the remaining bytes */ crc32_given = IVAL(dec_buffer.data, 0); crc32_calc = crc32_calc_buffer(dec_buffer.data + 4 , dec_buffer.length - 4); if (crc32_given != crc32_calc) { DEBUG(0,("CRC32: given[0x%08X] calc[0x%08X]\n", crc32_given, crc32_calc)); return data_blob_const(NULL, 0); } checked_buffer = data_blob_talloc(mem_ctx, dec_buffer.data + 4, dec_buffer.length - 4); if (!checked_buffer.data) { return data_blob_const(NULL, 0); } /* * some attributes seem to be in a usable form after this decryption * (supplementalCredentials, priorValue, currentValue, trustAuthOutgoing, * trustAuthIncoming, initialAuthOutgoing, initialAuthIncoming) * At least supplementalCredentials contains plaintext * like "Primary:Kerberos" (in unicode form) * * some attributes seem to have some additional encryption * dBCSPwd, unicodePwd, ntPwdHistory, lmPwdHistory * * it's the sam_rid_crypt() function, as the value is constant, * so it doesn't depend on sessionkeys. */ if (rcrypt) { uint32_t i, num_hashes; if ((checked_buffer.length % 16) != 0) { return data_blob_const(NULL, 0); } plain_buffer = data_blob_talloc(mem_ctx, checked_buffer.data, checked_buffer.length); if (!plain_buffer.data) { return data_blob_const(NULL, 0); } num_hashes = plain_buffer.length / 16; for (i = 0; i < num_hashes; i++) { uint32_t offset = i * 16; sam_rid_crypt(rid, checked_buffer.data + offset, plain_buffer.data + offset, 0); } } else { plain_buffer = checked_buffer; } return plain_buffer;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?