libnet_become_dc.c
来自「samba最新软件」· C语言 代码 · 共 2,239 行 · 第 1/5 页
C
2,239 行
* CN=<new_dc_netbios_name>,CN=Servers,CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>> * serverReference:CN=<new_dc_netbios_name>,CN=Computers,<domain_partition> * Result: * <attributeOrValueExist> *//* * LDAP modify 1st LDAP connection: * * see: becomeDC_ldap1_server_object_modify() * * Request (replace): * CN=<new_dc_netbios_name>,CN=Servers,CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>> * serverReference:CN=<new_dc_netbios_name>,CN=Computers,<domain_partition> * Result: * <success> *//* * Open 1st DRSUAPI connection to the DC using admin credentials * DsBind with DRSUAPI_DS_BIND_GUID_W2K3 ("6afab99c-6e26-464a-975f-f58f105218bc") * (w2k3 does 2 DsBind() calls here..., where is first is unused and contains garbage at the end) * * see: becomeDC_drsuapi_connect_send(), becomeDC_drsuapi1_connect_recv(), * becomeDC_drsuapi_bind_send(), becomeDC_drsuapi_bind_recv() and becomeDC_drsuapi1_bind_recv() *//* * DsAddEntry to create the CN=NTDS Settings,CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name, ... * on the 1st DRSUAPI connection * * see: becomeDC_drsuapi1_add_entry_send() and becomeDC_drsuapi1_add_entry_recv() *//*************************************************************** * Add this stage we call the prepare_db() callback function * of the caller, to see if he wants us to continue * * see: becomeDC_prepare_db() ***************************************************************//* * Open 2nd and 3rd DRSUAPI connection to the DC using admin credentials * - a DsBind with DRSUAPI_DS_BIND_GUID_W2K3 ("6afab99c-6e26-464a-975f-f58f105218bc") * on the 2nd connection * * see: becomeDC_drsuapi_connect_send(), becomeDC_drsuapi2_connect_recv(), * becomeDC_drsuapi_bind_send(), becomeDC_drsuapi_bind_recv(), becomeDC_drsuapi2_bind_recv() * and becomeDC_drsuapi3_connect_recv() *//* * replicate CN=Schema,CN=Configuration,... * on the 3rd DRSUAPI connection and the bind_handle from the 2nd connection * * see: becomeDC_drsuapi_pull_partition_send(), becomeDC_drsuapi_pull_partition_recv(), * becomeDC_drsuapi3_pull_schema_send() and becomeDC_drsuapi3_pull_schema_recv() * *************************************************************** * Add this stage we call the schema_chunk() callback function * for each replication message ***************************************************************//* * replicate CN=Configuration,... * on the 3rd DRSUAPI connection and the bind_handle from the 2nd connection * * see: becomeDC_drsuapi_pull_partition_send(), becomeDC_drsuapi_pull_partition_recv(), * becomeDC_drsuapi3_pull_config_send() and becomeDC_drsuapi3_pull_config_recv() * *************************************************************** * Add this stage we call the config_chunk() callback function * for each replication message ***************************************************************//* * LDAP unbind on the 1st LDAP connection * * not implemented, because it's not needed... *//* * Open 2nd LDAP connection to the DC using admin credentials * * see: becomeDC_connect_ldap2() and becomeDC_ldap_connect() *//* * LDAP search 2nd LDAP connection: * * not implemented because it gives no new information * same as becomeDC_ldap1_computer_object() * * Request: * basedn: <domain_partition> * scope: sub * filter: (&(|(objectClass=user)(objectClass=computer))(sAMAccountName=<new_dc_account_name>)) * attrs: distinguishedName * userAccountControl * Result: * CN=<new_dc_netbios_name>,CN=Computers,<domain_partition> * distinguishedName: CN=<new_dc_netbios_name>,CN=Computers,<domain_partition> * userAccoountControl: 4096 <0x00001000> *//* * LDAP search 2nd LDAP connection: * * not implemented because it gives no new information * same as becomeDC_ldap1_computer_object() * * Request: * basedn: CN=<new_dc_netbios_name>,CN=Computers,<domain_partition> * scope: base * filter: (objectClass=*) * attrs: userAccountControl * Result: * CN=<new_dc_netbios_name>,CN=Computers,<domain_partition> * userAccoountControl: 4096 <0x00001000> *//* * LDAP modify 2nd LDAP connection: * * see: becomeDC_ldap2_modify_computer() * * Request (replace): * CN=<new_dc_netbios_name>,CN=Computers,<domain_partition> * userAccoountControl: 532480 <0x82000> * Result: * <success> *//* * LDAP search 2nd LDAP connection: * * see: becomeDC_ldap2_move_computer() * * Request: * basedn: <WKGUID=2fbac1870ade11d297c400c04fd8d5cd,<domain_partition>> * scope: base * filter: (objectClass=*) * attrs: 1.1 * Result: * CN=Domain Controllers,<domain_partition> *//* * LDAP search 2nd LDAP connection: * * not implemented because it gives no new information * * Request: * basedn: CN=Domain Controllers,<domain_partition> * scope: base * filter: (objectClass=*) * attrs: distinguishedName * Result: * CN=Domain Controller,<domain_partition> * distinguishedName: CN=Domain Controllers,<domain_partition> *//* * LDAP modifyRDN 2nd LDAP connection: * * see: becomeDC_ldap2_move_computer() * * Request: * entry: CN=<new_dc_netbios_name>,CN=Computers,<domain_partition> * newrdn: CN=<new_dc_netbios_name> * deleteoldrdn: TRUE * newparent: CN=Domain Controllers,<domain_partition> * Result: * <success> *//* * LDAP unbind on the 2nd LDAP connection * * not implemented, because it's not needed... *//* * replicate Domain Partition * on the 3rd DRSUAPI connection and the bind_handle from the 2nd connection * * see: becomeDC_drsuapi_pull_partition_send(), becomeDC_drsuapi_pull_partition_recv(), * becomeDC_drsuapi3_pull_domain_send() and becomeDC_drsuapi3_pull_domain_recv() * *************************************************************** * Add this stage we call the domain_chunk() callback function * for each replication message ***************************************************************//* call DsReplicaUpdateRefs() for all partitions like this: * req1: struct drsuapi_DsReplicaUpdateRefsRequest1 * * naming_context: struct drsuapi_DsReplicaObjectIdentifier * __ndr_size : 0x000000ae (174) * __ndr_size_sid : 0x00000000 (0) * guid : 00000000-0000-0000-0000-000000000000 * sid : S-0-0 * dn : 'CN=Schema,CN=Configuration,DC=w2k3,DC=vmnet1,DC=vm,DC=base' * * dest_dsa_dns_name : '4a0df188-a0b8-47ea-bbe5-e614723f16dd._msdcs.w2k3.vmnet1.vm.base' * dest_dsa_guid : 4a0df188-a0b8-47ea-bbe5-e614723f16dd * options : 0x0000001c (28) * 0: DRSUAPI_DS_REPLICA_UPDATE_ASYNCHRONOUS_OPERATION * 0: DRSUAPI_DS_REPLICA_UPDATE_WRITEABLE * 1: DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE * 1: DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE * 1: DRSUAPI_DS_REPLICA_UPDATE_0x00000010 * * 4a0df188-a0b8-47ea-bbe5-e614723f16dd is the objectGUID the DsAddEntry() returned for the * CN=NTDS Settings,CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name, ... * on the 2nd!!! DRSUAPI connection * * see: becomeDC_drsuapi_update_refs_send(), becomeDC_drsuapi2_update_refs_schema_recv(), * becomeDC_drsuapi2_update_refs_config_recv() and becomeDC_drsuapi2_update_refs_domain_recv() *//* * Windows does opens the 4th and 5th DRSUAPI connection... * and does a DsBind() with the objectGUID from DsAddEntry() as bind_guid * on the 4th connection * * and then 2 full replications of the domain partition on the 5th connection * with the bind_handle from the 4th connection * * not implemented because it gives no new information */struct libnet_BecomeDC_state { struct composite_context *creq; struct libnet_context *libnet; struct dom_sid zero_sid; struct { struct cldap_socket *sock; struct cldap_netlogon io; struct NETLOGON_SAM_LOGON_RESPONSE_EX netlogon; } cldap; struct becomeDC_ldap { struct ldb_context *ldb; const struct ldb_message *rootdse; } ldap1, ldap2; struct becomeDC_drsuapi { struct libnet_BecomeDC_state *s; struct dcerpc_binding *binding; struct dcerpc_pipe *pipe; DATA_BLOB gensec_skey; struct drsuapi_DsBind bind_r; struct GUID bind_guid; struct drsuapi_DsBindInfoCtr bind_info_ctr; struct drsuapi_DsBindInfo28 local_info28; struct drsuapi_DsBindInfo28 remote_info28; struct policy_handle bind_handle; } drsuapi1, drsuapi2, drsuapi3; struct libnet_BecomeDC_Domain domain; struct libnet_BecomeDC_Forest forest; struct libnet_BecomeDC_SourceDSA source_dsa; struct libnet_BecomeDC_DestDSA dest_dsa; struct libnet_BecomeDC_Partition schema_part, config_part, domain_part; struct becomeDC_fsmo { const char *dns_name; const char *server_dn_str; const char *ntds_dn_str; struct GUID ntds_guid; } infrastructure_fsmo; struct becomeDC_fsmo rid_manager_fsmo; struct libnet_BecomeDC_CheckOptions _co; struct libnet_BecomeDC_PrepareDB _pp; struct libnet_BecomeDC_StoreChunk _sc; struct libnet_BecomeDC_Callbacks callbacks;};static void becomeDC_recv_cldap(struct cldap_request *req);static void becomeDC_send_cldap(struct libnet_BecomeDC_state *s){ struct composite_context *c = s->creq; struct cldap_request *req; s->cldap.io.in.dest_address = s->source_dsa.address; s->cldap.io.in.dest_port = lp_cldap_port(s->libnet->lp_ctx); s->cldap.io.in.realm = s->domain.dns_name; s->cldap.io.in.host = s->dest_dsa.netbios_name; s->cldap.io.in.user = NULL; s->cldap.io.in.domain_guid = NULL; s->cldap.io.in.domain_sid = NULL; s->cldap.io.in.acct_control = -1; s->cldap.io.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; s->cldap.io.in.map_response = true; s->cldap.sock = cldap_socket_init(s, s->libnet->event_ctx, lp_iconv_convenience(s->libnet->lp_ctx)); if (composite_nomem(s->cldap.sock, c)) return; req = cldap_netlogon_send(s->cldap.sock, &s->cldap.io); if (composite_nomem(req, c)) return; req->async.fn = becomeDC_recv_cldap; req->async.private = s;}static void becomeDC_connect_ldap1(struct libnet_BecomeDC_state *s);static void becomeDC_recv_cldap(struct cldap_request *req){ struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private, struct libnet_BecomeDC_state); struct composite_context *c = s->creq; c->status = cldap_netlogon_recv(req, s, &s->cldap.io); if (!composite_is_ok(c)) return; s->cldap.netlogon = s->cldap.io.out.netlogon.nt5_ex; s->domain.dns_name = s->cldap.netlogon.dns_domain; s->domain.netbios_name = s->cldap.netlogon.domain; s->domain.guid = s->cldap.netlogon.domain_uuid; s->forest.dns_name = s->cldap.netlogon.forest; s->source_dsa.dns_name = s->cldap.netlogon.pdc_dns_name; s->source_dsa.netbios_name = s->cldap.netlogon.pdc_name; s->source_dsa.site_name = s->cldap.netlogon.server_site; s->dest_dsa.site_name = s->cldap.netlogon.client_site; becomeDC_connect_ldap1(s);}static NTSTATUS becomeDC_ldap_connect(struct libnet_BecomeDC_state *s, struct becomeDC_ldap *ldap){ char *url; url = talloc_asprintf(s, "ldap://%s/", s->source_dsa.dns_name); NT_STATUS_HAVE_NO_MEMORY(url); ldap->ldb = ldb_wrap_connect(s, s->libnet->event_ctx, s->libnet->lp_ctx, url, NULL, s->libnet->cred, 0, NULL); talloc_free(url); if (ldap->ldb == NULL) { return NT_STATUS_UNEXPECTED_NETWORK_ERROR; } return NT_STATUS_OK;}static NTSTATUS becomeDC_ldap1_rootdse(struct libnet_BecomeDC_state *s){ int ret; struct ldb_result *r; struct ldb_dn *basedn; static const char *attrs[] = { "*", NULL }; basedn = ldb_dn_new(s, s->ldap1.ldb, NULL); NT_STATUS_HAVE_NO_MEMORY(basedn); ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE, "(objectClass=*)", attrs, &r); talloc_free(basedn); if (ret != LDB_SUCCESS) { return NT_STATUS_LDAP(ret); } else if (r->count != 1) { talloc_free(r); return NT_STATUS_INVALID_NETWORK_RESPONSE; } talloc_steal(s, r); s->ldap1.rootdse = r->msgs[0]; s->domain.dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "defaultNamingContext", NULL); if (!s->domain.dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE; s->forest.root_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "rootDomainNamingContext", NULL); if (!s->forest.root_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE; s->forest.config_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "configurationNamingContext", NULL); if (!s->forest.config_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE; s->forest.schema_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "schemaNamingContext", NULL); if (!s->forest.schema_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE; s->source_dsa.server_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "serverName", NULL); if (!s->source_dsa.server_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE; s->source_dsa.ntds_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "dsServiceName", NULL); if (!s->source_dsa.ntds_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE; return NT_STATUS_OK;}static NTSTATUS becomeDC_ldap1_crossref_behavior_version(struct libnet_BecomeDC_state *s){ int ret; struct ldb_result *r; struct ldb_dn *basedn; static const char *attrs[] = { "msDs-Behavior-Version", NULL }; basedn = ldb_dn_new(s, s->ldap1.ldb, s->forest.config_dn_str); NT_STATUS_HAVE_NO_MEMORY(basedn); ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_ONELEVEL, "(cn=Partitions)", attrs, &r); talloc_free(basedn); if (ret != LDB_SUCCESS) { return NT_STATUS_LDAP(ret); } else if (r->count != 1) { talloc_free(r); return NT_STATUS_INVALID_NETWORK_RESPONSE; } s->forest.crossref_behavior_version = ldb_msg_find_attr_as_uint(r->msgs[0], "msDs-Behavior-Version", 0); talloc_free(r); return NT_STATUS_OK;}static NTSTATUS becomeDC_ldap1_domain_behavior_version(struct libnet_BecomeDC_state *s){ int ret; struct ldb_result *r; struct ldb_dn *basedn; static const char *attrs[] = { "msDs-Behavior-Version", NULL }; basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str); NT_STATUS_HAVE_NO_MEMORY(basedn); ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?