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,
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
struct {
struct cldap_socket *sock;
struct cldap_netlogon io;
- struct nbt_cldap_netlogon_5 netlogon5;
+ struct NETLOGON_SAM_LOGON_RESPONSE_EX netlogon;
} cldap;
struct {
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;
} 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);
}
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;
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);
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;
int ret;
struct ldb_result *r;
struct ldb_dn *basedn;
- char *filter;
static const char *attrs[] = {
"distinguishedName",
"userAccountControl",
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);
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) {
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);
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);
}
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;
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)) {
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;
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)) {
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);
}
/* 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;