• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source4/dsdb/repl/
1/*
2   Unix SMB/CIFS mplementation.
3   DSDB replication service
4
5   Copyright (C) Stefan Metzmacher 2007
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 3 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20*/
21
22#include "includes.h"
23#include "dsdb/samdb/samdb.h"
24#include "auth/auth.h"
25#include "smbd/service.h"
26#include "lib/events/events.h"
27#include "lib/messaging/irpc.h"
28#include "dsdb/repl/drepl_service.h"
29#include "lib/ldb/include/ldb_errors.h"
30#include "../lib/util/dlinklist.h"
31#include "librpc/gen_ndr/ndr_misc.h"
32#include "librpc/gen_ndr/ndr_drsuapi.h"
33#include "librpc/gen_ndr/ndr_drsblobs.h"
34#include "param/param.h"
35
36WERROR dreplsrv_load_partitions(struct dreplsrv_service *s)
37{
38	WERROR status;
39	struct ldb_dn *basedn;
40	struct ldb_result *r;
41	struct ldb_message_element *el;
42	static const char *attrs[] = { "namingContexts", NULL };
43	uint32_t i;
44	int ret;
45
46	basedn = ldb_dn_new(s, s->samdb, NULL);
47	W_ERROR_HAVE_NO_MEMORY(basedn);
48
49	ret = ldb_search(s->samdb, s, &r, basedn, LDB_SCOPE_BASE, attrs,
50			 "(objectClass=*)");
51	talloc_free(basedn);
52	if (ret != LDB_SUCCESS) {
53		return WERR_FOOBAR;
54	} else if (r->count != 1) {
55		talloc_free(r);
56		return WERR_FOOBAR;
57	}
58
59	el = ldb_msg_find_element(r->msgs[0], "namingContexts");
60	if (!el) {
61		return WERR_FOOBAR;
62	}
63
64	for (i=0; el && i < el->num_values; i++) {
65		const char *v = (const char *)el->values[i].data;
66		struct ldb_dn *pdn;
67		struct dreplsrv_partition *p;
68
69		pdn = ldb_dn_new(s, s->samdb, v);
70		if (!ldb_dn_validate(pdn)) {
71			return WERR_FOOBAR;
72		}
73
74		p = talloc_zero(s, struct dreplsrv_partition);
75		W_ERROR_HAVE_NO_MEMORY(p);
76
77		p->dn = talloc_steal(p, pdn);
78
79		DLIST_ADD(s->partitions, p);
80
81		DEBUG(2, ("dreplsrv_partition[%s] loaded\n", v));
82	}
83
84	talloc_free(r);
85
86	status = dreplsrv_refresh_partitions(s);
87	W_ERROR_NOT_OK_RETURN(status);
88
89	return WERR_OK;
90}
91
92static WERROR dreplsrv_out_connection_attach(struct dreplsrv_service *s,
93					     const struct repsFromTo1 *rft,
94					     struct dreplsrv_out_connection **_conn)
95{
96	struct dreplsrv_out_connection *cur, *conn = NULL;
97	const char *hostname;
98
99	if (!rft->other_info) {
100		return WERR_FOOBAR;
101	}
102
103	if (!rft->other_info->dns_name) {
104		return WERR_FOOBAR;
105	}
106
107	hostname = rft->other_info->dns_name;
108
109	for (cur = s->connections; cur; cur = cur->next) {
110		if (strcmp(cur->binding->host, hostname) == 0) {
111			conn = cur;
112			break;
113		}
114	}
115
116	if (!conn) {
117		NTSTATUS nt_status;
118		char *binding_str;
119
120		conn = talloc_zero(s, struct dreplsrv_out_connection);
121		W_ERROR_HAVE_NO_MEMORY(conn);
122
123		conn->service	= s;
124
125		binding_str = talloc_asprintf(conn, "ncacn_ip_tcp:%s[krb5,seal]",
126					      hostname);
127		W_ERROR_HAVE_NO_MEMORY(binding_str);
128		nt_status = dcerpc_parse_binding(conn, binding_str, &conn->binding);
129		talloc_free(binding_str);
130		if (!NT_STATUS_IS_OK(nt_status)) {
131			return ntstatus_to_werror(nt_status);
132		}
133
134		DLIST_ADD_END(s->connections, conn, struct dreplsrv_out_connection *);
135
136		DEBUG(2,("dreplsrv_out_connection_attach(%s): create\n", conn->binding->host));
137	} else {
138		DEBUG(2,("dreplsrv_out_connection_attach(%s): attach\n", conn->binding->host));
139	}
140
141	*_conn = conn;
142	return WERR_OK;
143}
144
145static WERROR dreplsrv_partition_add_source_dsa(struct dreplsrv_service *s,
146						struct dreplsrv_partition *p,
147						const struct ldb_val *val)
148{
149	WERROR status;
150	enum ndr_err_code ndr_err;
151	struct dreplsrv_partition_source_dsa *source, *s2;
152
153	source = talloc_zero(p, struct dreplsrv_partition_source_dsa);
154	W_ERROR_HAVE_NO_MEMORY(source);
155
156	ndr_err = ndr_pull_struct_blob(val, source,
157				       lp_iconv_convenience(s->task->lp_ctx), &source->_repsFromBlob,
158				       (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob);
159	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
160		NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
161		talloc_free(source);
162		return ntstatus_to_werror(nt_status);
163	}
164	/* NDR_PRINT_DEBUG(repsFromToBlob, &source->_repsFromBlob); */
165	if (source->_repsFromBlob.version != 1) {
166		talloc_free(source);
167		return WERR_DS_DRA_INTERNAL_ERROR;
168	}
169
170	source->partition	= p;
171	source->repsFrom1	= &source->_repsFromBlob.ctr.ctr1;
172
173	status = dreplsrv_out_connection_attach(s, source->repsFrom1, &source->conn);
174	W_ERROR_NOT_OK_RETURN(status);
175
176	/* remove any existing source with the same GUID */
177	for (s2=p->sources; s2; s2=s2->next) {
178		if (GUID_compare(&s2->repsFrom1->source_dsa_obj_guid,
179				 &source->repsFrom1->source_dsa_obj_guid) == 0) {
180			talloc_free(s2->repsFrom1->other_info);
181			*s2->repsFrom1 = *source->repsFrom1;
182			talloc_steal(s2, s2->repsFrom1->other_info);
183			talloc_free(source);
184			return WERR_OK;
185		}
186	}
187
188	DLIST_ADD_END(p->sources, source, struct dreplsrv_partition_source_dsa *);
189	return WERR_OK;
190}
191
192static WERROR dreplsrv_refresh_partition(struct dreplsrv_service *s,
193					 struct dreplsrv_partition *p)
194{
195	WERROR status;
196	const struct ldb_val *ouv_value;
197	struct replUpToDateVectorBlob ouv;
198	struct dom_sid *nc_sid;
199	struct ldb_message_element *orf_el = NULL;
200	struct ldb_result *r;
201	uint32_t i;
202	int ret;
203	TALLOC_CTX *mem_ctx = talloc_new(p);
204	static const char *attrs[] = {
205		"objectSid",
206		"objectGUID",
207		"replUpToDateVector",
208		"repsFrom",
209		NULL
210	};
211
212	DEBUG(2, ("dreplsrv_refresh_partition(%s)\n",
213		ldb_dn_get_linearized(p->dn)));
214
215	ret = ldb_search(s->samdb, mem_ctx, &r, p->dn, LDB_SCOPE_BASE, attrs,
216			 "(objectClass=*)");
217	if (ret != LDB_SUCCESS) {
218		talloc_free(mem_ctx);
219		return WERR_FOOBAR;
220	} else if (r->count != 1) {
221		talloc_free(mem_ctx);
222		return WERR_FOOBAR;
223	}
224
225	talloc_free(discard_const(p->nc.dn));
226	ZERO_STRUCT(p->nc);
227	p->nc.dn	= ldb_dn_alloc_linearized(p, p->dn);
228	W_ERROR_HAVE_NO_MEMORY(p->nc.dn);
229	p->nc.guid	= samdb_result_guid(r->msgs[0], "objectGUID");
230	nc_sid		= samdb_result_dom_sid(p, r->msgs[0], "objectSid");
231	if (nc_sid) {
232		p->nc.sid	= *nc_sid;
233		talloc_free(nc_sid);
234	}
235
236	ouv_value = ldb_msg_find_ldb_val(r->msgs[0], "replUpToDateVector");
237	if (ouv_value) {
238		enum ndr_err_code ndr_err;
239		ndr_err = ndr_pull_struct_blob(ouv_value, mem_ctx,
240					       lp_iconv_convenience(s->task->lp_ctx), &ouv,
241					       (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob);
242		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
243			NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
244			talloc_free(mem_ctx);
245			return ntstatus_to_werror(nt_status);
246		}
247		/* NDR_PRINT_DEBUG(replUpToDateVectorBlob, &ouv); */
248		if (ouv.version != 2) {
249			talloc_free(mem_ctx);
250			return WERR_DS_DRA_INTERNAL_ERROR;
251		}
252
253		p->uptodatevector.count		= ouv.ctr.ctr2.count;
254		p->uptodatevector.reserved	= ouv.ctr.ctr2.reserved;
255		talloc_free(p->uptodatevector.cursors);
256		p->uptodatevector.cursors	= talloc_steal(p, ouv.ctr.ctr2.cursors);
257	}
258
259	/*
260	 * TODO: add our own uptodatevector cursor
261	 */
262
263
264	orf_el = ldb_msg_find_element(r->msgs[0], "repsFrom");
265	if (orf_el) {
266		for (i=0; i < orf_el->num_values; i++) {
267			status = dreplsrv_partition_add_source_dsa(s, p, &orf_el->values[i]);
268			W_ERROR_NOT_OK_RETURN(status);
269		}
270	}
271
272	talloc_free(mem_ctx);
273
274	return WERR_OK;
275}
276
277WERROR dreplsrv_refresh_partitions(struct dreplsrv_service *s)
278{
279	WERROR status;
280	struct dreplsrv_partition *p;
281
282	for (p = s->partitions; p; p = p->next) {
283		status = dreplsrv_refresh_partition(s, p);
284		W_ERROR_NOT_OK_RETURN(status);
285	}
286
287	return WERR_OK;
288}
289