s4-loadparm: 2nd half of lp_ to lpcfg_ conversion
[samba.git] / source4 / libnet / libnet_unbecome_dc.c
index da7ae5e1e7131d816ea1bad1aa67f3b4930bd0b8..cf0142da8625caa7b80d3f6e4694a7fef0a3f12a 100644 (file)
@@ -5,7 +5,7 @@
 
    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 2 of the License, or
+   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,
@@ -14,8 +14,7 @@
    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, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "libcli/cldap/cldap.h"
 #include "lib/ldb/include/ldb.h"
 #include "lib/ldb/include/ldb_errors.h"
-#include "lib/db_wrap.h"
+#include "ldb_wrap.h"
 #include "dsdb/samdb/samdb.h"
-#include "dsdb/common/flags.h"
+#include "../libds/common/flags.h"
 #include "librpc/gen_ndr/ndr_drsuapi_c.h"
+#include "param/param.h"
+#include "lib/tsocket/tsocket.h"
 
 /*****************************************************************************
  * Windows 2003 (w2k3) does the following steps when changing the server role
@@ -193,7 +194,7 @@ struct libnet_UnbecomeDC_state {
        struct {
                struct cldap_socket *sock;
                struct cldap_netlogon io;
-               struct nbt_cldap_netlogon_5 netlogon5;
+               struct NETLOGON_SAM_LOGON_RESPONSE_EX netlogon;
        } cldap;
 
        struct {
@@ -203,6 +204,7 @@ struct libnet_UnbecomeDC_state {
        struct {
                struct dcerpc_binding *binding;
                struct dcerpc_pipe *pipe;
+               struct dcerpc_binding_handle *drsuapi_handle;
                struct drsuapi_DsBind bind_r;
                struct GUID bind_guid;
                struct drsuapi_DsBindInfoCtr bind_info_ctr;
@@ -250,53 +252,67 @@ struct libnet_UnbecomeDC_state {
        } dest_dsa;
 };
 
-static void unbecomeDC_recv_cldap(struct cldap_request *req);
+static void unbecomeDC_recv_cldap(struct tevent_req *req);
 
 static void unbecomeDC_send_cldap(struct libnet_UnbecomeDC_state *s)
 {
        struct composite_context *c = s->creq;
-       struct cldap_request *req;
+       struct tevent_req *req;
+       struct tsocket_address *dest_address;
+       int ret;
 
-       s->cldap.io.in.dest_address     = s->source_dsa.address;
+       s->cldap.io.in.dest_address     = NULL;
+       s->cldap.io.in.dest_port        = 0;
        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          = 6;
+       s->cldap.io.in.version          = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
+       s->cldap.io.in.map_response     = true;
+
+       ret = tsocket_address_inet_from_strings(s, "ip",
+                                               s->source_dsa.address,
+                                               lpcfg_cldap_port(s->libnet->lp_ctx),
+                                               &dest_address);
+       if (ret != 0) {
+               c->status = map_nt_error_from_unix(errno);
+               if (!composite_is_ok(c)) return;
+       }
 
-       s->cldap.sock = cldap_socket_init(s, s->libnet->event_ctx);
-       if (composite_nomem(s->cldap.sock, c)) return;
+       c->status = cldap_socket_init(s, s->libnet->event_ctx,
+                                     NULL, dest_address, &s->cldap.sock);
+       if (!composite_is_ok(c)) return;
 
-       req = cldap_netlogon_send(s->cldap.sock, &s->cldap.io);
+       req = cldap_netlogon_send(s, s->cldap.sock, &s->cldap.io);
        if (composite_nomem(req, c)) return;
-       req->async.fn           = unbecomeDC_recv_cldap;
-       req->async.private      = s;
+       tevent_req_set_callback(req, unbecomeDC_recv_cldap, s);
 }
 
 static void unbecomeDC_connect_ldap(struct libnet_UnbecomeDC_state *s);
 
-static void unbecomeDC_recv_cldap(struct cldap_request *req)
+static void unbecomeDC_recv_cldap(struct tevent_req *req)
 {
-       struct libnet_UnbecomeDC_state *s = talloc_get_type(req->async.private,
+       struct libnet_UnbecomeDC_state *s = tevent_req_callback_data(req,
                                            struct libnet_UnbecomeDC_state);
        struct composite_context *c = s->creq;
 
        c->status = cldap_netlogon_recv(req, s, &s->cldap.io);
+       talloc_free(req);
        if (!composite_is_ok(c)) return;
 
-       s->cldap.netlogon5 = s->cldap.io.out.netlogon.logon5;
+       s->cldap.netlogon = s->cldap.io.out.netlogon.data.nt5_ex;
 
-       s->domain.dns_name              = s->cldap.netlogon5.dns_domain;
-       s->domain.netbios_name          = s->cldap.netlogon5.domain;
-       s->domain.guid                  = s->cldap.netlogon5.domain_uuid;
+       s->domain.dns_name              = s->cldap.netlogon.dns_domain;
+       s->domain.netbios_name          = s->cldap.netlogon.domain_name;
+       s->domain.guid                  = s->cldap.netlogon.domain_uuid;
 
-       s->source_dsa.dns_name          = s->cldap.netlogon5.pdc_dns_name;
-       s->source_dsa.netbios_name      = s->cldap.netlogon5.pdc_name;
-       s->source_dsa.site_name         = s->cldap.netlogon5.server_site;
+       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.netlogon5.client_site;
+       s->dest_dsa.site_name           = s->cldap.netlogon.client_site;
 
        unbecomeDC_connect_ldap(s);
 }
@@ -308,10 +324,10 @@ static NTSTATUS unbecomeDC_ldap_connect(struct libnet_UnbecomeDC_state *s)
        url = talloc_asprintf(s, "ldap://%s/", s->source_dsa.dns_name);
        NT_STATUS_HAVE_NO_MEMORY(url);
 
-       s->ldap.ldb = ldb_wrap_connect(s, url,
+       s->ldap.ldb = ldb_wrap_connect(s, s->libnet->event_ctx, s->libnet->lp_ctx, url,
                                       NULL,
                                       s->libnet->cred,
-                                      0, NULL);
+                                      0);
        talloc_free(url);
        if (s->ldap.ldb == NULL) {
                return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
@@ -334,8 +350,8 @@ static NTSTATUS unbecomeDC_ldap_rootdse(struct libnet_UnbecomeDC_state *s)
        basedn = ldb_dn_new(s, s->ldap.ldb, NULL);
        NT_STATUS_HAVE_NO_MEMORY(basedn);
 
-       ret = ldb_search(s->ldap.ldb, basedn, LDB_SCOPE_BASE, 
-                        "(objectClass=*)", attrs, &r);
+       ret = ldb_search(s->ldap.ldb, s, &r, basedn, LDB_SCOPE_BASE, attrs,
+                        "(objectClass=*)");
        talloc_free(basedn);
        if (ret != LDB_SUCCESS) {
                return NT_STATUS_LDAP(ret);
@@ -343,7 +359,6 @@ static NTSTATUS unbecomeDC_ldap_rootdse(struct libnet_UnbecomeDC_state *s)
                talloc_free(r);
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
        }
-       talloc_steal(s, r);
 
        s->domain.dn_str        = ldb_msg_find_attr_as_string(r->msgs[0], "defaultNamingContext", NULL);
        if (!s->domain.dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
@@ -368,7 +383,6 @@ static NTSTATUS unbecomeDC_ldap_computer_object(struct libnet_UnbecomeDC_state *
        int ret;
        struct ldb_result *r;
        struct ldb_dn *basedn;
-       char *filter;
        static const char *attrs[] = {
                "distinguishedName",
                "userAccountControl",
@@ -378,12 +392,9 @@ static NTSTATUS unbecomeDC_ldap_computer_object(struct libnet_UnbecomeDC_state *
        basedn = ldb_dn_new(s, s->ldap.ldb, s->domain.dn_str);
        NT_STATUS_HAVE_NO_MEMORY(basedn);
 
-       filter = talloc_asprintf(basedn, "(&(|(objectClass=user)(objectClass=computer))(sAMAccountName=%s$))",
-                                s->dest_dsa.netbios_name);
-       NT_STATUS_HAVE_NO_MEMORY(filter);
-
-       ret = ldb_search(s->ldap.ldb, basedn, LDB_SCOPE_SUBTREE, 
-                        filter, attrs, &r);
+       ret = ldb_search(s->ldap.ldb, s, &r, basedn, LDB_SCOPE_SUBTREE, attrs,
+                        "(&(|(objectClass=user)(objectClass=computer))(sAMAccountName=%s$))",
+                        s->dest_dsa.netbios_name);
        talloc_free(basedn);
        if (ret != LDB_SUCCESS) {
                return NT_STATUS_LDAP(ret);
@@ -407,7 +418,7 @@ static NTSTATUS unbecomeDC_ldap_modify_computer(struct libnet_UnbecomeDC_state *
        int ret;
        struct ldb_message *msg;
        uint32_t user_account_control = UF_WORKSTATION_TRUST_ACCOUNT;
-       uint32_t i;
+       unsigned int i;
 
        /* as the value is already as we want it to be, we're done */
        if (s->dest_dsa.user_account_control == user_account_control) {
@@ -459,8 +470,8 @@ static NTSTATUS unbecomeDC_ldap_move_computer(struct libnet_UnbecomeDC_state *s)
                                s->domain.dn_str);
        NT_STATUS_HAVE_NO_MEMORY(basedn);
 
