1 /*
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Guenther Deschner 2009-2010
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "lib/replace/replace.h"
21 #include "libcli/util/ntstatus.h"
22 #include "libcli/util/werror.h"
23 #include "lib/util/data_blob.h"
24 #include "lib/util/time.h"
25 #include "libcli/resolve/resolve.h"
26 #include "nsswitch/libwbclient/wbclient.h"
27 #include "torture/smbtorture.h"
28 #include "torture/winbind/proto.h"
29 #include "lib/util/util_net.h"
30 #include "lib/util/charset/charset.h"
31 #include "libcli/auth/libcli_auth.h"
32 #include "lib/param/param.h"
33 #include "lib/util/samba_util.h"
34 #include "auth/credentials/credentials.h"
35 #include "lib/cmdline/popt_common.h"
36 
37 #include <gnutls/gnutls.h>
38 #include <gnutls/crypto.h>
39 
40 #define WBC_ERROR_EQUAL(x,y) (x == y)
41 
42 #define torture_assert_wbc_equal(torture_ctx, got, expected, cmt, cmt_arg)	\
43 	do { wbcErr __got = got, __expected = expected; \
44 	if (!WBC_ERROR_EQUAL(__got, __expected)) { \
45 		torture_result(torture_ctx, TORTURE_FAIL, __location__": "#got" was %s, expected %s: " cmt, wbcErrorString(__got), wbcErrorString(__expected), cmt_arg); \
46 		return false; \
47 	} \
48 	} while (0)
49 
50 #define torture_assert_wbc_ok(torture_ctx,expr,cmt,cmt_arg)			\
51 	torture_assert_wbc_equal(torture_ctx,expr,WBC_ERR_SUCCESS,cmt,cmt_arg)
52 
53 #define torture_assert_wbc_equal_goto_fail(torture_ctx, got, expected, cmt, cmt_arg)	\
54 	do { wbcErr __got = got, __expected = expected; \
55 	if (!WBC_ERROR_EQUAL(__got, __expected)) { \
56 		torture_result(torture_ctx, TORTURE_FAIL, __location__": "#got" was %s, expected %s: " cmt, wbcErrorString(__got), wbcErrorString(__expected), cmt_arg); \
57 		goto fail;						\
58 	} \
59 	} while (0)
60 
61 #define torture_assert_wbc_ok_goto_fail(torture_ctx,expr,cmt,cmt_arg)			\
62 	torture_assert_wbc_equal_goto_fail(torture_ctx,expr,WBC_ERR_SUCCESS,cmt,cmt_arg)
63 
64 #define torture_assert_str_equal_goto_fail(torture_ctx,got,expected,cmt)\
65 	do { const char *__got = (got), *__expected = (expected); \
66 	if (strcmp(__got, __expected) != 0) { \
67 		torture_result(torture_ctx, TORTURE_FAIL, \
68 			__location__": "#got" was %s, expected %s: %s", \
69 			__got, __expected, cmt); \
70 		goto fail;;			 \
71 	} \
72 	} while(0)
73 
test_wbc_ping(struct torture_context * tctx)74 static bool test_wbc_ping(struct torture_context *tctx)
75 {
76 	torture_assert_wbc_ok(tctx, wbcPing(),
77 		"%s", "wbcPing failed");
78 
79 	return true;
80 }
81 
test_wbc_pingdc(struct torture_context * tctx)82 static bool test_wbc_pingdc(struct torture_context *tctx)
83 {
84 	struct wbcInterfaceDetails *details = NULL;
85 	wbcErr ret = false;
86 
87 	torture_assert_wbc_equal_goto_fail(tctx,
88 					   wbcPingDc("random_string", NULL),
89 					   WBC_ERR_DOMAIN_NOT_FOUND,
90 					   "%s",
91 					   "wbcPingDc failed");
92 	torture_assert_wbc_ok_goto_fail(tctx, wbcPingDc(NULL, NULL),
93 		"%s", "wbcPingDc failed");
94 
95 	torture_assert_wbc_ok_goto_fail(tctx, wbcInterfaceDetails(&details),
96 		"%s", "wbcInterfaceDetails failed");
97 	torture_assert_goto(tctx, details, ret, fail,
98 		       "wbcInterfaceDetails returned NULL pointer");
99 	torture_assert_goto(tctx, details->netbios_domain, ret, fail,
100 		       "wbcInterfaceDetails returned NULL netbios_domain");
101 
102 	torture_assert_wbc_ok_goto_fail(tctx,
103 					wbcPingDc(details->netbios_domain, NULL),
104 					"wbcPingDc(%s) failed",
105 					details->netbios_domain);
106 
107 	torture_assert_wbc_ok_goto_fail(tctx,
108 					wbcPingDc("BUILTIN", NULL),
109 					"%s",
110 					"wbcPingDc(BUILTIN) failed");
111 
112 	ret = true;
113 fail:
114 	wbcFreeMemory(details);
115 	return ret;
116 }
117 
test_wbc_pingdc2(struct torture_context * tctx)118 static bool test_wbc_pingdc2(struct torture_context *tctx)
119 {
120 	struct wbcInterfaceDetails *details = NULL;
121 	char *name = NULL;
122 	wbcErr ret = false;
123 
124 	torture_assert_wbc_equal_goto_fail(tctx,
125 					   wbcPingDc2("random_string", NULL, &name),
126 					   WBC_ERR_DOMAIN_NOT_FOUND,
127 					   "%s",
128 					   "wbcPingDc2 failed");
129 	torture_assert_wbc_ok_goto_fail(tctx,
130 					wbcPingDc2(NULL, NULL, &name),
131 					"%s",
132 					"wbcPingDc2 failed");
133 	wbcFreeMemory(name);
134 	name = NULL;
135 
136 	torture_assert_wbc_ok_goto_fail(tctx,
137 					wbcInterfaceDetails(&details),
138 					"%s",
139 					"wbcInterfaceDetails failed");
140 	torture_assert_goto(tctx,
141 			    details,
142 			    ret,
143 			    fail,
144 			    "wbcInterfaceDetails returned NULL pointer");
145 	torture_assert_goto(tctx,
146 			    details->netbios_domain,
147 			    ret,
148 			    fail,
149 			    "wbcInterfaceDetails returned NULL netbios_domain");
150 
151 	torture_assert_wbc_ok_goto_fail(tctx,
152 					wbcPingDc2(details->netbios_domain, NULL, &name),
153 					"wbcPingDc2(%s) failed",
154 					details->netbios_domain);
155 	wbcFreeMemory(name);
156 	name = NULL;
157 
158 	torture_assert_wbc_ok_goto_fail(tctx,
159 					wbcPingDc2("BUILTIN", NULL, &name),
160 					"%s",
161 					"wbcPingDc2(BUILTIN) failed");
162 
163 	ret = true;
164 fail:
165 	wbcFreeMemory(name);
166 	wbcFreeMemory(details);
167 
168 	return ret;
169 }
170 
test_wbc_library_details(struct torture_context * tctx)171 static bool test_wbc_library_details(struct torture_context *tctx)
172 {
173 	struct wbcLibraryDetails *details;
174 
175 	torture_assert_wbc_ok(tctx, wbcLibraryDetails(&details),
176 		"%s", "wbcLibraryDetails failed");
177 	torture_assert(tctx, details,
178 		"wbcLibraryDetails returned NULL pointer");
179 
180 	wbcFreeMemory(details);
181 
182 	return true;
183 }
184 
test_wbc_interface_details(struct torture_context * tctx)185 static bool test_wbc_interface_details(struct torture_context *tctx)
186 {
187 	struct wbcInterfaceDetails *details;
188 
189 	torture_assert_wbc_ok(tctx, wbcInterfaceDetails(&details),
190 		"%s", "wbcInterfaceDetails failed");
191 	torture_assert(tctx, details,
192 		       "wbcInterfaceDetails returned NULL pointer");
193 
194 	wbcFreeMemory(details);
195 
196 	return true;
197 }
198 
test_wbc_sidtypestring(struct torture_context * tctx)199 static bool test_wbc_sidtypestring(struct torture_context *tctx)
200 {
201 	torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_USE_NONE),
202 				 "SID_NONE", "SID_NONE failed");
203 	torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_USER),
204 				 "SID_USER", "SID_USER failed");
205 	torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_DOM_GRP),
206 				 "SID_DOM_GROUP", "SID_DOM_GROUP failed");
207 	torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_DOMAIN),
208 				 "SID_DOMAIN", "SID_DOMAIN failed");
209 	torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_ALIAS),
210 				 "SID_ALIAS", "SID_ALIAS failed");
211 	torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_WKN_GRP),
212 				 "SID_WKN_GROUP", "SID_WKN_GROUP failed");
213 	torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_DELETED),
214 				 "SID_DELETED", "SID_DELETED failed");
215 	torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_INVALID),
216 				 "SID_INVALID", "SID_INVALID failed");
217 	torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_UNKNOWN),
218 				 "SID_UNKNOWN", "SID_UNKNOWN failed");
219 	torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_COMPUTER),
220 				 "SID_COMPUTER",  "SID_COMPUTER failed");
221 	torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_LABEL),
222 				 "SID_LABEL",  "SID_LABEL failed");
223 	return true;
224 }
225 
test_wbc_sidtostring(struct torture_context * tctx)226 static bool test_wbc_sidtostring(struct torture_context *tctx)
227 {
228 	struct wbcDomainSid sid;
229 	const char *sid_string = "S-1-5-32";
230 	char *sid_string2;
231 
232 	torture_assert_wbc_ok(tctx, wbcStringToSid(sid_string, &sid),
233 			      "wbcStringToSid of %s failed", sid_string);
234 	torture_assert_wbc_ok(tctx, wbcSidToString(&sid, &sid_string2),
235 			      "wbcSidToString of %s failed", sid_string);
236 	torture_assert_str_equal(tctx, sid_string, sid_string2,
237 		"sid strings differ");
238 	wbcFreeMemory(sid_string2);
239 
240 	return true;
241 }
242 
test_wbc_guidtostring(struct torture_context * tctx)243 static bool test_wbc_guidtostring(struct torture_context *tctx)
244 {
245 	struct wbcGuid guid;
246 	const char *guid_string = "f7cf07b4-1487-45c7-824d-8b18cc580811";
247 	char *guid_string2;
248 
249 	torture_assert_wbc_ok(tctx, wbcStringToGuid(guid_string, &guid),
250 			      "wbcStringToGuid of %s failed", guid_string);
251 	torture_assert_wbc_ok(tctx, wbcGuidToString(&guid, &guid_string2),
252 			      "wbcGuidToString of %s failed", guid_string);
253 	torture_assert_str_equal(tctx, guid_string, guid_string2,
254 				 "guid strings differ");
255 	wbcFreeMemory(guid_string2);
256 
257 	return true;
258 }
259 
test_wbc_domain_info(struct torture_context * tctx)260 static bool test_wbc_domain_info(struct torture_context *tctx)
261 {
262 	struct wbcDomainInfo *info = NULL;
263 	struct wbcInterfaceDetails *details = NULL;
264 	wbcErr ret = false;
265 
266 	torture_assert_wbc_ok_goto_fail(tctx,
267 					wbcInterfaceDetails(&details),
268 					"%s",
269 					"wbcInterfaceDetails failed");
270 	torture_assert_wbc_ok_goto_fail(tctx,
271 					wbcDomainInfo(details->netbios_domain, &info),
272 					"%s",
273 					"wbcDomainInfo failed");
274 
275 	torture_assert_goto(tctx,
276 			    info,
277 			    ret,
278 			    fail,
279 			    "wbcDomainInfo returned NULL pointer");
280 
281 	ret = true;
282 fail:
283 	wbcFreeMemory(details);
284 	wbcFreeMemory(info);
285 
286 	return ret;
287 }
288 
test_wbc_users(struct torture_context * tctx)289 static bool test_wbc_users(struct torture_context *tctx)
290 {
291 	const char *domain_name = NULL;
292 	uint32_t num_users;
293 	const char **users = NULL;
294 	uint32_t i;
295 	struct wbcInterfaceDetails *details = NULL;
296 	struct wbcDomainSid *sids = NULL;
297 	char *domain = NULL;
298 	char *name = NULL;
299 	char *sid_string = NULL;
300 	wbcErr ret = false;
301 	char separator;
302 
303 	torture_assert_wbc_ok(tctx, wbcInterfaceDetails(&details),
304 		"%s", "wbcInterfaceDetails failed");
305 
306 	domain_name = talloc_strdup(tctx, details->netbios_domain);
307 	torture_assert_goto(tctx,
308 			    domain_name != NULL,
309 			    ret,
310 			    fail,
311 			    "Failed to allocate domain_name");
312 	separator = details->winbind_separator;
313 	wbcFreeMemory(details);
314 	details = NULL;
315 
316 	torture_assert_wbc_ok_goto_fail(tctx,
317 					wbcListUsers(domain_name, &num_users, &users),
318 					"%s",
319 					"wbcListUsers failed");
320 	torture_assert_goto(tctx,
321 			    !(num_users > 0 && !users),
322 			    ret,
323 			    fail,
324 			    "wbcListUsers returned invalid results");
325 
326 	for (i = 0; i < MIN(num_users, 100); i++) {
327 		struct wbcDomainSid sid;
328 		enum wbcSidType name_type;
329 		uint32_t num_sids;
330 		const char *user;
331 		char *c;
332 
333 		c = strchr(users[i], separator);
334 
335 		if (c == NULL) {
336 			/*
337 			 * NT4 DC
338 			 * user name does not contain DOMAIN SEPARATOR prefix.
339 			 */
340 
341 			user = users[i];
342 		} else {
343 			/*
344 			 * AD DC
345 			 * user name starts with DOMAIN SEPARATOR prefix.
346 			 */
347 			const char *dom;
348 
349 			*c = '\0';
350 			dom = users[i];
351 			user = c + 1;
352 
353 			torture_assert_str_equal_goto(tctx, dom, domain_name,
354 						      ret, fail, "Domain part "
355 						      "of user name does not "
356 						      "match domain name.\n");
357 		}
358 
359 		torture_assert_wbc_ok_goto_fail(tctx,
360 						wbcLookupName(domain_name, user,
361 							      &sid, &name_type),
362 						"wbcLookupName of %s failed",
363 						users[i]);
364 		torture_assert_int_equal_goto(tctx,
365 					      name_type, WBC_SID_NAME_USER,
366 					      ret,
367 					      fail,
368 					      "wbcLookupName expected WBC_SID_NAME_USER");
369 		wbcSidToString(&sid, &sid_string);
370 		torture_assert_wbc_ok_goto_fail(tctx,
371 						wbcLookupSid(&sid,
372 							     &domain,
373 							     &name,
374 							     &name_type),
375 						"wbcLookupSid of %s failed",
376 						sid_string);
377 		torture_assert_int_equal_goto(tctx,
378 					      name_type, WBC_SID_NAME_USER,
379 					      ret,
380 					      fail,
381 					      "wbcLookupSid of expected WBC_SID_NAME_USER");
382 		torture_assert_goto(tctx,
383 				    name,
384 				    ret,
385 				    fail,
386 				    "wbcLookupSid returned no name");
387 		wbcFreeMemory(domain);
388 		domain = NULL;
389 		wbcFreeMemory(name);
390 		name = NULL;
391 
392 		torture_assert_wbc_ok_goto_fail(tctx,
393 						wbcLookupUserSids(&sid, true, &num_sids, &sids),
394 						"wbcLookupUserSids of %s failed", sid_string);
395 		torture_assert_wbc_ok_goto_fail(tctx,
396 						wbcGetDisplayName(&sid,
397 								  &domain,
398 								  &name,
399 								  &name_type),
400 						"wbcGetDisplayName of %s failed",
401 						sid_string);
402 		wbcFreeMemory(domain);
403 		domain = NULL;
404 		wbcFreeMemory(name);
405 		name = NULL;
406 		wbcFreeMemory(sids);
407 		sids = NULL;
408 		wbcFreeMemory(sid_string);
409 		sid_string = NULL;
410 	}
411 
412 	ret = true;
413 fail:
414 	wbcFreeMemory(details);
415 	wbcFreeMemory(users);
416 	wbcFreeMemory(domain);
417 	wbcFreeMemory(name);
418 	wbcFreeMemory(sids);
419 	wbcFreeMemory(sid_string);
420 
421 	return ret;
422 }
423 
test_wbc_groups(struct torture_context * tctx)424 static bool test_wbc_groups(struct torture_context *tctx)
425 {
426 	wbcErr ret = false;
427 	const char *domain_name = NULL;
428 	uint32_t num_groups;
429 	const char **groups = NULL;
430 	uint32_t i;
431 	struct wbcInterfaceDetails *details = NULL;
432 	char *domain = NULL;
433 	char *name = NULL;
434 	char *sid_string = NULL;
435 	char separator;
436 
437 	torture_assert_wbc_ok(tctx, wbcInterfaceDetails(&details),
438 			      "%s", "wbcInterfaceDetails failed");
439 
440 	domain_name = talloc_strdup(tctx, details->netbios_domain);
441 	torture_assert_goto(tctx,
442 			    domain_name != NULL,
443 			    ret,
444 			    fail,
445 			    "Failed to allocate domain_name");
446 	separator = details->winbind_separator;
447 	wbcFreeMemory(details);
448 	details = NULL;
449 
450 	torture_assert_wbc_ok_goto_fail(tctx,
451 					wbcListGroups(domain_name, &num_groups, &groups),
452 					"wbcListGroups in %s failed",
453 					domain_name);
454 	torture_assert_goto(tctx,
455 			    !(num_groups > 0 && !groups),
456 			    ret,
457 			    fail,
458 			    "wbcListGroups returned invalid results");
459 
460 	for (i=0; i < MIN(num_groups,100); i++) {
461 		struct wbcDomainSid sid;
462 		enum wbcSidType name_type;
463 		const char *group;
464 		char *c;
465 
466 		c = strchr(groups[i], separator);
467 
468 		if (c == NULL) {
469 			/*
470 			 * NT4 DC
471 			 * group name does not contain DOMAIN SEPARATOR prefix.
472 			 */
473 
474 			group = groups[i];
475 		} else {
476 			/*
477 			 * AD DC
478 			 * group name starts with DOMAIN SEPARATOR prefix.
479 			 */
480 			const char *dom;
481 
482 
483 			*c = '\0';
484 			dom = groups[i];
485 			group = c + 1;
486 
487 			torture_assert_str_equal_goto(tctx, dom, domain_name,
488 						      ret, fail, "Domain part "
489 						      "of group name does not "
490 						      "match domain name.\n");
491 		}
492 
493 		torture_assert_wbc_ok_goto_fail(tctx,
494 						wbcLookupName(domain_name,
495 							      group,
496 							      &sid,
497 							      &name_type),
498 						"wbcLookupName for %s failed",
499 						domain_name);
500 		wbcSidToString(&sid, &sid_string);
501 		torture_assert_wbc_ok_goto_fail(tctx,
502 						wbcLookupSid(&sid,
503 							     &domain,
504 							     &name,
505 							     &name_type),
506 						"wbcLookupSid of %s failed",
507 						sid_string);
508 		torture_assert_goto(tctx,
509 				    name,
510 				    ret,
511 				    fail,
512 				    "wbcLookupSid returned no name");
513 
514 		wbcFreeMemory(domain);
515 		domain = NULL;
516 		wbcFreeMemory(name);
517 		name = NULL;
518 		wbcFreeMemory(sid_string);
519 		sid_string = NULL;
520 	}
521 
522 	ret = true;
523 fail:
524 	wbcFreeMemory(details);
525 	wbcFreeMemory(groups);
526 	wbcFreeMemory(domain);
527 	wbcFreeMemory(name);
528 	wbcFreeMemory(sid_string);
529 
530 	return ret;
531 }
532 
test_wbc_trusts(struct torture_context * tctx)533 static bool test_wbc_trusts(struct torture_context *tctx)
534 {
535 	struct wbcDomainInfo *domains = NULL;
536 	struct wbcAuthErrorInfo *error = NULL;
537 	size_t num_domains;
538 	uint32_t i;
539 	wbcErr ret = false;
540 
541 	torture_assert_wbc_ok_goto_fail(tctx,
542 					wbcListTrusts(&domains, &num_domains),
543 					"%s",
544 					"wbcListTrusts failed");
545 	torture_assert_goto(tctx,
546 			    !(num_domains > 0 && !domains),
547 			    ret,
548 			    fail,
549 			    "wbcListTrusts returned invalid results");
550 
551 	for (i=0; i < MIN(num_domains,100); i++) {
552 
553 		/*
554 		struct wbcDomainSid sid;
555 		enum wbcSidType name_type;
556 		char *domain;
557 		char *name;
558 		*/
559 		torture_assert_wbc_ok_goto_fail(tctx,
560 						wbcCheckTrustCredentials(domains[i].short_name,
561 									 &error),
562 						"%s",
563 						"wbcCheckTrustCredentials failed");
564 		/*
565 		torture_assert_wbc_ok(tctx, wbcLookupName(domains[i].short_name, NULL, &sid, &name_type),
566 			"wbcLookupName failed");
567 		torture_assert_int_equal(tctx, name_type, WBC_SID_NAME_DOMAIN,
568 			"wbcLookupName expected WBC_SID_NAME_DOMAIN");
569 		torture_assert_wbc_ok(tctx, wbcLookupSid(&sid, &domain, &name, &name_type),
570 			"wbcLookupSid failed");
571 		torture_assert_int_equal(tctx, name_type, WBC_SID_NAME_DOMAIN,
572 			"wbcLookupSid expected WBC_SID_NAME_DOMAIN");
573 		torture_assert(tctx, name,
574 			"wbcLookupSid returned no name");
575 		*/
576 		wbcFreeMemory(error);
577 		error = NULL;
578 	}
579 
580 	ret = true;
581 fail:
582 	wbcFreeMemory(domains);
583 	wbcFreeMemory(error);
584 
585 	return ret;
586 }
587 
test_wbc_lookupdc(struct torture_context * tctx)588 static bool test_wbc_lookupdc(struct torture_context *tctx)
589 {
590 	const char *domain_name = NULL;
591 	struct wbcInterfaceDetails *details;
592 	struct wbcDomainControllerInfo *dc_info;
593 
594 	torture_assert_wbc_ok(tctx, wbcInterfaceDetails(&details),
595 		"%s", "wbcInterfaceDetails failed");
596 
597 	domain_name = talloc_strdup(tctx, details->netbios_domain);
598 	wbcFreeMemory(details);
599 
600 	torture_assert_wbc_ok(tctx, wbcLookupDomainController(domain_name, 0, &dc_info),
601 			      "wbcLookupDomainController for %s failed", domain_name);
602 	wbcFreeMemory(dc_info);
603 
604 	return true;
605 }
606 
test_wbc_lookupdcex(struct torture_context * tctx)607 static bool test_wbc_lookupdcex(struct torture_context *tctx)
608 {
609 	const char *domain_name = NULL;
610 	struct wbcInterfaceDetails *details;
611 	struct wbcDomainControllerInfoEx *dc_info;
612 
613 	torture_assert_wbc_ok(tctx, wbcInterfaceDetails(&details),
614 		"%s", "wbcInterfaceDetails failed");
615 
616 	domain_name = talloc_strdup(tctx, details->netbios_domain);
617 	wbcFreeMemory(details);
618 
619 	torture_assert_wbc_ok(tctx, wbcLookupDomainControllerEx(domain_name, NULL, NULL, 0, &dc_info),
620 		"wbcLookupDomainControllerEx for %s failed", domain_name);
621 	wbcFreeMemory(dc_info);
622 
623 	return true;
624 }
625 
test_wbc_resolve_winsbyname(struct torture_context * tctx)626 static bool test_wbc_resolve_winsbyname(struct torture_context *tctx)
627 {
628 	const char *name;
629 	char *ip;
630 	wbcErr ret;
631 
632 	name = torture_setting_string(tctx, "host", NULL);
633 
634 	torture_comment(tctx, "test-WinsByName: host='%s'\n", name);
635 
636 	ret = wbcResolveWinsByName(name, &ip);
637 
638 	if (is_ipaddress(name)) {
639 		torture_assert_wbc_equal(tctx, ret, WBC_ERR_DOMAIN_NOT_FOUND, "wbcResolveWinsByName of %s failed", name);
640 	} else {
641 		torture_assert_wbc_ok(tctx, ret, "wbcResolveWinsByName for %s failed", name);
642 	}
643 
644 	return true;
645 }
646 
test_wbc_resolve_winsbyip(struct torture_context * tctx)647 static bool test_wbc_resolve_winsbyip(struct torture_context *tctx)
648 {
649 	const char *ip;
650 	const char *host;
651 	struct nbt_name nbt_name;
652 	char *name;
653 	wbcErr ret;
654 	NTSTATUS status;
655 
656 	host = torture_setting_string(tctx, "host", NULL);
657 
658 	torture_comment(tctx, "test-WinsByIp: host='%s'\n", host);
659 
660 	make_nbt_name_server(&nbt_name, host);
661 
662 	status = resolve_name_ex(lpcfg_resolve_context(tctx->lp_ctx),
663 				 0, 0, &nbt_name, tctx, &ip, tctx->ev);
664 	torture_assert_ntstatus_ok(tctx, status,
665 			talloc_asprintf(tctx,"Failed to resolve %s: %s",
666 					nbt_name.name, nt_errstr(status)));
667 
668 	torture_comment(tctx, "test-WinsByIp: ip='%s'\n", ip);
669 
670 	ret = wbcResolveWinsByIP(ip, &name);
671 
672 	torture_assert_wbc_ok(tctx, ret, "wbcResolveWinsByIP for %s failed", ip);
673 
674 	wbcFreeMemory(name);
675 
676 	return true;
677 }
678 
test_wbc_lookup_rids(struct torture_context * tctx)679 static bool test_wbc_lookup_rids(struct torture_context *tctx)
680 {
681 	struct wbcDomainSid builtin;
682 	uint32_t rids[2] = { 544, 545 };
683 	const char *domain_name = NULL;
684 	const char **names = NULL;
685 	enum wbcSidType *types;
686 	wbcErr ret = false;
687 
688 	wbcStringToSid("S-1-5-32", &builtin);
689 
690 	ret = wbcLookupRids(&builtin, 2, rids, &domain_name, &names,
691 			    &types);
692 	torture_assert_wbc_ok_goto_fail(
693 		tctx, ret, "%s", "wbcLookupRids for 544 and 545 failed");
694 
695 	torture_assert_str_equal(
696 		tctx, names[0], "Administrators",
697 		"S-1-5-32-544 not mapped to 'Administrators'");
698 	torture_assert_str_equal_goto_fail(
699 		tctx, names[1], "Users", "S-1-5-32-545 not mapped to 'Users'");
700 
701 	ret = true;
702 fail:
703 	wbcFreeMemory(discard_const_p(char ,domain_name));
704 	wbcFreeMemory(names);
705 	wbcFreeMemory(types);
706 	return ret;
707 }
708 
test_wbc_get_sidaliases(struct torture_context * tctx)709 static bool test_wbc_get_sidaliases(struct torture_context *tctx)
710 {
711 	struct wbcDomainSid builtin;
712 	struct wbcDomainInfo *info = NULL;
713 	struct wbcInterfaceDetails *details = NULL;
714 	struct wbcDomainSid sids[2];
715 	uint32_t *rids = NULL;
716 	uint32_t num_rids;
717 	wbcErr ret = false;
718 
719 	torture_assert_wbc_ok_goto_fail(tctx,
720 					wbcInterfaceDetails(&details),
721 					"%s",
722 					"wbcInterfaceDetails failed");
723 	torture_assert_wbc_ok_goto_fail(tctx,
724 					wbcDomainInfo(details->netbios_domain, &info),
725 					"wbcDomainInfo of %s failed",
726 					details->netbios_domain);
727 
728 	sids[0] = info->sid;
729 	sids[0].sub_auths[sids[0].num_auths++] = 500;
730 	sids[1] = info->sid;
731 	sids[1].sub_auths[sids[1].num_auths++] = 512;
732 
733 	torture_assert_wbc_ok_goto_fail(tctx,
734 					wbcStringToSid("S-1-5-32", &builtin),
735 					"wbcStringToSid of %s failed",
736 					"S-1-5-32");
737 
738 	ret = wbcGetSidAliases(&builtin, sids, 2, &rids, &num_rids);
739 	torture_assert_wbc_ok_goto_fail(tctx,
740 					ret,
741 					"%s",
742 					"wbcGetSidAliases failed");
743 
744 	ret = true;
745 fail:
746 	wbcFreeMemory(details);
747 	wbcFreeMemory(info);
748 	wbcFreeMemory(rids);
749 	return ret;
750 }
751 
test_wbc_authenticate_user_int(struct torture_context * tctx,const char * correct_password)752 static bool test_wbc_authenticate_user_int(struct torture_context *tctx,
753 					   const char *correct_password)
754 {
755 	struct wbcAuthUserParams params;
756 	struct wbcAuthUserInfo *info = NULL;
757 	struct wbcAuthErrorInfo *error = NULL;
758 	wbcErr ret;
759 
760 	ret = wbcAuthenticateUser(cli_credentials_get_username(
761 			popt_get_cmdline_credentials()), correct_password);
762 	torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
763 		 "wbcAuthenticateUser of %s failed",
764 		 cli_credentials_get_username(popt_get_cmdline_credentials()));
765 
766 	ZERO_STRUCT(params);
767 	params.account_name		=
768 		cli_credentials_get_username(popt_get_cmdline_credentials());
769 	params.level			= WBC_AUTH_USER_LEVEL_PLAIN;
770 	params.password.plaintext	= correct_password;
771 
772 	ret = wbcAuthenticateUserEx(&params, &info, &error);
773 	torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
774 				 "wbcAuthenticateUserEx of %s failed", params.account_name);
775 	wbcFreeMemory(info);
776 	info = NULL;
777 
778 	wbcFreeMemory(error);
779 	error = NULL;
780 
781 	params.password.plaintext       = "wrong";
782 	ret = wbcAuthenticateUserEx(&params, &info, &error);
783 	torture_assert_wbc_equal(tctx, ret, WBC_ERR_AUTH_ERROR,
784 				 "wbcAuthenticateUserEx for %s succeeded where it "
785 				 "should have failed", params.account_name);
786 	wbcFreeMemory(info);
787 	info = NULL;
788 
789 	wbcFreeMemory(error);
790 	error = NULL;
791 
792 	return true;
793 }
794 
test_wbc_authenticate_user(struct torture_context * tctx)795 static bool test_wbc_authenticate_user(struct torture_context *tctx)
796 {
797 	return test_wbc_authenticate_user_int(tctx,
798 		cli_credentials_get_password(popt_get_cmdline_credentials()));
799 }
800 
test_wbc_change_password(struct torture_context * tctx)801 static bool test_wbc_change_password(struct torture_context *tctx)
802 {
803 	wbcErr ret;
804 	const char *oldpass =
805 		cli_credentials_get_password(popt_get_cmdline_credentials());
806 	const char *newpass = "Koo8irei%$";
807 
808 	struct samr_CryptPassword new_nt_password;
809 	struct samr_CryptPassword new_lm_password;
810 	struct samr_Password old_nt_hash_enc;
811 	struct samr_Password old_lanman_hash_enc;
812 
813 	gnutls_cipher_hd_t cipher_hnd = NULL;
814 
815 	uint8_t old_nt_hash[16];
816 	uint8_t old_lanman_hash[16];
817 	uint8_t new_nt_hash[16];
818 	uint8_t new_lanman_hash[16];
819 	gnutls_datum_t old_nt_key = {
820 		.data = old_nt_hash,
821 		.size = sizeof(old_nt_hash),
822 	};
823 
824 	struct wbcChangePasswordParams params;
825 
826 	if (oldpass == NULL) {
827 		torture_skip(tctx,
828 			"skipping wbcChangeUserPassword test as old password cannot be retrieved\n");
829 	}
830 
831 	ZERO_STRUCT(params);
832 
833 	E_md4hash(oldpass, old_nt_hash);
834 	E_md4hash(newpass, new_nt_hash);
835 
836 	if (lpcfg_client_lanman_auth(tctx->lp_ctx) &&
837 	    E_deshash(newpass, new_lanman_hash) &&
838 	    E_deshash(oldpass, old_lanman_hash)) {
839 
840 		/* E_deshash returns false for 'long' passwords (> 14
841 		   DOS chars).  This allows us to match Win2k, which
842 		   does not store a LM hash for these passwords (which
843 		   would reduce the effective password length to 14) */
844 
845 		encode_pw_buffer(new_lm_password.data, newpass, STR_UNICODE);
846 
847 		gnutls_cipher_init(&cipher_hnd,
848 				   GNUTLS_CIPHER_ARCFOUR_128,
849 				   &old_nt_key,
850 				   NULL);
851 		gnutls_cipher_encrypt(cipher_hnd,
852 				      new_lm_password.data,
853 				      516);
854 		gnutls_cipher_deinit(cipher_hnd);
855 
856 		E_old_pw_hash(new_nt_hash, old_lanman_hash,
857 			      old_lanman_hash_enc.hash);
858 
859 		params.old_password.response.old_lm_hash_enc_length =
860 			sizeof(old_lanman_hash_enc.hash);
861 		params.old_password.response.old_lm_hash_enc_data =
862 			old_lanman_hash_enc.hash;
863 		params.new_password.response.lm_length =
864 			sizeof(new_lm_password.data);
865 		params.new_password.response.lm_data =
866 			new_lm_password.data;
867 	} else {
868 		ZERO_STRUCT(new_lm_password);
869 		ZERO_STRUCT(old_lanman_hash_enc);
870 	}
871 
872 	encode_pw_buffer(new_nt_password.data, newpass, STR_UNICODE);
873 
874 	gnutls_cipher_init(&cipher_hnd,
875 			   GNUTLS_CIPHER_ARCFOUR_128,
876 			   &old_nt_key,
877 			   NULL);
878 	gnutls_cipher_encrypt(cipher_hnd,
879 			      new_nt_password.data,
880 			      516);
881 	gnutls_cipher_deinit(cipher_hnd);
882 
883 	E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);
884 
885 	params.old_password.response.old_nt_hash_enc_length =
886 		sizeof(old_nt_hash_enc.hash);
887 	params.old_password.response.old_nt_hash_enc_data =
888 		old_nt_hash_enc.hash;
889 	params.new_password.response.nt_length = sizeof(new_nt_password.data);
890 	params.new_password.response.nt_data = new_nt_password.data;
891 
892 	params.level = WBC_CHANGE_PASSWORD_LEVEL_RESPONSE;
893 	params.account_name =
894 		cli_credentials_get_username(popt_get_cmdline_credentials());
895 	params.domain_name =
896 		cli_credentials_get_domain(popt_get_cmdline_credentials());
897 
898 	ret = wbcChangeUserPasswordEx(&params, NULL, NULL, NULL);
899 	torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
900 				 "wbcChangeUserPassword for %s failed", params.account_name);
901 
902 	if (!test_wbc_authenticate_user_int(tctx, newpass)) {
903 		return false;
904 	}
905 
906 	ret = wbcChangeUserPassword(
907 		cli_credentials_get_username(popt_get_cmdline_credentials()),
908 		newpass,
909 		cli_credentials_get_password(popt_get_cmdline_credentials()));
910 	torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
911 				 "wbcChangeUserPassword for %s failed", params.account_name);
912 
913 	return test_wbc_authenticate_user_int(tctx,
914 		cli_credentials_get_password(popt_get_cmdline_credentials()));
915 }
916 
test_wbc_logon_user(struct torture_context * tctx)917 static bool test_wbc_logon_user(struct torture_context *tctx)
918 {
919 	struct wbcLogonUserParams params;
920 	struct wbcLogonUserInfo *info = NULL;
921 	struct wbcAuthErrorInfo *error = NULL;
922 	struct wbcUserPasswordPolicyInfo *policy = NULL;
923 	struct wbcInterfaceDetails *iface;
924 	struct wbcDomainSid sid;
925 	enum wbcSidType sidtype;
926 	char *sidstr;
927 	wbcErr ret;
928 
929 	ZERO_STRUCT(params);
930 
931 	ret = wbcLogonUser(&params, &info, &error, &policy);
932 	torture_assert_wbc_equal(tctx, ret, WBC_ERR_INVALID_PARAM,
933 				 "%s", "wbcLogonUser succeeded for NULL where it should "
934 				 "have failed");
935 
936 	params.username =
937 		cli_credentials_get_username(popt_get_cmdline_credentials());
938 	params.password =
939 		cli_credentials_get_password(popt_get_cmdline_credentials());
940 
941 	ret = wbcAddNamedBlob(&params.num_blobs, &params.blobs,
942 			      "foo", 0, discard_const_p(uint8_t, "bar"), 4);
943 	torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
944 				 "%s", "wbcAddNamedBlob failed");
945 
946 	ret = wbcLogonUser(&params, &info, &error, &policy);
947 	torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
948 				 "wbcLogonUser for %s failed", params.username);
949 	wbcFreeMemory(info); info = NULL;
950 	wbcFreeMemory(error); error = NULL;
951 	wbcFreeMemory(policy); policy = NULL;
952 
953 	params.password = "wrong";
954 
955 	ret = wbcLogonUser(&params, &info, &error, &policy);
956 	torture_assert_wbc_equal(tctx, ret, WBC_ERR_AUTH_ERROR,
957 				 "wbcLogonUser for %s should have failed with "
958 				 "WBC_ERR_AUTH_ERROR", params.username);
959 	wbcFreeMemory(info); info = NULL;
960 	wbcFreeMemory(error); error = NULL;
961 	wbcFreeMemory(policy); policy = NULL;
962 
963 	ret = wbcAddNamedBlob(&params.num_blobs, &params.blobs,
964 			      "membership_of", 0,
965 			      discard_const_p(uint8_t, "S-1-2-3-4"),
966 			      strlen("S-1-2-3-4")+1);
967 	torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
968 				 "%s", "wbcAddNamedBlob failed");
969 	params.password =
970 		cli_credentials_get_password(popt_get_cmdline_credentials());
971 	ret = wbcLogonUser(&params, &info, &error, &policy);
972 	torture_assert_wbc_equal(tctx, ret, WBC_ERR_AUTH_ERROR,
973 				 "wbcLogonUser for %s should have failed with "
974 				 "WBC_ERR_AUTH_ERROR", params.username);
975 	wbcFreeMemory(info); info = NULL;
976 	wbcFreeMemory(error); error = NULL;
977 	wbcFreeMemory(policy); policy = NULL;
978 	wbcFreeMemory(params.blobs);
979 	params.blobs = NULL; params.num_blobs = 0;
980 
981 	ret = wbcInterfaceDetails(&iface);
982 	torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
983 				 "%s", "wbcInterfaceDetails failed");
984 
985 	ret = wbcLookupName(iface->netbios_domain,
986 		cli_credentials_get_username(popt_get_cmdline_credentials()),
987 		&sid,
988 		&sidtype);
989 	wbcFreeMemory(iface);
990 	torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
991 		"wbcLookupName for %s failed",
992 		cli_credentials_get_username(popt_get_cmdline_credentials()));
993 
994 	ret = wbcSidToString(&sid, &sidstr);
995 	torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
996 				 "%s", "wbcSidToString failed");
997 
998 	ret = wbcAddNamedBlob(&params.num_blobs, &params.blobs,
999 			      "membership_of", 0,
1000 			      (uint8_t *)sidstr, strlen(sidstr)+1);
1001 	torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
1002 				 "%s", "wbcAddNamedBlob failed");
1003 	wbcFreeMemory(sidstr);
1004 	params.password =
1005 		cli_credentials_get_password(popt_get_cmdline_credentials());
1006 	ret = wbcLogonUser(&params, &info, &error, &policy);
1007 	torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
1008 				 "wbcLogonUser for %s failed", params.username);
1009 	wbcFreeMemory(info); info = NULL;
1010 	wbcFreeMemory(error); error = NULL;
1011 	wbcFreeMemory(policy); policy = NULL;
1012 	wbcFreeMemory(params.blobs);
1013 	params.blobs = NULL; params.num_blobs = 0;
1014 
1015 	return true;
1016 }
1017 
test_wbc_getgroups(struct torture_context * tctx)1018 static bool test_wbc_getgroups(struct torture_context *tctx)
1019 {
1020 	wbcErr ret;
1021 	uint32_t num_groups;
1022 	gid_t *groups;
1023 
1024 	ret = wbcGetGroups(
1025 		cli_credentials_get_username(popt_get_cmdline_credentials()),
1026 		&num_groups,
1027 		&groups);
1028 	torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
1029 		"wbcGetGroups for %s failed",
1030 		cli_credentials_get_username(popt_get_cmdline_credentials()));
1031 	wbcFreeMemory(groups);
1032 	return true;
1033 }
1034 
torture_wbclient(TALLOC_CTX * ctx)1035 struct torture_suite *torture_wbclient(TALLOC_CTX *ctx)
1036 {
1037 	struct torture_suite *suite = torture_suite_create(ctx, "wbclient");
1038 
1039 	torture_suite_add_simple_test(suite, "wbcPing", test_wbc_ping);
1040 	torture_suite_add_simple_test(suite, "wbcPingDc", test_wbc_pingdc);
1041 	torture_suite_add_simple_test(suite, "wbcPingDc2", test_wbc_pingdc2);
1042 	torture_suite_add_simple_test(suite, "wbcLibraryDetails", test_wbc_library_details);
1043 	torture_suite_add_simple_test(suite, "wbcInterfaceDetails", test_wbc_interface_details);
1044 	torture_suite_add_simple_test(suite, "wbcSidTypeString", test_wbc_sidtypestring);
1045 	torture_suite_add_simple_test(suite, "wbcSidToString", test_wbc_sidtostring);
1046 	torture_suite_add_simple_test(suite, "wbcGuidToString", test_wbc_guidtostring);
1047 	torture_suite_add_simple_test(suite, "wbcDomainInfo", test_wbc_domain_info);
1048 	torture_suite_add_simple_test(suite, "wbcListUsers", test_wbc_users);
1049 	torture_suite_add_simple_test(suite, "wbcListGroups", test_wbc_groups);
1050 	torture_suite_add_simple_test(suite, "wbcListTrusts", test_wbc_trusts);
1051 	torture_suite_add_simple_test(suite, "wbcLookupDomainController", test_wbc_lookupdc);
1052 	torture_suite_add_simple_test(suite, "wbcLookupDomainControllerEx", test_wbc_lookupdcex);
1053 	torture_suite_add_simple_test(suite, "wbcResolveWinsByName", test_wbc_resolve_winsbyname);
1054 	torture_suite_add_simple_test(suite, "wbcResolveWinsByIP", test_wbc_resolve_winsbyip);
1055 	torture_suite_add_simple_test(suite, "wbcLookupRids",
1056 				      test_wbc_lookup_rids);
1057 	torture_suite_add_simple_test(suite, "wbcGetSidAliases",
1058 				      test_wbc_get_sidaliases);
1059 	torture_suite_add_simple_test(suite, "wbcAuthenticateUser",
1060 				      test_wbc_authenticate_user);
1061 	torture_suite_add_simple_test(suite, "wbcLogonUser",
1062 				      test_wbc_logon_user);
1063 	torture_suite_add_simple_test(suite, "wbcChangeUserPassword",
1064 				      test_wbc_change_password);
1065 	torture_suite_add_simple_test(suite, "wbcGetGroups",
1066 				      test_wbc_getgroups);
1067 
1068 	return suite;
1069 }
1070