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