-       ret = ldb_search(s->ldap.ldb, basedn, LDB_SCOPE_BASE,
-                        "(objectClass=*)", _1_1_attrs, &r);
+       ret = ldb_search(s->ldap.ldb, s, &r, basedn, LDB_SCOPE_BASE,
+                        _1_1_attrs, "(objectClass=*)");
        talloc_free(basedn);
        if (ret != LDB_SUCCESS) {
                return NT_STATUS_LDAP(ret);
@@ -538,8 +549,9 @@ static void unbecomeDC_drsuapi_connect_send(struct libnet_UnbecomeDC_state *s)
        talloc_free(binding_str);
        if (!composite_is_ok(c)) return;
 
-       creq = dcerpc_pipe_connect_b_send(s, s->drsuapi.binding, &dcerpc_table_drsuapi,
-                                         s->libnet->cred, s->libnet->event_ctx);
+       creq = dcerpc_pipe_connect_b_send(s, s->drsuapi.binding, &ndr_table_drsuapi,
+                                         s->libnet->cred, s->libnet->event_ctx,
+                                         s->libnet->lp_ctx);
        composite_continue(c, creq, unbecomeDC_drsuapi_connect_recv, s);
 }
 
@@ -554,23 +566,25 @@ static void unbecomeDC_drsuapi_connect_recv(struct composite_context *req)
        c->status = dcerpc_pipe_connect_b_recv(req, s, &s->drsuapi.pipe);
        if (!composite_is_ok(c)) return;
 
