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