root/source4/libnet/libnet_unbecome_dc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. unbecomeDC_send_cldap
  2. unbecomeDC_recv_cldap
  3. unbecomeDC_ldap_connect
  4. unbecomeDC_ldap_rootdse
  5. unbecomeDC_ldap_computer_object
  6. unbecomeDC_ldap_modify_computer
  7. unbecomeDC_ldap_move_computer
  8. unbecomeDC_connect_ldap
  9. unbecomeDC_drsuapi_connect_send
  10. unbecomeDC_drsuapi_connect_recv
  11. unbecomeDC_drsuapi_bind_send
  12. unbecomeDC_drsuapi_bind_recv
  13. unbecomeDC_drsuapi_remove_ds_server_send
  14. unbecomeDC_drsuapi_remove_ds_server_recv
  15. libnet_UnbecomeDC_send
  16. libnet_UnbecomeDC_recv
  17. libnet_UnbecomeDC

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

/* [<][>][^][v][top][bottom][index][help] */