Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : test suite for RAP sam operations
4 :
5 : Copyright (C) Guenther Deschner 2010-2011
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "includes.h"
22 : #include "libcli/libcli.h"
23 : #include "torture/torture.h"
24 : #include "torture/util.h"
25 : #include "torture/smbtorture.h"
26 : #include "torture/util.h"
27 : #include "libcli/rap/rap.h"
28 : #include "torture/rap/proto.h"
29 : #include "../libcli/auth/libcli_auth.h"
30 : #include "torture/rpc/torture_rpc.h"
31 :
32 : #include <gnutls/gnutls.h>
33 : #include <gnutls/crypto.h>
34 :
35 : #define TEST_RAP_USER "torture_rap_user"
36 :
37 12 : static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
38 : {
39 12 : size_t len = MAX(8, min_len);
40 12 : char *s = generate_random_password(mem_ctx, len, len+6);
41 12 : printf("Generated password '%s'\n", s);
42 12 : return s;
43 : }
44 :
45 4 : static bool test_userpasswordset2_args(struct torture_context *tctx,
46 : struct smbcli_state *cli,
47 : const char *username,
48 : const char **password)
49 : {
50 0 : struct rap_NetUserPasswordSet2 r;
51 4 : char *newpass = samr_rand_pass(tctx, 8);
52 :
53 4 : ZERO_STRUCT(r);
54 :
55 4 : r.in.UserName = username;
56 :
57 4 : memcpy(r.in.OldPassword, *password, MIN(strlen(*password), 16));
58 4 : memcpy(r.in.NewPassword, newpass, MIN(strlen(newpass), 16));
59 4 : r.in.EncryptedPassword = 0;
60 4 : r.in.RealPasswordLength = strlen(newpass);
61 :
62 4 : torture_comment(tctx, "Testing rap_NetUserPasswordSet2(%s)\n", r.in.UserName);
63 :
64 4 : torture_assert_ntstatus_ok(tctx,
65 : smbcli_rap_netuserpasswordset2(cli->tree, tctx, &r),
66 : "smbcli_rap_netuserpasswordset2 failed");
67 4 : if (!W_ERROR_IS_OK(W_ERROR(r.out.status))) {
68 4 : torture_warning(tctx, "RAP NetUserPasswordSet2 gave: %s\n",
69 4 : win_errstr(W_ERROR(r.out.status)));
70 : } else {
71 0 : *password = newpass;
72 : }
73 :
74 4 : return true;
75 : }
76 :
77 4 : static bool test_userpasswordset2_crypt_args(struct torture_context *tctx,
78 : struct smbcli_state *cli,
79 : const char *username,
80 : const char **password)
81 : {
82 0 : struct rap_NetUserPasswordSet2 r;
83 4 : char *newpass = samr_rand_pass(tctx, 8);
84 :
85 4 : r.in.UserName = username;
86 :
87 4 : E_deshash(*password, r.in.OldPassword);
88 4 : E_deshash(newpass, r.in.NewPassword);
89 :
90 4 : r.in.RealPasswordLength = strlen(newpass);
91 4 : r.in.EncryptedPassword = 1;
92 :
93 4 : torture_comment(tctx, "Testing rap_NetUserPasswordSet2(%s)\n", r.in.UserName);
94 :
95 4 : torture_assert_ntstatus_ok(tctx,
96 : smbcli_rap_netuserpasswordset2(cli->tree, tctx, &r),
97 : "smbcli_rap_netuserpasswordset2 failed");
98 4 : if (!W_ERROR_IS_OK(W_ERROR(r.out.status))) {
99 4 : torture_warning(tctx, "RAP NetUserPasswordSet2 gave: %s\n",
100 4 : win_errstr(W_ERROR(r.out.status)));
101 : } else {
102 0 : *password = newpass;
103 : }
104 :
105 4 : return true;
106 : }
107 :
108 4 : static bool test_userpasswordset2(struct torture_context *tctx,
109 : struct smbcli_state *cli)
110 : {
111 0 : struct test_join *join_ctx;
112 0 : const char *password;
113 4 : bool ret = true;
114 :
115 4 : join_ctx = torture_create_testuser_max_pwlen(tctx, TEST_RAP_USER,
116 : torture_setting_string(tctx, "workgroup", NULL),
117 : ACB_NORMAL,
118 : &password, 14);
119 4 : if (join_ctx == NULL) {
120 0 : torture_fail(tctx, "failed to create user\n");
121 : }
122 :
123 4 : ret &= test_userpasswordset2_args(tctx, cli, TEST_RAP_USER, &password);
124 4 : ret &= test_userpasswordset2_crypt_args(tctx, cli, TEST_RAP_USER, &password);
125 :
126 4 : torture_leave_domain(tctx, join_ctx);
127 :
128 4 : return ret;
129 : }
130 :
131 4 : static bool test_oemchangepassword_args(struct torture_context *tctx,
132 : struct smbcli_state *cli,
133 : const char *username,
134 : const char **password)
135 : {
136 0 : struct rap_NetOEMChangePassword r;
137 :
138 4 : const char *oldpass = *password;
139 4 : char *newpass = samr_rand_pass(tctx, 9);
140 0 : uint8_t old_pw_hash[16];
141 0 : uint8_t new_pw_hash[16];
142 4 : gnutls_cipher_hd_t cipher_hnd = NULL;
143 4 : gnutls_datum_t pw_key = {
144 : .data = old_pw_hash,
145 : .size = sizeof(old_pw_hash),
146 : };
147 :
148 4 : r.in.UserName = username;
149 :
150 4 : E_deshash(oldpass, old_pw_hash);
151 4 : E_deshash(newpass, new_pw_hash);
152 :
153 4 : encode_pw_buffer(r.in.crypt_password, newpass, STR_ASCII);
154 :
155 4 : gnutls_cipher_init(&cipher_hnd,
156 : GNUTLS_CIPHER_ARCFOUR_128,
157 : &pw_key,
158 : NULL);
159 4 : gnutls_cipher_encrypt(cipher_hnd,
160 : r.in.crypt_password,
161 : 516);
162 4 : gnutls_cipher_deinit(cipher_hnd);
163 4 : E_old_pw_hash(new_pw_hash, old_pw_hash, r.in.password_hash);
164 :
165 4 : torture_comment(tctx, "Testing rap_NetOEMChangePassword(%s)\n", r.in.UserName);
166 :
167 4 : torture_assert_ntstatus_ok(tctx,
168 : smbcli_rap_netoemchangepassword(cli->tree, tctx, &r),
169 : "smbcli_rap_netoemchangepassword failed");
170 4 : if (!W_ERROR_IS_OK(W_ERROR(r.out.status))) {
171 2 : torture_warning(tctx, "RAP NetOEMChangePassword gave: %s\n",
172 2 : win_errstr(W_ERROR(r.out.status)));
173 : } else {
174 2 : *password = newpass;
175 : }
176 :
177 4 : return true;
178 : }
179 :
180 4 : static bool test_oemchangepassword(struct torture_context *tctx,
181 : struct smbcli_state *cli)
182 : {
183 :
184 0 : struct test_join *join_ctx;
185 0 : const char *password;
186 0 : bool ret;
187 :
188 4 : join_ctx = torture_create_testuser_max_pwlen(tctx, TEST_RAP_USER,
189 : torture_setting_string(tctx, "workgroup", NULL),
190 : ACB_NORMAL,
191 : &password, 14);
192 4 : if (join_ctx == NULL) {
193 0 : torture_fail(tctx, "failed to create user\n");
194 : }
195 :
196 4 : ret = test_oemchangepassword_args(tctx, cli, TEST_RAP_USER, &password);
197 :
198 4 : torture_leave_domain(tctx, join_ctx);
199 :
200 4 : return ret;
201 : }
202 :
203 4 : static bool test_usergetinfo_byname(struct torture_context *tctx,
204 : struct smbcli_state *cli,
205 : const char *UserName)
206 : {
207 0 : struct rap_NetUserGetInfo r;
208 0 : int i;
209 4 : uint16_t levels[] = { 0, 1, 2, 10, 11 };
210 :
211 24 : for (i=0; i < ARRAY_SIZE(levels); i++) {
212 :
213 20 : r.in.UserName = UserName;
214 20 : r.in.level = levels[i];
215 20 : r.in.bufsize = 8192;
216 :
217 20 : torture_comment(tctx,
218 20 : "Testing rap_NetUserGetInfo(%s) level %d\n", r.in.UserName, r.in.level);
219 :
220 20 : torture_assert_ntstatus_ok(tctx,
221 : smbcli_rap_netusergetinfo(cli->tree, tctx, &r),
222 : "smbcli_rap_netusergetinfo failed");
223 20 : torture_assert_werr_ok(tctx, W_ERROR(r.out.status),
224 : "smbcli_rap_netusergetinfo failed");
225 : }
226 :
227 4 : return true;
228 : }
229 :
230 4 : static bool test_usergetinfo(struct torture_context *tctx,
231 : struct smbcli_state *cli)
232 : {
233 :
234 0 : struct test_join *join_ctx;
235 0 : const char *password;
236 0 : bool ret;
237 :
238 4 : join_ctx = torture_create_testuser_max_pwlen(tctx, TEST_RAP_USER,
239 : torture_setting_string(tctx, "workgroup", NULL),
240 : ACB_NORMAL,
241 : &password, 14);
242 4 : if (join_ctx == NULL) {
243 0 : torture_fail(tctx, "failed to create user\n");
244 : }
245 :
246 4 : ret = test_usergetinfo_byname(tctx, cli, TEST_RAP_USER);
247 :
248 4 : torture_leave_domain(tctx, join_ctx);
249 :
250 4 : return ret;
251 : }
252 :
253 4 : static bool test_useradd(struct torture_context *tctx,
254 : struct smbcli_state *cli)
255 : {
256 :
257 0 : struct rap_NetUserAdd r;
258 0 : struct rap_NetUserInfo1 info1;
259 0 : int i;
260 4 : uint16_t levels[] = { 1 };
261 4 : const char *username = TEST_RAP_USER;
262 :
263 4 : for (i=0; i < ARRAY_SIZE(levels); i++) {
264 :
265 0 : const char *pwd;
266 :
267 4 : pwd = generate_random_password(tctx, 9, 16);
268 :
269 4 : r.in.level = levels[i];
270 4 : r.in.bufsize = 0xffff;
271 4 : r.in.pwdlength = strlen(pwd);
272 4 : r.in.unknown = 0;
273 :
274 4 : switch (r.in.level) {
275 4 : case 1:
276 4 : ZERO_STRUCT(info1);
277 :
278 4 : info1.Name = username;
279 4 : memcpy(info1.Password, pwd, MIN(strlen(pwd), 16));
280 4 : info1.Priv = USER_PRIV_USER;
281 4 : info1.Flags = 0x21;
282 4 : info1.HomeDir = "home_dir";
283 4 : info1.Comment = "comment";
284 4 : info1.ScriptPath = "logon_script";
285 :
286 4 : r.in.info.info1 = info1;
287 4 : break;
288 : }
289 :
290 4 : torture_comment(tctx,
291 4 : "Testing rap_NetUserAdd(%s) level %d\n", username, r.in.level);
292 :
293 4 : torture_assert_ntstatus_ok(tctx,
294 : smbcli_rap_netuseradd(cli->tree, tctx, &r),
295 : "smbcli_rap_netuseradd failed");
296 4 : torture_assert_werr_ok(tctx, W_ERROR(r.out.status),
297 : "smbcli_rap_netuseradd failed");
298 :
299 0 : torture_assert_ntstatus_ok(tctx,
300 : smbcli_rap_netuseradd(cli->tree, tctx, &r),
301 : "2nd smbcli_rap_netuseradd failed");
302 0 : torture_assert_werr_equal(tctx, W_ERROR(r.out.status), WERR_NERR_USEREXISTS,
303 : "2nd smbcli_rap_netuseradd failed");
304 :
305 : {
306 0 : struct rap_NetUserDelete d;
307 :
308 0 : d.in.UserName = username;
309 :
310 0 : smbcli_rap_netuserdelete(cli->tree, tctx, &d);
311 : }
312 : }
313 :
314 0 : return true;
315 : }
316 :
317 4 : static bool test_userdelete(struct torture_context *tctx,
318 : struct smbcli_state *cli)
319 : {
320 :
321 0 : struct rap_NetUserDelete r;
322 :
323 : {
324 0 : struct rap_NetUserAdd a;
325 0 : const char *pwd;
326 :
327 4 : ZERO_STRUCT(a.in.info.info1);
328 :
329 4 : pwd = generate_random_password(tctx, 9, 16);
330 :
331 4 : a.in.level = 1;
332 4 : a.in.bufsize = 0xffff;
333 4 : a.in.pwdlength = strlen(pwd);
334 4 : a.in.unknown = 0;
335 4 : a.in.info.info1.Name = TEST_RAP_USER;
336 4 : a.in.info.info1.Priv = USER_PRIV_USER;
337 :
338 4 : memcpy(a.in.info.info1.Password, pwd, MIN(strlen(pwd), 16));
339 :
340 4 : torture_assert_ntstatus_ok(tctx,
341 : smbcli_rap_netuseradd(cli->tree, tctx, &a),
342 : "smbcli_rap_netuseradd failed");
343 : }
344 :
345 4 : r.in.UserName = TEST_RAP_USER;
346 :
347 4 : torture_comment(tctx,
348 : "Testing rap_NetUserDelete(%s)\n", r.in.UserName);
349 :
350 4 : torture_assert_ntstatus_ok(tctx,
351 : smbcli_rap_netuserdelete(cli->tree, tctx, &r),
352 : "smbcli_rap_netuserdelete failed");
353 4 : torture_assert_werr_ok(tctx, W_ERROR(r.out.status),
354 : "smbcli_rap_netuserdelete failed");
355 :
356 0 : torture_assert_ntstatus_ok(tctx,
357 : smbcli_rap_netuserdelete(cli->tree, tctx, &r),
358 : "2nd smbcli_rap_netuserdelete failed");
359 0 : torture_assert_werr_equal(tctx, W_ERROR(r.out.status), WERR_NERR_USERNOTFOUND,
360 : "2nd smbcli_rap_netuserdelete failed");
361 :
362 0 : return true;
363 : }
364 :
365 2354 : struct torture_suite *torture_rap_sam(TALLOC_CTX *mem_ctx)
366 : {
367 2354 : struct torture_suite *suite = torture_suite_create(mem_ctx, "sam");
368 :
369 2354 : torture_suite_add_1smb_test(suite, "userpasswordset2", test_userpasswordset2);
370 2354 : torture_suite_add_1smb_test(suite, "oemchangepassword", test_oemchangepassword);
371 2354 : torture_suite_add_1smb_test(suite, "usergetinfo", test_usergetinfo);
372 2354 : torture_suite_add_1smb_test(suite, "useradd", test_useradd);
373 2354 : torture_suite_add_1smb_test(suite, "userdelete", test_userdelete);
374 :
375 2354 : return suite;
376 : }
|