r25262: add WINBIND-STRUCT-LIST_TRUSTDOM torture test
[kai/samba.git] / source / torture / winbind / struct_based.c
1 /*
2    Unix SMB/CIFS implementation.
3    SMB torture tester - winbind struct based protocol
4    Copyright (C) Stefan Metzmacher 2007
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 "includes.h"
21 #include "pstring.h"
22 #include "torture/torture.h"
23 #include "torture/winbind/proto.h"
24 #include "nsswitch/winbind_client.h"
25 #include "libcli/security/security.h"
26 #include "param/param.h"
27
28 #define DO_STRUCT_REQ_REP(op,req,rep) do { \
29         NSS_STATUS _result; \
30         _result = winbindd_request_response(op, req, rep); \
31         torture_assert_int_equal(torture, _result, NSS_STATUS_SUCCESS, \
32                                  __STRING(op) "(struct based)"); \
33 } while (0)
34
35 static bool torture_winbind_struct_ping(struct torture_context *torture)
36 {
37         struct timeval tv = timeval_current();
38         int timelimit = torture_setting_int(torture, "timelimit", 5);
39         uint32_t total = 0;
40
41         torture_comment(torture,
42                         "Running WINBINDD_PING (struct based) for %d seconds\n",
43                         timelimit);
44
45         while (timeval_elapsed(&tv) < timelimit) {
46                 DO_STRUCT_REQ_REP(WINBINDD_PING, NULL, NULL);
47                 total++;
48         }
49
50         torture_comment(torture,
51                         "%u (%.1f/s) WINBINDD_PING (struct based)\n",
52                         total, total / timeval_elapsed(&tv));
53
54         return true;
55 }
56
57 struct torture_trust_domain {
58         const char *netbios_name;
59         const char *dns_name;
60         struct dom_sid *sid;
61 };
62
63 static bool get_trusted_domains(struct torture_context *torture,
64                                 struct torture_trust_domain **_d)
65 {
66         struct winbindd_request req;
67         struct winbindd_response rep;
68         struct torture_trust_domain *d = NULL;
69         uint32_t dcount = 0;
70         fstring line;
71         const char *extra_data;
72
73         ZERO_STRUCT(req);
74         ZERO_STRUCT(rep);
75
76         DO_STRUCT_REQ_REP(WINBINDD_LIST_TRUSTDOM, &req, &rep);
77
78         extra_data = (char *)rep.extra_data.data;
79         torture_assert(torture, extra_data, "NULL trust list");
80
81         while (next_token(&extra_data, line, "\n", sizeof(fstring))) {
82                 char *p, *lp;
83
84                 d = talloc_realloc(torture, d,
85                                    struct torture_trust_domain,
86                                    dcount + 2);
87                 ZERO_STRUCT(d[dcount+1]);
88
89                 lp = line;
90                 p = strchr(lp, '\\');
91                 torture_assert(torture, p, "missing 1st '\\' in line");
92                 *p = 0;
93                 d[dcount].netbios_name = talloc_strdup(d, lp);
94                 torture_assert(torture, strlen(d[dcount].netbios_name) > 0,
95                                "empty netbios_name");
96
97                 lp = p+1;
98                 p = strchr(lp, '\\');
99                 torture_assert(torture, p, "missing 2nd '\\' in line");
100                 *p = 0;
101                 d[dcount].dns_name = talloc_strdup(d, lp);
102                 /* it's ok to have an empty dns_name */
103
104                 lp = p+1;
105                 d[dcount].sid = dom_sid_parse_talloc(d, lp);
106                 torture_assert(torture, d[dcount].sid,
107                                "failed to parse sid");
108
109                 dcount++;
110         }
111
112         SAFE_FREE(rep.extra_data.data);
113         *_d = d;
114         return true;
115 }
116
117 static bool torture_winbind_struct_list_trustdom(struct torture_context *torture)
118 {
119         struct winbindd_request req;
120         struct winbindd_response rep;
121         char *list1;
122         char *list2;
123         bool ok;
124         struct torture_trust_domain *listd = NULL;
125         uint32_t i;
126
127         torture_comment(torture, "Running WINBINDD_LIST_TRUSTDOM (struct based)\n");
128
129         ZERO_STRUCT(req);
130         ZERO_STRUCT(rep);
131
132         req.data.list_all_domains = false;
133
134         DO_STRUCT_REQ_REP(WINBINDD_LIST_TRUSTDOM, &req, &rep);
135
136         list1 = (char *)rep.extra_data.data;
137         torture_assert(torture, list1, "NULL trust list");
138
139         torture_comment(torture, "%s\n", list1);
140
141         ZERO_STRUCT(req);
142         ZERO_STRUCT(rep);
143
144         req.data.list_all_domains = true;
145
146         DO_STRUCT_REQ_REP(WINBINDD_LIST_TRUSTDOM, &req, &rep);
147
148         list2 = (char *)rep.extra_data.data;
149         torture_assert(torture, list2, "NULL trust list");
150
151         /*
152          * The list_all_domains parameter should be ignored
153          */
154         torture_assert_str_equal(torture, list2, list1, "list_all_domains not ignored");
155
156         SAFE_FREE(list1);
157         SAFE_FREE(list2);
158
159         ok = get_trusted_domains(torture, &listd);
160         torture_assert(torture, ok, "failed to get trust list");
161
162         for (i=0; listd[i].netbios_name; i++) {
163                 if (i == 0) {
164                         struct dom_sid *builtin_sid;
165
166                         builtin_sid = dom_sid_parse_talloc(torture, SID_BUILTIN);
167
168                         torture_assert_str_equal(torture,
169                                                  listd[i].netbios_name,
170                                                  NAME_BUILTIN,
171                                                  "first domain should be 'BUILTIN'");
172
173                         torture_assert_str_equal(torture,
174                                                  listd[i].dns_name,
175                                                  "",
176                                                  "BUILTIN domain should not have a dns name");
177
178                         ok = dom_sid_equal(builtin_sid,
179                                            listd[i].sid);
180                         torture_assert(torture, ok, "BUILTIN domain should have S-1-5-32");
181                                        
182                         continue;
183                 }
184
185                 /*
186                  * TODO: verify the content of the 2nd and 3rd (in member server mode)
187                  *       domain entries
188                  */
189         }
190
191         torture_assert(torture, i >= 2,
192                        "The list of trusted domain should contain 2 entries");
193
194         return true;
195 }
196
197 static bool torture_winbind_struct_getdcname(struct torture_context *torture)
198 {
199         struct winbindd_request req;
200         struct winbindd_response rep;
201
202         torture_comment(torture, "Running WINBINDD_GETDCNAME (struct based)\n");
203
204         ZERO_STRUCT(req);
205         ZERO_STRUCT(rep);
206
207         fstrcpy(req.domain_name, lp_workgroup());
208
209         DO_STRUCT_REQ_REP(WINBINDD_GETDCNAME, &req, &rep);
210
211         /*
212          * TODO: test all trusted domains
213          */
214
215         return true;
216 }
217
218 struct torture_suite *torture_winbind_struct_init(void)
219 {
220         struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "STRUCT");
221
222         torture_suite_add_simple_test(suite, "PING", torture_winbind_struct_ping);
223         torture_suite_add_simple_test(suite, "GETDCNAME", torture_winbind_struct_getdcname);
224         torture_suite_add_simple_test(suite, "LIST_TRUSTDOM", torture_winbind_struct_list_trustdom);
225
226         suite->description = talloc_strdup(suite, "WINBIND - struct based protocol tests");
227
228         return suite;
229 }