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