Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : SMB torture tester
4 : Copyright (C) Guenther Deschner 2009
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 "torture/smbtorture.h"
22 : #include <netapi.h>
23 : #include "torture/libnetapi/proto.h"
24 :
25 : #undef strcasecmp
26 :
27 : #define TORTURE_TEST_USER "testuser"
28 :
29 : #define NETAPI_STATUS(tctx, x,y,fn) \
30 : torture_warning(tctx, "FAILURE: line %d: %s failed with status: %s (%d)\n", \
31 : __LINE__, fn, libnetapi_get_error_string(x,y), y);
32 :
33 : #define NETAPI_STATUS_MSG(tctx, x,y,fn,z) \
34 : torture_warning(tctx, "FAILURE: line %d: %s failed with status: %s (%d), %s\n", \
35 : __LINE__, fn, libnetapi_get_error_string(x,y), y, z);
36 :
37 4 : static NET_API_STATUS test_netgroupenum(struct torture_context *tctx,
38 : const char *hostname,
39 : uint32_t level,
40 : const char *groupname)
41 : {
42 0 : NET_API_STATUS status;
43 4 : uint32_t entries_read = 0;
44 4 : uint32_t total_entries = 0;
45 4 : uint32_t resume_handle = 0;
46 4 : int found_group = 0;
47 4 : const char *current_name = NULL;
48 4 : uint8_t *buffer = NULL;
49 0 : int i;
50 :
51 4 : struct GROUP_INFO_0 *info0 = NULL;
52 4 : struct GROUP_INFO_1 *info1 = NULL;
53 4 : struct GROUP_INFO_2 *info2 = NULL;
54 4 : struct GROUP_INFO_3 *info3 = NULL;
55 :
56 4 : torture_comment(tctx, "Testing NetGroupEnum level %d\n", level);
57 :
58 0 : do {
59 4 : status = NetGroupEnum(hostname,
60 : level,
61 : &buffer,
62 : (uint32_t)-1,
63 : &entries_read,
64 : &total_entries,
65 : &resume_handle);
66 4 : if (status == 0 || status == ERROR_MORE_DATA) {
67 4 : switch (level) {
68 1 : case 0:
69 1 : info0 = (struct GROUP_INFO_0 *)buffer;
70 1 : break;
71 1 : case 1:
72 1 : info1 = (struct GROUP_INFO_1 *)buffer;
73 1 : break;
74 1 : case 2:
75 1 : info2 = (struct GROUP_INFO_2 *)buffer;
76 1 : break;
77 1 : case 3:
78 1 : info3 = (struct GROUP_INFO_3 *)buffer;
79 1 : break;
80 0 : default:
81 0 : return -1;
82 : }
83 :
84 60 : for (i=0; i<entries_read; i++) {
85 :
86 56 : switch (level) {
87 14 : case 0:
88 14 : current_name = info0->grpi0_name;
89 14 : break;
90 14 : case 1:
91 14 : current_name = info1->grpi1_name;
92 14 : break;
93 14 : case 2:
94 14 : current_name = info2->grpi2_name;
95 14 : break;
96 14 : case 3:
97 14 : current_name = info3->grpi3_name;
98 14 : break;
99 0 : default:
100 0 : break;
101 : }
102 :
103 56 : if (strcasecmp(current_name, groupname) == 0) {
104 4 : found_group = 1;
105 : }
106 :
107 56 : switch (level) {
108 14 : case 0:
109 14 : info0++;
110 14 : break;
111 14 : case 1:
112 14 : info1++;
113 14 : break;
114 14 : case 2:
115 14 : info2++;
116 14 : break;
117 14 : case 3:
118 14 : info3++;
119 14 : break;
120 : }
121 : }
122 4 : NetApiBufferFree(buffer);
123 : }
124 4 : } while (status == ERROR_MORE_DATA);
125 :
126 4 : if (status) {
127 0 : return status;
128 : }
129 :
130 4 : if (!found_group) {
131 0 : torture_comment(tctx, "failed to get group\n");
132 0 : return -1;
133 : }
134 :
135 4 : return 0;
136 : }
137 :
138 6 : static NET_API_STATUS test_netgroupgetusers(struct torture_context *tctx,
139 : const char *hostname,
140 : uint32_t level,
141 : const char *groupname,
142 : const char *username)
143 : {
144 0 : NET_API_STATUS status;
145 6 : uint32_t entries_read = 0;
146 6 : uint32_t total_entries = 0;
147 6 : uint32_t resume_handle = 0;
148 6 : int found_user = 0;
149 6 : const char *current_name = NULL;
150 6 : uint8_t *buffer = NULL;
151 0 : int i;
152 :
153 6 : struct GROUP_USERS_INFO_0 *info0 = NULL;
154 6 : struct GROUP_USERS_INFO_1 *info1 = NULL;
155 :
156 6 : torture_comment(tctx, "Testing NetGroupGetUsers level %d\n", level);
157 :
158 0 : do {
159 6 : status = NetGroupGetUsers(hostname,
160 : groupname,
161 : level,
162 : &buffer,
163 : (uint32_t)-1,
164 : &entries_read,
165 : &total_entries,
166 : &resume_handle);
167 6 : if (status == 0 || status == ERROR_MORE_DATA) {
168 :
169 6 : switch (level) {
170 4 : case 0:
171 4 : info0 = (struct GROUP_USERS_INFO_0 *)buffer;
172 4 : break;
173 2 : case 1:
174 2 : info1 = (struct GROUP_USERS_INFO_1 *)buffer;
175 2 : break;
176 0 : default:
177 0 : break;
178 : }
179 9 : for (i=0; i<entries_read; i++) {
180 3 : switch (level) {
181 2 : case 0:
182 2 : current_name = info0->grui0_name;
183 2 : break;
184 1 : case 1:
185 1 : current_name = info1->grui1_name;
186 1 : break;
187 0 : default:
188 0 : break;
189 : }
190 :
191 3 : if (username && strcasecmp(current_name, username) == 0) {
192 3 : found_user = 1;
193 : }
194 :
195 3 : switch (level) {
196 2 : case 0:
197 2 : info0++;
198 2 : break;
199 1 : case 1:
200 1 : info1++;
201 1 : break;
202 : }
203 : }
204 6 : NetApiBufferFree(buffer);
205 : }
206 6 : } while (status == ERROR_MORE_DATA);
207 :
208 6 : if (status) {
209 0 : return status;
210 : }
211 :
212 6 : if (username && !found_user) {
213 0 : torture_comment(tctx, "failed to get user\n");
214 0 : return -1;
215 : }
216 :
217 6 : return 0;
218 : }
219 :
220 1 : static NET_API_STATUS test_netgroupsetusers(struct torture_context *tctx,
221 : const char *hostname,
222 : const char *groupname,
223 : uint32_t level,
224 : size_t num_entries,
225 : const char **names)
226 : {
227 0 : NET_API_STATUS status;
228 1 : uint8_t *buffer = NULL;
229 1 : int i = 0;
230 1 : size_t buf_size = 0;
231 :
232 1 : struct GROUP_USERS_INFO_0 *g0 = NULL;
233 1 : struct GROUP_USERS_INFO_1 *g1 = NULL;
234 :
235 1 : torture_comment(tctx, "Testing NetGroupSetUsers level %d\n", level);
236 :
237 1 : switch (level) {
238 1 : case 0:
239 1 : buf_size = sizeof(struct GROUP_USERS_INFO_0) * num_entries;
240 :
241 1 : status = NetApiBufferAllocate(buf_size, (void **)&g0);
242 1 : if (status) {
243 0 : goto out;
244 : }
245 :
246 2 : for (i=0; i<num_entries; i++) {
247 1 : g0[i].grui0_name = names[i];
248 : }
249 :
250 1 : buffer = (uint8_t *)g0;
251 1 : break;
252 0 : case 1:
253 0 : buf_size = sizeof(struct GROUP_USERS_INFO_1) * num_entries;
254 :
255 0 : status = NetApiBufferAllocate(buf_size, (void **)&g1);
256 0 : if (status) {
257 0 : goto out;
258 : }
259 :
260 0 : for (i=0; i<num_entries; i++) {
261 0 : g1[i].grui1_name = names[i];
262 : }
263 :
264 0 : buffer = (uint8_t *)g1;
265 0 : break;
266 0 : default:
267 0 : break;
268 : }
269 :
270 : /* NetGroupSetUsers */
271 :
272 1 : status = NetGroupSetUsers(hostname,
273 : groupname,
274 : level,
275 : buffer,
276 : num_entries);
277 1 : if (status) {
278 0 : goto out;
279 : }
280 :
281 1 : out:
282 1 : NetApiBufferFree(buffer);
283 1 : return status;
284 : }
285 :
286 1 : bool torture_libnetapi_group(struct torture_context *tctx)
287 : {
288 1 : NET_API_STATUS status = 0;
289 0 : const char *username, *groupname, *groupname2;
290 1 : uint8_t *buffer = NULL;
291 0 : struct GROUP_INFO_0 g0;
292 1 : uint32_t parm_err = 0;
293 1 : uint32_t levels[] = { 0, 1, 2, 3};
294 1 : uint32_t enum_levels[] = { 0, 1, 2, 3};
295 1 : uint32_t getmem_levels[] = { 0, 1};
296 0 : int i;
297 1 : const char *hostname = torture_setting_string(tctx, "host", NULL);
298 0 : struct libnetapi_ctx *ctx;
299 :
300 1 : torture_assert(tctx, torture_libnetapi_init_context(tctx, &ctx),
301 : "failed to initialize libnetapi");
302 :
303 1 : torture_comment(tctx, "NetGroup tests\n");
304 :
305 1 : username = "torture_test_user";
306 1 : groupname = "torture_test_group";
307 1 : groupname2 = "torture_test_group2";
308 :
309 : /* cleanup */
310 1 : NetGroupDel(hostname, groupname);
311 1 : NetGroupDel(hostname, groupname2);
312 1 : NetUserDel(hostname, username);
313 :
314 : /* add a group */
315 :
316 1 : g0.grpi0_name = groupname;
317 :
318 1 : torture_comment(tctx, "Testing NetGroupAdd\n");
319 :
320 1 : status = NetGroupAdd(hostname, 0, (uint8_t *)&g0, &parm_err);
321 1 : if (status) {
322 0 : NETAPI_STATUS(tctx, ctx, status, "NetGroupAdd");
323 0 : goto out;
324 : }
325 :
326 : /* 2nd add must fail */
327 :
328 1 : status = NetGroupAdd(hostname, 0, (uint8_t *)&g0, &parm_err);
329 1 : if (status == 0) {
330 0 : NETAPI_STATUS(tctx, ctx, status, "NetGroupAdd");
331 0 : status = -1;
332 0 : goto out;
333 : }
334 :
335 : /* test enum */
336 :
337 5 : for (i=0; i<ARRAY_SIZE(enum_levels); i++) {
338 :
339 4 : status = test_netgroupenum(tctx, hostname, enum_levels[i], groupname);
340 4 : if (status) {
341 0 : NETAPI_STATUS(tctx, ctx, status, "NetGroupEnum");
342 0 : goto out;
343 : }
344 : }
345 :
346 : /* basic queries */
347 :
348 5 : for (i=0; i<ARRAY_SIZE(levels); i++) {
349 :
350 4 : torture_comment(tctx, "Testing NetGroupGetInfo level %d\n", levels[i]);
351 :
352 4 : status = NetGroupGetInfo(hostname, groupname, levels[i], &buffer);
353 4 : if (status && status != 124) {
354 0 : NETAPI_STATUS(tctx, ctx, status, "NetGroupGetInfo");
355 0 : goto out;
356 : }
357 : }
358 :
359 : /* group rename */
360 :
361 1 : g0.grpi0_name = groupname2;
362 :
363 1 : torture_comment(tctx, "Testing NetGroupSetInfo level 0\n");
364 :
365 1 : status = NetGroupSetInfo(hostname, groupname, 0, (uint8_t *)&g0, &parm_err);
366 1 : switch ((uint32_t)status) {
367 1 : case 0:
368 1 : break;
369 0 : case 50: /* not supported */
370 : case 124: /* not implemented */
371 0 : groupname2 = groupname;
372 0 : goto skip_rename;
373 0 : default:
374 0 : NETAPI_STATUS(tctx, ctx, status, "NetGroupSetInfo");
375 0 : goto out;
376 : }
377 :
378 : /* should not exist anymore */
379 :
380 1 : status = NetGroupDel(hostname, groupname);
381 1 : if (status == 0) {
382 0 : NETAPI_STATUS(tctx, ctx, status, "NetGroupDel");
383 0 : goto out;
384 : }
385 :
386 1 : skip_rename:
387 : /* query info */
388 :
389 5 : for (i=0; i<ARRAY_SIZE(levels); i++) {
390 :
391 4 : status = NetGroupGetInfo(hostname, groupname2, levels[i], &buffer);
392 4 : if (status && status != 124) {
393 0 : NETAPI_STATUS(tctx, ctx, status, "NetGroupGetInfo");
394 0 : goto out;
395 : }
396 : }
397 :
398 : /* add user to group */
399 :
400 1 : status = test_netuseradd(tctx, hostname, username);
401 1 : if (status) {
402 0 : NETAPI_STATUS(tctx, ctx, status, "NetUserAdd");
403 0 : goto out;
404 : }
405 :
406 : /* should not be member */
407 :
408 3 : for (i=0; i<ARRAY_SIZE(getmem_levels); i++) {
409 :
410 2 : status = test_netgroupgetusers(tctx, hostname, getmem_levels[i], groupname2, NULL);
411 2 : if (status) {
412 0 : NETAPI_STATUS(tctx, ctx, status, "NetGroupGetUsers");
413 0 : goto out;
414 : }
415 : }
416 :
417 1 : torture_comment(tctx, "Testing NetGroupAddUser\n");
418 :
419 1 : status = NetGroupAddUser(hostname, groupname2, username);
420 1 : if (status) {
421 0 : NETAPI_STATUS(tctx, ctx, status, "NetGroupAddUser");
422 0 : goto out;
423 : }
424 :
425 : /* should be member */
426 :
427 3 : for (i=0; i<ARRAY_SIZE(getmem_levels); i++) {
428 :
429 2 : status = test_netgroupgetusers(tctx, hostname, getmem_levels[i], groupname2, username);
430 2 : if (status) {
431 0 : NETAPI_STATUS(tctx, ctx, status, "NetGroupGetUsers");
432 0 : goto out;
433 : }
434 : }
435 :
436 1 : torture_comment(tctx, "Testing NetGroupDelUser\n");
437 :
438 1 : status = NetGroupDelUser(hostname, groupname2, username);
439 1 : if (status) {
440 0 : NETAPI_STATUS(tctx, ctx, status, "NetGroupDelUser");
441 0 : goto out;
442 : }
443 :
444 : /* should not be member */
445 :
446 1 : status = test_netgroupgetusers(tctx, hostname, 0, groupname2, NULL);
447 1 : if (status) {
448 0 : NETAPI_STATUS(tctx, ctx, status, "NetGroupGetUsers");
449 0 : goto out;
450 : }
451 :
452 : /* set it again via explicit member set */
453 :
454 1 : status = test_netgroupsetusers(tctx, hostname, groupname2, 0, 1, &username);
455 1 : if (status) {
456 0 : NETAPI_STATUS(tctx, ctx, status, "NetGroupSetUsers");
457 0 : goto out;
458 : }
459 :
460 : /* should be member */
461 :
462 1 : status = test_netgroupgetusers(tctx, hostname, 0, groupname2, username);
463 1 : if (status) {
464 0 : NETAPI_STATUS(tctx, ctx, status, "NetGroupGetUsers");
465 0 : goto out;
466 : }
467 : #if 0
468 : /* wipe out member list */
469 :
470 : status = test_netgroupsetusers(hostname, groupname2, 0, 0, NULL);
471 : if (status) {
472 : NETAPI_STATUS(tctx, ctx, status, "NetGroupSetUsers");
473 : goto out;
474 : }
475 :
476 : /* should not be member */
477 :
478 : status = test_netgroupgetusers(hostname, 0, groupname2, NULL);
479 : if (status) {
480 : NETAPI_STATUS(tctx, ctx, status, "NetGroupGetUsers");
481 : goto out;
482 : }
483 : #endif
484 1 : status = NetUserDel(hostname, username);
485 1 : if (status) {
486 0 : NETAPI_STATUS(tctx, ctx, status, "NetUserDel");
487 0 : goto out;
488 : }
489 :
490 : /* delete */
491 :
492 1 : torture_comment(tctx, "Testing NetGroupDel\n");
493 :
494 1 : status = NetGroupDel(hostname, groupname2);
495 1 : if (status) {
496 0 : NETAPI_STATUS(tctx, ctx, status, "NetGroupDel");
497 0 : goto out;
498 0 : };
499 :
500 : /* should not exist anymore */
501 :
502 1 : status = NetGroupGetInfo(hostname, groupname2, 0, &buffer);
503 1 : if (status == 0) {
504 0 : NETAPI_STATUS_MSG(tctx, ctx, status, "NetGroupGetInfo", "expected failure and error code");
505 0 : status = -1;
506 0 : goto out;
507 0 : };
508 :
509 1 : status = 0;
510 :
511 1 : torture_comment(tctx, "NetGroup tests succeeded\n");
512 1 : out:
513 1 : if (status != 0) {
514 0 : torture_comment(tctx, "NetGroup testsuite failed with: %s\n",
515 : libnetapi_get_error_string(ctx, status));
516 0 : libnetapi_free(ctx);
517 0 : return false;
518 : }
519 :
520 1 : libnetapi_free(ctx);
521 1 : return true;
522 : }
|