• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src/router/samba-3.5.8/source4/torture/ldap/
1/*
2   Unix SMB/CIFS mplementation.
3
4   test CLDAP operations
5
6   Copyright (C) Andrew Tridgell 2005
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
21*/
22
23#include "includes.h"
24#include "libcli/cldap/cldap.h"
25#include "libcli/ldap/ldap.h"
26#include "librpc/gen_ndr/ndr_nbt.h"
27#include "librpc/gen_ndr/netlogon.h"
28#include "torture/torture.h"
29#include "lib/ldb/include/ldb.h"
30#include "param/param.h"
31#include "../lib/tsocket/tsocket.h"
32
33#define CHECK_STATUS(status, correct) torture_assert_ntstatus_equal(tctx, status, correct, "incorrect status")
34
35#define CHECK_VAL(v, correct) torture_assert_int_equal(tctx, (v), (correct), "incorrect value");
36
37#define CHECK_STRING(v, correct) torture_assert_str_equal(tctx, v, correct, "incorrect value");
38/*
39  test netlogon operations
40*/
41static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
42{
43	struct cldap_socket *cldap;
44	NTSTATUS status;
45	struct cldap_netlogon search, empty_search;
46	struct netlogon_samlogon_response n1;
47	struct GUID guid;
48	int i;
49	struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(tctx->lp_ctx);
50	struct tsocket_address *dest_addr;
51	int ret;
52
53	ret = tsocket_address_inet_from_strings(tctx, "ip",
54						dest,
55						lp_cldap_port(tctx->lp_ctx),
56						&dest_addr);
57	CHECK_VAL(ret, 0);
58
59	status = cldap_socket_init(tctx, NULL, NULL, dest_addr, &cldap);
60	CHECK_STATUS(status, NT_STATUS_OK);
61
62	ZERO_STRUCT(search);
63	search.in.dest_address = NULL;
64	search.in.dest_port = 0;
65	search.in.acct_control = -1;
66	search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
67	search.in.map_response = true;
68
69	empty_search = search;
70
71	printf("Trying without any attributes\n");
72	search = empty_search;
73	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
74	CHECK_STATUS(status, NT_STATUS_OK);
75
76	n1 = search.out.netlogon;
77
78	search.in.user         = "Administrator";
79	search.in.realm        = n1.data.nt5_ex.dns_domain;
80	search.in.host         = "__cldap_torture__";
81
82	printf("Scanning for netlogon levels\n");
83	for (i=0;i<256;i++) {
84		search.in.version = i;
85		printf("Trying netlogon level %d\n", i);
86		status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
87		CHECK_STATUS(status, NT_STATUS_OK);
88	}
89
90	printf("Scanning for netlogon level bits\n");
91	for (i=0;i<31;i++) {
92		search.in.version = (1<<i);
93		printf("Trying netlogon level 0x%x\n", i);
94		status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
95		CHECK_STATUS(status, NT_STATUS_OK);
96	}
97
98	search.in.version = NETLOGON_NT_VERSION_5|NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_IP;
99
100	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
101	CHECK_STATUS(status, NT_STATUS_OK);
102
103	printf("Trying with User=NULL\n");
104
105	search.in.user = NULL;
106	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
107	CHECK_STATUS(status, NT_STATUS_OK);
108	CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
109	CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
110
111	printf("Trying with User=Administrator\n");
112
113	search.in.user = "Administrator";
114	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
115	CHECK_STATUS(status, NT_STATUS_OK);
116
117	CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
118	CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
119
120	search.in.version = NETLOGON_NT_VERSION_5;
121	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
122	CHECK_STATUS(status, NT_STATUS_OK);
123
124	printf("Trying with User=NULL\n");
125
126	search.in.user = NULL;
127	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
128	CHECK_STATUS(status, NT_STATUS_OK);
129	CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
130	CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE);
131
132	printf("Trying with User=Administrator\n");
133
134	search.in.user = "Administrator";
135	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
136	CHECK_STATUS(status, NT_STATUS_OK);
137
138	CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
139	CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN);
140
141	search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
142
143	printf("Trying with a GUID\n");
144	search.in.realm       = NULL;
145	search.in.domain_guid = GUID_string(tctx, &n1.data.nt5_ex.domain_uuid);
146	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
147	CHECK_STATUS(status, NT_STATUS_OK);
148	CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
149	CHECK_STRING(GUID_string(tctx, &search.out.netlogon.data.nt5_ex.domain_uuid), search.in.domain_guid);
150
151	printf("Trying with a incorrect GUID\n");
152	guid = GUID_random();
153	search.in.user        = NULL;
154	search.in.domain_guid = GUID_string(tctx, &guid);
155	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
156	CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
157
158	printf("Trying with a AAC\n");
159	search.in.acct_control = ACB_WSTRUST|ACB_SVRTRUST;
160	search.in.realm = n1.data.nt5_ex.dns_domain;
161	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
162	CHECK_STATUS(status, NT_STATUS_OK);
163	CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
164	CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
165
166	printf("Trying with a zero AAC\n");
167	search.in.acct_control = 0x0;
168	search.in.realm = n1.data.nt5_ex.dns_domain;
169	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
170	CHECK_STATUS(status, NT_STATUS_OK);
171	CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
172	CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
173
174	printf("Trying with a zero AAC and user=Administrator\n");
175	search.in.acct_control = 0x0;
176	search.in.user = "Administrator";
177	search.in.realm = n1.data.nt5_ex.dns_domain;
178	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
179	CHECK_STATUS(status, NT_STATUS_OK);
180	CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
181	CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "Administrator");
182
183	printf("Trying with a bad AAC\n");
184	search.in.user = NULL;
185	search.in.acct_control = 0xFF00FF00;
186	search.in.realm = n1.data.nt5_ex.dns_domain;
187	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
188	CHECK_STATUS(status, NT_STATUS_OK);
189	CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
190	CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
191
192	printf("Trying with a user only\n");
193	search = empty_search;
194	search.in.user = "Administrator";
195	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
196	CHECK_STATUS(status, NT_STATUS_OK);
197	CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
198	CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
199
200	printf("Trying with just a bad username\n");
201	search.in.user = "___no_such_user___";
202	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
203	CHECK_STATUS(status, NT_STATUS_OK);
204	CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
205	CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
206	CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
207
208	printf("Trying with just a bad domain\n");
209	search = empty_search;
210	search.in.realm = "___no_such_domain___";
211	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
212	CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
213
214	printf("Trying with a incorrect domain and correct guid\n");
215	search.in.domain_guid = GUID_string(tctx, &n1.data.nt5_ex.domain_uuid);
216	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
217	CHECK_STATUS(status, NT_STATUS_OK);
218	CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
219	CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
220	CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
221
222	printf("Trying with a incorrect domain and incorrect guid\n");
223	search.in.domain_guid = GUID_string(tctx, &guid);
224	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
225	CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
226	CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
227	CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
228	CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
229
230	printf("Trying with a incorrect GUID and correct domain\n");
231	search.in.domain_guid = GUID_string(tctx, &guid);
232	search.in.realm = n1.data.nt5_ex.dns_domain;
233	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
234	CHECK_STATUS(status, NT_STATUS_OK);
235	CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
236	CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
237	CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
238
239	return true;
240}
241
242/*
243  test cldap netlogon server type flags
244*/
245static bool test_cldap_netlogon_flags(struct torture_context *tctx,
246	const char *dest)
247{
248	struct cldap_socket *cldap;
249	NTSTATUS status;
250	struct cldap_netlogon search;
251	struct netlogon_samlogon_response n1;
252	uint32_t server_type;
253	struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(tctx->lp_ctx);
254
255	/* cldap_socket_init should now know about the dest. address */
256	status = cldap_socket_init(tctx, NULL, NULL, NULL, &cldap);
257	CHECK_STATUS(status, NT_STATUS_OK);
258
259	printf("Printing out netlogon server type flags: %s\n", dest);
260
261	ZERO_STRUCT(search);
262	search.in.dest_address = dest;
263	search.in.dest_port = lp_cldap_port(tctx->lp_ctx);
264	search.in.acct_control = -1;
265	search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
266	search.in.map_response = true;
267
268	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
269	CHECK_STATUS(status, NT_STATUS_OK);
270
271	n1 = search.out.netlogon;
272	if (n1.ntver == NETLOGON_NT_VERSION_5)
273		server_type = n1.data.nt5.server_type;
274	else if (n1.ntver == NETLOGON_NT_VERSION_5EX)
275		server_type = n1.data.nt5_ex.server_type;
276
277	printf("The word is: %i\n", server_type);
278	if (server_type & NBT_SERVER_PDC)
279		printf("NBT_SERVER_PDC ");
280	if (server_type & NBT_SERVER_GC)
281		printf("NBT_SERVER_GC ");
282	if (server_type & NBT_SERVER_LDAP)
283		printf("NBT_SERVER_LDAP ");
284	if (server_type & NBT_SERVER_DS)
285		printf("NBT_SERVER_DS ");
286	if (server_type & NBT_SERVER_KDC)
287		printf("NBT_SERVER_KDC ");
288	if (server_type & NBT_SERVER_TIMESERV)
289		printf("NBT_SERVER_TIMESERV ");
290	if (server_type & NBT_SERVER_CLOSEST)
291		printf("NBT_SERVER_CLOSEST ");
292	if (server_type & NBT_SERVER_WRITABLE)
293		printf("NBT_SERVER_WRITABLE ");
294	if (server_type & NBT_SERVER_GOOD_TIMESERV)
295		printf("NBT_SERVER_GOOD_TIMESERV ");
296	if (server_type & NBT_SERVER_NDNC)
297		printf("NBT_SERVER_NDNC ");
298	if (server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6)
299		printf("NBT_SERVER_SELECT_SECRET_DOMAIN_6");
300	if (server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6)
301		printf("NBT_SERVER_FULL_SECRET_DOMAIN_6");
302	if (server_type & DS_DNS_CONTROLLER)
303		printf("DS_DNS_CONTROLLER ");
304	if (server_type & DS_DNS_DOMAIN)
305		printf("DS_DNS_DOMAIN ");
306	if (server_type & DS_DNS_FOREST)
307		printf("DS_DNS_FOREST ");
308
309	printf("\n");
310
311	return true;
312}
313
314/*
315  convert a ldap result message to a ldb message. This allows us to
316  use the convenient ldif dump routines in ldb to print out cldap
317  search results
318*/
319static struct ldb_message *ldap_msg_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct ldap_SearchResEntry *res)
320{
321	struct ldb_message *msg;
322
323	msg = ldb_msg_new(mem_ctx);
324	msg->dn = ldb_dn_new(msg, ldb, res->dn);
325	msg->num_elements = res->num_attributes;
326	msg->elements = talloc_steal(msg, res->attributes);
327	return msg;
328}
329
330/*
331  dump a set of cldap results
332*/
333static void cldap_dump_results(struct cldap_search *search)
334{
335	struct ldb_ldif ldif;
336	struct ldb_context *ldb;
337
338	if (!search || !(search->out.response)) {
339		return;
340	}
341
342	/* we need a ldb context to use ldb_ldif_write_file() */
343	ldb = ldb_init(NULL, NULL);
344
345	ZERO_STRUCT(ldif);
346	ldif.msg = ldap_msg_to_ldb(ldb, ldb, search->out.response);
347
348	ldb_ldif_write_file(ldb, stdout, &ldif);
349
350	talloc_free(ldb);
351}
352
353
354/*
355  test cldap netlogon server type flag "NBT_SERVER_DS_DNS_FOREST"
356*/
357static bool test_cldap_netlogon_flag_ds_dns_forest(struct torture_context *tctx,
358	const char *dest)
359{
360	struct cldap_socket *cldap;
361	NTSTATUS status;
362	struct cldap_netlogon search;
363	uint32_t server_type;
364	struct netlogon_samlogon_response n1;
365	struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(tctx->lp_ctx);
366	bool result = true;
367
368	/* cldap_socket_init should now know about the dest. address */
369	status = cldap_socket_init(tctx, NULL, NULL, NULL, &cldap);
370	CHECK_STATUS(status, NT_STATUS_OK);
371
372	printf("Testing netlogon server type flag NBT_SERVER_DS_DNS_FOREST: ");
373
374	ZERO_STRUCT(search);
375	search.in.dest_address = dest;
376	search.in.dest_port = lp_cldap_port(tctx->lp_ctx);
377	search.in.acct_control = -1;
378	search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
379	search.in.map_response = true;
380
381	status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
382	CHECK_STATUS(status, NT_STATUS_OK);
383
384	n1 = search.out.netlogon;
385	if (n1.ntver == NETLOGON_NT_VERSION_5)
386		server_type = n1.data.nt5.server_type;
387	else if (n1.ntver == NETLOGON_NT_VERSION_5EX)
388		server_type = n1.data.nt5_ex.server_type;
389
390	if (server_type & DS_DNS_FOREST) {
391		struct cldap_search search2;
392		const char *attrs[] = { "defaultNamingContext", "rootDomainNamingContext",
393			NULL };
394		struct ldb_context *ldb;
395		struct ldb_message *msg;
396
397		/* Trying to fetch the attributes "defaultNamingContext" and
398		   "rootDomainNamingContext" */
399		ZERO_STRUCT(search2);
400		search2.in.dest_address = dest;
401		search2.in.dest_port = lp_cldap_port(tctx->lp_ctx);
402		search2.in.timeout = 10;
403		search2.in.retries = 3;
404		search2.in.filter = "(objectclass=*)";
405		search2.in.attributes = attrs;
406
407		status = cldap_search(cldap, tctx, &search2);
408		CHECK_STATUS(status, NT_STATUS_OK);
409
410		ldb = ldb_init(NULL, NULL);
411
412		msg = ldap_msg_to_ldb(ldb, ldb, search2.out.response);
413
414		/* Try to compare the two attributes */
415		if (ldb_msg_element_compare(ldb_msg_find_element(msg, attrs[0]),
416			ldb_msg_find_element(msg, attrs[1])))
417			result = false;
418
419		talloc_free(ldb);
420	}
421
422	if (result)
423		printf("passed\n");
424	else
425		printf("failed\n");
426
427	return result;
428}
429
430/*
431  test generic cldap operations
432*/
433static bool test_cldap_generic(struct torture_context *tctx, const char *dest)
434{
435	struct cldap_socket *cldap;
436	NTSTATUS status;
437	struct cldap_search search;
438	const char *attrs1[] = { "currentTime", "highestCommittedUSN", NULL };
439	const char *attrs2[] = { "currentTime", "highestCommittedUSN", "netlogon", NULL };
440	const char *attrs3[] = { "netlogon", NULL };
441
442	/* cldap_socket_init should now know about the dest. address */
443	status = cldap_socket_init(tctx, NULL, NULL, NULL, &cldap);
444	CHECK_STATUS(status, NT_STATUS_OK);
445
446	ZERO_STRUCT(search);
447	search.in.dest_address = dest;
448	search.in.dest_port = lp_cldap_port(tctx->lp_ctx);
449	search.in.timeout = 10;
450	search.in.retries = 3;
451
452	status = cldap_search(cldap, tctx, &search);
453	CHECK_STATUS(status, NT_STATUS_OK);
454
455	printf("fetching whole rootDSE\n");
456	search.in.filter = "(objectclass=*)";
457	search.in.attributes = NULL;
458
459	status = cldap_search(cldap, tctx, &search);
460	CHECK_STATUS(status, NT_STATUS_OK);
461
462	if (DEBUGLVL(3)) cldap_dump_results(&search);
463
464	printf("fetching currentTime and USN\n");
465	search.in.filter = "(objectclass=*)";
466	search.in.attributes = attrs1;
467
468	status = cldap_search(cldap, tctx, &search);
469	CHECK_STATUS(status, NT_STATUS_OK);
470
471	if (DEBUGLVL(3)) cldap_dump_results(&search);
472
473	printf("Testing currentTime, USN and netlogon\n");
474	search.in.filter = "(objectclass=*)";
475	search.in.attributes = attrs2;
476
477	status = cldap_search(cldap, tctx, &search);
478	CHECK_STATUS(status, NT_STATUS_OK);
479
480	if (DEBUGLVL(3)) cldap_dump_results(&search);
481
482	printf("Testing objectClass=* and netlogon\n");
483	search.in.filter = "(objectclass2=*)";
484	search.in.attributes = attrs3;
485
486	status = cldap_search(cldap, tctx, &search);
487	CHECK_STATUS(status, NT_STATUS_OK);
488
489	if (DEBUGLVL(3)) cldap_dump_results(&search);
490
491	printf("Testing a false expression\n");
492	search.in.filter = "(&(objectclass=*)(highestCommittedUSN=2))";
493	search.in.attributes = attrs1;
494
495	status = cldap_search(cldap, tctx, &search);
496	CHECK_STATUS(status, NT_STATUS_OK);
497
498	if (DEBUGLVL(3)) cldap_dump_results(&search);
499
500	return true;
501}
502
503bool torture_cldap(struct torture_context *torture)
504{
505	bool ret = true;
506	const char *host = torture_setting_string(torture, "host", NULL);
507
508	ret &= test_cldap_netlogon(torture, host);
509	ret &= test_cldap_netlogon_flags(torture, host);
510	ret &= test_cldap_netlogon_flag_ds_dns_forest(torture, host);
511	ret &= test_cldap_generic(torture, host);
512
513	return ret;
514}
515
516