s3:build: fix typo in definition of --enable-external-libtdb
[Samba/gbeck.git] / source3 / libnet / libnet_samsync.c
blob1141bed730b4b6f7f7cb354254e4aec1cc8a8c73
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 "rpc_client/rpc_client.h"
30 #include "../librpc/gen_ndr/ndr_netlogon.h"
31 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
32 #include "../libcli/security/security.h"
33 #include "messages.h"
35 /**
36 * Fix up the delta, dealing with encryption issues so that the final
37 * callback need only do the printing or application logic
40 static NTSTATUS samsync_fix_delta_array(TALLOC_CTX *mem_ctx,
41 struct netlogon_creds_CredentialState *creds,
42 enum netr_SamDatabaseID database_id,
43 struct netr_DELTA_ENUM_ARRAY *r)
45 NTSTATUS status;
46 int i;
48 for (i = 0; i < r->num_deltas; i++) {
50 status = samsync_fix_delta(mem_ctx,
51 creds,
52 database_id,
53 &r->delta_enum[i]);
54 if (!NT_STATUS_IS_OK(status)) {
55 return status;
59 return NT_STATUS_OK;
62 /**
63 * libnet_samsync_init_context
66 NTSTATUS libnet_samsync_init_context(TALLOC_CTX *mem_ctx,
67 const struct dom_sid *domain_sid,
68 struct samsync_context **ctx_p)
70 struct samsync_context *ctx;
72 *ctx_p = NULL;
74 ctx = TALLOC_ZERO_P(mem_ctx, struct samsync_context);
75 NT_STATUS_HAVE_NO_MEMORY(ctx);
77 if (domain_sid) {
78 ctx->domain_sid = dom_sid_dup(mem_ctx, domain_sid);
79 NT_STATUS_HAVE_NO_MEMORY(ctx->domain_sid);
81 ctx->domain_sid_str = sid_string_talloc(mem_ctx, ctx->domain_sid);
82 NT_STATUS_HAVE_NO_MEMORY(ctx->domain_sid_str);
85 ctx->msg_ctx = messaging_init(ctx, procid_self(),
86 event_context_init(ctx));
87 NT_STATUS_HAVE_NO_MEMORY(ctx->msg_ctx);
89 *ctx_p = ctx;
91 return NT_STATUS_OK;
94 /**
95 * samsync_database_str
98 static const char *samsync_database_str(enum netr_SamDatabaseID database_id)
101 switch (database_id) {
102 case SAM_DATABASE_DOMAIN:
103 return "DOMAIN";
104 case SAM_DATABASE_BUILTIN:
105 return "BUILTIN";
106 case SAM_DATABASE_PRIVS:
107 return "PRIVS";
108 default:
109 return "unknown";
114 * samsync_debug_str
117 static const char *samsync_debug_str(TALLOC_CTX *mem_ctx,
118 enum net_samsync_mode mode,
119 enum netr_SamDatabaseID database_id)
121 const char *action = NULL;
123 switch (mode) {
124 case NET_SAMSYNC_MODE_DUMP:
125 action = "Dumping (to stdout)";
126 break;
127 case NET_SAMSYNC_MODE_FETCH_PASSDB:
128 action = "Fetching (to passdb)";
129 break;
130 case NET_SAMSYNC_MODE_FETCH_LDIF:
131 action = "Fetching (to ldif)";
132 break;
133 case NET_SAMSYNC_MODE_FETCH_KEYTAB:
134 action = "Fetching (to keytab)";
135 break;
136 default:
137 action = "Unknown";
138 break;
141 return talloc_asprintf(mem_ctx, "%s %s database",
142 action, samsync_database_str(database_id));
146 * libnet_samsync
149 static void libnet_init_netr_ChangeLogEntry(struct samsync_object *o,
150 struct netr_ChangeLogEntry *e)
152 ZERO_STRUCTP(e);
154 e->db_index = o->database_id;
155 e->delta_type = o->object_type;
157 switch (e->delta_type) {
158 case NETR_DELTA_DOMAIN:
159 case NETR_DELTA_DELETE_GROUP:
160 case NETR_DELTA_RENAME_GROUP:
161 case NETR_DELTA_DELETE_USER:
162 case NETR_DELTA_RENAME_USER:
163 case NETR_DELTA_DELETE_ALIAS:
164 case NETR_DELTA_RENAME_ALIAS:
165 case NETR_DELTA_DELETE_TRUST:
166 case NETR_DELTA_DELETE_ACCOUNT:
167 case NETR_DELTA_DELETE_SECRET:
168 case NETR_DELTA_DELETE_GROUP2:
169 case NETR_DELTA_DELETE_USER2:
170 case NETR_DELTA_MODIFY_COUNT:
171 break;
172 case NETR_DELTA_USER:
173 case NETR_DELTA_GROUP:
174 case NETR_DELTA_GROUP_MEMBER:
175 case NETR_DELTA_ALIAS:
176 case NETR_DELTA_ALIAS_MEMBER:
177 e->object_rid = o->object_identifier.rid;
178 break;
179 case NETR_DELTA_SECRET:
180 e->object.object_name = o->object_identifier.name;
181 e->flags = NETR_CHANGELOG_NAME_INCLUDED;
182 break;
183 case NETR_DELTA_TRUSTED_DOMAIN:
184 case NETR_DELTA_ACCOUNT:
185 case NETR_DELTA_POLICY:
186 e->object.object_sid = o->object_identifier.sid;
187 e->flags = NETR_CHANGELOG_SID_INCLUDED;
188 break;
189 default:
190 break;
195 * libnet_samsync_delta
198 static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx,
199 enum netr_SamDatabaseID database_id,
200 uint64_t *sequence_num,
201 struct samsync_context *ctx,
202 struct netr_ChangeLogEntry *e)
204 NTSTATUS result, status;
205 NTSTATUS callback_status;
206 const char *logon_server = ctx->cli->desthost;
207 const char *computername = global_myname();
208 struct netr_Authenticator credential;
209 struct netr_Authenticator return_authenticator;
210 uint16_t restart_state = 0;
211 uint32_t sync_context = 0;
212 struct dcerpc_binding_handle *b = ctx->cli->binding_handle;
214 ZERO_STRUCT(return_authenticator);
216 do {
217 struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
219 netlogon_creds_client_authenticator(ctx->cli->dc, &credential);
221 if (ctx->single_object_replication &&
222 !ctx->force_full_replication) {
223 status = dcerpc_netr_DatabaseRedo(b, mem_ctx,
224 logon_server,
225 computername,
226 &credential,
227 &return_authenticator,
230 &delta_enum_array,
231 &result);
232 } else if (!ctx->force_full_replication &&
233 sequence_num && (*sequence_num > 0)) {
234 status = dcerpc_netr_DatabaseDeltas(b, mem_ctx,
235 logon_server,
236 computername,
237 &credential,
238 &return_authenticator,
239 database_id,
240 sequence_num,
241 &delta_enum_array,
242 0xffff,
243 &result);
244 } else {
245 status = dcerpc_netr_DatabaseSync2(b, mem_ctx,
246 logon_server,
247 computername,
248 &credential,
249 &return_authenticator,
250 database_id,
251 restart_state,
252 &sync_context,
253 &delta_enum_array,
254 0xffff,
255 &result);
258 if (!NT_STATUS_IS_OK(status)) {
259 return status;
262 /* Check returned credentials. */
263 if (!netlogon_creds_client_check(ctx->cli->dc,
264 &return_authenticator.cred)) {
265 DEBUG(0,("credentials chain check failed\n"));
266 return NT_STATUS_ACCESS_DENIED;
269 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) {
270 return result;
273 if (NT_STATUS_IS_ERR(result)) {
274 break;
277 samsync_fix_delta_array(mem_ctx,
278 ctx->cli->dc,
279 database_id,
280 delta_enum_array);
282 /* Process results */
283 callback_status = ctx->ops->process_objects(mem_ctx, database_id,
284 delta_enum_array,
285 sequence_num,
286 ctx);
287 if (!NT_STATUS_IS_OK(callback_status)) {
288 result = callback_status;
289 goto out;
292 TALLOC_FREE(delta_enum_array);
294 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
296 out:
298 return result;
302 * libnet_samsync
305 NTSTATUS libnet_samsync(enum netr_SamDatabaseID database_id,
306 struct samsync_context *ctx)
308 NTSTATUS status = NT_STATUS_OK;
309 NTSTATUS callback_status;
310 TALLOC_CTX *mem_ctx;
311 const char *debug_str;
312 uint64_t sequence_num = 0;
313 int i = 0;
315 if (!(mem_ctx = talloc_new(ctx))) {
316 return NT_STATUS_NO_MEMORY;
319 if (!ctx->ops) {
320 return NT_STATUS_INVALID_PARAMETER;
323 if (ctx->ops->startup) {
324 status = ctx->ops->startup(mem_ctx, ctx,
325 database_id, &sequence_num);
326 if (!NT_STATUS_IS_OK(status)) {
327 goto done;
331 debug_str = samsync_debug_str(mem_ctx, ctx->mode, database_id);
332 if (debug_str) {
333 d_fprintf(stderr, "%s\n", debug_str);
336 if (!ctx->single_object_replication) {
337 status = libnet_samsync_delta(mem_ctx, database_id,
338 &sequence_num, ctx, NULL);
339 goto done;
342 for (i=0; i<ctx->num_objects; i++) {
344 struct netr_ChangeLogEntry e;
346 if (ctx->objects[i].database_id != database_id) {
347 continue;
350 libnet_init_netr_ChangeLogEntry(&ctx->objects[i], &e);
352 status = libnet_samsync_delta(mem_ctx, database_id,
353 &sequence_num, ctx, &e);
354 if (!NT_STATUS_IS_OK(status)) {
355 goto done;
359 done:
361 if (NT_STATUS_IS_OK(status) && ctx->ops->finish) {
362 callback_status = ctx->ops->finish(mem_ctx, ctx,
363 database_id, sequence_num);
364 if (!NT_STATUS_IS_OK(callback_status)) {
365 status = callback_status;
369 if (NT_STATUS_IS_ERR(status) && !ctx->error_message) {
371 ctx->error_message = talloc_asprintf(ctx,
372 "Failed to fetch %s database: %s",
373 samsync_database_str(database_id),
374 nt_errstr(status));
376 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
378 ctx->error_message =
379 talloc_asprintf_append(ctx->error_message,
380 "\nPerhaps %s is a Windows native mode domain?",
381 ctx->domain_name);
385 talloc_destroy(mem_ctx);
387 return status;
391 * pull_netr_AcctLockStr
394 NTSTATUS pull_netr_AcctLockStr(TALLOC_CTX *mem_ctx,
395 struct lsa_BinaryString *r,
396 struct netr_AcctLockStr **str_p)
398 struct netr_AcctLockStr *str;
399 enum ndr_err_code ndr_err;
400 DATA_BLOB blob;
402 if (!mem_ctx || !r || !str_p) {
403 return NT_STATUS_INVALID_PARAMETER;
406 *str_p = NULL;
408 str = TALLOC_ZERO_P(mem_ctx, struct netr_AcctLockStr);
409 if (!str) {
410 return NT_STATUS_NO_MEMORY;
413 blob = data_blob_const(r->array, r->length);
415 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, str,
416 (ndr_pull_flags_fn_t)ndr_pull_netr_AcctLockStr);
418 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
419 return ndr_map_error2ntstatus(ndr_err);
422 *str_p = str;
424 return NT_STATUS_OK;