summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/libnet/config.mk1
-rw-r--r--source4/libnet/libnet.h1
-rw-r--r--source4/libnet/libnet_unbecome_dc.c260
-rw-r--r--source4/libnet/libnet_unbecome_dc.h32
4 files changed, 294 insertions, 0 deletions
diff --git a/source4/libnet/config.mk b/source4/libnet/config.mk
index 2402974a82..77b3876375 100644
--- a/source4/libnet/config.mk
+++ b/source4/libnet/config.mk
@@ -15,6 +15,7 @@ OBJ_FILES = \
libnet_join.o \
libnet_site.o \
libnet_become_dc.o \
+ libnet_unbecome_dc.o \
libnet_vampire.o \
libnet_samdump.o \
libnet_samdump_keytab.o \
diff --git a/source4/libnet/libnet.h b/source4/libnet/libnet.h
index 7f5ac96b30..b3660af702 100644
--- a/source4/libnet/libnet.h
+++ b/source4/libnet/libnet.h
@@ -59,6 +59,7 @@ struct libnet_context {
#include "libnet/libnet_join.h"
#include "libnet/libnet_site.h"
#include "libnet/libnet_become_dc.h"
+#include "libnet/libnet_unbecome_dc.h"
#include "libnet/libnet_vampire.h"
#include "libnet/libnet_user.h"
#include "libnet/libnet_share.h"
diff --git a/source4/libnet/libnet_unbecome_dc.c b/source4/libnet/libnet_unbecome_dc.c
new file mode 100644
index 0000000000..4e12ca7c8d
--- /dev/null
+++ b/source4/libnet/libnet_unbecome_dc.c
@@ -0,0 +1,260 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Stefan Metzmacher 2006
+
+ 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
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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.
+*/
+
+#include "includes.h"
+#include "libnet/libnet.h"
+#include "libcli/composite/composite.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 "dsdb/samdb/samdb.h"
+
+struct libnet_UnbecomeDC_state {
+ struct composite_context *creq;
+
+ struct libnet_context *libnet;
+
+ struct {
+ struct cldap_socket *sock;
+ struct cldap_netlogon io;
+ struct nbt_cldap_netlogon_5 netlogon5;
+ } cldap;
+
+ struct {
+ struct ldb_context *ldb;
+ } ldap;
+
+ struct {
+ /* input */
+ const char *dns_name;
+ const char *netbios_name;
+
+ /* constructed */
+ struct GUID guid;
+ const char *dn_str;
+ } domain;
+
+ struct {
+ /* constructed */
+ const char *config_dn_str;
+ } forest;
+
+ struct {
+ /* input */
+ const char *address;
+
+ /* constructed */
+ const char *dns_name;
+ const char *netbios_name;
+ const char *site_name;
+ } source_dsa;
+
+ struct {
+ /* input */
+ const char *netbios_name;
+
+ /* constructed */
+ const char *dns_name;
+ const char *site_name;
+ const char *computer_dn_str;
+ const char *server_dn_str;
+ uint32_t user_account_control;
+ } dest_dsa;
+};
+
+static void unbecomeDC_connect_ldap(struct libnet_UnbecomeDC_state *s);
+
+static void unbecomeDC_recv_cldap(struct cldap_request *req)
+{
+ struct libnet_UnbecomeDC_state *s = talloc_get_type(req->async.private,
+ struct libnet_UnbecomeDC_state);
+ struct composite_context *c = s->creq;
+
+ c->status = cldap_netlogon_recv(req, s, &s->cldap.io);
+ if (!composite_is_ok(c)) return;
+
+ s->cldap.netlogon5 = s->cldap.io.out.netlogon.logon5;
+
+ 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->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->dest_dsa.site_name = s->cldap.netlogon5.client_site;
+
+ unbecomeDC_connect_ldap(s);
+}
+
+static void unbecomeDC_send_cldap(struct libnet_UnbecomeDC_state *s)
+{
+ struct composite_context *c = s->creq;
+ struct cldap_request *req;
+
+ s->cldap.io.in.dest_address = s->source_dsa.address;
+ s->cldap.io.in.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.sock = cldap_socket_init(s, s->libnet->event_ctx);
+ if (composite_nomem(s->cldap.sock, c)) return;
+
+ req = cldap_netlogon_send(s->cldap.sock, &s->cldap.io);
+ if (composite_nomem(req, c)) return;
+ req->async.fn = unbecomeDC_recv_cldap;
+ req->async.private = s;
+}
+
+static NTSTATUS unbecomeDC_ldap_connect(struct libnet_UnbecomeDC_state *s)
+{
+ char *url;
+
+ 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,
+ NULL,
+ s->libnet->cred,
+ 0, NULL);
+ talloc_free(url);
+ if (s->ldap.ldb == NULL) {
+ return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS unbecomeDC_ldap_rootdse(struct libnet_UnbecomeDC_state *s)
+{
+ int ret;
+ struct ldb_result *r;
+ struct ldb_dn *basedn;
+ static const char *attrs[] = {
+ "defaultNamingContext",
+ "configurationNamingContext",
+ NULL
+ };
+
+ 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);
+ talloc_free(basedn);
+ if (ret != LDB_SUCCESS) {
+ return NT_STATUS_LDAP(ret);
+ } else if (r->count != 1) {
+ talloc_free(r);
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+ talloc_steal(s, r);
+
+ s->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;
+ talloc_steal(s, s->domain.dn_str);
+
+ s->forest.config_dn_str = ldb_msg_find_attr_as_string(r->msgs[0], "configurationNamingContext", NULL);
+ if (!s->forest.config_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ talloc_steal(s, s->forest.config_dn_str);
+
+ talloc_free(r);
+ return NT_STATUS_OK;
+}
+
+static void unbecomeDC_connect_ldap(struct libnet_UnbecomeDC_state *s)
+{
+ struct composite_context *c = s->creq;
+
+ c->status = unbecomeDC_ldap_connect(s);
+ if (!composite_is_ok(c)) return;
+
+ c->status = unbecomeDC_ldap_rootdse(s);
+ if (!composite_is_ok(c)) return;
+
+ composite_error(c, NT_STATUS_NOT_IMPLEMENTED);
+}
+
+struct composite_context *libnet_UnbecomeDC_send(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_UnbecomeDC *r)
+{
+ struct composite_context *c;
+ struct libnet_UnbecomeDC_state *s;
+ char *tmp_name;
+
+ c = composite_create(mem_ctx, ctx->event_ctx);
+ if (c == NULL) return NULL;
+
+ s = talloc_zero(c, struct libnet_UnbecomeDC_state);
+ if (composite_nomem(s, c)) return c;
+ c->private_data = s;
+ s->creq = c;
+ s->libnet = ctx;
+
+ /* Domain input */
+ s->domain.dns_name = talloc_strdup(s, r->in.domain_dns_name);
+ if (composite_nomem(s->domain.dns_name, c)) return c;
+ s->domain.netbios_name = talloc_strdup(s, r->in.domain_netbios_name);
+ if (composite_nomem(s->domain.netbios_name, c)) return c;
+
+ /* Source DSA input */
+ s->source_dsa.address = talloc_strdup(s, r->in.source_dsa_address);
+ if (composite_nomem(s->source_dsa.address, c)) return c;
+
+ /* Destination DSA input */
+ s->dest_dsa.netbios_name= talloc_strdup(s, r->in.dest_dsa_netbios_name);
+ if (composite_nomem(s->dest_dsa.netbios_name, c)) return 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->domain.dns_name);
+ if (composite_nomem(s->dest_dsa.dns_name, c)) return c;
+
+ unbecomeDC_send_cldap(s);
+ return c;
+}
+
+NTSTATUS libnet_UnbecomeDC_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, struct libnet_UnbecomeDC *r)
+{
+ NTSTATUS status;
+
+ status = composite_wait(c);
+
+ ZERO_STRUCT(r->out);
+
+ talloc_free(c);
+ return status;
+}
+
+NTSTATUS libnet_UnbecomeDC(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_UnbecomeDC *r)
+{
+ NTSTATUS status;
+ struct composite_context *c;
+ c = libnet_UnbecomeDC_send(ctx, mem_ctx, r);
+ status = libnet_UnbecomeDC_recv(c, mem_ctx, r);
+ return status;
+}
diff --git a/source4/libnet/libnet_unbecome_dc.h b/source4/libnet/libnet_unbecome_dc.h
new file mode 100644
index 0000000000..b7011c03db
--- /dev/null
+++ b/source4/libnet/libnet_unbecome_dc.h
@@ -0,0 +1,32 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Stefan Metzmacher 2006
+
+ 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
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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.
+*/
+
+struct libnet_UnbecomeDC {
+ struct {
+ const char *domain_dns_name;
+ const char *domain_netbios_name;
+ const char *source_dsa_address;
+ const char *dest_dsa_netbios_name;
+ } in;
+
+ struct {
+ const char *error_string;
+ } out;
+};