ldb: move struct ldb_debug_ops to ldb_private.h
[samba.git] / source4 / torture / libnetapi / libnetapi_user.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 #undef strcasecmp
26
27 #define TORTURE_TEST_USER "torture_testuser"
28 #define TORTURE_TEST_USER2 "torture_testuser2"
29
30 #define NETAPI_STATUS(tctx, x,y,fn) \
31         torture_warning(tctx, "FAILURE: line %d: %s failed with status: %s (%d)\n", \
32                 __LINE__, fn, libnetapi_get_error_string(x,y), y);
33
34 static NET_API_STATUS test_netuserenum(struct torture_context *tctx,
35                                        const char *hostname,
36                                        uint32_t level,
37                                        const char *username)
38 {
39         NET_API_STATUS status;
40         uint32_t entries_read = 0;
41         uint32_t total_entries = 0;
42         uint32_t resume_handle = 0;
43         const char *current_name = NULL;
44         int found_user = 0;
45         uint8_t *buffer = NULL;
46         int i;
47
48         struct USER_INFO_0 *info0 = NULL;
49         struct USER_INFO_1 *info1 = NULL;
50         struct USER_INFO_2 *info2 = NULL;
51         struct USER_INFO_3 *info3 = NULL;
52         struct USER_INFO_4 *info4 = NULL;
53         struct USER_INFO_10 *info10 = NULL;
54         struct USER_INFO_11 *info11 = NULL;
55         struct USER_INFO_20 *info20 = NULL;
56         struct USER_INFO_23 *info23 = NULL;
57
58         torture_comment(tctx, "Testing NetUserEnum level %d\n", level);
59
60         do {
61                 status = NetUserEnum(hostname,
62                                      level,
63                                      FILTER_NORMAL_ACCOUNT,
64                                      &buffer,
65                                      (uint32_t)-1,
66                                      &entries_read,
67                                      &total_entries,
68                                      &resume_handle);
69                 if (status == 0 || status == ERROR_MORE_DATA) {
70                         switch (level) {
71                                 case 0:
72                                         info0 = (struct USER_INFO_0 *)buffer;
73                                         break;
74                                 case 1:
75                                         info1 = (struct USER_INFO_1 *)buffer;
76                                         break;
77                                 case 2:
78                                         info2 = (struct USER_INFO_2 *)buffer;
79                                         break;
80                                 case 3:
81                                         info3 = (struct USER_INFO_3 *)buffer;
82                                         break;
83                                 case 4:
84                                         info4 = (struct USER_INFO_4 *)buffer;
85                                         break;
86                                 case 10:
87                                         info10 = (struct USER_INFO_10 *)buffer;
88                                         break;
89                                 case 11:
90                                         info11 = (struct USER_INFO_11 *)buffer;
91                                         break;
92                                 case 20:
93                                         info20 = (struct USER_INFO_20 *)buffer;
94                                         break;
95                                 case 23:
96                                         info23 = (struct USER_INFO_23 *)buffer;
97                                         break;
98                                 default:
99                                         return -1;
100                         }
101
102                         for (i=0; i<entries_read; i++) {
103
104                                 switch (level) {
105                                         case 0:
106                                                 current_name = info0->usri0_name;
107                                                 break;
108                                         case 1:
109                                                 current_name = info1->usri1_name;
110                                                 break;
111                                         case 2:
112                                                 current_name = info2->usri2_name;
113                                                 break;
114                                         case 3:
115                                                 current_name = info3->usri3_name;
116                                                 break;
117                                         case 4:
118                                                 current_name = info4->usri4_name;
119                                                 break;
120                                         case 10:
121                                                 current_name = info10->usri10_name;
122                                                 break;
123                                         case 11:
124                                                 current_name = info11->usri11_name;
125                                                 break;
126                                         case 20:
127                                                 current_name = info20->usri20_name;
128                                                 break;
129                                         case 23:
130                                                 current_name = info23->usri23_name;
131                                                 break;
132                                         default:
133                                                 return -1;
134                                 }
135
136                                 if (strcasecmp(current_name, username) == 0) {
137                                         found_user = 1;
138                                 }
139
140                                 switch (level) {
141                                         case 0:
142                                                 info0++;
143                                                 break;
144                                         case 1:
145                                                 info1++;
146                                                 break;
147                                         case 2:
148                                                 info2++;
149                                                 break;
150                                         case 3:
151                                                 info3++;
152                                                 break;
153                                         case 4:
154                                                 info4++;
155                                                 break;
156                                         case 10:
157                                                 info10++;
158                                                 break;
159                                         case 11:
160                                                 info11++;
161                                                 break;
162                                         case 20:
163                                                 info20++;
164                                                 break;
165                                         case 23:
166                                                 info23++;
167                                                 break;
168                                         default:
169                                                 break;
170                                 }
171                         }
172                         NetApiBufferFree(buffer);
173                 }
174         } while (status == ERROR_MORE_DATA);
175
176         if (status) {
177                 return status;
178         }
179
180         if (!found_user) {
181                 torture_comment(tctx, "failed to get user\n");
182                 return -1;
183         }
184
185         return 0;
186 }
187
188 NET_API_STATUS test_netuseradd(struct torture_context *tctx,
189                                const char *hostname,
190                                const char *username)
191 {
192         struct USER_INFO_1 u1;
193         uint32_t parm_err = 0;
194
195         ZERO_STRUCT(u1);
196
197         torture_comment(tctx, "Testing NetUserAdd\n");
198
199         u1.usri1_name = username;
200         u1.usri1_password = "W297!832jD8J";
201         u1.usri1_password_age = 0;
202         u1.usri1_priv = 0;
203         u1.usri1_home_dir = NULL;
204         u1.usri1_comment = "User created using Samba NetApi Example code";
205         u1.usri1_flags = 0;
206         u1.usri1_script_path = NULL;
207
208         return NetUserAdd(hostname, 1, (uint8_t *)&u1, &parm_err);
209 }
210
211 static NET_API_STATUS test_netusermodals(struct torture_context *tctx,
212                                          struct libnetapi_ctx *ctx,
213                                          const char *hostname)
214 {
215         NET_API_STATUS status;
216         struct USER_MODALS_INFO_0 *u0 = NULL;
217         struct USER_MODALS_INFO_0 *_u0 = NULL;
218         uint8_t *buffer = NULL;
219         uint32_t parm_err = 0;
220         uint32_t levels[] = { 0, 1, 2, 3 };
221         int i = 0;
222
223         for (i=0; i<ARRAY_SIZE(levels); i++) {
224
225                 torture_comment(tctx, "Testing NetUserModalsGet level %d\n", levels[i]);
226
227                 status = NetUserModalsGet(hostname, levels[i], &buffer);
228                 if (status) {
229                         NETAPI_STATUS(tctx, ctx, status, "NetUserModalsGet");
230                         return status;
231                 }
232         }
233
234         status = NetUserModalsGet(hostname, 0, (uint8_t **)&u0);
235         if (status) {
236                 NETAPI_STATUS(tctx, ctx, status, "NetUserModalsGet");
237                 return status;
238         }
239
240         torture_comment(tctx, "Testing NetUserModalsSet\n");
241
242         status = NetUserModalsSet(hostname, 0, (uint8_t *)u0, &parm_err);
243         if (status) {
244                 NETAPI_STATUS(tctx, ctx, status, "NetUserModalsSet");
245                 return status;
246         }
247
248         status = NetUserModalsGet(hostname, 0, (uint8_t **)&_u0);
249         if (status) {
250                 NETAPI_STATUS(tctx, ctx, status, "NetUserModalsGet");
251                 return status;
252         }
253
254         if (memcmp(u0, _u0, sizeof(*u0)) != 0) {
255                 torture_comment(tctx, "USER_MODALS_INFO_0 struct has changed!!!!\n");
256                 return -1;
257         }
258
259         return 0;
260 }
261
262 static NET_API_STATUS test_netusergetgroups(struct torture_context *tctx,
263                                             const char *hostname,
264                                             uint32_t level,
265                                             const char *username,
266                                             const char *groupname)
267 {
268         NET_API_STATUS status;
269         uint32_t entries_read = 0;
270         uint32_t total_entries = 0;
271         const char *current_name;
272         int found_group = 0;
273         uint8_t *buffer = NULL;
274         int i;
275
276         struct GROUP_USERS_INFO_0 *i0 = NULL;
277         struct GROUP_USERS_INFO_1 *i1 = NULL;
278
279         torture_comment(tctx, "Testing NetUserGetGroups level %d\n", level);
280
281         do {
282                 status = NetUserGetGroups(hostname,
283                                           username,
284                                           level,
285                                           &buffer,
286                                           (uint32_t)-1,
287                                           &entries_read,
288                                           &total_entries);
289                 if (status == 0 || status == ERROR_MORE_DATA) {
290                         switch (level) {
291                                 case 0:
292                                         i0 = (struct GROUP_USERS_INFO_0 *)buffer;
293                                         break;
294                                 case 1:
295                                         i1 = (struct GROUP_USERS_INFO_1 *)buffer;
296                                         break;
297                                 default:
298                                         return -1;
299                         }
300
301                         for (i=0; i<entries_read; i++) {
302
303                                 switch (level) {
304                                         case 0:
305                                                 current_name = i0->grui0_name;
306                                                 break;
307                                         case 1:
308                                                 current_name = i1->grui1_name;
309                                                 break;
310                                         default:
311                                                 return -1;
312                                 }
313
314                                 if (groupname && strcasecmp(current_name, groupname) == 0) {
315                                         found_group = 1;
316                                 }
317
318                                 switch (level) {
319                                         case 0:
320                                                 i0++;
321                                                 break;
322                                         case 1:
323                                                 i1++;
324                                                 break;
325                                         default:
326                                                 break;
327                                 }
328                         }
329                         NetApiBufferFree(buffer);
330                 }
331         } while (status == ERROR_MORE_DATA);
332
333         if (status) {
334                 return status;
335         }
336
337         if (groupname && !found_group) {
338                 torture_comment(tctx, "failed to get membership\n");
339                 return -1;
340         }
341
342         return 0;
343 }
344
345 bool torture_libnetapi_user(struct torture_context *tctx)
346 {
347         NET_API_STATUS status = 0;
348         uint8_t *buffer = NULL;
349         uint32_t levels[] = { 0, 1, 2, 3, 4, 10, 11, 20, 23 };
350         uint32_t enum_levels[] = { 0, 1, 2, 3, 4, 10, 11, 20, 23 };
351         uint32_t getgr_levels[] = { 0, 1 };
352         int i;
353
354         struct USER_INFO_0 u0;
355         struct USER_INFO_1007 u1007;
356         uint32_t parm_err = 0;
357
358         const char *hostname = torture_setting_string(tctx, "host", NULL);
359         struct libnetapi_ctx *ctx;
360
361         torture_assert(tctx, torture_libnetapi_init_context(tctx, &ctx),
362                        "failed to initialize libnetapi");
363
364         torture_comment(tctx, "NetUser tests\n");
365
366         /* cleanup */
367
368         NetUserDel(hostname, TORTURE_TEST_USER);
369         NetUserDel(hostname, TORTURE_TEST_USER2);
370
371         /* add a user */
372
373         status = test_netuseradd(tctx, hostname, TORTURE_TEST_USER);
374         if (status) {
375                 NETAPI_STATUS(tctx, ctx, status, "NetUserAdd");
376                 goto out;
377         }
378
379         /* enum the new user */
380
381         for (i=0; i<ARRAY_SIZE(enum_levels); i++) {
382
383                 status = test_netuserenum(tctx, hostname, enum_levels[i], TORTURE_TEST_USER);
384                 if (status) {
385                         NETAPI_STATUS(tctx, ctx, status, "NetUserEnum");
386                         goto out;
387                 }
388         }
389
390         /* basic queries */
391
392         for (i=0; i<ARRAY_SIZE(levels); i++) {
393
394                 torture_comment(tctx, "Testing NetUserGetInfo level %d\n", levels[i]);
395
396                 status = NetUserGetInfo(hostname, TORTURE_TEST_USER, levels[i], &buffer);
397                 if (status && status != 124) {
398                         NETAPI_STATUS(tctx, ctx, status, "NetUserGetInfo");
399                         goto out;
400                 }
401         }
402
403         /* testing getgroups */
404
405         for (i=0; i<ARRAY_SIZE(getgr_levels); i++) {
406
407                 status = test_netusergetgroups(tctx, hostname, getgr_levels[i], TORTURE_TEST_USER, NULL);
408                 if (status) {
409                         NETAPI_STATUS(tctx, ctx, status, "NetUserGetGroups");
410                         goto out;
411                 }
412         }
413
414         /* modify description */
415
416         torture_comment(tctx, "Testing NetUserSetInfo level %d\n", 1007);
417
418         u1007.usri1007_comment = "NetApi modified user";
419
420         status = NetUserSetInfo(hostname, TORTURE_TEST_USER, 1007, (uint8_t *)&u1007, &parm_err);
421         if (status) {
422                 NETAPI_STATUS(tctx, ctx, status, "NetUserSetInfo");
423                 goto out;
424         }
425
426         /* query info */
427
428         for (i=0; i<ARRAY_SIZE(levels); i++) {
429                 status = NetUserGetInfo(hostname, TORTURE_TEST_USER, levels[i], &buffer);
430                 if (status && status != 124) {
431                         NETAPI_STATUS(tctx, ctx, status, "NetUserGetInfo");
432                         goto out;
433                 }
434         }
435
436         torture_comment(tctx, "Testing NetUserSetInfo level 0\n");
437
438         u0.usri0_name = TORTURE_TEST_USER2;
439
440         status = NetUserSetInfo(hostname, TORTURE_TEST_USER, 0, (uint8_t *)&u0, &parm_err);
441         if (status) {
442                 NETAPI_STATUS(tctx, ctx, status, "NetUserSetInfo");
443                 goto out;
444         }
445
446         /* delete */
447
448         torture_comment(tctx, "Testing NetUserDel\n");
449
450         status = NetUserDel(hostname, TORTURE_TEST_USER2);
451         if (status) {
452                 NETAPI_STATUS(tctx, ctx, status, "NetUserDel");
453                 goto out;
454         }
455
456         /* should not exist anymore */
457
458         status = NetUserGetInfo(hostname, TORTURE_TEST_USER2, 0, &buffer);
459         if (status == 0) {
460                 NETAPI_STATUS(tctx, ctx, status, "NetUserGetInfo");
461                 status = -1;
462                 goto out;
463         }
464
465         status = test_netusermodals(tctx, ctx, hostname);
466         if (status) {
467                 goto out;
468         }
469
470         status = 0;
471
472         torture_comment(tctx, "NetUser tests succeeded\n");
473  out:
474         /* cleanup */
475         NetUserDel(hostname, TORTURE_TEST_USER);
476         NetUserDel(hostname, TORTURE_TEST_USER2);
477
478         if (status != 0) {
479                 torture_comment(tctx, "NetUser testsuite failed with: %s\n",
480                         libnetapi_get_error_string(ctx, status));
481                 libnetapi_free(ctx);
482                 return false;
483         }
484
485         libnetapi_free(ctx);
486         return true;
487 }