source: vendor/3.6.0/source3/libnet/libnet_samsync.c

Last change on this file was 740, checked in by Silvan Scherrer, 13 years ago

Samba Server: update vendor to 3.6.0

File size: 10.2 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 Extract the user/system database from a remote SamSync server
5
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
7 Copyright (C) Guenther Deschner <gd@samba.org> 2008
8
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.
13
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.
18
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/>.
21*/
22
23
24#include "includes.h"
25#include "libnet/libnet_samsync.h"
26#include "../libcli/samsync/samsync.h"
27#include "../libcli/auth/libcli_auth.h"
28#include "rpc_client/rpc_client.h"
29#include "../librpc/gen_ndr/ndr_netlogon.h"
30#include "../librpc/gen_ndr/ndr_netlogon_c.h"
31#include "../libcli/security/security.h"
32#include "messages.h"
33
34/**
35 * Fix up the delta, dealing with encryption issues so that the final
36 * callback need only do the printing or application logic
37 */
38
39static NTSTATUS samsync_fix_delta_array(TALLOC_CTX *mem_ctx,
40 struct netlogon_creds_CredentialState *creds,
41 enum netr_SamDatabaseID database_id,
42 struct netr_DELTA_ENUM_ARRAY *r)
43{
44 NTSTATUS status;
45 int i;
46
47 for (i = 0; i < r->num_deltas; i++) {
48
49 status = samsync_fix_delta(mem_ctx,
50 creds,
51 database_id,
52 &r->delta_enum[i]);
53 if (!NT_STATUS_IS_OK(status)) {
54 return status;
55 }
56 }
57
58 return NT_STATUS_OK;
59}
60
61/**
62 * libnet_samsync_init_context
63 */
64
65NTSTATUS libnet_samsync_init_context(TALLOC_CTX *mem_ctx,
66 const struct dom_sid *domain_sid,
67 struct samsync_context **ctx_p)
68{
69 struct samsync_context *ctx;
70
71 *ctx_p = NULL;
72
73 ctx = TALLOC_ZERO_P(mem_ctx, struct samsync_context);
74 NT_STATUS_HAVE_NO_MEMORY(ctx);
75
76 if (domain_sid) {
77 ctx->domain_sid = dom_sid_dup(mem_ctx, domain_sid);
78 NT_STATUS_HAVE_NO_MEMORY(ctx->domain_sid);
79
80 ctx->domain_sid_str = sid_string_talloc(mem_ctx, ctx->domain_sid);
81 NT_STATUS_HAVE_NO_MEMORY(ctx->domain_sid_str);
82 }
83
84 ctx->msg_ctx = messaging_init(ctx, procid_self(),
85 event_context_init(ctx));
86 NT_STATUS_HAVE_NO_MEMORY(ctx->msg_ctx);
87
88 *ctx_p = ctx;
89
90 return NT_STATUS_OK;
91}
92
93/**
94 * samsync_database_str
95 */
96
97static const char *samsync_database_str(enum netr_SamDatabaseID database_id)
98{
99
100 switch (database_id) {
101 case SAM_DATABASE_DOMAIN:
102 return "DOMAIN";
103 case SAM_DATABASE_BUILTIN:
104 return "BUILTIN";
105 case SAM_DATABASE_PRIVS:
106 return "PRIVS";
107 default:
108 return "unknown";
109 }
110}
111
112/**
113 * samsync_debug_str
114 */
115
116static const char *samsync_debug_str(TALLOC_CTX *mem_ctx,
117 enum net_samsync_mode mode,
118 enum netr_SamDatabaseID database_id)
119{
120 const char *action = NULL;
121
122 switch (mode) {
123 case NET_SAMSYNC_MODE_DUMP:
124 action = "Dumping (to stdout)";
125 break;
126 case NET_SAMSYNC_MODE_FETCH_PASSDB:
127 action = "Fetching (to passdb)";
128 break;
129 case NET_SAMSYNC_MODE_FETCH_LDIF:
130 action = "Fetching (to ldif)";
131 break;
132 case NET_SAMSYNC_MODE_FETCH_KEYTAB:
133 action = "Fetching (to keytab)";
134 break;
135 default:
136 action = "Unknown";
137 break;
138 }
139
140 return talloc_asprintf(mem_ctx, "%s %s database",
141 action, samsync_database_str(database_id));
142}
143
144/**
145 * libnet_samsync
146 */
147
148static void libnet_init_netr_ChangeLogEntry(struct samsync_object *o,
149 struct netr_ChangeLogEntry *e)
150{
151 ZERO_STRUCTP(e);
152
153 e->db_index = o->database_id;
154 e->delta_type = o->object_type;
155
156 switch (e->delta_type) {
157 case NETR_DELTA_DOMAIN:
158 case NETR_DELTA_DELETE_GROUP:
159 case NETR_DELTA_RENAME_GROUP:
160 case NETR_DELTA_DELETE_USER:
161 case NETR_DELTA_RENAME_USER:
162 case NETR_DELTA_DELETE_ALIAS:
163 case NETR_DELTA_RENAME_ALIAS:
164 case NETR_DELTA_DELETE_TRUST:
165 case NETR_DELTA_DELETE_ACCOUNT:
166 case NETR_DELTA_DELETE_SECRET:
167 case NETR_DELTA_DELETE_GROUP2:
168 case NETR_DELTA_DELETE_USER2:
169 case NETR_DELTA_MODIFY_COUNT:
170 break;
171 case NETR_DELTA_USER:
172 case NETR_DELTA_GROUP:
173 case NETR_DELTA_GROUP_MEMBER:
174 case NETR_DELTA_ALIAS:
175 case NETR_DELTA_ALIAS_MEMBER:
176 e->object_rid = o->object_identifier.rid;
177 break;
178 case NETR_DELTA_SECRET:
179 e->object.object_name = o->object_identifier.name;
180 e->flags = NETR_CHANGELOG_NAME_INCLUDED;
181 break;
182 case NETR_DELTA_TRUSTED_DOMAIN:
183 case NETR_DELTA_ACCOUNT:
184 case NETR_DELTA_POLICY:
185 e->object.object_sid = o->object_identifier.sid;
186 e->flags = NETR_CHANGELOG_SID_INCLUDED;
187 break;
188 default:
189 break;
190 }
191}
192
193/**
194 * libnet_samsync_delta
195 */
196
197static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx,
198 enum netr_SamDatabaseID database_id,
199 uint64_t *sequence_num,
200 struct samsync_context *ctx,
201 struct netr_ChangeLogEntry *e)
202{
203 NTSTATUS result, status;
204 NTSTATUS callback_status;
205 const char *logon_server = ctx->cli->desthost;
206 const char *computername = global_myname();
207 struct netr_Authenticator credential;
208 struct netr_Authenticator return_authenticator;
209 uint16_t restart_state = 0;
210 uint32_t sync_context = 0;
211 struct dcerpc_binding_handle *b = ctx->cli->binding_handle;
212
213 ZERO_STRUCT(return_authenticator);
214
215 do {
216 struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
217
218 netlogon_creds_client_authenticator(ctx->cli->dc, &credential);
219
220 if (ctx->single_object_replication &&
221 !ctx->force_full_replication) {
222 status = dcerpc_netr_DatabaseRedo(b, mem_ctx,
223 logon_server,
224 computername,
225 &credential,
226 &return_authenticator,
227 *e,
228 0,
229 &delta_enum_array,
230 &result);
231 } else if (!ctx->force_full_replication &&
232 sequence_num && (*sequence_num > 0)) {
233 status = dcerpc_netr_DatabaseDeltas(b, mem_ctx,
234 logon_server,
235 computername,
236 &credential,
237 &return_authenticator,
238 database_id,
239 sequence_num,
240 &delta_enum_array,
241 0xffff,
242 &result);
243 } else {
244 status = dcerpc_netr_DatabaseSync2(b, mem_ctx,
245 logon_server,
246 computername,
247 &credential,
248 &return_authenticator,
249 database_id,
250 restart_state,
251 &sync_context,
252 &delta_enum_array,
253 0xffff,
254 &result);
255 }
256
257 if (!NT_STATUS_IS_OK(status)) {
258 return status;
259 }
260
261 /* Check returned credentials. */
262 if (!netlogon_creds_client_check(ctx->cli->dc,
263 &return_authenticator.cred)) {
264 DEBUG(0,("credentials chain check failed\n"));
265 return NT_STATUS_ACCESS_DENIED;
266 }
267
268 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) {
269 return result;
270 }
271
272 if (NT_STATUS_IS_ERR(result)) {
273 break;
274 }
275
276 samsync_fix_delta_array(mem_ctx,
277 ctx->cli->dc,
278 database_id,
279 delta_enum_array);
280
281 /* Process results */
282 callback_status = ctx->ops->process_objects(mem_ctx, database_id,
283 delta_enum_array,
284 sequence_num,
285 ctx);
286 if (!NT_STATUS_IS_OK(callback_status)) {
287 result = callback_status;
288 goto out;
289 }
290
291 TALLOC_FREE(delta_enum_array);
292
293 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
294
295 out:
296
297 return result;
298}
299
300/**
301 * libnet_samsync
302 */
303
304NTSTATUS libnet_samsync(enum netr_SamDatabaseID database_id,
305 struct samsync_context *ctx)
306{
307 NTSTATUS status = NT_STATUS_OK;
308 NTSTATUS callback_status;
309 TALLOC_CTX *mem_ctx;
310 const char *debug_str;
311 uint64_t sequence_num = 0;
312 int i = 0;
313
314 if (!(mem_ctx = talloc_new(ctx))) {
315 return NT_STATUS_NO_MEMORY;
316 }
317
318 if (!ctx->ops) {
319 return NT_STATUS_INVALID_PARAMETER;
320 }
321
322 if (ctx->ops->startup) {
323 status = ctx->ops->startup(mem_ctx, ctx,
324 database_id, &sequence_num);
325 if (!NT_STATUS_IS_OK(status)) {
326 goto done;
327 }
328 }
329
330 debug_str = samsync_debug_str(mem_ctx, ctx->mode, database_id);
331 if (debug_str) {
332 d_fprintf(stderr, "%s\n", debug_str);
333 }
334
335 if (!ctx->single_object_replication) {
336 status = libnet_samsync_delta(mem_ctx, database_id,
337 &sequence_num, ctx, NULL);
338 goto done;
339 }
340
341 for (i=0; i<ctx->num_objects; i++) {
342
343 struct netr_ChangeLogEntry e;
344
345 if (ctx->objects[i].database_id != database_id) {
346 continue;
347 }
348
349 libnet_init_netr_ChangeLogEntry(&ctx->objects[i], &e);
350
351 status = libnet_samsync_delta(mem_ctx, database_id,
352 &sequence_num, ctx, &e);
353 if (!NT_STATUS_IS_OK(status)) {
354 goto done;
355 }
356 }
357
358 done:
359
360 if (NT_STATUS_IS_OK(status) && ctx->ops->finish) {
361 callback_status = ctx->ops->finish(mem_ctx, ctx,
362 database_id, sequence_num);
363 if (!NT_STATUS_IS_OK(callback_status)) {
364 status = callback_status;
365 }
366 }
367
368 if (NT_STATUS_IS_ERR(status) && !ctx->error_message) {
369
370 ctx->error_message = talloc_asprintf(ctx,
371 "Failed to fetch %s database: %s",
372 samsync_database_str(database_id),
373 nt_errstr(status));
374
375 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
376
377 ctx->error_message =
378 talloc_asprintf_append(ctx->error_message,
379 "\nPerhaps %s is a Windows native mode domain?",
380 ctx->domain_name);
381 }
382 }
383
384 talloc_destroy(mem_ctx);
385
386 return status;
387}
388
389/**
390 * pull_netr_AcctLockStr
391 */
392
393NTSTATUS pull_netr_AcctLockStr(TALLOC_CTX *mem_ctx,
394 struct lsa_BinaryString *r,
395 struct netr_AcctLockStr **str_p)
396{
397 struct netr_AcctLockStr *str;
398 enum ndr_err_code ndr_err;
399 DATA_BLOB blob;
400
401 if (!mem_ctx || !r || !str_p) {
402 return NT_STATUS_INVALID_PARAMETER;
403 }
404
405 *str_p = NULL;
406
407 str = TALLOC_ZERO_P(mem_ctx, struct netr_AcctLockStr);
408 if (!str) {
409 return NT_STATUS_NO_MEMORY;
410 }
411
412 blob = data_blob_const(r->array, r->length);
413
414 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, str,
415 (ndr_pull_flags_fn_t)ndr_pull_netr_AcctLockStr);
416
417 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
418 return ndr_map_error2ntstatus(ndr_err);
419 }
420
421 *str_p = str;
422
423 return NT_STATUS_OK;
424}
425
Note: See TracBrowser for help on using the repository browser.