s4:ldb:python/api: use only one ldb file in test_contains()
[Samba/gebeck_regimport.git] / source3 / libnet / libnet_samsync.c
bloba464a004ab4220e54737ad2fa308a85f3784d909
1 /*
2 Unix SMB/CIFS implementation.
4 Extract the user/system database from a remote SamSync server
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
7 Copyright (C) Guenther Deschner <gd@samba.org> 2008
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "libnet/libnet_samsync.h"
26 #include "../lib/crypto/crypto.h"
27 #include "../libcli/samsync/samsync.h"
28 #include "../libcli/auth/libcli_auth.h"
29 #include "../librpc/gen_ndr/ndr_netlogon.h"
30 #include "../librpc/gen_ndr/cli_netlogon.h"
31 #include "../libcli/security/security.h"
33 /**
34 * Fix up the delta, dealing with encryption issues so that the final
35 * callback need only do the printing or application logic
38 static NTSTATUS samsync_fix_delta_array(TALLOC_CTX *mem_ctx,
39 struct netlogon_creds_CredentialState *creds,
40 enum netr_SamDatabaseID database_id,
41 struct netr_DELTA_ENUM_ARRAY *r)
43 NTSTATUS status;
44 int i;
46 for (i = 0; i < r->num_deltas; i++) {
48 status = samsync_fix_delta(mem_ctx,
49 creds,
50 database_id,
51 &r->delta_enum[i]);
52 if (!NT_STATUS_IS_OK(status)) {
53 return status;
57 return NT_STATUS_OK;
60 /**
61 * libnet_samsync_init_context
64 NTSTATUS libnet_samsync_init_context(TALLOC_CTX *mem_ctx,
65 const struct dom_sid *domain_sid,
66 struct samsync_context **ctx_p)
68 struct samsync_context *ctx;
70 *ctx_p = NULL;
72 ctx = TALLOC_ZERO_P(mem_ctx, struct samsync_context);
73 NT_STATUS_HAVE_NO_MEMORY(ctx);
75 if (domain_sid) {
76 ctx->domain_sid = dom_sid_dup(mem_ctx, domain_sid);
77 NT_STATUS_HAVE_NO_MEMORY(ctx->domain_sid);
79 ctx->domain_sid_str = sid_string_talloc(mem_ctx, ctx->domain_sid);
80 NT_STATUS_HAVE_NO_MEMORY(ctx->domain_sid_str);
83 ctx->msg_ctx = messaging_init(ctx, procid_self(),
84 event_context_init(ctx));
85 NT_STATUS_HAVE_NO_MEMORY(ctx->msg_ctx);
87 *ctx_p = ctx;
89 return NT_STATUS_OK;
92 /**
93 * samsync_database_str
96 static const char *samsync_database_str(enum netr_SamDatabaseID database_id)
99 switch (database_id) {
100 case SAM_DATABASE_DOMAIN:
101 return "DOMAIN";
102 case SAM_DATABASE_BUILTIN:
103 return "BUILTIN";
104 case SAM_DATABASE_PRIVS:
105 return "PRIVS";
106 default:
107 return "unknown";
112 * samsync_debug_str
115 static const char *samsync_debug_str(TALLOC_CTX *mem_ctx,
116 enum net_samsync_mode mode,
117 enum netr_SamDatabaseID database_id)
119 const char *action = NULL;
121 switch (mode) {
122 case NET_SAMSYNC_MODE_DUMP:
123 action = "Dumping (to stdout)";
124 break;
125 case NET_SAMSYNC_MODE_FETCH_PASSDB:
126 action = "Fetching (to passdb)";
127 break;
128 case NET_SAMSYNC_MODE_FETCH_LDIF:
129 action = "Fetching (to ldif)";
130 break;
131 case NET_SAMSYNC_MODE_FETCH_KEYTAB:
132 action = "Fetching (to keytab)";
133 break;
134 default:
135 action = "Unknown";
136 break;
139 return talloc_asprintf(mem_ctx, "%s %s database",
140 action, samsync_database_str(database_id));
144 * libnet_samsync
147 static void libnet_init_netr_ChangeLogEntry(struct samsync_object *o,
148 struct netr_ChangeLogEntry *e)
150 ZERO_STRUCTP(e);
152 e->db_index = o->database_id;
153 e->delta_type = o->object_type;
155 switch (e->delta_type) {
156 case NETR_DELTA_DOMAIN:
157 case NETR_DELTA_DELETE_GROUP:
158 case NETR_DELTA_RENAME_GROUP:
159 case NETR_DELTA_DELETE_USER:
160 case NETR_DELTA_RENAME_USER:
161 case NETR_DELTA_DELETE_ALIAS:
162 case NETR_DELTA_RENAME_ALIAS:
163 case NETR_DELTA_DELETE_TRUST:
164 case NETR_DELTA_DELETE_ACCOUNT:
165 case NETR_DELTA_DELETE_SECRET:
166 case NETR_DELTA_DELETE_GROUP2:
167 case NETR_DELTA_DELETE_USER2:
168 case NETR_DELTA_MODIFY_COUNT:
169 break;
170 case NETR_DELTA_USER:
171 case NETR_DELTA_GROUP:
172 case NETR_DELTA_GROUP_MEMBER:
173 case NETR_DELTA_ALIAS:
174 case NETR_DELTA_ALIAS_MEMBER:
175 e->object_rid = o->object_identifier.rid;
176 break;
177 case NETR_DELTA_SECRET:
178 e->object.object_name = o->object_identifier.name;
179 e->flags = NETR_CHANGELOG_NAME_INCLUDED;
180 break;
181 case NETR_DELTA_TRUSTED_DOMAIN:
182 case NETR_DELTA_ACCOUNT:
183 case NETR_DELTA_POLICY:
184 e->object.object_sid = o->object_identifier.sid;
185 e->flags = NETR_CHANGELOG_SID_INCLUDED;
186 break;
187 default:
188 break;
193 * libnet_samsync_delta
196 static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx,
197 enum netr_SamDatabaseID database_id,
198 uint64_t *sequence_num,
199 struct samsync_context *ctx,
200 struct netr_ChangeLogEntry *e)
202 NTSTATUS result;
203 NTSTATUS callback_status;
204 const char *logon_server = ctx->cli->desthost;
205 const char *computername = global_myname();
206 struct netr_Authenticator credential;
207 struct netr_Authenticator return_authenticator;
208 uint16_t restart_state = 0;
209 uint32_t sync_context = 0;
211 ZERO_STRUCT(return_authenticator);
213 do {
214 struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
216 netlogon_creds_client_authenticator(ctx->cli->dc, &credential);
218 if (ctx->single_object_replication &&
219 !ctx->force_full_replication) {
220 result = rpccli_netr_DatabaseRedo(ctx->cli, mem_ctx,
221 logon_server,
222 computername,
223 &credential,
224 &return_authenticator,
227 &delta_enum_array);
228 } else if (!ctx->force_full_replication &&
229 sequence_num && (*sequence_num > 0)) {
230 result = rpccli_netr_DatabaseDeltas(ctx->cli, mem_ctx,
231 logon_server,
232 computername,
233 &credential,
234 &return_authenticator,
235 database_id,
236 sequence_num,
237 &delta_enum_array,
238 0xffff);
239 } else {
240 result = rpccli_netr_DatabaseSync2(ctx->cli, mem_ctx,
241 logon_server,
242 computername,
243 &credential,
244 &return_authenticator,
245 database_id,
246 restart_state,
247 &sync_context,
248 &delta_enum_array,
249 0xffff);
252 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) {
253 return result;
256 /* Check returned credentials. */
257 if (!netlogon_creds_client_check(ctx->cli->dc,
258 &return_authenticator.cred)) {
259 DEBUG(0,("credentials chain check failed\n"));
260 return NT_STATUS_ACCESS_DENIED;
263 if (NT_STATUS_IS_ERR(result)) {
264 break;
267 samsync_fix_delta_array(mem_ctx,
268 ctx->cli->dc,
269 database_id,
270 delta_enum_array);
272 /* Process results */
273 callback_status = ctx->ops->process_objects(mem_ctx, database_id,
274 delta_enum_array,
275 sequence_num,
276 ctx);
277 if (!NT_STATUS_IS_OK(callback_status)) {
278 result = callback_status;
279 goto out;
282 TALLOC_FREE(delta_enum_array);
284 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
286 out:
288 return result;
292 * libnet_samsync
295 NTSTATUS libnet_samsync(enum netr_SamDatabaseID database_id,
296 struct samsync_context *ctx)
298 NTSTATUS status = NT_STATUS_OK;
299 NTSTATUS callback_status;
300 TALLOC_CTX *mem_ctx;
301 const char *debug_str;
302 uint64_t sequence_num = 0;
303 int i = 0;
305 if (!(mem_ctx = talloc_new(ctx))) {
306 return NT_STATUS_NO_MEMORY;
309 if (!ctx->ops) {
310 return NT_STATUS_INVALID_PARAMETER;
313 if (ctx->ops->startup) {
314 status = ctx->ops->startup(mem_ctx, ctx,
315 database_id, &sequence_num);
316 if (!NT_STATUS_IS_OK(status)) {
317 goto done;
321 debug_str = samsync_debug_str(mem_ctx, ctx->mode, database_id);
322 if (debug_str) {
323 d_fprintf(stderr, "%s\n", debug_str);
326 if (!ctx->single_object_replication) {
327 status = libnet_samsync_delta(mem_ctx, database_id,
328 &sequence_num, ctx, NULL);
329 goto done;
332 for (i=0; i<ctx->num_objects; i++) {
334 struct netr_ChangeLogEntry e;
336 if (ctx->objects[i].database_id != database_id) {
337 continue;
340 libnet_init_netr_ChangeLogEntry(&ctx->objects[i], &e);
342 status = libnet_samsync_delta(mem_ctx, database_id,
343 &sequence_num, ctx, &e);
344 if (!NT_STATUS_IS_OK(status)) {
345 goto done;
349 done:
351 if (NT_STATUS_IS_OK(status) && ctx->ops->finish) {
352 callback_status = ctx->ops->finish(mem_ctx, ctx,
353 database_id, sequence_num);
354 if (!NT_STATUS_IS_OK(callback_status)) {
355 status = callback_status;
359 if (NT_STATUS_IS_ERR(status) && !ctx->error_message) {
361 ctx->error_message = talloc_asprintf(ctx,
362 "Failed to fetch %s database: %s",
363 samsync_database_str(database_id),
364 nt_errstr(status));
366 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
368 ctx->error_message =
369 talloc_asprintf_append(ctx->error_message,
370 "\nPerhaps %s is a Windows native mode domain?",
371 ctx->domain_name);
375 talloc_destroy(mem_ctx);
377 return status;
381 * pull_netr_AcctLockStr
384 NTSTATUS pull_netr_AcctLockStr(TALLOC_CTX *mem_ctx,
385 struct lsa_BinaryString *r,
386 struct netr_AcctLockStr **str_p)
388 struct netr_AcctLockStr *str;
389 enum ndr_err_code ndr_err;
390 DATA_BLOB blob;
392 if (!mem_ctx || !r || !str_p) {
393 return NT_STATUS_INVALID_PARAMETER;
396 *str_p = NULL;
398 str = TALLOC_ZERO_P(mem_ctx, struct netr_AcctLockStr);
399 if (!str) {
400 return NT_STATUS_NO_MEMORY;
403 blob = data_blob_const(r->array, r->length);
405 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, str,
406 (ndr_pull_flags_fn_t)ndr_pull_netr_AcctLockStr);
408 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
409 return ndr_map_error2ntstatus(ndr_err);
412 *str_p = str;
414 return NT_STATUS_OK;