1 /*
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4 
5    Copyright (C) Guenther Deschner 2008
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 #include "includes.h"
22 #include "rpcclient.h"
23 #include "../librpc/gen_ndr/ndr_drsuapi_c.h"
24 
cracknames(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,struct policy_handle * bind_handle,enum drsuapi_DsNameFormat format_offered,enum drsuapi_DsNameFormat format_desired,int argc,const char ** argv,union drsuapi_DsNameCtr * ctr)25 static WERROR cracknames(struct rpc_pipe_client *cli,
26 			 TALLOC_CTX *mem_ctx,
27 			 struct policy_handle *bind_handle,
28 			 enum drsuapi_DsNameFormat format_offered,
29 			 enum drsuapi_DsNameFormat format_desired,
30 			 int argc,
31 			 const char **argv,
32 			 union drsuapi_DsNameCtr *ctr)
33 {
34 	NTSTATUS status;
35 	WERROR werr;
36 	int i;
37 	uint32_t level = 1;
38 	union drsuapi_DsNameRequest req;
39 	uint32_t level_out;
40 	struct drsuapi_DsNameString *names;
41 	struct dcerpc_binding_handle *b = cli->binding_handle;
42 
43 	names = talloc_zero_array(mem_ctx, struct drsuapi_DsNameString, argc);
44 	W_ERROR_HAVE_NO_MEMORY(names);
45 
46 	for (i=0; i<argc; i++) {
47 		names[i].str = argv[i];
48 	}
49 
50 	req.req1.codepage	= 1252; /* german */
51 	req.req1.language	= 0x00000407; /* german */
52 	req.req1.count		= argc;
53 	req.req1.names		= names;
54 	req.req1.format_flags	= DRSUAPI_DS_NAME_FLAG_NO_FLAGS;
55 	req.req1.format_offered	= format_offered;
56 	req.req1.format_desired	= format_desired;
57 
58 	status = dcerpc_drsuapi_DsCrackNames(b, mem_ctx,
59 					     bind_handle,
60 					     level,
61 					     &req,
62 					     &level_out,
63 					     ctr,
64 					     &werr);
65 	if (!NT_STATUS_IS_OK(status)) {
66 		return ntstatus_to_werror(status);
67 	}
68 
69 	if (!W_ERROR_IS_OK(werr)) {
70 		return werr;
71 	}
72 
73 	return WERR_OK;
74 }
75 
cmd_drsuapi_cracknames(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)76 static WERROR cmd_drsuapi_cracknames(struct rpc_pipe_client *cli,
77 				     TALLOC_CTX *mem_ctx, int argc,
78 				     const char **argv)
79 {
80 	NTSTATUS status;
81 	WERROR werr;
82 	int i;
83 
84 	struct GUID bind_guid;
85 	struct policy_handle bind_handle;
86 	struct dcerpc_binding_handle *b = cli->binding_handle;
87 
88 	union drsuapi_DsNameCtr ctr;
89 
90 	if (argc < 2) {
91 		printf("usage: %s name\n", argv[0]);
92 		return WERR_OK;
93 	}
94 
95 	GUID_from_string(DRSUAPI_DS_BIND_GUID, &bind_guid);
96 
97 	status = dcerpc_drsuapi_DsBind(b, mem_ctx,
98 				       &bind_guid,
99 				       NULL,
100 				       &bind_handle,
101 				       &werr);
102 
103 	if (!NT_STATUS_IS_OK(status)) {
104 		return ntstatus_to_werror(status);
105 	}
106 
107 	if (!W_ERROR_IS_OK(werr)) {
108 		return werr;
109 	}
110 
111 	werr = cracknames(cli, mem_ctx,
112 			  &bind_handle,
113 			  DRSUAPI_DS_NAME_FORMAT_UNKNOWN,
114 			  DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
115 			  1,
116 			  argv+1,
117 			  &ctr);
118 
119 	if (!W_ERROR_IS_OK(werr)) {
120 		goto out;
121 	}
122 
123 	for (i=0; i < ctr.ctr1->count; i++) {
124 		printf("status: %d\n",
125 			ctr.ctr1->array[i].status);
126 		printf("dns_domain_name: %s\n",
127 			ctr.ctr1->array[i].dns_domain_name);
128 		printf("result_name: %s\n",
129 			ctr.ctr1->array[i].result_name);
130 	}
131 
132  out:
133 	if (is_valid_policy_hnd(&bind_handle)) {
134 		WERROR _werr;
135 		dcerpc_drsuapi_DsUnbind(b, mem_ctx, &bind_handle, &_werr);
136 	}
137 
138 	return werr;
139 }
140 
display_domain_controller_info_01(struct drsuapi_DsGetDCConnection01 * r)141 static void display_domain_controller_info_01(struct drsuapi_DsGetDCConnection01 *r)
142 {
143 	printf("client_ip_address:\t%s\n", r->client_ip_address);
144 	printf("unknown2:\t%d\n", r->unknown2);
145 	printf("connection_time:\t%d\n", r->connection_time);
146 	printf("unknown4:\t%d\n", r->unknown4);
147 	printf("unknown5:\t%d\n", r->unknown5);
148 	printf("unknown6:\t%d\n", r->unknown6);
149 	printf("client_account:\t%s\n", r->client_account);
150 }
151 
display_domain_controller_info_1(struct drsuapi_DsGetDCInfo1 * r)152 static void display_domain_controller_info_1(struct drsuapi_DsGetDCInfo1 *r)
153 {
154 	printf("netbios_name:\t%s\n", r->netbios_name);
155 	printf("dns_name:\t%s\n", r->dns_name);
156 	printf("site_name:\t%s\n", r->site_name);
157 	printf("computer_dn:\t%s\n", r->computer_dn);
158 	printf("server_dn:\t%s\n", r->server_dn);
159 	printf("is_pdc:\t\t%s\n", r->is_pdc ? "true" : "false");
160 	printf("is_enabled:\t%s\n", r->is_enabled ? "true" : "false");
161 }
162 
display_domain_controller_info_2(struct drsuapi_DsGetDCInfo2 * r)163 static void display_domain_controller_info_2(struct drsuapi_DsGetDCInfo2 *r)
164 {
165 	printf("netbios_name:\t%s\n", r->netbios_name);
166 	printf("dns_name:\t%s\n", r->dns_name);
167 	printf("site_name:\t%s\n", r->site_name);
168 	printf("site_dn:\t%s\n", r->site_dn);
169 	printf("computer_dn:\t%s\n", r->computer_dn);
170 	printf("server_dn:\t%s\n", r->server_dn);
171 	printf("ntds_dn:\t%s\n", r->ntds_dn);
172 	printf("is_pdc:\t\t%s\n", r->is_pdc ? "true" : "false");
173 	printf("is_enabled:\t%s\n", r->is_enabled ? "true" : "false");
174 	printf("is_gc:\t\t%s\n", r->is_gc ? "true" : "false");
175 	printf("site_guid:\t%s\n", GUID_string(talloc_tos(), &r->site_guid));
176 	printf("computer_guid:\t%s\n", GUID_string(talloc_tos(), &r->computer_guid));
177 	printf("server_guid:\t%s\n", GUID_string(talloc_tos(), &r->server_guid));
178 	printf("ntds_guid:\t%s\n", GUID_string(talloc_tos(), &r->ntds_guid));
179 }
180 
display_domain_controller_info_3(struct drsuapi_DsGetDCInfo3 * r)181 static void display_domain_controller_info_3(struct drsuapi_DsGetDCInfo3 *r)
182 {
183 	printf("netbios_name:\t%s\n", r->netbios_name);
184 	printf("dns_name:\t%s\n", r->dns_name);
185 	printf("site_name:\t%s\n", r->site_name);
186 	printf("site_dn:\t%s\n", r->site_dn);
187 	printf("computer_dn:\t%s\n", r->computer_dn);
188 	printf("server_dn:\t%s\n", r->server_dn);
189 	printf("ntds_dn:\t%s\n", r->ntds_dn);
190 	printf("is_pdc:\t\t%s\n", r->is_pdc ? "true" : "false");
191 	printf("is_enabled:\t%s\n", r->is_enabled ? "true" : "false");
192 	printf("is_gc:\t\t%s\n", r->is_gc ? "true" : "false");
193 	printf("is_rodc:\t%s\n", r->is_rodc ? "true" : "false");
194 	printf("site_guid:\t%s\n", GUID_string(talloc_tos(), &r->site_guid));
195 	printf("computer_guid:\t%s\n", GUID_string(talloc_tos(), &r->computer_guid));
196 	printf("server_guid:\t%s\n", GUID_string(talloc_tos(), &r->server_guid));
197 	printf("ntds_guid:\t%s\n", GUID_string(talloc_tos(), &r->ntds_guid));
198 }
199 
display_domain_controller_info(int32_t level,union drsuapi_DsGetDCInfoCtr * ctr)200 static void display_domain_controller_info(int32_t level,
201 					   union drsuapi_DsGetDCInfoCtr *ctr)
202 {
203 	int i;
204 
205 	switch (level) {
206 		case DRSUAPI_DC_CONNECTION_CTR_01:
207 			for (i=0; i<ctr->ctr01.count; i++) {
208 				printf("----------\n");
209 				display_domain_controller_info_01(&ctr->ctr01.array[i]);
210 			}
211 			break;
212 		case DRSUAPI_DC_INFO_CTR_1:
213 			for (i=0; i<ctr->ctr1.count; i++) {
214 				printf("----------\n");
215 				display_domain_controller_info_1(&ctr->ctr1.array[i]);
216 			}
217 			break;
218 		case DRSUAPI_DC_INFO_CTR_2:
219 			for (i=0; i<ctr->ctr2.count; i++) {
220 				printf("----------\n");
221 				display_domain_controller_info_2(&ctr->ctr2.array[i]);
222 			}
223 			break;
224 		case DRSUAPI_DC_INFO_CTR_3:
225 			for (i=0; i<ctr->ctr3.count; i++) {
226 				printf("----------\n");
227 				display_domain_controller_info_3(&ctr->ctr3.array[i]);
228 			}
229 			break;
230 		default:
231 			break;
232 	}
233 }
234 
cmd_drsuapi_getdcinfo(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)235 static WERROR cmd_drsuapi_getdcinfo(struct rpc_pipe_client *cli,
236 				    TALLOC_CTX *mem_ctx, int argc,
237 				    const char **argv)
238 {
239 	NTSTATUS status;
240 	WERROR werr;
241 
242 	struct GUID bind_guid;
243 	struct policy_handle bind_handle;
244 	struct dcerpc_binding_handle *b = cli->binding_handle;
245 
246 	const char *domain = NULL;
247 	int32_t level = 1;
248 	int32_t level_out;
249 	union drsuapi_DsGetDCInfoRequest req;
250 	union drsuapi_DsGetDCInfoCtr ctr;
251 
252 	if (argc < 2) {
253 		printf("usage: %s domain [level]\n", argv[0]);
254 		return WERR_OK;
255 	}
256 
257 	domain = argv[1];
258 	if (argc >= 3) {
259 		level = atoi(argv[2]);
260 	}
261 
262 	GUID_from_string(DRSUAPI_DS_BIND_GUID, &bind_guid);
263 
264 	status = dcerpc_drsuapi_DsBind(b, mem_ctx,
265 				       &bind_guid,
266 				       NULL,
267 				       &bind_handle,
268 				       &werr);
269 
270 	if (!NT_STATUS_IS_OK(status)) {
271 		return ntstatus_to_werror(status);
272 	}
273 
274 	if (!W_ERROR_IS_OK(werr)) {
275 		return werr;
276 	}
277 
278 	req.req1.domain_name = domain;
279 	req.req1.level = level;
280 
281 	status = dcerpc_drsuapi_DsGetDomainControllerInfo(b, mem_ctx,
282 							  &bind_handle,
283 							  1,
284 							  &req,
285 							  &level_out,
286 							  &ctr,
287 							  &werr);
288 	if (!NT_STATUS_IS_OK(status)) {
289 		werr = ntstatus_to_werror(status);
290 		goto out;
291 	}
292 
293 	if (!W_ERROR_IS_OK(werr)) {
294 		goto out;
295 	}
296 
297 	display_domain_controller_info(level_out, &ctr);
298  out:
299 	if (is_valid_policy_hnd(&bind_handle)) {
300 		WERROR _werr;
301 		dcerpc_drsuapi_DsUnbind(b, mem_ctx, &bind_handle, &_werr);
302 	}
303 
304 	return werr;
305 }
306 
cmd_drsuapi_writeaccountspn(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)307 static WERROR cmd_drsuapi_writeaccountspn(struct rpc_pipe_client *cli,
308 					  TALLOC_CTX *mem_ctx, int argc,
309 					  const char **argv)
310 {
311 	NTSTATUS status;
312 	WERROR werr;
313 
314 	struct GUID bind_guid;
315 	struct policy_handle bind_handle;
316 	struct dcerpc_binding_handle *b = cli->binding_handle;
317 	struct drsuapi_DsNameString *spn_names = NULL;
318 
319 	int i = 0;
320 	uint32_t level_out;
321 	union drsuapi_DsWriteAccountSpnRequest req;
322 	union drsuapi_DsWriteAccountSpnResult result;
323 
324 	if (argc < 4) {
325 		printf("usage: %s [add|replace|delete] dn [spn_names]+\n", argv[0]);
326 		return WERR_OK;
327 	}
328 
329 	req.req1.unknown1 = 0;  /* Unused, must be 0 */
330 	req.req1.object_dn = argv[2];
331 	req.req1.count = argc - 3;
332 
333 	if (strcmp(argv[1], "add") == 0) {
334 		req.req1.operation = DRSUAPI_DS_SPN_OPERATION_ADD;
335 	} else if (strcmp(argv[1], "replace") == 0) {
336 		req.req1.operation = DRSUAPI_DS_SPN_OPERATION_REPLACE;
337 	} else if (strcmp(argv[1], "delete") == 0) {
338 		req.req1.operation = DRSUAPI_DS_SPN_OPERATION_DELETE;
339 	} else {
340 		printf("usage: %s [add|replace|delete] dn [spn_names]+\n", argv[0]);
341 		return WERR_OK;
342 	}
343 
344 	spn_names = talloc_zero_array(mem_ctx,
345 				      struct drsuapi_DsNameString,
346 				      req.req1.count);
347 	W_ERROR_HAVE_NO_MEMORY(spn_names);
348 
349 	for (i=0; i<req.req1.count; i++) {
350 		spn_names[i].str = argv[i + 3];
351 	}
352 
353 	req.req1.spn_names = spn_names;
354 
355 	GUID_from_string(DRSUAPI_DS_BIND_GUID, &bind_guid);
356 
357 	status = dcerpc_drsuapi_DsBind(b, mem_ctx,
358 				       &bind_guid,
359 				       NULL,
360 				       &bind_handle,
361 				       &werr);
362 
363 	if (!NT_STATUS_IS_OK(status)) {
364 		return ntstatus_to_werror(status);
365 	}
366 
367 	if (!W_ERROR_IS_OK(werr)) {
368 		return werr;
369 	}
370 
371 	status = dcerpc_drsuapi_DsWriteAccountSpn(b, mem_ctx,
372 						  &bind_handle,
373 						  1,
374 						  &req,
375 						  &level_out,
376 						  &result,
377 						  &werr);
378 
379 	if (!NT_STATUS_IS_OK(status)) {
380 		werr = ntstatus_to_werror(status);
381 		goto out;
382 	}
383 
384 	if (!W_ERROR_IS_OK(werr)) {
385 		goto out;
386 	}
387 
388  out:
389 	if (is_valid_policy_hnd(&bind_handle)) {
390 		WERROR _werr;
391 		dcerpc_drsuapi_DsUnbind(b, mem_ctx, &bind_handle, &_werr);
392 	}
393 
394 	return werr;
395 }
396 
cmd_drsuapi_getncchanges(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)397 static WERROR cmd_drsuapi_getncchanges(struct rpc_pipe_client *cli,
398 				       TALLOC_CTX *mem_ctx, int argc,
399 				       const char **argv)
400 {
401 	NTSTATUS status;
402 	WERROR werr;
403 
404 	struct policy_handle bind_handle;
405 	struct dcerpc_binding_handle *b = cli->binding_handle;
406 
407 	struct GUID bind_guid;
408 	struct drsuapi_DsBindInfoCtr bind_info;
409 	struct drsuapi_DsBindInfo28 info28;
410 
411 	const char *nc_dn = NULL;
412 
413 	DATA_BLOB session_key;
414 
415 	uint32_t level = 8;
416 	bool single = false;
417 	uint32_t level_out = 0;
418 	union drsuapi_DsGetNCChangesRequest req;
419 	union drsuapi_DsGetNCChangesCtr ctr;
420 	struct drsuapi_DsReplicaObjectIdentifier nc;
421 
422 	struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL;
423 	struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL;
424 	uint32_t out_level = 0;
425 	int y;
426 
427 	uint32_t supported_extensions = 0;
428 	uint32_t replica_flags	= DRSUAPI_DRS_WRIT_REP |
429 				  DRSUAPI_DRS_INIT_SYNC |
430 				  DRSUAPI_DRS_PER_SYNC |
431 				  DRSUAPI_DRS_GET_ANC |
432 				  DRSUAPI_DRS_NEVER_SYNCED;
433 
434 	if (argc > 3) {
435 		printf("usage: %s [naming_context_or_object_dn [single]]\n", argv[0]);
436 		return WERR_OK;
437 	}
438 
439 	if (argc >= 2) {
440 		nc_dn = argv[1];
441 	}
442 
443 	if (argc == 3) {
444 		if (strequal(argv[2], "single")) {
445 			single = true;
446 		} else {
447 			printf("warning: ignoring unknown argument '%s'\n",
448 			       argv[2]);
449 		}
450 	}
451 
452 	ZERO_STRUCT(info28);
453 
454 	ZERO_STRUCT(req);
455 
456 	GUID_from_string(DRSUAPI_DS_BIND_GUID, &bind_guid);
457 
458 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_BASE;
459 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION;
460 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI;
461 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2;
462 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS;
463 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1;
464 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION;
465 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
466 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
467 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
468 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2;
469 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD;
470 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND;
471 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO;
472 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION;
473 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01;
474 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP;
475 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY;
476 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3;
477 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2;
478 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6;
479 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS;
480 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8;
481 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5;
482 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6;
483 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
484 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7;
485 	info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT;
486 	info28.site_guid		= GUID_zero();
487 	info28.pid			= 0;
488 	info28.repl_epoch		= 0;
489 
490 	bind_info.length = 28;
491 	bind_info.info.info28 = info28;
492 
493 	status = dcerpc_drsuapi_DsBind(b, mem_ctx,
494 				       &bind_guid,
495 				       &bind_info,
496 				       &bind_handle,
497 				       &werr);
498 
499 	if (!NT_STATUS_IS_OK(status)) {
500 		return ntstatus_to_werror(status);
501 	}
502 
503 	if (!W_ERROR_IS_OK(werr)) {
504 		return werr;
505 	}
506 
507 	if (bind_info.length == 24) {
508 		supported_extensions = bind_info.info.info24.supported_extensions;
509 	} else if (bind_info.length == 28) {
510 		supported_extensions = bind_info.info.info28.supported_extensions;
511 	} else if (bind_info.length == 32) {
512 		supported_extensions = bind_info.info.info32.supported_extensions;
513 	} else if (bind_info.length == 48) {
514 		supported_extensions = bind_info.info.info48.supported_extensions;
515 	} else if (bind_info.length == 52) {
516 		supported_extensions = bind_info.info.info52.supported_extensions;
517 	}
518 
519 	if (!nc_dn) {
520 
521 		union drsuapi_DsNameCtr crack_ctr;
522 		const char *name;
523 
524 		name = talloc_asprintf(mem_ctx, "%s\\", lp_workgroup());
525 		W_ERROR_HAVE_NO_MEMORY(name);
526 
527 		werr = cracknames(cli, mem_ctx,
528 				  &bind_handle,
529 				  DRSUAPI_DS_NAME_FORMAT_UNKNOWN,
530 				  DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
531 				  1,
532 				  &name,
533 				  &crack_ctr);
534 		if (!W_ERROR_IS_OK(werr)) {
535 			return werr;
536 		}
537 
538 		if (crack_ctr.ctr1->count != 1) {
539 			return WERR_NO_SUCH_DOMAIN;
540 		}
541 
542 		if (crack_ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
543 			return WERR_NO_SUCH_DOMAIN;
544 		}
545 
546 		nc_dn = talloc_strdup(mem_ctx, crack_ctr.ctr1->array[0].result_name);
547 		W_ERROR_HAVE_NO_MEMORY(nc_dn);
548 
549 		printf("using: %s\n", nc_dn);
550 	}
551 
552 	nc.dn = nc_dn;
553 	nc.guid = GUID_zero();
554 	nc.sid = (struct dom_sid) {0};
555 
556 	if (supported_extensions & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8) {
557 		level = 8;
558 		req.req8.naming_context		= &nc;
559 		req.req8.replica_flags		= replica_flags;
560 		req.req8.max_object_count	= 402;
561 		req.req8.max_ndr_size		= 402116;
562 		if (single) {
563 			req.req8.extended_op	= DRSUAPI_EXOP_REPL_OBJ;
564 		}
565 	} else {
566 		level = 5;
567 		req.req5.naming_context		= &nc;
568 		req.req5.replica_flags		= replica_flags;
569 		req.req5.max_object_count	= 402;
570 		req.req5.max_ndr_size		= 402116;
571 		if (single) {
572 			req.req5.extended_op	= DRSUAPI_EXOP_REPL_OBJ;
573 		}
574 	}
575 
576 	for (y=0; ;y++) {
577 
578 		if (level == 8) {
579 			DEBUG(1,("start[%d] tmp_higest_usn: %llu , highest_usn: %llu\n",y,
580 				(long long)req.req8.highwatermark.tmp_highest_usn,
581 				(long long)req.req8.highwatermark.highest_usn));
582 		}
583 
584 		status = dcerpc_drsuapi_DsGetNCChanges(b, mem_ctx,
585 						       &bind_handle,
586 						       level,
587 						       &req,
588 						       &level_out,
589 						       &ctr,
590 						       &werr);
591 		if (!NT_STATUS_IS_OK(status)) {
592 			werr = ntstatus_to_werror(status);
593 			printf("Failed to get NC Changes: %s",
594 				get_friendly_nt_error_msg(status));
595 			goto out;
596 		}
597 
598 		if (!W_ERROR_IS_OK(werr)) {
599 			printf("Failed to get NC Changes: %s",
600 				get_friendly_werror_msg(werr));
601 			goto out;
602 		}
603 
604 		if (level_out == 1) {
605 			out_level = 1;
606 			ctr1 = &ctr.ctr1;
607 		} else if (level_out == 2 && ctr.ctr2.mszip1.ts) {
608 			out_level = 1;
609 			ctr1 = &ctr.ctr2.mszip1.ts->ctr1;
610 		}
611 
612 		status = cli_get_session_key(mem_ctx, cli, &session_key);
613 		if (!NT_STATUS_IS_OK(status)) {
614 			printf("Failed to get Session Key: %s",
615 				nt_errstr(status));
616 			return ntstatus_to_werror(status);
617 		}
618 
619 		if (out_level == 1) {
620 			DEBUG(1,("end[%d] tmp_highest_usn: %llu , highest_usn: %llu\n",y,
621 				(long long)ctr1->new_highwatermark.tmp_highest_usn,
622 				(long long)ctr1->new_highwatermark.highest_usn));
623 #if 0
624 			libnet_dssync_decrypt_attributes(mem_ctx,
625 							 &session_key,
626 							 ctr1->first_object);
627 #endif
628 			if (ctr1->more_data) {
629 				req.req5.highwatermark = ctr1->new_highwatermark;
630 				continue;
631 			}
632 		}
633 
634 		if (level_out == 6) {
635 			out_level = 6;
636 			ctr6 = &ctr.ctr6;
637 		} else if (level_out == 7
638 			   && ctr.ctr7.level == 6
639 			   && ctr.ctr7.type == DRSUAPI_COMPRESSION_TYPE_MSZIP
640 			   && ctr.ctr7.ctr.mszip6.ts) {
641 			out_level = 6;
642 			ctr6 = &ctr.ctr7.ctr.mszip6.ts->ctr6;
643 		} else if (level_out == 7
644 			   && ctr.ctr7.level == 6
645 			   && ctr.ctr7.type == DRSUAPI_COMPRESSION_TYPE_XPRESS
646 			   && ctr.ctr7.ctr.xpress6.ts) {
647 			out_level = 6;
648 			ctr6 = &ctr.ctr7.ctr.xpress6.ts->ctr6;
649 		}
650 
651 		if (out_level == 6) {
652 			DEBUG(1,("end[%d] tmp_highest_usn: %llu , highest_usn: %llu\n",y,
653 				(long long)ctr6->new_highwatermark.tmp_highest_usn,
654 				(long long)ctr6->new_highwatermark.highest_usn));
655 #if 0
656 			libnet_dssync_decrypt_attributes(mem_ctx,
657 							 &session_key,
658 							 ctr6->first_object);
659 #endif
660 			if (ctr6->more_data) {
661 				req.req8.highwatermark = ctr6->new_highwatermark;
662 				continue;
663 			}
664 		}
665 
666 		break;
667 	}
668 
669  out:
670 	return werr;
671 }
672 
673 /* List of commands exported by this module */
674 
675 struct cmd_set drsuapi_commands[] = {
676 
677 	{
678 		.name = "DRSUAPI",
679 	},
680 	{
681 		.name               = "dscracknames",
682 		.returntype         = RPC_RTYPE_WERROR,
683 		.ntfn               = NULL,
684 		.wfn                = cmd_drsuapi_cracknames,
685 		.table              = &ndr_table_drsuapi,
686 		.rpc_pipe           = NULL,
687 		.description        = "Crack Name",
688 		.usage              = "",
689 	},
690 	{
691 		.name               = "dsgetdcinfo",
692 		.returntype         = RPC_RTYPE_WERROR,
693 		.ntfn               = NULL,
694 		.wfn                = cmd_drsuapi_getdcinfo,
695 		.table              = &ndr_table_drsuapi,
696 		.rpc_pipe           = NULL,
697 		.description        = "Get Domain Controller Info",
698 		.usage              = "",
699 	},
700 	{
701 		.name               = "dsgetncchanges",
702 		.returntype         = RPC_RTYPE_WERROR,
703 		.ntfn               = NULL,
704 		.wfn                = cmd_drsuapi_getncchanges,
705 		.table              = &ndr_table_drsuapi,
706 		.rpc_pipe           = NULL,
707 		.description        = "Get NC Changes",
708 		.usage              = "",
709 	},
710 	{
711 		.name               = "dswriteaccountspn",
712 		.returntype         = RPC_RTYPE_WERROR,
713 		.ntfn               = NULL,
714 		.wfn                = cmd_drsuapi_writeaccountspn,
715 		.table              = &ndr_table_drsuapi,
716 		.rpc_pipe           = NULL,
717 		.description        = "Write Account SPN",
718 		.usage              = "",
719 	},
720 	{
721 		.name = NULL,
722 	},
723 };
724