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