+       s->drsuapi.drsuapi_handle = s->drsuapi.pipe->binding_handle;
+
        unbecomeDC_drsuapi_bind_send(s);
 }
 
-static void unbecomeDC_drsuapi_bind_recv(struct rpc_request *req);
+static void unbecomeDC_drsuapi_bind_recv(struct tevent_req *subreq);
 
 static void unbecomeDC_drsuapi_bind_send(struct libnet_UnbecomeDC_state *s)
 {
        struct composite_context *c = s->creq;
-       struct rpc_request *req;
        struct drsuapi_DsBindInfo28 *bind_info28;
+       struct tevent_req *subreq;
 
        GUID_from_string(DRSUAPI_DS_BIND_GUID, &s->drsuapi.bind_guid);
 
        bind_info28                             = &s->drsuapi.local_info28;
        bind_info28->supported_extensions       = 0;
        bind_info28->site_guid                  = GUID_zero();
-       bind_info28->u1                         = 508;
+       bind_info28->pid                        = 0;
        bind_info28->repl_epoch                 = 0;
 
        s->drsuapi.bind_info_ctr.length         = 28;
@@ -580,19 +594,23 @@ static void unbecomeDC_drsuapi_bind_send(struct libnet_UnbecomeDC_state *s)
        s->drsuapi.bind_r.in.bind_info = &s->drsuapi.bind_info_ctr;
        s->drsuapi.bind_r.out.bind_handle = &s->drsuapi.bind_handle;
 
-       req = dcerpc_drsuapi_DsBind_send(s->drsuapi.pipe, s, &s->drsuapi.bind_r);
-       composite_continue_rpc(c, req, unbecomeDC_drsuapi_bind_recv, s);
+       subreq = dcerpc_drsuapi_DsBind_r_send(s, c->event_ctx,
+                                             s->drsuapi.drsuapi_handle,
+                                             &s->drsuapi.bind_r);
+       if (composite_nomem(subreq, c)) return;
+       tevent_req_set_callback(subreq, unbecomeDC_drsuapi_bind_recv, s);
 }
 
 static void unbecomeDC_drsuapi_remove_ds_server_send(struct libnet_UnbecomeDC_state *s);
 
