LCOV - code coverage report
Current view: top level - source4/libnet - libnet_unbecome_dc.c (source / functions) Hit Total Coverage
Test: coverage report for master 469b22b8 Lines: 224 321 69.8 %
Date: 2024-06-10 12:05:21 Functions: 17 17 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Copyright (C) Stefan Metzmacher <metze@samba.org> 2006
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "libnet/libnet.h"
      22             : #include "libcli/composite/composite.h"
      23             : #include "libcli/cldap/cldap.h"
      24             : #include <ldb.h>
      25             : #include <ldb_errors.h>
      26             : #include "ldb_wrap.h"
      27             : #include "dsdb/samdb/samdb.h"
      28             : #include "../libds/common/flags.h"
      29             : #include "librpc/gen_ndr/ndr_drsuapi_c.h"
      30             : #include "param/param.h"
      31             : #include "lib/tsocket/tsocket.h"
      32             : 
      33             : /*****************************************************************************
      34             :  * Windows 2003 (w2k3) does the following steps when changing the server role
      35             :  * from domain controller back to domain member
      36             :  *
      37             :  * We mostly do the same.
      38             :  *****************************************************************************/
      39             : 
      40             : /*
      41             :  * lookup DC:
      42             :  * - using nbt name<1C> request and a samlogon mailslot request
      43             :  * or
      44             :  * - using a DNS SRV _ldap._tcp.dc._msdcs. request and a CLDAP netlogon request
      45             :  *
      46             :  * see: unbecomeDC_send_cldap() and unbecomeDC_recv_cldap()
      47             :  */
      48             : 
      49             : /*
      50             :  * Open 1st LDAP connection to the DC using admin credentials
      51             :  *
      52             :  * see: unbecomeDC_ldap_connect()
      53             :  */
      54             : 
      55             : /*
      56             :  * LDAP search 1st LDAP connection:
      57             :  *
      58             :  * see: unbecomeDC_ldap_rootdse()
      59             :  *
      60             :  * Request:
      61             :  *      basedn: ""
      62             :  *      scope:  base
      63             :  *      filter: (objectClass=*)
      64             :  *      attrs:  defaultNamingContext
      65             :  *              configurationNamingContext
      66             :  * Result:
      67             :  *      ""
      68             :  *              defaultNamingContext:   <domain_partition>
      69             :  *              configurationNamingContext:CN=Configuration,<domain_partition>
      70             :  */
      71             : 
      72             : /*
      73             :  * LDAP search 1st LDAP connection:
      74             :  * 
      75             :  * see: unbecomeDC_ldap_computer_object()
      76             :  *
      77             :  * Request:
      78             :  *      basedn: <domain_partition>
      79             :  *      scope:  sub
      80             :  *      filter: (&(|(objectClass=user)(objectClass=computer))(sAMAccountName=<new_dc_account_name>))
      81             :  *      attrs:  distinguishedName
      82             :  *              userAccountControl
      83             :  * Result:
      84             :  *      CN=<new_dc_netbios_name>,CN=Domain Controllers,<domain_partition>
      85             :  *              distinguishedName:      CN=<new_dc_netbios_name>,CN=Domain Controllers,<domain_partition>
      86             :  *              userAccoountControl:    532480 <0x82000>
      87             :  */
      88             : 
      89             : /*
      90             :  * LDAP search 1st LDAP connection:
      91             :  * 
      92             :  * see: unbecomeDC_ldap_modify_computer()
      93             :  *
      94             :  * Request:
      95             :  *      basedn: CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
      96             :  *      scope:  base
      97             :  *      filter: (objectClass=*)
      98             :  *      attrs:  userAccountControl
      99             :  * Result:
     100             :  *      CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
     101             :  *              userAccoountControl:    532480 <0x82000>
     102             :  */
     103             : 
     104             : /*
     105             :  * LDAP modify 1st LDAP connection:
     106             :  *
     107             :  * see: unbecomeDC_ldap_modify_computer()
     108             :  * 
     109             :  * Request (replace):
     110             :  *      CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
     111             :  *      userAccoountControl:    4096 <0x1000>
     112             :  * Result:
     113             :  *      <success>
     114             :  */
     115             : 
     116             : /*
     117             :  * LDAP search 1st LDAP connection:
     118             :  * 
     119             :  * see: unbecomeDC_ldap_move_computer()
     120             :  *
     121             :  * Request:
     122             :  *      basedn: <WKGUID=aa312825768811d1aded00c04fd8d5cd,<domain_partition>>
     123             :  *      scope:  base
     124             :  *      filter: (objectClass=*)
     125             :  *      attrs:  1.1
     126             :  * Result:
     127             :  *      CN=Computers,<domain_partition>
     128             :  */
     129             : 
     130             : /*
     131             :  * LDAP search 1st LDAP connection:
     132             :  *
     133             :  * not implemented because it doesn't give any new information
     134             :  *
     135             :  * Request:
     136             :  *      basedn: CN=Computers,<domain_partition>
     137             :  *      scope:  base
     138             :  *      filter: (objectClass=*)
     139             :  *      attrs:  distinguishedName
     140             :  * Result:
     141             :  *      CN=Computers,<domain_partition>
     142             :  *              distinguishedName:      CN=Computers,<domain_partition>
     143             :  */
     144             : 
     145             : /*
     146             :  * LDAP modifyRDN 1st LDAP connection:
     147             :  * 
     148             :  * see: unbecomeDC_ldap_move_computer()
     149             :  *
     150             :  * Request:
     151             :  *      entry:          CN=<new_dc_netbios_name>,CN=Domain Controllers,<domain_partition>
     152             :  *      newrdn:         CN=<new_dc_netbios_name>
     153             :  *      deleteoldrdn:   TRUE
     154             :  *      newparent:      CN=Computers,<domain_partition>
     155             :  * Result:
     156             :  *      <success>
     157             :  */
     158             : 
     159             : /*
     160             :  * LDAP unbind on the 1st LDAP connection
     161             :  *
     162             :  * not implemented, because it's not needed...
     163             :  */
     164             : 
     165             : /*
     166             :  * Open 1st DRSUAPI connection to the DC using admin credentials
     167             :  * DsBind with DRSUAPI_DS_BIND_GUID ("e24d201a-4fd6-11d1-a3da-0000f875ae0d")
     168             :  *
     169             :  * see: unbecomeDC_drsuapi_connect_send(), unbecomeDC_drsuapi_connect_recv(),
     170             :  *      unbecomeDC_drsuapi_bind_send() and unbecomeDC_drsuapi_bind_recv()
     171             :  */
     172             : 
     173             : /*
     174             :  * DsRemoveDsServer to remove the 
     175             :  * CN=<machine_name>,CN=Servers,CN=<site_name>,CN=Configuration,<domain_partition>
     176             :  * and CN=NTDS Settings,CN=<machine_name>,CN=Servers,CN=<site_name>,CN=Configuration,<domain_partition>
     177             :  * on the 1st DRSUAPI connection
     178             :  *
     179             :  * see: unbecomeDC_drsuapi_remove_ds_server_send() and unbecomeDC_drsuapi_remove_ds_server_recv()
     180             :  */
     181             : 
     182             : /*
     183             :  * DsUnbind on the 1st DRSUAPI connection
     184             :  *
     185             :  * not implemented, because it's not needed...
     186             :  */
     187             : 
     188             : 
     189             : struct libnet_UnbecomeDC_state {
     190             :         struct composite_context *creq;
     191             : 
     192             :         struct libnet_context *libnet;
     193             : 
     194             :         struct {
     195             :                 struct cldap_socket *sock;
     196             :                 struct cldap_netlogon io;
     197             :                 struct NETLOGON_SAM_LOGON_RESPONSE_EX netlogon;
     198             :         } cldap;
     199             : 
     200             :         struct {
     201             :                 struct ldb_context *ldb;
     202             :         } ldap;
     203             : 
     204             :         struct {
     205             :                 struct dcerpc_binding *binding;
     206             :                 struct dcerpc_pipe *pipe;
     207             :                 struct dcerpc_binding_handle *drsuapi_handle;
     208             :                 struct drsuapi_DsBind bind_r;
     209             :                 struct GUID bind_guid;
     210             :                 struct drsuapi_DsBindInfoCtr bind_info_ctr;
     211             :                 struct drsuapi_DsBindInfo28 local_info28;
     212             :                 struct drsuapi_DsBindInfo28 remote_info28;
     213             :                 struct policy_handle bind_handle;
     214             :                 struct drsuapi_DsRemoveDSServer rm_ds_srv_r;
     215             :         } drsuapi;
     216             : 
     217             :         struct {
     218             :                 /* input */
     219             :                 const char *dns_name;
     220             :                 const char *netbios_name;
     221             : 
     222             :                 /* constructed */
     223             :                 struct GUID guid;
     224             :                 const char *dn_str;
     225             :         } domain;
     226             : 
     227             :         struct {
     228             :                 /* constructed */
     229             :                 const char *config_dn_str;
     230             :         } forest;
     231             : 
     232             :         struct {
     233             :                 /* input */
     234             :                 const char *address;
     235             : 
     236             :                 /* constructed */
     237             :                 const char *dns_name;
     238             :                 const char *netbios_name;
     239             :                 const char *site_name;
     240             :         } source_dsa;
     241             : 
     242             :         struct {
     243             :                 /* input */
     244             :                 const char *netbios_name;
     245             : 
     246             :                 /* constructed */
     247             :                 const char *dns_name;
     248             :                 const char *site_name;
     249             :                 const char *computer_dn_str;
     250             :                 const char *server_dn_str;
     251             :                 uint32_t user_account_control;
     252             :         } dest_dsa;
     253             : };
     254             : 
     255             : static void unbecomeDC_recv_cldap(struct tevent_req *req);
     256             : 
     257           4 : static void unbecomeDC_send_cldap(struct libnet_UnbecomeDC_state *s)
     258             : {
     259           4 :         struct composite_context *c = s->creq;
     260           0 :         struct tevent_req *req;
     261           0 :         struct tsocket_address *dest_address;
     262           0 :         int ret;
     263             : 
     264           4 :         s->cldap.io.in.dest_address  = NULL;
     265           4 :         s->cldap.io.in.dest_port     = 0;
     266           4 :         s->cldap.io.in.realm         = s->domain.dns_name;
     267           4 :         s->cldap.io.in.host          = s->dest_dsa.netbios_name;
     268           4 :         s->cldap.io.in.user          = NULL;
     269           4 :         s->cldap.io.in.domain_guid   = NULL;
     270           4 :         s->cldap.io.in.domain_sid    = NULL;
     271           4 :         s->cldap.io.in.acct_control  = -1;
     272           4 :         s->cldap.io.in.version               = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
     273           4 :         s->cldap.io.in.map_response  = true;
     274             : 
     275           4 :         ret = tsocket_address_inet_from_strings(s, "ip",
     276             :                                                 s->source_dsa.address,
     277             :                                                 lpcfg_cldap_port(s->libnet->lp_ctx),
     278             :                                                 &dest_address);
     279           4 :         if (ret != 0) {
     280           0 :                 c->status = map_nt_error_from_unix_common(errno);
     281           0 :                 if (!composite_is_ok(c)) return;
     282             :         }
     283             : 
     284           4 :         c->status = cldap_socket_init(s, NULL, dest_address, &s->cldap.sock);
     285           4 :         if (!composite_is_ok(c)) return;
     286             : 
     287           4 :         req = cldap_netlogon_send(s, s->libnet->event_ctx,
     288           4 :                                   s->cldap.sock, &s->cldap.io);
     289           4 :         if (composite_nomem(req, c)) return;
     290           4 :         tevent_req_set_callback(req, unbecomeDC_recv_cldap, s);
     291             : }
     292             : 
     293             : static void unbecomeDC_connect_ldap(struct libnet_UnbecomeDC_state *s);
     294             : 
     295           4 : static void unbecomeDC_recv_cldap(struct tevent_req *req)
     296             : {
     297           4 :         struct libnet_UnbecomeDC_state *s = tevent_req_callback_data(req,
     298             :                                             struct libnet_UnbecomeDC_state);
     299           4 :         struct composite_context *c = s->creq;
     300             : 
     301           4 :         c->status = cldap_netlogon_recv(req, s, &s->cldap.io);
     302           4 :         talloc_free(req);
     303           4 :         if (!composite_is_ok(c)) return;
     304             : 
     305           4 :         s->cldap.netlogon = s->cldap.io.out.netlogon.data.nt5_ex;
     306             : 
     307           4 :         s->domain.dns_name           = s->cldap.netlogon.dns_domain;
     308           4 :         s->domain.netbios_name               = s->cldap.netlogon.domain_name;
     309           4 :         s->domain.guid                       = s->cldap.netlogon.domain_uuid;
     310             : 
     311           4 :         s->source_dsa.dns_name               = s->cldap.netlogon.pdc_dns_name;
     312           4 :         s->source_dsa.netbios_name   = s->cldap.netlogon.pdc_name;
     313           4 :         s->source_dsa.site_name              = s->cldap.netlogon.server_site;
     314             : 
     315           4 :         s->dest_dsa.site_name                = s->cldap.netlogon.client_site;
     316             : 
     317           4 :         unbecomeDC_connect_ldap(s);
     318             : }
     319             : 
     320           4 : static NTSTATUS unbecomeDC_ldap_connect(struct libnet_UnbecomeDC_state *s)
     321             : {
     322           0 :         char *url;
     323             : 
     324           4 :         url = talloc_asprintf(s, "ldap://%s/", s->source_dsa.dns_name);
     325           4 :         NT_STATUS_HAVE_NO_MEMORY(url);
     326             : 
     327           8 :         s->ldap.ldb = ldb_wrap_connect(s, s->libnet->event_ctx, s->libnet->lp_ctx, url,
     328             :                                        NULL,
     329           4 :                                        s->libnet->cred,
     330             :                                        0);
     331           4 :         talloc_free(url);
     332           4 :         if (s->ldap.ldb == NULL) {
     333           0 :                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
     334             :         }
     335             : 
     336           4 :         return NT_STATUS_OK;
     337             : }
     338             : 
     339           4 : static NTSTATUS unbecomeDC_ldap_rootdse(struct libnet_UnbecomeDC_state *s)
     340             : {
     341           0 :         int ret;
     342           0 :         struct ldb_result *r;
     343           0 :         struct ldb_dn *basedn;
     344           0 :         static const char *attrs[] = {
     345             :                 "defaultNamingContext",
     346             :                 "configurationNamingContext",
     347             :                 NULL
     348             :         };
     349             : 
     350           4 :         basedn = ldb_dn_new(s, s->ldap.ldb, NULL);
     351           4 :         NT_STATUS_HAVE_NO_MEMORY(basedn);
     352             : 
     353           4 :         ret = ldb_search(s->ldap.ldb, s, &r, basedn, LDB_SCOPE_BASE, attrs,
     354             :                          "(objectClass=*)");
     355           4 :         talloc_free(basedn);
     356           4 :         if (ret != LDB_SUCCESS) {
     357           0 :                 return NT_STATUS_LDAP(ret);
     358           4 :         } else if (r->count != 1) {
     359           0 :                 talloc_free(r);
     360           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     361             :         }
     362             : 
     363           4 :         s->domain.dn_str     = ldb_msg_find_attr_as_string(r->msgs[0], "defaultNamingContext", NULL);
     364           4 :         if (!s->domain.dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
     365           4 :         talloc_steal(s, s->domain.dn_str);
     366             : 
     367           4 :         s->forest.config_dn_str      = ldb_msg_find_attr_as_string(r->msgs[0], "configurationNamingContext", NULL);
     368           4 :         if (!s->forest.config_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
     369           4 :         talloc_steal(s, s->forest.config_dn_str);
     370             : 
     371           4 :         s->dest_dsa.server_dn_str = talloc_asprintf(s, "CN=%s,CN=Servers,CN=%s,CN=Sites,%s",
     372             :                                                     s->dest_dsa.netbios_name,
     373             :                                                     s->dest_dsa.site_name,
     374             :                                                     s->forest.config_dn_str);
     375           4 :         NT_STATUS_HAVE_NO_MEMORY(s->dest_dsa.server_dn_str);
     376             : 
     377           4 :         talloc_free(r);
     378           4 :         return NT_STATUS_OK;
     379             : }
     380             : 
     381           4 : static NTSTATUS unbecomeDC_ldap_computer_object(struct libnet_UnbecomeDC_state *s)
     382             : {
     383           0 :         int ret;
     384           0 :         struct ldb_result *r;
     385           0 :         struct ldb_dn *basedn;
     386           0 :         static const char *attrs[] = {
     387             :                 "distinguishedName",
     388             :                 "userAccountControl",
     389             :                 NULL
     390             :         };
     391             : 
     392           4 :         basedn = ldb_dn_new(s, s->ldap.ldb, s->domain.dn_str);
     393           4 :         NT_STATUS_HAVE_NO_MEMORY(basedn);
     394             : 
     395           4 :         ret = ldb_search(s->ldap.ldb, s, &r, basedn, LDB_SCOPE_SUBTREE, attrs,
     396             :                          "(&(|(objectClass=user)(objectClass=computer))(sAMAccountName=%s$))",
     397             :                          s->dest_dsa.netbios_name);
     398           4 :         talloc_free(basedn);
     399           4 :         if (ret != LDB_SUCCESS) {
     400           0 :                 return NT_STATUS_LDAP(ret);
     401           4 :         } else if (r->count != 1) {
     402           0 :                 talloc_free(r);
     403           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     404             :         }
     405             : 
     406           4 :         s->dest_dsa.computer_dn_str  = ldb_msg_find_attr_as_string(r->msgs[0], "distinguishedName", NULL);
     407           4 :         if (!s->dest_dsa.computer_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
     408           4 :         talloc_steal(s, s->dest_dsa.computer_dn_str);
     409             : 
     410           4 :         s->dest_dsa.user_account_control = ldb_msg_find_attr_as_uint(r->msgs[0], "userAccountControl", 0);
     411             : 
     412           4 :         talloc_free(r);
     413           4 :         return NT_STATUS_OK;
     414             : }
     415             : 
     416           4 : static NTSTATUS unbecomeDC_ldap_modify_computer(struct libnet_UnbecomeDC_state *s)
     417             : {
     418           0 :         int ret;
     419           0 :         struct ldb_message *msg;
     420           4 :         uint32_t user_account_control = UF_WORKSTATION_TRUST_ACCOUNT;
     421           0 :         unsigned int i;
     422             : 
     423             :         /* as the value is already as we want it to be, we're done */
     424           4 :         if (s->dest_dsa.user_account_control == user_account_control) {
     425           0 :                 return NT_STATUS_OK;
     426             :         }
     427             : 
     428             :         /* make a 'modify' msg, and only for serverReference */
     429           4 :         msg = ldb_msg_new(s);
     430           4 :         NT_STATUS_HAVE_NO_MEMORY(msg);
     431           4 :         msg->dn = ldb_dn_new(msg, s->ldap.ldb, s->dest_dsa.computer_dn_str);
     432           4 :         NT_STATUS_HAVE_NO_MEMORY(msg->dn);
     433             : 
     434           4 :         ret = samdb_msg_add_uint(s->ldap.ldb, msg, msg, "userAccountControl",
     435             :                                  user_account_control);
     436           4 :         if (ret != LDB_SUCCESS) {
     437           0 :                 talloc_free(msg);
     438           0 :                 return NT_STATUS_NO_MEMORY;
     439             :         }
     440             : 
     441             :         /* mark all the message elements (should be just one)
     442             :            as LDB_FLAG_MOD_REPLACE */
     443           8 :         for (i=0;i<msg->num_elements;i++) {
     444           4 :                 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
     445             :         }
     446             : 
     447           4 :         ret = ldb_modify(s->ldap.ldb, msg);
     448           4 :         talloc_free(msg);
     449           4 :         if (ret != LDB_SUCCESS) {
     450           0 :                 return NT_STATUS_LDAP(ret);
     451             :         }
     452             : 
     453           4 :         s->dest_dsa.user_account_control = user_account_control;
     454             : 
     455           4 :         return NT_STATUS_OK;
     456             : }
     457             : 
     458           4 : static NTSTATUS unbecomeDC_ldap_move_computer(struct libnet_UnbecomeDC_state *s)
     459             : {
     460           0 :         int ret;
     461           0 :         struct ldb_result *r;
     462           0 :         struct ldb_dn *basedn;
     463           0 :         struct ldb_dn *old_dn;
     464           0 :         struct ldb_dn *new_dn;
     465           0 :         static const char *_1_1_attrs[] = {
     466             :                 "1.1",
     467             :                 NULL
     468             :         };
     469             : 
     470           4 :         basedn = ldb_dn_new_fmt(s, s->ldap.ldb, "<WKGUID=aa312825768811d1aded00c04fd8d5cd,%s>",
     471             :                                 s->domain.dn_str);
     472           4 :         NT_STATUS_HAVE_NO_MEMORY(basedn);
     473             : 
     474           4 :         ret = ldb_search(s->ldap.ldb, s, &r, basedn, LDB_SCOPE_BASE,
     475             :                          _1_1_attrs, "(objectClass=*)");
     476           4 :         talloc_free(basedn);
     477           4 :         if (ret != LDB_SUCCESS) {
     478           0 :                 return NT_STATUS_LDAP(ret);
     479           4 :         } else if (r->count != 1) {
     480           0 :                 talloc_free(r);
     481           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     482             :         }
     483             : 
     484           4 :         old_dn = ldb_dn_new(r, s->ldap.ldb, s->dest_dsa.computer_dn_str);
     485           4 :         NT_STATUS_HAVE_NO_MEMORY(old_dn);
     486             : 
     487           4 :         new_dn = r->msgs[0]->dn;
     488             : 
     489           4 :         if (!ldb_dn_add_child_fmt(new_dn, "CN=%s", s->dest_dsa.netbios_name)) {
     490           0 :                 talloc_free(r);
     491           0 :                 return NT_STATUS_NO_MEMORY;
     492             :         }
     493             : 
     494           4 :         if (ldb_dn_compare(old_dn, new_dn) == 0) {
     495             :                 /* we don't need to rename if the old and new dn match */
     496           0 :                 talloc_free(r);
     497           0 :                 return NT_STATUS_OK;
     498             :         }
     499             : 
     500           4 :         ret = ldb_rename(s->ldap.ldb, old_dn, new_dn);
     501           4 :         if (ret != LDB_SUCCESS) {
     502           0 :                 talloc_free(r);
     503           0 :                 return NT_STATUS_LDAP(ret);
     504             :         }
     505             : 
     506           4 :         s->dest_dsa.computer_dn_str = ldb_dn_alloc_linearized(s, new_dn);
     507           4 :         NT_STATUS_HAVE_NO_MEMORY(s->dest_dsa.computer_dn_str);
     508             : 
     509           4 :         talloc_free(r);
     510             : 
     511           4 :         return NT_STATUS_OK;
     512             : }
     513             : 
     514             : static void unbecomeDC_drsuapi_connect_send(struct libnet_UnbecomeDC_state *s);
     515             : 
     516           4 : static void unbecomeDC_connect_ldap(struct libnet_UnbecomeDC_state *s)
     517             : {
     518           4 :         struct composite_context *c = s->creq;
     519             : 
     520           4 :         c->status = unbecomeDC_ldap_connect(s);
     521           4 :         if (!composite_is_ok(c)) return;
     522             : 
     523           4 :         c->status = unbecomeDC_ldap_rootdse(s);
     524           4 :         if (!composite_is_ok(c)) return;
     525             : 
     526           4 :         c->status = unbecomeDC_ldap_computer_object(s);
     527           4 :         if (!composite_is_ok(c)) return;
     528             : 
     529           4 :         c->status = unbecomeDC_ldap_modify_computer(s);
     530           4 :         if (!composite_is_ok(c)) return;
     531             : 
     532           4 :         c->status = unbecomeDC_ldap_move_computer(s);
     533           4 :         if (!composite_is_ok(c)) return;
     534             : 
     535           4 :         unbecomeDC_drsuapi_connect_send(s);
     536             : }
     537             : 
     538             : static void unbecomeDC_drsuapi_connect_recv(struct composite_context *creq);
     539             : 
     540           4 : static void unbecomeDC_drsuapi_connect_send(struct libnet_UnbecomeDC_state *s)
     541             : {
     542           4 :         struct composite_context *c = s->creq;
     543           0 :         struct composite_context *creq;
     544           0 :         char *binding_str;
     545             : 
     546           4 :         binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[seal,target_hostname=%s]",
     547             :                                       s->source_dsa.address,
     548             :                                       s->source_dsa.dns_name);
     549           4 :         if (composite_nomem(binding_str, c)) return;
     550             : 
     551           4 :         c->status = dcerpc_parse_binding(s, binding_str, &s->drsuapi.binding);
     552           4 :         talloc_free(binding_str);
     553           4 :         if (!composite_is_ok(c)) return;
     554             : 
     555           4 :         if (DEBUGLEVEL >= 10) {
     556           0 :                 c->status = dcerpc_binding_set_flags(s->drsuapi.binding,
     557             :                                                      DCERPC_DEBUG_PRINT_BOTH,
     558             :                                                      0);
     559           0 :                 if (!composite_is_ok(c)) return;
     560             :         }
     561             : 
     562           4 :         creq = dcerpc_pipe_connect_b_send(s, s->drsuapi.binding, &ndr_table_drsuapi,
     563           4 :                                           s->libnet->cred, s->libnet->event_ctx,
     564           4 :                                           s->libnet->lp_ctx);
     565           4 :         composite_continue(c, creq, unbecomeDC_drsuapi_connect_recv, s);
     566             : }
     567             : 
     568             : static void unbecomeDC_drsuapi_bind_send(struct libnet_UnbecomeDC_state *s);
     569             : 
     570           4 : static void unbecomeDC_drsuapi_connect_recv(struct composite_context *req)
     571             : {
     572           4 :         struct libnet_UnbecomeDC_state *s = talloc_get_type(req->async.private_data,
     573             :                                             struct libnet_UnbecomeDC_state);
     574           4 :         struct composite_context *c = s->creq;
     575             : 
     576           4 :         c->status = dcerpc_pipe_connect_b_recv(req, s, &s->drsuapi.pipe);
     577           4 :         if (!composite_is_ok(c)) return;
     578             : 
     579           4 :         s->drsuapi.drsuapi_handle = s->drsuapi.pipe->binding_handle;
     580             : 
     581           4 :         unbecomeDC_drsuapi_bind_send(s);
     582             : }
     583             : 
     584             : static void unbecomeDC_drsuapi_bind_recv(struct tevent_req *subreq);
     585             : 
     586           4 : static void unbecomeDC_drsuapi_bind_send(struct libnet_UnbecomeDC_state *s)
     587             : {
     588           4 :         struct composite_context *c = s->creq;
     589           0 :         struct drsuapi_DsBindInfo28 *bind_info28;
     590           0 :         struct tevent_req *subreq;
     591             : 
     592           4 :         GUID_from_string(DRSUAPI_DS_BIND_GUID, &s->drsuapi.bind_guid);
     593             : 
     594           4 :         bind_info28                             = &s->drsuapi.local_info28;
     595           4 :         bind_info28->supported_extensions    = 0;
     596           4 :         bind_info28->site_guid                       = GUID_zero();
     597           4 :         bind_info28->pid                     = 0;
     598           4 :         bind_info28->repl_epoch                      = 0;
     599             : 
     600           4 :         s->drsuapi.bind_info_ctr.length              = 28;
     601           4 :         s->drsuapi.bind_info_ctr.info.info28 = *bind_info28;
     602             : 
     603           4 :         s->drsuapi.bind_r.in.bind_guid = &s->drsuapi.bind_guid;
     604           4 :         s->drsuapi.bind_r.in.bind_info = &s->drsuapi.bind_info_ctr;
     605           4 :         s->drsuapi.bind_r.out.bind_handle = &s->drsuapi.bind_handle;
     606             : 
     607           4 :         subreq = dcerpc_drsuapi_DsBind_r_send(s, c->event_ctx,
     608             :                                               s->drsuapi.drsuapi_handle,
     609             :                                               &s->drsuapi.bind_r);
     610           4 :         if (composite_nomem(subreq, c)) return;
     611           4 :         tevent_req_set_callback(subreq, unbecomeDC_drsuapi_bind_recv, s);
     612             : }
     613             : 
     614             : static void unbecomeDC_drsuapi_remove_ds_server_send(struct libnet_UnbecomeDC_state *s);
     615             : 
     616           4 : static void unbecomeDC_drsuapi_bind_recv(struct tevent_req *subreq)
     617             : {
     618           4 :         struct libnet_UnbecomeDC_state *s = tevent_req_callback_data(subreq,
     619             :                                             struct libnet_UnbecomeDC_state);
     620           4 :         struct composite_context *c = s->creq;
     621             : 
     622           4 :         c->status = dcerpc_drsuapi_DsBind_r_recv(subreq, s);
     623           4 :         TALLOC_FREE(subreq);
     624           4 :         if (!composite_is_ok(c)) return;
     625             : 
     626           4 :         if (!W_ERROR_IS_OK(s->drsuapi.bind_r.out.result)) {
     627           0 :                 composite_error(c, werror_to_ntstatus(s->drsuapi.bind_r.out.result));
     628           0 :                 return;
     629             :         }
     630             : 
     631           4 :         ZERO_STRUCT(s->drsuapi.remote_info28);
     632           4 :         if (s->drsuapi.bind_r.out.bind_info) {
     633           4 :                 switch (s->drsuapi.bind_r.out.bind_info->length) {
     634           0 :                 case 24: {
     635           0 :                         struct drsuapi_DsBindInfo24 *info24;
     636           0 :                         info24 = &s->drsuapi.bind_r.out.bind_info->info.info24;
     637           0 :                         s->drsuapi.remote_info28.supported_extensions        = info24->supported_extensions;
     638           0 :                         s->drsuapi.remote_info28.site_guid           = info24->site_guid;
     639           0 :                         s->drsuapi.remote_info28.pid                 = info24->pid;
     640           0 :                         s->drsuapi.remote_info28.repl_epoch          = 0;
     641           0 :                         break;
     642             :                 }
     643           4 :                 case 28: {
     644           4 :                         s->drsuapi.remote_info28 = s->drsuapi.bind_r.out.bind_info->info.info28;
     645           4 :                         break;
     646             :                 }
     647           0 :                 case 32: {
     648           0 :                         struct drsuapi_DsBindInfo32 *info32;
     649           0 :                         info32 = &s->drsuapi.bind_r.out.bind_info->info.info32;
     650           0 :                         s->drsuapi.remote_info28.supported_extensions        = info32->supported_extensions;
     651           0 :                         s->drsuapi.remote_info28.site_guid           = info32->site_guid;
     652           0 :                         s->drsuapi.remote_info28.pid                 = info32->pid;
     653           0 :                         s->drsuapi.remote_info28.repl_epoch          = info32->repl_epoch;
     654           0 :                         break;
     655             :                 }
     656           0 :                 case 48: {
     657           0 :                         struct drsuapi_DsBindInfo48 *info48;
     658           0 :                         info48 = &s->drsuapi.bind_r.out.bind_info->info.info48;
     659           0 :                         s->drsuapi.remote_info28.supported_extensions        = info48->supported_extensions;
     660           0 :                         s->drsuapi.remote_info28.site_guid           = info48->site_guid;
     661           0 :                         s->drsuapi.remote_info28.pid                 = info48->pid;
     662           0 :                         s->drsuapi.remote_info28.repl_epoch          = info48->repl_epoch;
     663           0 :                         break;
     664             :                 }
     665           0 :                 case 52: {
     666           0 :                         struct drsuapi_DsBindInfo52 *info52;
     667           0 :                         info52 = &s->drsuapi.bind_r.out.bind_info->info.info52;
     668           0 :                         s->drsuapi.remote_info28.supported_extensions        = info52->supported_extensions;
     669           0 :                         s->drsuapi.remote_info28.site_guid           = info52->site_guid;
     670           0 :                         s->drsuapi.remote_info28.pid                 = info52->pid;
     671           0 :                         s->drsuapi.remote_info28.repl_epoch          = info52->repl_epoch;
     672           0 :                         break;
     673             :                 }
     674           0 :                 default:
     675           0 :                         DEBUG(1, ("Warning: invalid info length in bind info: %d\n",
     676             :                                 s->drsuapi.bind_r.out.bind_info->length));
     677           0 :                         break;
     678             :                 }
     679             :         }
     680             : 
     681           4 :         unbecomeDC_drsuapi_remove_ds_server_send(s);
     682             : }
     683             : 
     684             : static void unbecomeDC_drsuapi_remove_ds_server_recv(struct tevent_req *subreq);
     685             : 
     686           4 : static void unbecomeDC_drsuapi_remove_ds_server_send(struct libnet_UnbecomeDC_state *s)
     687             : {
     688           4 :         struct composite_context *c = s->creq;
     689           4 :         struct drsuapi_DsRemoveDSServer *r = &s->drsuapi.rm_ds_srv_r;
     690           0 :         struct tevent_req *subreq;
     691             : 
     692           4 :         r->in.bind_handle    = &s->drsuapi.bind_handle;
     693           4 :         r->in.level          = 1;
     694           4 :         r->in.req            = talloc(s, union drsuapi_DsRemoveDSServerRequest);
     695           4 :         r->in.req->req1.server_dn = s->dest_dsa.server_dn_str;
     696           4 :         r->in.req->req1.domain_dn = s->domain.dn_str;
     697           4 :         r->in.req->req1.commit    = true;
     698             : 
     699           4 :         r->out.level_out     = talloc(s, uint32_t);
     700           4 :         r->out.res           = talloc(s, union drsuapi_DsRemoveDSServerResult);
     701             : 
     702           4 :         subreq = dcerpc_drsuapi_DsRemoveDSServer_r_send(s, c->event_ctx,
     703             :                                                         s->drsuapi.drsuapi_handle,
     704             :                                                         r);
     705           4 :         if (composite_nomem(subreq, c)) return;
     706           4 :         tevent_req_set_callback(subreq, unbecomeDC_drsuapi_remove_ds_server_recv, s);
     707             : }
     708             : 
     709           4 : static void unbecomeDC_drsuapi_remove_ds_server_recv(struct tevent_req *subreq)
     710             : {
     711           4 :         struct libnet_UnbecomeDC_state *s = tevent_req_callback_data(subreq,
     712             :                                             struct libnet_UnbecomeDC_state);
     713           4 :         struct composite_context *c = s->creq;
     714           4 :         struct drsuapi_DsRemoveDSServer *r = &s->drsuapi.rm_ds_srv_r;
     715             : 
     716           4 :         c->status = dcerpc_drsuapi_DsRemoveDSServer_r_recv(subreq, s);
     717           4 :         TALLOC_FREE(subreq);
     718           4 :         if (!composite_is_ok(c)) return;
     719             : 
     720           4 :         if (!W_ERROR_IS_OK(r->out.result)) {
     721           0 :                 composite_error(c, werror_to_ntstatus(r->out.result));
     722           0 :                 return;
     723             :         }
     724             : 
     725           4 :         if (*r->out.level_out != 1) {
     726           0 :                 composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
     727           0 :                 return;
     728             :         }
     729             : 
     730           4 :         composite_done(c);
     731             : }
     732             : 
     733           4 : struct composite_context *libnet_UnbecomeDC_send(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_UnbecomeDC *r)
     734             : {
     735           0 :         struct composite_context *c;
     736           0 :         struct libnet_UnbecomeDC_state *s;
     737           0 :         char *tmp_name;
     738             : 
     739           4 :         c = composite_create(mem_ctx, ctx->event_ctx);
     740           4 :         if (c == NULL) return NULL;
     741             : 
     742           4 :         s = talloc_zero(c, struct libnet_UnbecomeDC_state);
     743           4 :         if (composite_nomem(s, c)) return c;
     744           4 :         c->private_data = s;
     745           4 :         s->creq              = c;
     746           4 :         s->libnet    = ctx;
     747             : 
     748             :         /* Domain input */
     749           4 :         s->domain.dns_name   = talloc_strdup(s, r->in.domain_dns_name);
     750           4 :         if (composite_nomem(s->domain.dns_name, c)) return c;
     751           4 :         s->domain.netbios_name       = talloc_strdup(s, r->in.domain_netbios_name);
     752           4 :         if (composite_nomem(s->domain.netbios_name, c)) return c;
     753             : 
     754             :         /* Source DSA input */
     755           4 :         s->source_dsa.address        = talloc_strdup(s, r->in.source_dsa_address);
     756           4 :         if (composite_nomem(s->source_dsa.address, c)) return c;
     757             : 
     758             :         /* Destination DSA input */
     759           4 :         s->dest_dsa.netbios_name= talloc_strdup(s, r->in.dest_dsa_netbios_name);
     760           4 :         if (composite_nomem(s->dest_dsa.netbios_name, c)) return c;
     761             : 
     762             :         /* Destination DSA dns_name construction */
     763           4 :         tmp_name                = strlower_talloc(s, s->dest_dsa.netbios_name);
     764           4 :         if (composite_nomem(tmp_name, c)) return c;
     765           4 :         s->dest_dsa.dns_name = talloc_asprintf_append_buffer(tmp_name, ".%s",
     766             :                                                          s->domain.dns_name);
     767           4 :         if (composite_nomem(s->dest_dsa.dns_name, c)) return c;
     768             : 
     769           4 :         unbecomeDC_send_cldap(s);
     770           4 :         return c;
     771             : }
     772             : 
     773           4 : NTSTATUS libnet_UnbecomeDC_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, struct libnet_UnbecomeDC *r)
     774             : {
     775           0 :         NTSTATUS status;
     776             : 
     777           4 :         status = composite_wait(c);
     778             : 
     779           4 :         ZERO_STRUCT(r->out);
     780             : 
     781           4 :         talloc_free(c);
     782           4 :         return status;
     783             : }
     784             : 
     785           4 : NTSTATUS libnet_UnbecomeDC(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_UnbecomeDC *r)
     786             : {
     787           0 :         NTSTATUS status;
     788           0 :         struct composite_context *c;
     789           4 :         c = libnet_UnbecomeDC_send(ctx, mem_ctx, r);
     790           4 :         status = libnet_UnbecomeDC_recv(c, mem_ctx, r);
     791           4 :         return status;
     792             : }

Generated by: LCOV version 1.14