s4:smbd: Add tstream to the stream_connection structure
[Samba/ekacnet.git] / source3 / libnet / libnet_samsync.c
blobcbe4b80b616791e5f6ee20b4d4175b0aab020a8d
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.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/cli_netlogon.h"
31 /**
32 * Fix up the delta, dealing with encryption issues so that the final
33 * callback need only do the printing or application logic
36 static NTSTATUS samsync_fix_delta_array(TALLOC_CTX *mem_ctx,
37 struct netlogon_creds_CredentialState *creds,
38 enum netr_SamDatabaseID database_id,
39 struct netr_DELTA_ENUM_ARRAY *r)
41 NTSTATUS status;
42 int i;
44 for (i = 0; i < r->num_deltas; i++) {
46 status = samsync_fix_delta(mem_ctx,
47 creds,
48 database_id,
49 &r->delta_enum[i]);
50 if (!NT_STATUS_IS_OK(status)) {
51 return status;
55 return NT_STATUS_OK;
58 /**
59 * libnet_samsync_init_context
62 NTSTATUS libnet_samsync_init_context(TALLOC_CTX *mem_ctx,
63 const struct dom_sid *domain_sid,
64 struct samsync_context **ctx_p)
66 struct samsync_context *ctx;
68 *ctx_p = NULL;
70 ctx = TALLOC_ZERO_P(mem_ctx, struct samsync_context);
71 NT_STATUS_HAVE_NO_MEMORY(ctx);
73 if (domain_sid) {
74 ctx->domain_sid = sid_dup_talloc(mem_ctx, domain_sid);
75 NT_STATUS_HAVE_NO_MEMORY(ctx->domain_sid);
77 ctx->domain_sid_str = sid_string_talloc(mem_ctx, ctx->domain_sid);
78 NT_STATUS_HAVE_NO_MEMORY(ctx->domain_sid_str);
81 *ctx_p = ctx;
83 return NT_STATUS_OK;
86 /**
87 * samsync_database_str
90 static const char *samsync_database_str(enum netr_SamDatabaseID database_id)
93 switch (database_id) {
94 case SAM_DATABASE_DOMAIN:
95 return "DOMAIN";
96 case SAM_DATABASE_BUILTIN:
97 return "BUILTIN";
98 case SAM_DATABASE_PRIVS:
99 return "PRIVS";
100 default:
101 return "unknown";
106 * samsync_debug_str
109 static const char *samsync_debug_str(TALLOC_CTX *mem_ctx,
110 enum net_samsync_mode mode,
111 enum netr_SamDatabaseID database_id)
113 const char *action = NULL;
115 switch (mode) {
116 case NET_SAMSYNC_MODE_DUMP:
117 action = "Dumping (to stdout)";
118 break;
119 case NET_SAMSYNC_MODE_FETCH_PASSDB:
120 action = "Fetching (to passdb)";
121 break;
122 case NET_SAMSYNC_MODE_FETCH_LDIF:
123 action = "Fetching (to ldif)";
124 break;
125 case NET_SAMSYNC_MODE_FETCH_KEYTAB:
126 action = "Fetching (to keytab)";
127 break;
128 default:
129 action = "Unknown";
130 break;
133 return talloc_asprintf(mem_ctx, "%s %s database",
134 action, samsync_database_str(database_id));
138 * libnet_samsync
141 static void libnet_init_netr_ChangeLogEntry(struct samsync_object *o,
142 struct netr_ChangeLogEntry *e)
144 ZERO_STRUCTP(e);
146 e->db_index = o->database_id;
147 e->delta_type = o->object_type;
149 switch (e->delta_type) {
150 case NETR_DELTA_DOMAIN:
151 case NETR_DELTA_DELETE_GROUP:
152 case NETR_DELTA_RENAME_GROUP:
153 case NETR_DELTA_DELETE_USER:
154 case NETR_DELTA_RENAME_USER:
155 case NETR_DELTA_DELETE_ALIAS:
156 case NETR_DELTA_RENAME_ALIAS:
157 case NETR_DELTA_DELETE_TRUST:
158 case NETR_DELTA_DELETE_ACCOUNT:
159 case NETR_DELTA_DELETE_SECRET:
160 case NETR_DELTA_DELETE_GROUP2:
161 case NETR_DELTA_DELETE_USER2:
162 case NETR_DELTA_MODIFY_COUNT:
163 break;
164 case NETR_DELTA_USER:
165 case NETR_DELTA_GROUP:
166 case NETR_DELTA_GROUP_MEMBER:
167 case NETR_DELTA_ALIAS:
168 case NETR_DELTA_ALIAS_MEMBER:
169 e->object_rid = o->object_identifier.rid;
170 break;
171 case NETR_DELTA_SECRET:
172 e->object.object_name = o->object_identifier.name;
173 e->flags = NETR_CHANGELOG_NAME_INCLUDED;
174 break;
175 case NETR_DELTA_TRUSTED_DOMAIN:
176 case NETR_DELTA_ACCOUNT:
177 case NETR_DELTA_POLICY:
178 e->object.object_sid = o->object_identifier.sid;
179 e->flags = NETR_CHANGELOG_SID_INCLUDED;
180 break;
181 default:
182 break;
187 * libnet_samsync_delta
190 static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx,
191 enum netr_SamDatabaseID database_id,
192 uint64_t *sequence_num,
193 struct samsync_context *ctx,
194 struct netr_ChangeLogEntry *e)
196 NTSTATUS result;
197 NTSTATUS callback_status;
198 const char *logon_server = ctx->cli->desthost;
199 const char *computername = global_myname();
200 struct netr_Authenticator credential;
201 struct netr_Authenticator return_authenticator;
202 uint16_t restart_state = 0;
203 uint32_t sync_context = 0;
205 ZERO_STRUCT(return_authenticator);
207 do {
208 struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
210 netlogon_creds_client_authenticator(ctx->cli->dc, &credential);
212 if (ctx->single_object_replication &&
213 !ctx->force_full_replication) {
214 result = rpccli_netr_DatabaseRedo(ctx->cli, mem_ctx,
215 logon_server,
216 computername,
217 &credential,
218 &return_authenticator,
221 &delta_enum_array);
222 } else if (!ctx->force_full_replication &&
223 sequence_num && (*sequence_num > 0)) {
224 result = rpccli_netr_DatabaseDeltas(ctx->cli, mem_ctx,
225 logon_server,
226 computername,
227 &credential,
228 &return_authenticator,
229 database_id,
230 sequence_num,
231 &delta_enum_array,
232 0xffff);
233 } else {
234 result = rpccli_netr_DatabaseSync2(ctx->cli, mem_ctx,
235 logon_server,
236 computername,
237 &credential,
238 &return_authenticator,
239 database_id,
240 restart_state,
241 &sync_context,
242 &delta_enum_array,
243 0xffff);
246 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) {
247 return result;
250 /* Check returned credentials. */
251 if (!netlogon_creds_client_check(ctx->cli->dc,
252 &return_authenticator.cred)) {
253 DEBUG(0,("credentials chain check failed\n"));
254 return NT_STATUS_ACCESS_DENIED;
257 if (NT_STATUS_IS_ERR(result)) {
258 break;
261 samsync_fix_delta_array(mem_ctx,
262 ctx->cli->dc,
263 database_id,
264 delta_enum_array);
266 /* Process results */
267 callback_status = ctx->ops->process_objects(mem_ctx, database_id,
268 delta_enum_array,
269 sequence_num,
270 ctx);
271 if (!NT_STATUS_IS_OK(callback_status)) {
272 result = callback_status;
273 goto out;
276 TALLOC_FREE(delta_enum_array);
278 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
280 out:
282 return result;
286 * libnet_samsync
289 NTSTATUS libnet_samsync(enum netr_SamDatabaseID database_id,
290 struct samsync_context *ctx)
292 NTSTATUS status = NT_STATUS_OK;
293 NTSTATUS callback_status;
294 TALLOC_CTX *mem_ctx;
295 const char *debug_str;
296 uint64_t sequence_num = 0;
297 int i = 0;
299 if (!(mem_ctx = talloc_new(ctx))) {
300 return NT_STATUS_NO_MEMORY;
303 if (!ctx->ops) {
304 return NT_STATUS_INVALID_PARAMETER;
307 if (ctx->ops->startup) {
308 status = ctx->ops->startup(mem_ctx, ctx,
309 database_id, &sequence_num);
310 if (!NT_STATUS_IS_OK(status)) {
311 goto done;
315 debug_str = samsync_debug_str(mem_ctx, ctx->mode, database_id);
316 if (debug_str) {
317 d_fprintf(stderr, "%s\n", debug_str);
320 if (!ctx->single_object_replication) {
321 status = libnet_samsync_delta(mem_ctx, database_id,
322 &sequence_num, ctx, NULL);
323 goto done;
326 for (i=0; i<ctx->num_objects; i++) {
328 struct netr_ChangeLogEntry e;
330 if (ctx->objects[i].database_id != database_id) {
331 continue;
334 libnet_init_netr_ChangeLogEntry(&ctx->objects[i], &e);
336 status = libnet_samsync_delta(mem_ctx, database_id,
337 &sequence_num, ctx, &e);
338 if (!NT_STATUS_IS_OK(status)) {
339 goto done;
343 done:
345 if (NT_STATUS_IS_OK(status) && ctx->ops->finish) {
346 callback_status = ctx->ops->finish(mem_ctx, ctx,
347 database_id, sequence_num);
348 if (!NT_STATUS_IS_OK(callback_status)) {
349 status = callback_status;
353 if (NT_STATUS_IS_ERR(status) && !ctx->error_message) {
355 ctx->error_message = talloc_asprintf(ctx,
356 "Failed to fetch %s database: %s",
357 samsync_database_str(database_id),
358 nt_errstr(status));
360 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
362 ctx->error_message =
363 talloc_asprintf_append(ctx->error_message,
364 "\nPerhaps %s is a Windows native mode domain?",
365 ctx->domain_name);
369 talloc_destroy(mem_ctx);
371 return status;
375 * pull_netr_AcctLockStr
378 NTSTATUS pull_netr_AcctLockStr(TALLOC_CTX *mem_ctx,
379 struct lsa_BinaryString *r,
380 struct netr_AcctLockStr **str_p)
382 struct netr_AcctLockStr *str;
383 enum ndr_err_code ndr_err;
384 DATA_BLOB blob;
386 if (!mem_ctx || !r || !str_p) {
387 return NT_STATUS_INVALID_PARAMETER;
390 *str_p = NULL;
392 str = TALLOC_ZERO_P(mem_ctx, struct netr_AcctLockStr);
393 if (!str) {
394 return NT_STATUS_NO_MEMORY;
397 blob = data_blob_const(r->array, r->length);
399 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, str,
400 (ndr_pull_flags_fn_t)ndr_pull_netr_AcctLockStr);
402 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
403 return ndr_map_error2ntstatus(ndr_err);
406 *str_p = str;
408 return NT_STATUS_OK;