-static void unbecomeDC_drsuapi_bind_recv(struct rpc_request *req)
+static void unbecomeDC_drsuapi_bind_recv(struct tevent_req *subreq)
 {
-       struct libnet_UnbecomeDC_state *s = talloc_get_type(req->async.private,
+       struct libnet_UnbecomeDC_state *s = tevent_req_callback_data(subreq,
                                            struct libnet_UnbecomeDC_state);
        struct composite_context *c = s->creq;
 
-       c->status = dcerpc_ndr_request_recv(req);
+       c->status = dcerpc_drsuapi_DsBind_r_recv(subreq, s);
+       TALLOC_FREE(subreq);
        if (!composite_is_ok(c)) return;
 
        if (!W_ERROR_IS_OK(s->drsuapi.bind_r.out.result)) {
@@ -608,10 +626,19 @@ static void unbecomeDC_drsuapi_bind_recv(struct rpc_request *req)
                        info24 = &s->drsuapi.bind_r.out.bind_info->info.info24;
                        s->drsuapi.remote_info28.supported_extensions   = info24->supported_extensions;
                        s->drsuapi.remote_info28.site_guid              = info24->site_guid;
-                       s->drsuapi.remote_info28.u1                     = info24->u1;
+                       s->drsuapi.remote_info28.pid                    = info24->pid;
                        s->drsuapi.remote_info28.repl_epoch             = 0;
                        break;
                }
+               case 48: {
+                       struct drsuapi_DsBindInfo48 *info48;
+                       info48 = &s->drsuapi.bind_r.out.bind_info->info.info48;
+                       s->drsuapi.remote_info28.supported_extensions   = info48->supported_extensions;
+                       s->drsuapi.remote_info28.site_guid              = info48->site_guid;
+                       s->drsuapi.remote_info28.pid                    = info48->pid;
+                       s->drsuapi.remote_info28.repl_epoch             = info48->repl_epoch;
+                       break;
+               }
                case 28:
                        s->drsuapi.remote_info28 = s->drsuapi.bind_r.out.bind_info->info.info28;
                        break;
@@ -621,32 +648,40 @@ static void unbecomeDC_drsuapi_bind_recv(struct rpc_request *req)
        unbecomeDC_drsuapi_remove_ds_server_send(s);
 }
 
-static void unbecomeDC_drsuapi_remove_ds_server_recv(struct rpc_request *req);
+static void unbecomeDC_drsuapi_remove_ds_server_recv(struct tevent_req *subreq);
 
 static void unbecomeDC_drsuapi_remove_ds_server_send(struct libnet_UnbecomeDC_state *s)
 {
        struct composite_context *c = s->creq;
-       struct rpc_request *req;
        struct drsuapi_DsRemoveDSServer *r = &s->drsuapi.rm_ds_srv_r;
+       struct tevent_req *subreq;
 
        r->in.bind_handle       = &s->drsuapi.bind_handle;
        r->in.level             = 1;
-       r->in.req.req1.server_dn= s->dest_dsa.server_dn_str;
-       r->in.req.req1.domain_dn= s->domain.dn_str;
-       r->in.req.req1.unknown  = 0x00000001;
-
-       req = dcerpc_drsuapi_DsRemoveDSServer_send(s->drsuapi.pipe, s, r);
-       composite_continue_rpc(c, req, unbecomeDC_drsuapi_remove_ds_server_recv, s);
+       r->in.req               = talloc(s, union drsuapi_DsRemoveDSServerRequest);
+       r->in.req->req1.server_dn = s->dest_dsa.server_dn_str;
+       r->in.req->req1.domain_dn = s->domain.dn_str;
+       r->in.req->req1.commit  = true;
+
+       r->out.level_out        = talloc(s, uint32_t);
+       r->out.res              = talloc(s, union drsuapi_DsRemoveDSServerResult);
+
+       subreq = dcerpc_drsuapi_DsRemoveDSServer_r_send(s, c->event_ctx,
+                                                       s->drsuapi.drsuapi_handle,
+                                                       r);
+       if (composite_nomem(subreq, c)) return;
+       tevent_req_set_callback(subreq, unbecomeDC_drsuapi_remove_ds_server_recv, s);
 }
 
-static void unbecomeDC_drsuapi_remove_ds_server_recv(struct rpc_request *req)
+static void unbecomeDC_drsuapi_remove_ds_server_recv(struct tevent_req *subreq)
 {
-       struct libnet_UnbecomeDC_state *s = talloc_get_type(req->async.private,
+       struct libnet_UnbecomeDC_state *s = tevent_req_callback_data(subreq,
                                            struct libnet_UnbecomeDC_state);
        struct composite_context *c = s->creq;
        struct drsuapi_DsRemoveDSServer *r = &s->drsuapi.rm_ds_srv_r;
 
-       c->status = dcerpc_ndr_request_recv(req);
+       c->status = dcerpc_drsuapi_DsRemoveDSServer_r_recv(subreq, s);
+       TALLOC_FREE(subreq);
        if (!composite_is_ok(c)) return;
 
        if (!W_ERROR_IS_OK(r->out.result)) {
@@ -654,15 +689,10 @@ static void unbecomeDC_drsuapi_remove_ds_server_recv(struct rpc_request *req)
                return;
        }
 
-       if (r->out.level != 1) {
+       if (*r->out.level_out != 1) {
                composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
                return;
        }
-               
-       if (!W_ERROR_IS_OK(r->out.res.res1.status)) {
-               composite_error(c, werror_to_ntstatus(r->out.res.res1.status));
-               return;
-       }
 
        composite_done(c);
 }
@@ -699,7 +729,7 @@ struct composite_context *libnet_UnbecomeDC_send(struct libnet_context *ctx, TAL
        /* Destination DSA dns_name construction */
        tmp_name                = strlower_talloc(s, s->dest_dsa.netbios_name);
        if (composite_nomem(tmp_name, c)) return c;
-       s->dest_dsa.dns_name    = talloc_asprintf_append(tmp_name, ".%s",
+       s->dest_dsa.dns_name    = talloc_asprintf_append_buffer(tmp_name, ".%s",
                                                         s->domain.dns_name);
        if (composite_nomem(s->dest_dsa.dns_name, c)) return c;