s4:torture: use tctx->ev as event context for polling
[kai/samba.git] / source4 / torture / rpc / samba3rpc.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    dcerpc torture tests, designed to walk Samba3 code paths
5
6    Copyright (C) Volker Lendecke 2006
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/raw/raw_proto.h"
25 #include "torture/util.h"
26 #include "libcli/rap/rap.h"
27 #include "librpc/gen_ndr/ndr_lsa_c.h"
28 #include "librpc/gen_ndr/ndr_samr_c.h"
29 #include "librpc/gen_ndr/ndr_netlogon_c.h"
30 #include "librpc/gen_ndr/ndr_srvsvc_c.h"
31 #include "librpc/gen_ndr/ndr_spoolss_c.h"
32 #include "librpc/gen_ndr/ndr_winreg_c.h"
33 #include "librpc/gen_ndr/ndr_wkssvc_c.h"
34 #include "lib/cmdline/popt_common.h"
35 #include "torture/rpc/torture_rpc.h"
36 #include "libcli/libcli.h"
37 #include "libcli/smb_composite/smb_composite.h"
38 #include "libcli/auth/libcli_auth.h"
39 #include "../lib/crypto/crypto.h"
40 #include "libcli/security/security.h"
41 #include "param/param.h"
42 #include "lib/registry/registry.h"
43 #include "libcli/resolve/resolve.h"
44 #include "torture/ndr/ndr.h"
45
46 /*
47  * This tests a RPC call using an invalid vuid
48  */
49
50 bool torture_bind_authcontext(struct torture_context *torture)
51 {
52         TALLOC_CTX *mem_ctx;
53         NTSTATUS status;
54         bool ret = false;
55         struct lsa_ObjectAttribute objectattr;
56         struct lsa_OpenPolicy2 openpolicy;
57         struct policy_handle handle;
58         struct lsa_Close close_handle;
59         struct smbcli_session *tmp;
60         struct smbcli_session *session2;
61         struct smbcli_state *cli;
62         struct dcerpc_pipe *lsa_pipe;
63         struct dcerpc_binding_handle *lsa_handle;
64         struct cli_credentials *anon_creds;
65         struct smb_composite_sesssetup setup;
66         struct smbcli_options options;
67         struct smbcli_session_options session_options;
68
69         mem_ctx = talloc_init("torture_bind_authcontext");
70
71         if (mem_ctx == NULL) {
72                 torture_comment(torture, "talloc_init failed\n");
73                 return false;
74         }
75
76         lpcfg_smbcli_options(torture->lp_ctx, &options);
77         lpcfg_smbcli_session_options(torture->lp_ctx, &session_options);
78
79         status = smbcli_full_connection(mem_ctx, &cli,
80                                         torture_setting_string(torture, "host", NULL),
81                                         lpcfg_smb_ports(torture->lp_ctx),
82                                         "IPC$", NULL,
83                                         lpcfg_socket_options(torture->lp_ctx),
84                                         cmdline_credentials,
85                                         lpcfg_resolve_context(torture->lp_ctx),
86                                         torture->ev, &options, &session_options,
87                                         lpcfg_gensec_settings(torture, torture->lp_ctx));
88         if (!NT_STATUS_IS_OK(status)) {
89                 torture_comment(torture, "smbcli_full_connection failed: %s\n",
90                          nt_errstr(status));
91                 goto done;
92         }
93
94         lsa_pipe = dcerpc_pipe_init(mem_ctx, torture->ev);
95         if (lsa_pipe == NULL) {
96                 torture_comment(torture, "dcerpc_pipe_init failed\n");
97                 goto done;
98         }
99         lsa_handle = lsa_pipe->binding_handle;
100
101         status = dcerpc_pipe_open_smb(lsa_pipe, cli->tree, "\\lsarpc");
102         if (!NT_STATUS_IS_OK(status)) {
103                 torture_comment(torture, "dcerpc_pipe_open_smb failed: %s\n",
104                          nt_errstr(status));
105                 goto done;
106         }
107
108         status = dcerpc_bind_auth_none(lsa_pipe, &ndr_table_lsarpc);
109         if (!NT_STATUS_IS_OK(status)) {
110                 torture_comment(torture, "dcerpc_bind_auth_none failed: %s\n",
111                          nt_errstr(status));
112                 goto done;
113         }
114
115         openpolicy.in.system_name =talloc_asprintf(
116                 mem_ctx, "\\\\%s", dcerpc_server_name(lsa_pipe));
117         ZERO_STRUCT(objectattr);
118         openpolicy.in.attr = &objectattr;
119         openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
120         openpolicy.out.handle = &handle;
121
122         status = dcerpc_lsa_OpenPolicy2_r(lsa_handle, mem_ctx, &openpolicy);
123
124         if (!NT_STATUS_IS_OK(status)) {
125                 torture_comment(torture, "dcerpc_lsa_OpenPolicy2 failed: %s\n",
126                          nt_errstr(status));
127                 goto done;
128         }
129         if (!NT_STATUS_IS_OK(openpolicy.out.result)) {
130                 torture_comment(torture, "dcerpc_lsa_OpenPolicy2 failed: %s\n",
131                          nt_errstr(openpolicy.out.result));
132                 goto done;
133         }
134
135         close_handle.in.handle = &handle;
136         close_handle.out.handle = &handle;
137
138         status = dcerpc_lsa_Close_r(lsa_handle, mem_ctx, &close_handle);
139         if (!NT_STATUS_IS_OK(status)) {
140                 torture_comment(torture, "dcerpc_lsa_Close failed: %s\n",
141                          nt_errstr(status));
142                 goto done;
143         }
144         if (!NT_STATUS_IS_OK(close_handle.out.result)) {
145                 torture_comment(torture, "dcerpc_lsa_Close failed: %s\n",
146                          nt_errstr(close_handle.out.result));
147                 goto done;
148         }
149
150         session2 = smbcli_session_init(cli->transport, mem_ctx, false, session_options);
151         if (session2 == NULL) {
152                 torture_comment(torture, "smbcli_session_init failed\n");
153                 goto done;
154         }
155
156         if (!(anon_creds = cli_credentials_init_anon(mem_ctx))) {
157                 torture_comment(torture, "create_anon_creds failed\n");
158                 goto done;
159         }
160
161         setup.in.sesskey = cli->transport->negotiate.sesskey;
162         setup.in.capabilities = cli->transport->negotiate.capabilities;
163         setup.in.workgroup = "";
164         setup.in.credentials = anon_creds;
165         setup.in.gensec_settings = lpcfg_gensec_settings(torture, torture->lp_ctx);
166
167         status = smb_composite_sesssetup(session2, &setup);
168         if (!NT_STATUS_IS_OK(status)) {
169                 torture_comment(torture, "anon session setup failed: %s\n",
170                          nt_errstr(status));
171                 goto done;
172         }
173         session2->vuid = setup.out.vuid;
174
175         tmp = cli->tree->session;
176         cli->tree->session = session2;
177
178         status = dcerpc_lsa_OpenPolicy2_r(lsa_handle, mem_ctx, &openpolicy);
179
180         cli->tree->session = tmp;
181         talloc_free(lsa_pipe);
182         lsa_pipe = NULL;
183
184         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
185                 torture_comment(torture, "dcerpc_lsa_OpenPolicy2 with wrong vuid gave %s, "
186                          "expected NT_STATUS_INVALID_HANDLE\n",
187                          nt_errstr(status));
188                 goto done;
189         }
190
191         ret = true;
192  done:
193         talloc_free(mem_ctx);
194         return ret;
195 }
196
197 /*
198  * Bind to lsa using a specific auth method
199  */
200
201 static bool bindtest(struct torture_context *tctx,
202                      struct smbcli_state *cli,
203                      struct cli_credentials *credentials,
204                      uint8_t auth_type, uint8_t auth_level)
205 {
206         TALLOC_CTX *mem_ctx;
207         bool ret = false;
208         NTSTATUS status;
209
210         struct dcerpc_pipe *lsa_pipe;
211         struct dcerpc_binding_handle *lsa_handle;
212         struct lsa_ObjectAttribute objectattr;
213         struct lsa_OpenPolicy2 openpolicy;
214         struct lsa_QueryInfoPolicy query;
215         union lsa_PolicyInformation *info = NULL;
216         struct policy_handle handle;
217         struct lsa_Close close_handle;
218
219         if ((mem_ctx = talloc_init("bindtest")) == NULL) {
220                 torture_comment(tctx, "talloc_init failed\n");
221                 return false;
222         }
223
224         lsa_pipe = dcerpc_pipe_init(mem_ctx, tctx->ev);
225         if (lsa_pipe == NULL) {
226                 torture_comment(tctx, "dcerpc_pipe_init failed\n");
227                 goto done;
228         }
229         lsa_handle = lsa_pipe->binding_handle;
230
231         status = dcerpc_pipe_open_smb(lsa_pipe, cli->tree, "\\lsarpc");
232         if (!NT_STATUS_IS_OK(status)) {
233                 torture_comment(tctx, "dcerpc_pipe_open_smb failed: %s\n",
234                          nt_errstr(status));
235                 goto done;
236         }
237
238         status = dcerpc_bind_auth(lsa_pipe, &ndr_table_lsarpc,
239                                   credentials, lpcfg_gensec_settings(tctx->lp_ctx, tctx->lp_ctx), auth_type, auth_level,
240                                   NULL);
241         if (!NT_STATUS_IS_OK(status)) {
242                 torture_comment(tctx, "dcerpc_bind_auth failed: %s\n", nt_errstr(status));
243                 goto done;
244         }
245
246         openpolicy.in.system_name =talloc_asprintf(
247                 mem_ctx, "\\\\%s", dcerpc_server_name(lsa_pipe));
248         ZERO_STRUCT(objectattr);
249         openpolicy.in.attr = &objectattr;
250         openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
251         openpolicy.out.handle = &handle;
252
253         status = dcerpc_lsa_OpenPolicy2_r(lsa_handle, mem_ctx, &openpolicy);
254
255         if (!NT_STATUS_IS_OK(status)) {
256                 torture_comment(tctx, "dcerpc_lsa_OpenPolicy2 failed: %s\n",
257                          nt_errstr(status));
258                 goto done;
259         }
260         if (!NT_STATUS_IS_OK(openpolicy.out.result)) {
261                 torture_comment(tctx, "dcerpc_lsa_OpenPolicy2 failed: %s\n",
262                          nt_errstr(openpolicy.out.result));
263                 goto done;
264         }
265
266         query.in.handle = &handle;
267         query.in.level = LSA_POLICY_INFO_DOMAIN;
268         query.out.info = &info;
269
270         status = dcerpc_lsa_QueryInfoPolicy_r(lsa_handle, mem_ctx, &query);
271         if (!NT_STATUS_IS_OK(status)) {
272                 torture_comment(tctx, "dcerpc_lsa_QueryInfoPolicy failed: %s\n",
273                          nt_errstr(status));
274                 goto done;
275         }
276         if (!NT_STATUS_IS_OK(query.out.result)) {
277                 torture_comment(tctx, "dcerpc_lsa_QueryInfoPolicy failed: %s\n",
278                          nt_errstr(query.out.result));
279                 goto done;
280         }
281
282         close_handle.in.handle = &handle;
283         close_handle.out.handle = &handle;
284
285         status = dcerpc_lsa_Close_r(lsa_handle, mem_ctx, &close_handle);
286         if (!NT_STATUS_IS_OK(status)) {
287                 torture_comment(tctx, "dcerpc_lsa_Close failed: %s\n",
288                          nt_errstr(status));
289                 goto done;
290         }
291         if (!NT_STATUS_IS_OK(close_handle.out.result)) {
292                 torture_comment(tctx, "dcerpc_lsa_Close failed: %s\n",
293                          nt_errstr(close_handle.out.result));
294                 goto done;
295         }
296
297
298         ret = true;
299  done:
300         talloc_free(mem_ctx);
301         return ret;
302 }
303
304 /*
305  * test authenticated RPC binds with the variants Samba3 does support
306  */
307
308 static bool torture_bind_samba3(struct torture_context *torture)
309 {
310         TALLOC_CTX *mem_ctx;
311         NTSTATUS status;
312         bool ret = false;
313         struct smbcli_state *cli;
314         struct smbcli_options options;
315         struct smbcli_session_options session_options;
316
317         mem_ctx = talloc_init("torture_bind_authcontext");
318
319         if (mem_ctx == NULL) {
320                 torture_comment(torture, "talloc_init failed\n");
321                 return false;
322         }
323
324         lpcfg_smbcli_options(torture->lp_ctx, &options);
325         lpcfg_smbcli_session_options(torture->lp_ctx, &session_options);
326
327         status = smbcli_full_connection(mem_ctx, &cli,
328                                         torture_setting_string(torture, "host", NULL),
329                                         lpcfg_smb_ports(torture->lp_ctx),
330                                         "IPC$", NULL,
331                                         lpcfg_socket_options(torture->lp_ctx),
332                                         cmdline_credentials,
333                                         lpcfg_resolve_context(torture->lp_ctx),
334                                         torture->ev, &options, &session_options,
335                                         lpcfg_gensec_settings(torture, torture->lp_ctx));
336         if (!NT_STATUS_IS_OK(status)) {
337                 torture_comment(torture, "smbcli_full_connection failed: %s\n",
338                          nt_errstr(status));
339                 goto done;
340         }
341
342         ret = true;
343
344         ret &= bindtest(torture, cli, cmdline_credentials, DCERPC_AUTH_TYPE_NTLMSSP,
345                         DCERPC_AUTH_LEVEL_INTEGRITY);
346         ret &= bindtest(torture, cli, cmdline_credentials, DCERPC_AUTH_TYPE_NTLMSSP,
347                         DCERPC_AUTH_LEVEL_PRIVACY);
348         ret &= bindtest(torture, cli, cmdline_credentials, DCERPC_AUTH_TYPE_SPNEGO,
349                         DCERPC_AUTH_LEVEL_INTEGRITY);
350         ret &= bindtest(torture, cli, cmdline_credentials, DCERPC_AUTH_TYPE_SPNEGO,
351                         DCERPC_AUTH_LEVEL_PRIVACY);
352
353  done:
354         talloc_free(mem_ctx);
355         return ret;
356 }
357
358 /*
359  * Lookup or create a user and return all necessary info
360  */
361
362 static bool get_usr_handle(struct torture_context *tctx,
363                            struct smbcli_state *cli,
364                            TALLOC_CTX *mem_ctx,
365                            struct cli_credentials *admin_creds,
366                            uint8_t auth_type,
367                            uint8_t auth_level,
368                            const char *username,
369                            char **domain,
370                            struct dcerpc_pipe **result_pipe,
371                            struct policy_handle **result_handle,
372                            struct dom_sid **sid_p)
373 {
374         struct dcerpc_pipe *samr_pipe;
375         struct dcerpc_binding_handle *samr_handle;
376         NTSTATUS status;
377         struct policy_handle conn_handle;
378         struct policy_handle domain_handle;
379         struct policy_handle *user_handle;
380         struct samr_Connect2 conn;
381         struct samr_EnumDomains enumdom;
382         uint32_t resume_handle = 0;
383         uint32_t num_entries = 0;
384         struct samr_SamArray *sam = NULL;
385         struct samr_LookupDomain l;
386         struct dom_sid2 *sid = NULL;
387         int dom_idx;
388         struct lsa_String domain_name;
389         struct lsa_String user_name;
390         struct samr_OpenDomain o;
391         struct samr_CreateUser2 c;
392         uint32_t user_rid,access_granted;
393
394         samr_pipe = dcerpc_pipe_init(mem_ctx, tctx->ev);
395         torture_assert(tctx, samr_pipe, "dcerpc_pipe_init failed");
396
397         samr_handle = samr_pipe->binding_handle;
398
399         torture_assert_ntstatus_ok(tctx,
400                 dcerpc_pipe_open_smb(samr_pipe, cli->tree, "\\samr"),
401                 "dcerpc_pipe_open_smb failed");
402
403         if (admin_creds != NULL) {
404                 torture_assert_ntstatus_ok(tctx,
405                         dcerpc_bind_auth(samr_pipe, &ndr_table_samr,
406                                           admin_creds, lpcfg_gensec_settings(tctx->lp_ctx, tctx->lp_ctx), auth_type, auth_level,
407                                           NULL),
408                         "dcerpc_bind_auth failed");
409         } else {
410                 /* We must have an authenticated SMB connection */
411                 torture_assert_ntstatus_ok(tctx,
412                         dcerpc_bind_auth_none(samr_pipe, &ndr_table_samr),
413                         "dcerpc_bind_auth_none failed");
414         }
415
416         conn.in.system_name = talloc_asprintf(
417                 mem_ctx, "\\\\%s", dcerpc_server_name(samr_pipe));
418         conn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
419         conn.out.connect_handle = &conn_handle;
420
421         torture_assert_ntstatus_ok(tctx,
422                 dcerpc_samr_Connect2_r(samr_handle, mem_ctx, &conn),
423                 "samr_Connect2 failed");
424         torture_assert_ntstatus_ok(tctx, conn.out.result,
425                 "samr_Connect2 failed");
426
427         enumdom.in.connect_handle = &conn_handle;
428         enumdom.in.resume_handle = &resume_handle;
429         enumdom.in.buf_size = (uint32_t)-1;
430         enumdom.out.resume_handle = &resume_handle;
431         enumdom.out.num_entries = &num_entries;
432         enumdom.out.sam = &sam;
433
434         torture_assert_ntstatus_ok(tctx,
435                 dcerpc_samr_EnumDomains_r(samr_handle, mem_ctx, &enumdom),
436                 "samr_EnumDomains failed");
437         torture_assert_ntstatus_ok(tctx, enumdom.out.result,
438                 "samr_EnumDomains failed");
439
440         torture_assert_int_equal(tctx, *enumdom.out.num_entries, 2,
441                 "samr_EnumDomains returned unexpected num_entries");
442
443         dom_idx = strequal(sam->entries[0].name.string,
444                            "builtin") ? 1:0;
445
446         l.in.connect_handle = &conn_handle;
447         domain_name.string = sam->entries[dom_idx].name.string;
448         *domain = talloc_strdup(mem_ctx, domain_name.string);
449         l.in.domain_name = &domain_name;
450         l.out.sid = &sid;
451
452         torture_assert_ntstatus_ok(tctx,
453                 dcerpc_samr_LookupDomain_r(samr_handle, mem_ctx, &l),
454                 "samr_LookupDomain failed");
455         torture_assert_ntstatus_ok(tctx, l.out.result,
456                 "samr_LookupDomain failed");
457
458         o.in.connect_handle = &conn_handle;
459         o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
460         o.in.sid = *l.out.sid;
461         o.out.domain_handle = &domain_handle;
462
463         torture_assert_ntstatus_ok(tctx,
464                 dcerpc_samr_OpenDomain_r(samr_handle, mem_ctx, &o),
465                 "samr_OpenDomain failed");
466         torture_assert_ntstatus_ok(tctx, o.out.result,
467                 "samr_OpenDomain failed");
468
469         c.in.domain_handle = &domain_handle;
470         user_name.string = username;
471         c.in.account_name = &user_name;
472         c.in.acct_flags = ACB_NORMAL;
473         c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
474         user_handle = talloc(mem_ctx, struct policy_handle);
475         c.out.user_handle = user_handle;
476         c.out.access_granted = &access_granted;
477         c.out.rid = &user_rid;
478
479         torture_assert_ntstatus_ok(tctx,
480                 dcerpc_samr_CreateUser2_r(samr_handle, mem_ctx, &c),
481                 "samr_CreateUser2 failed");
482
483         if (NT_STATUS_EQUAL(c.out.result, NT_STATUS_USER_EXISTS)) {
484                 struct samr_LookupNames ln;
485                 struct samr_OpenUser ou;
486                 struct samr_Ids rids, types;
487
488                 ln.in.domain_handle = &domain_handle;
489                 ln.in.num_names = 1;
490                 ln.in.names = &user_name;
491                 ln.out.rids = &rids;
492                 ln.out.types = &types;
493
494                 torture_assert_ntstatus_ok(tctx,
495                         dcerpc_samr_LookupNames_r(samr_handle, mem_ctx, &ln),
496                         "samr_LookupNames failed");
497                 torture_assert_ntstatus_ok(tctx, ln.out.result,
498                         "samr_LookupNames failed");
499
500                 ou.in.domain_handle = &domain_handle;
501                 ou.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
502                 user_rid = ou.in.rid = ln.out.rids->ids[0];
503                 ou.out.user_handle = user_handle;
504
505                 torture_assert_ntstatus_ok(tctx,
506                         dcerpc_samr_OpenUser_r(samr_handle, mem_ctx, &ou),
507                         "samr_OpenUser failed");
508                 status = ou.out.result;
509         } else {
510                 status = c.out.result;
511         }
512
513         torture_assert_ntstatus_ok(tctx, status,
514                 "samr_CreateUser failed");
515
516         *result_pipe = samr_pipe;
517         *result_handle = user_handle;
518         if (sid_p != NULL) {
519                 *sid_p = dom_sid_add_rid(mem_ctx, *l.out.sid, user_rid);
520         }
521         return true;
522
523 }
524
525 /*
526  * Create a test user
527  */
528
529 static bool create_user(struct torture_context *tctx,
530                         TALLOC_CTX *mem_ctx, struct smbcli_state *cli,
531                         struct cli_credentials *admin_creds,
532                         const char *username, const char *password,
533                         char **domain_name,
534                         struct dom_sid **user_sid)
535 {
536         TALLOC_CTX *tmp_ctx;
537         NTSTATUS status;
538         struct dcerpc_pipe *samr_pipe;
539         struct dcerpc_binding_handle *samr_handle;
540         struct policy_handle *wks_handle;
541         bool ret = false;
542
543         if (!(tmp_ctx = talloc_new(mem_ctx))) {
544                 torture_comment(tctx, "talloc_init failed\n");
545                 return false;
546         }
547
548         ret = get_usr_handle(tctx, cli, tmp_ctx, admin_creds,
549                              DCERPC_AUTH_TYPE_NTLMSSP,
550                              DCERPC_AUTH_LEVEL_INTEGRITY,
551                              username, domain_name, &samr_pipe, &wks_handle,
552                              user_sid);
553         if (ret == false) {
554                 torture_comment(tctx, "get_usr_handle failed\n");
555                 goto done;
556         }
557         samr_handle = samr_pipe->binding_handle;
558
559         {
560                 struct samr_SetUserInfo2 sui2;
561                 struct samr_SetUserInfo sui;
562                 struct samr_QueryUserInfo qui;
563                 union samr_UserInfo u_info;
564                 union samr_UserInfo *info;
565                 DATA_BLOB session_key;
566
567
568                 ZERO_STRUCT(u_info);
569                 encode_pw_buffer(u_info.info23.password.data, password,
570                                  STR_UNICODE);
571
572                 status = dcerpc_fetch_session_key(samr_pipe, &session_key);
573                 if (!NT_STATUS_IS_OK(status)) {
574                         torture_comment(tctx, "dcerpc_fetch_session_key failed\n");
575                         goto done;
576                 }
577                 arcfour_crypt_blob(u_info.info23.password.data, 516,
578                                    &session_key);
579                 u_info.info23.info.password_expired = 0;
580                 u_info.info23.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT |
581                                                     SAMR_FIELD_LM_PASSWORD_PRESENT |
582                                                     SAMR_FIELD_EXPIRED_FLAG;
583                 sui2.in.user_handle = wks_handle;
584                 sui2.in.info = &u_info;
585                 sui2.in.level = 23;
586
587                 status = dcerpc_samr_SetUserInfo2_r(samr_handle, tmp_ctx, &sui2);
588                 if (!NT_STATUS_IS_OK(status)) {
589                         torture_comment(tctx, "samr_SetUserInfo(23) failed: %s\n",
590                                  nt_errstr(status));
591                         goto done;
592                 }
593                 if (!NT_STATUS_IS_OK(sui2.out.result)) {
594                         torture_comment(tctx, "samr_SetUserInfo(23) failed: %s\n",
595                                  nt_errstr(sui2.out.result));
596                         goto done;
597                 }
598
599                 u_info.info16.acct_flags = ACB_NORMAL;
600                 sui.in.user_handle = wks_handle;
601                 sui.in.info = &u_info;
602                 sui.in.level = 16;
603
604                 status = dcerpc_samr_SetUserInfo_r(samr_handle, tmp_ctx, &sui);
605                 if (!NT_STATUS_IS_OK(status) || !NT_STATUS_IS_OK(sui.out.result)) {
606                         torture_comment(tctx, "samr_SetUserInfo(16) failed\n");
607                         goto done;
608                 }
609
610                 qui.in.user_handle = wks_handle;
611                 qui.in.level = 21;
612                 qui.out.info = &info;
613
614                 status = dcerpc_samr_QueryUserInfo_r(samr_handle, tmp_ctx, &qui);
615                 if (!NT_STATUS_IS_OK(status) || !NT_STATUS_IS_OK(qui.out.result)) {
616                         torture_comment(tctx, "samr_QueryUserInfo(21) failed\n");
617                         goto done;
618                 }
619
620                 info->info21.allow_password_change = 0;
621                 info->info21.force_password_change = 0;
622                 info->info21.account_name.string = NULL;
623                 info->info21.rid = 0;
624                 info->info21.acct_expiry = 0;
625                 info->info21.fields_present = 0x81827fa; /* copy usrmgr.exe */
626
627                 u_info.info21 = info->info21;
628                 sui.in.user_handle = wks_handle;
629                 sui.in.info = &u_info;
630                 sui.in.level = 21;
631
632                 status = dcerpc_samr_SetUserInfo_r(samr_handle, tmp_ctx, &sui);
633                 if (!NT_STATUS_IS_OK(status) || !NT_STATUS_IS_OK(sui.out.result)) {
634                         torture_comment(tctx, "samr_SetUserInfo(21) failed\n");
635                         goto done;
636                 }
637         }
638
639         *domain_name= talloc_steal(mem_ctx, *domain_name);
640         *user_sid = talloc_steal(mem_ctx, *user_sid);
641         ret = true;
642  done:
643         talloc_free(tmp_ctx);
644         return ret;
645 }
646
647 /*
648  * Delete a test user
649  */
650
651 static bool delete_user(struct torture_context *tctx,
652                         struct smbcli_state *cli,
653                         struct cli_credentials *admin_creds,
654                         const char *username)
655 {
656         TALLOC_CTX *mem_ctx;
657         NTSTATUS status;
658         char *dom_name;
659         struct dcerpc_pipe *samr_pipe;
660         struct dcerpc_binding_handle *samr_handle;
661         struct policy_handle *user_handle;
662         bool ret = false;
663
664         if ((mem_ctx = talloc_init("leave")) == NULL) {
665                 torture_comment(tctx, "talloc_init failed\n");
666                 return false;
667         }
668
669         ret = get_usr_handle(tctx, cli, mem_ctx, admin_creds,
670                              DCERPC_AUTH_TYPE_NTLMSSP,
671                              DCERPC_AUTH_LEVEL_INTEGRITY,
672                              username, &dom_name, &samr_pipe,
673                              &user_handle, NULL);
674         if (ret == false) {
675                 torture_comment(tctx, "get_wks_handle failed\n");
676                 goto done;
677         }
678         samr_handle = samr_pipe->binding_handle;
679
680         {
681                 struct samr_DeleteUser d;
682
683                 d.in.user_handle = user_handle;
684                 d.out.user_handle = user_handle;
685
686                 status = dcerpc_samr_DeleteUser_r(samr_handle, mem_ctx, &d);
687                 if (!NT_STATUS_IS_OK(status)) {
688                         torture_comment(tctx, "samr_DeleteUser failed %s\n", nt_errstr(status));
689                         goto done;
690                 }
691                 if (!NT_STATUS_IS_OK(d.out.result)) {
692                         torture_comment(tctx, "samr_DeleteUser failed %s\n", nt_errstr(d.out.result));
693                         goto done;
694                 }
695
696         }
697
698         ret = true;
699
700  done:
701         talloc_free(mem_ctx);
702         return ret;
703 }
704
705 /*
706  * Do a Samba3-style join
707  */
708
709 static bool join3(struct torture_context *tctx,
710                   struct smbcli_state *cli,
711                   bool use_level25,
712                   struct cli_credentials *admin_creds,
713                   struct cli_credentials *wks_creds)
714 {
715         TALLOC_CTX *mem_ctx;
716         NTSTATUS status;
717         char *dom_name;
718         struct dcerpc_pipe *samr_pipe;
719         struct dcerpc_binding_handle *samr_handle;
720         struct policy_handle *wks_handle;
721         bool ret = false;
722         NTTIME last_password_change;
723
724         if ((mem_ctx = talloc_init("join3")) == NULL) {
725                 torture_comment(tctx, "talloc_init failed\n");
726                 return false;
727         }
728
729         ret = get_usr_handle(
730                 tctx, cli, mem_ctx, admin_creds,
731                 DCERPC_AUTH_TYPE_NTLMSSP,
732                 DCERPC_AUTH_LEVEL_PRIVACY,
733                 talloc_asprintf(mem_ctx, "%s$",
734                                 cli_credentials_get_workstation(wks_creds)),
735                 &dom_name, &samr_pipe, &wks_handle, NULL);
736         if (ret == false) {
737                 torture_comment(tctx, "get_wks_handle failed\n");
738                 goto done;
739         }
740         samr_handle = samr_pipe->binding_handle;
741
742         {
743                 struct samr_QueryUserInfo q;
744                 union samr_UserInfo *info;
745
746                 q.in.user_handle = wks_handle;
747                 q.in.level = 21;
748                 q.out.info = &info;
749
750                 status = dcerpc_samr_QueryUserInfo_r(samr_handle, mem_ctx, &q);
751                 if (!NT_STATUS_IS_OK(status)) {
752                         torture_warning(tctx, "QueryUserInfo failed: %s\n",
753                                   nt_errstr(status));
754                         goto done;
755                 }
756                 if (!NT_STATUS_IS_OK(q.out.result)) {
757                         torture_warning(tctx, "QueryUserInfo failed: %s\n",
758                                   nt_errstr(q.out.result));
759                         goto done;
760                 }
761
762
763                 last_password_change = info->info21.last_password_change;
764         }
765
766         cli_credentials_set_domain(wks_creds, dom_name, CRED_SPECIFIED);
767
768         if (use_level25) {
769                 struct samr_SetUserInfo2 sui2;
770                 union samr_UserInfo u_info;
771                 struct samr_UserInfo21 *i21 = &u_info.info25.info;
772                 DATA_BLOB session_key;
773                 DATA_BLOB confounded_session_key = data_blob_talloc(
774                         mem_ctx, NULL, 16);
775                 struct MD5Context ctx;
776                 uint8_t confounder[16];
777
778                 ZERO_STRUCT(u_info);
779
780                 i21->full_name.string = talloc_asprintf(
781                         mem_ctx, "%s$",
782                         cli_credentials_get_workstation(wks_creds));
783                 i21->acct_flags = ACB_WSTRUST;
784                 i21->fields_present = SAMR_FIELD_FULL_NAME |
785                         SAMR_FIELD_ACCT_FLAGS | SAMR_FIELD_NT_PASSWORD_PRESENT;
786                 /* this would break the test result expectations
787                 i21->fields_present |= SAMR_FIELD_EXPIRED_FLAG;
788                 i21->password_expired = 1;
789                 */
790
791                 encode_pw_buffer(u_info.info25.password.data,
792                                  cli_credentials_get_password(wks_creds),
793                                  STR_UNICODE);
794                 status = dcerpc_fetch_session_key(samr_pipe, &session_key);
795                 if (!NT_STATUS_IS_OK(status)) {
796                         torture_comment(tctx, "dcerpc_fetch_session_key failed: %s\n",
797                                  nt_errstr(status));
798                         goto done;
799                 }
800                 generate_random_buffer((uint8_t *)confounder, 16);
801
802                 MD5Init(&ctx);
803                 MD5Update(&ctx, confounder, 16);
804                 MD5Update(&ctx, session_key.data, session_key.length);
805                 MD5Final(confounded_session_key.data, &ctx);
806
807                 arcfour_crypt_blob(u_info.info25.password.data, 516,
808                                    &confounded_session_key);
809                 memcpy(&u_info.info25.password.data[516], confounder, 16);
810
811                 sui2.in.user_handle = wks_handle;
812                 sui2.in.level = 25;
813                 sui2.in.info = &u_info;
814
815                 status = dcerpc_samr_SetUserInfo2_r(samr_handle, mem_ctx, &sui2);
816                 if (!NT_STATUS_IS_OK(status)) {
817                         torture_comment(tctx, "samr_SetUserInfo2(25) failed: %s\n",
818                                  nt_errstr(status));
819                         goto done;
820                 }
821                 if (!NT_STATUS_IS_OK(sui2.out.result)) {
822                         torture_comment(tctx, "samr_SetUserInfo2(25) failed: %s\n",
823                                  nt_errstr(sui2.out.result));
824                         goto done;
825                 }
826         } else {
827                 struct samr_SetUserInfo2 sui2;
828                 struct samr_SetUserInfo sui;
829                 union samr_UserInfo u_info;
830                 DATA_BLOB session_key;
831
832                 encode_pw_buffer(u_info.info24.password.data,
833                                  cli_credentials_get_password(wks_creds),
834                                  STR_UNICODE);
835                 /* just to make this test pass */
836                 u_info.info24.password_expired = 1;
837
838                 status = dcerpc_fetch_session_key(samr_pipe, &session_key);
839                 if (!NT_STATUS_IS_OK(status)) {
840                         torture_comment(tctx, "dcerpc_fetch_session_key failed\n");
841                         goto done;
842                 }
843                 arcfour_crypt_blob(u_info.info24.password.data, 516,
844                                    &session_key);
845                 sui2.in.user_handle = wks_handle;
846                 sui2.in.info = &u_info;
847                 sui2.in.level = 24;
848
849                 status = dcerpc_samr_SetUserInfo2_r(samr_handle, mem_ctx, &sui2);
850                 if (!NT_STATUS_IS_OK(status)) {
851                         torture_comment(tctx, "samr_SetUserInfo(24) failed: %s\n",
852                                  nt_errstr(status));
853                         goto done;
854                 }
855                 if (!NT_STATUS_IS_OK(sui2.out.result)) {
856                         torture_comment(tctx, "samr_SetUserInfo(24) failed: %s\n",
857                                  nt_errstr(sui2.out.result));
858                         goto done;
859                 }
860
861                 u_info.info16.acct_flags = ACB_WSTRUST;
862                 sui.in.user_handle = wks_handle;
863                 sui.in.info = &u_info;
864                 sui.in.level = 16;
865
866                 status = dcerpc_samr_SetUserInfo_r(samr_handle, mem_ctx, &sui);
867                 if (!NT_STATUS_IS_OK(status) || !NT_STATUS_IS_OK(sui.out.result)) {
868                         torture_comment(tctx, "samr_SetUserInfo(16) failed\n");
869                         goto done;
870                 }
871         }
872
873         {
874                 struct samr_QueryUserInfo q;
875                 union samr_UserInfo *info;
876
877                 q.in.user_handle = wks_handle;
878                 q.in.level = 21;
879                 q.out.info = &info;
880
881                 status = dcerpc_samr_QueryUserInfo_r(samr_handle, mem_ctx, &q);
882                 if (!NT_STATUS_IS_OK(status)) {
883                         torture_warning(tctx, "QueryUserInfo failed: %s\n",
884                                   nt_errstr(status));
885                         goto done;
886                 }
887                 if (!NT_STATUS_IS_OK(q.out.result)) {
888                         torture_warning(tctx, "QueryUserInfo failed: %s\n",
889                                   nt_errstr(q.out.result));
890                         goto done;
891                 }
892
893                 if (use_level25) {
894                         if (last_password_change
895                             == info->info21.last_password_change) {
896                                 torture_warning(tctx, "last_password_change unchanged "
897                                          "during join, level25 must change "
898                                          "it\n");
899                                 goto done;
900                         }
901                 }
902                 else {
903                         if (last_password_change
904                             != info->info21.last_password_change) {
905                                 torture_warning(tctx, "last_password_change changed "
906                                          "during join, level24 doesn't "
907                                          "change it\n");
908                                 goto done;
909                         }
910                 }
911         }
912
913         ret = true;
914
915  done:
916         talloc_free(mem_ctx);
917         return ret;
918 }
919
920 /*
921  * Do a ReqChallenge/Auth2 and get the wks creds
922  */
923
924 static bool auth2(struct torture_context *tctx,
925                   struct smbcli_state *cli,
926                   struct cli_credentials *wks_cred)
927 {
928         TALLOC_CTX *mem_ctx;
929         struct dcerpc_pipe *net_pipe;
930         struct dcerpc_binding_handle *net_handle;
931         bool result = false;
932         NTSTATUS status;
933         struct netr_ServerReqChallenge r;
934         struct netr_Credential netr_cli_creds;
935         struct netr_Credential netr_srv_creds;
936         uint32_t negotiate_flags;
937         struct netr_ServerAuthenticate2 a;
938         struct netlogon_creds_CredentialState *creds_state;
939         struct netr_Credential netr_cred;
940         struct samr_Password mach_pw;
941
942         mem_ctx = talloc_new(NULL);
943         if (mem_ctx == NULL) {
944                 torture_comment(tctx, "talloc_new failed\n");
945                 return false;
946         }
947
948         net_pipe = dcerpc_pipe_init(mem_ctx, tctx->ev);
949         if (net_pipe == NULL) {
950                 torture_comment(tctx, "dcerpc_pipe_init failed\n");
951                 goto done;
952         }
953         net_handle = net_pipe->binding_handle;
954
955         status = dcerpc_pipe_open_smb(net_pipe, cli->tree, "\\netlogon");
956         if (!NT_STATUS_IS_OK(status)) {
957                 torture_comment(tctx, "dcerpc_pipe_open_smb failed: %s\n",
958                          nt_errstr(status));
959                 goto done;
960         }
961
962         status = dcerpc_bind_auth_none(net_pipe, &ndr_table_netlogon);
963         if (!NT_STATUS_IS_OK(status)) {
964                 torture_comment(tctx, "dcerpc_bind_auth_none failed: %s\n",
965                          nt_errstr(status));
966                 goto done;
967         }
968
969         r.in.computer_name = cli_credentials_get_workstation(wks_cred);
970         r.in.server_name = talloc_asprintf(
971                 mem_ctx, "\\\\%s", dcerpc_server_name(net_pipe));
972         if (r.in.server_name == NULL) {
973                 torture_comment(tctx, "talloc_asprintf failed\n");
974                 goto done;
975         }
976         generate_random_buffer(netr_cli_creds.data,
977                                sizeof(netr_cli_creds.data));
978         r.in.credentials = &netr_cli_creds;
979         r.out.return_credentials = &netr_srv_creds;
980
981         status = dcerpc_netr_ServerReqChallenge_r(net_handle, mem_ctx, &r);
982         if (!NT_STATUS_IS_OK(status)) {
983                 torture_comment(tctx, "netr_ServerReqChallenge failed: %s\n",
984                          nt_errstr(status));
985                 goto done;
986         }
987         if (!NT_STATUS_IS_OK(r.out.result)) {
988                 torture_comment(tctx, "netr_ServerReqChallenge failed: %s\n",
989                          nt_errstr(r.out.result));
990                 goto done;
991         }
992
993         negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS;
994         E_md4hash(cli_credentials_get_password(wks_cred), mach_pw.hash);
995
996         a.in.server_name = talloc_asprintf(
997                 mem_ctx, "\\\\%s", dcerpc_server_name(net_pipe));
998         a.in.account_name = talloc_asprintf(
999                 mem_ctx, "%s$", cli_credentials_get_workstation(wks_cred));
1000         a.in.computer_name = cli_credentials_get_workstation(wks_cred);
1001         a.in.secure_channel_type = SEC_CHAN_WKSTA;
1002         a.in.negotiate_flags = &negotiate_flags;
1003         a.out.negotiate_flags = &negotiate_flags;
1004         a.in.credentials = &netr_cred;
1005         a.out.return_credentials = &netr_cred;
1006
1007         creds_state = netlogon_creds_client_init(mem_ctx,
1008                                                  a.in.account_name,
1009                                                  a.in.computer_name,
1010                                                  r.in.credentials,
1011                                                  r.out.return_credentials, &mach_pw,
1012                                                  &netr_cred, negotiate_flags);
1013
1014         status = dcerpc_netr_ServerAuthenticate2_r(net_handle, mem_ctx, &a);
1015         if (!NT_STATUS_IS_OK(status)) {
1016                 torture_comment(tctx, "netr_ServerServerAuthenticate2 failed: %s\n",
1017                          nt_errstr(status));
1018                 goto done;
1019         }
1020         if (!NT_STATUS_IS_OK(a.out.result)) {
1021                 torture_comment(tctx, "netr_ServerServerAuthenticate2 failed: %s\n",
1022                          nt_errstr(a.out.result));
1023                 goto done;
1024         }
1025
1026         if (!netlogon_creds_client_check(creds_state, a.out.return_credentials)) {
1027                 torture_comment(tctx, "creds_client_check failed\n");
1028                 goto done;
1029         }
1030
1031         cli_credentials_set_netlogon_creds(wks_cred, creds_state);
1032
1033         result = true;
1034
1035  done:
1036         talloc_free(mem_ctx);
1037         return result;
1038 }
1039
1040 /*
1041  * Do a couple of schannel protected Netlogon ops: Interactive and Network
1042  * login, and change the wks password
1043  */
1044
1045 static bool schan(struct torture_context *tctx,
1046                   struct smbcli_state *cli,
1047                   struct cli_credentials *wks_creds,
1048                   struct cli_credentials *user_creds)
1049 {
1050         TALLOC_CTX *mem_ctx;
1051         NTSTATUS status;
1052         bool ret = false;
1053         struct dcerpc_pipe *net_pipe;
1054         struct dcerpc_binding_handle *net_handle;
1055         int i;
1056
1057         mem_ctx = talloc_new(NULL);
1058         if (mem_ctx == NULL) {
1059                 torture_comment(tctx, "talloc_new failed\n");
1060                 return false;
1061         }
1062
1063         net_pipe = dcerpc_pipe_init(mem_ctx, tctx->ev);
1064         if (net_pipe == NULL) {
1065                 torture_comment(tctx, "dcerpc_pipe_init failed\n");
1066                 goto done;
1067         }
1068         net_handle = net_pipe->binding_handle;
1069
1070         status = dcerpc_pipe_open_smb(net_pipe, cli->tree, "\\netlogon");
1071         if (!NT_STATUS_IS_OK(status)) {
1072                 torture_comment(tctx, "dcerpc_pipe_open_smb failed: %s\n",
1073                          nt_errstr(status));
1074                 goto done;
1075         }
1076
1077 #if 0
1078         net_pipe->conn->flags |= DCERPC_DEBUG_PRINT_IN |
1079                 DCERPC_DEBUG_PRINT_OUT;
1080 #endif
1081 #if 1
1082         net_pipe->conn->flags |= (DCERPC_SIGN | DCERPC_SEAL);
1083         status = dcerpc_bind_auth(net_pipe, &ndr_table_netlogon,
1084                                   wks_creds, lpcfg_gensec_settings(tctx->lp_ctx, tctx->lp_ctx), DCERPC_AUTH_TYPE_SCHANNEL,
1085                                   DCERPC_AUTH_LEVEL_PRIVACY,
1086                                   NULL);
1087 #else
1088         status = dcerpc_bind_auth_none(net_pipe, &ndr_table_netlogon);
1089 #endif
1090         if (!NT_STATUS_IS_OK(status)) {
1091                 torture_comment(tctx, "schannel bind failed: %s\n", nt_errstr(status));
1092                 goto done;
1093         }
1094
1095
1096         for (i=2; i<4; i++) {
1097                 int flags;
1098                 DATA_BLOB chal, nt_resp, lm_resp, names_blob, session_key;
1099                 struct netlogon_creds_CredentialState *creds_state;
1100                 struct netr_Authenticator netr_auth, netr_auth2;
1101                 struct netr_NetworkInfo ninfo;
1102                 struct netr_PasswordInfo pinfo;
1103                 struct netr_LogonSamLogon r;
1104                 union netr_LogonLevel logon;
1105                 union netr_Validation validation;
1106                 uint8_t authoritative;
1107                 struct netr_Authenticator return_authenticator;
1108
1109                 flags = CLI_CRED_LANMAN_AUTH | CLI_CRED_NTLM_AUTH |
1110                         CLI_CRED_NTLMv2_AUTH;
1111
1112                 chal = data_blob_talloc(mem_ctx, NULL, 8);
1113                 if (chal.data == NULL) {
1114                         torture_comment(tctx, "data_blob_talloc failed\n");
1115                         goto done;
1116                 }
1117
1118                 generate_random_buffer(chal.data, chal.length);
1119                 names_blob = NTLMv2_generate_names_blob(
1120                         mem_ctx,
1121                         cli_credentials_get_workstation(user_creds),
1122                         cli_credentials_get_domain(user_creds));
1123                 status = cli_credentials_get_ntlm_response(
1124                         user_creds, mem_ctx, &flags, chal, names_blob,
1125                         &lm_resp, &nt_resp, NULL, NULL);
1126                 if (!NT_STATUS_IS_OK(status)) {
1127                         torture_comment(tctx, "cli_credentials_get_ntlm_response failed:"
1128                                  " %s\n", nt_errstr(status));
1129                         goto done;
1130                 }
1131
1132                 creds_state = cli_credentials_get_netlogon_creds(wks_creds);
1133                 netlogon_creds_client_authenticator(creds_state, &netr_auth);
1134
1135                 ninfo.identity_info.account_name.string =
1136                         cli_credentials_get_username(user_creds);
1137                 ninfo.identity_info.domain_name.string =
1138                         cli_credentials_get_domain(user_creds);
1139                 ninfo.identity_info.parameter_control = 0;
1140                 ninfo.identity_info.logon_id_low = 0;
1141                 ninfo.identity_info.logon_id_high = 0;
1142                 ninfo.identity_info.workstation.string =
1143                         cli_credentials_get_workstation(user_creds);
1144                 memcpy(ninfo.challenge, chal.data, sizeof(ninfo.challenge));
1145                 ninfo.nt.length = nt_resp.length;
1146                 ninfo.nt.data = nt_resp.data;
1147                 ninfo.lm.length = lm_resp.length;
1148                 ninfo.lm.data = lm_resp.data;
1149
1150                 logon.network = &ninfo;
1151
1152                 r.in.server_name = talloc_asprintf(
1153                         mem_ctx, "\\\\%s", dcerpc_server_name(net_pipe));
1154                 ZERO_STRUCT(netr_auth2);
1155                 r.in.computer_name =
1156                         cli_credentials_get_workstation(wks_creds);
1157                 r.in.credential = &netr_auth;
1158                 r.in.return_authenticator = &netr_auth2;
1159                 r.in.logon_level = 2;
1160                 r.in.validation_level = i;
1161                 r.in.logon = &logon;
1162                 r.out.validation = &validation;
1163                 r.out.authoritative = &authoritative;
1164                 r.out.return_authenticator = &return_authenticator;
1165
1166                 status = dcerpc_netr_LogonSamLogon_r(net_handle, mem_ctx, &r);
1167                 if (!NT_STATUS_IS_OK(status)) {
1168                         torture_comment(tctx, "netr_LogonSamLogon failed: %s\n",
1169                                  nt_errstr(status));
1170                         goto done;
1171                 }
1172                 if (!NT_STATUS_IS_OK(r.out.result)) {
1173                         torture_comment(tctx, "netr_LogonSamLogon failed: %s\n",
1174                                  nt_errstr(r.out.result));
1175                         goto done;
1176                 }
1177
1178                 if ((r.out.return_authenticator == NULL) ||
1179                     (!netlogon_creds_client_check(creds_state,
1180                                          &r.out.return_authenticator->cred))) {
1181                         torture_comment(tctx, "Credentials check failed!\n");
1182                         goto done;
1183                 }
1184
1185                 netlogon_creds_client_authenticator(creds_state, &netr_auth);
1186
1187                 pinfo.identity_info = ninfo.identity_info;
1188                 ZERO_STRUCT(pinfo.lmpassword.hash);
1189                 E_md4hash(cli_credentials_get_password(user_creds),
1190                           pinfo.ntpassword.hash);
1191                 session_key = data_blob_talloc(mem_ctx,
1192                                                creds_state->session_key, 16);
1193                 arcfour_crypt_blob(pinfo.ntpassword.hash,
1194                                    sizeof(pinfo.ntpassword.hash),
1195                                    &session_key);
1196
1197                 logon.password = &pinfo;
1198
1199                 r.in.logon_level = 1;
1200                 r.in.logon = &logon;
1201                 r.out.return_authenticator = &return_authenticator;
1202
1203                 status = dcerpc_netr_LogonSamLogon_r(net_handle, mem_ctx, &r);
1204                 if (!NT_STATUS_IS_OK(status)) {
1205                         torture_comment(tctx, "netr_LogonSamLogon failed: %s\n",
1206                                  nt_errstr(status));
1207                         goto done;
1208                 }
1209                 if (!NT_STATUS_IS_OK(r.out.result)) {
1210                         torture_comment(tctx, "netr_LogonSamLogon failed: %s\n",
1211                                  nt_errstr(r.out.result));
1212                         goto done;
1213                 }
1214
1215                 if ((r.out.return_authenticator == NULL) ||
1216                     (!netlogon_creds_client_check(creds_state,
1217                                          &r.out.return_authenticator->cred))) {
1218                         torture_comment(tctx, "Credentials check failed!\n");
1219                         goto done;
1220                 }
1221         }
1222
1223         {
1224                 struct netr_ServerPasswordSet s;
1225                 char *password = generate_random_password(wks_creds, 8, 255);
1226                 struct netlogon_creds_CredentialState *creds_state;
1227                 struct netr_Authenticator credential, return_authenticator;
1228                 struct samr_Password new_password;
1229
1230                 s.in.server_name = talloc_asprintf(
1231                         mem_ctx, "\\\\%s", dcerpc_server_name(net_pipe));
1232                 s.in.computer_name = cli_credentials_get_workstation(wks_creds);
1233                 s.in.account_name = talloc_asprintf(
1234                         mem_ctx, "%s$", s.in.computer_name);
1235                 s.in.secure_channel_type = SEC_CHAN_WKSTA;
1236                 s.in.credential = &credential;
1237                 s.in.new_password = &new_password;
1238                 s.out.return_authenticator = &return_authenticator;
1239
1240                 E_md4hash(password, new_password.hash);
1241
1242                 creds_state = cli_credentials_get_netlogon_creds(wks_creds);
1243                 netlogon_creds_des_encrypt(creds_state, &new_password);
1244                 netlogon_creds_client_authenticator(creds_state, &credential);
1245
1246                 status = dcerpc_netr_ServerPasswordSet_r(net_handle, mem_ctx, &s);
1247                 if (!NT_STATUS_IS_OK(status)) {
1248                         torture_comment(tctx, "ServerPasswordSet - %s\n", nt_errstr(status));
1249                         goto done;
1250                 }
1251                 if (!NT_STATUS_IS_OK(s.out.result)) {
1252                         torture_comment(tctx, "ServerPasswordSet - %s\n", nt_errstr(s.out.result));
1253                         goto done;
1254                 }
1255
1256                 if (!netlogon_creds_client_check(creds_state,
1257                                                  &s.out.return_authenticator->cred)) {
1258                         torture_comment(tctx, "Credential chaining failed\n");
1259                 }
1260
1261                 cli_credentials_set_password(wks_creds, password,
1262                                              CRED_SPECIFIED);
1263         }
1264
1265         ret = true;
1266  done:
1267         talloc_free(mem_ctx);
1268         return ret;
1269 }
1270
1271 /*
1272  * Delete the wks account again
1273  */
1274
1275 static bool leave(struct torture_context *tctx,
1276                   struct smbcli_state *cli,
1277                   struct cli_credentials *admin_creds,
1278                   struct cli_credentials *wks_creds)
1279 {
1280         char *wks_name = talloc_asprintf(
1281                 NULL, "%s$", cli_credentials_get_workstation(wks_creds));
1282         bool ret;
1283
1284         ret = delete_user(tctx, cli, admin_creds, wks_name);
1285         talloc_free(wks_name);
1286         return ret;
1287 }
1288
1289 /*
1290  * Test the Samba3 DC code a bit. Join, do some schan netlogon ops, leave
1291  */
1292
1293 static bool torture_netlogon_samba3(struct torture_context *torture)
1294 {
1295         NTSTATUS status;
1296         struct smbcli_state *cli;
1297         struct cli_credentials *anon_creds;
1298         struct cli_credentials *wks_creds;
1299         const char *wks_name;
1300         int i;
1301         struct smbcli_options options;
1302         struct smbcli_session_options session_options;
1303
1304         wks_name = torture_setting_string(torture, "wksname", NULL);
1305         if (wks_name == NULL) {
1306                 wks_name = get_myname(torture);
1307         }
1308
1309         if (!(anon_creds = cli_credentials_init_anon(torture))) {
1310                 torture_fail(torture, "create_anon_creds failed\n");
1311         }
1312
1313         lpcfg_smbcli_options(torture->lp_ctx, &options);
1314         lpcfg_smbcli_session_options(torture->lp_ctx, &session_options);
1315
1316         status = smbcli_full_connection(torture, &cli,
1317                                         torture_setting_string(torture, "host", NULL),
1318                                         lpcfg_smb_ports(torture->lp_ctx),
1319                                         "IPC$", NULL,
1320                                         lpcfg_socket_options(torture->lp_ctx),
1321                                         anon_creds,
1322                                         lpcfg_resolve_context(torture->lp_ctx),
1323                                         torture->ev, &options, &session_options,
1324                                         lpcfg_gensec_settings(torture, torture->lp_ctx));
1325         torture_assert_ntstatus_ok(torture, status, "smbcli_full_connection failed\n");
1326
1327         wks_creds = cli_credentials_init(torture);
1328         if (wks_creds == NULL) {
1329                 torture_fail(torture, "cli_credentials_init failed\n");
1330         }
1331
1332         cli_credentials_set_conf(wks_creds, torture->lp_ctx);
1333         cli_credentials_set_secure_channel_type(wks_creds, SEC_CHAN_WKSTA);
1334         cli_credentials_set_username(wks_creds, wks_name, CRED_SPECIFIED);
1335         cli_credentials_set_workstation(wks_creds, wks_name, CRED_SPECIFIED);
1336         cli_credentials_set_password(wks_creds,
1337                                      generate_random_password(wks_creds, 8, 255),
1338                                      CRED_SPECIFIED);
1339
1340         torture_assert(torture,
1341                 join3(torture, cli, false, cmdline_credentials, wks_creds),
1342                 "join failed");
1343
1344         cli_credentials_set_domain(
1345                 cmdline_credentials, cli_credentials_get_domain(wks_creds),
1346                 CRED_SPECIFIED);
1347
1348         for (i=0; i<2; i++) {
1349
1350                 /* Do this more than once, the routine "schan" changes
1351                  * the workstation password using the netlogon
1352                  * password change routine */
1353
1354                 int j;
1355
1356                 torture_assert(torture,
1357                         auth2(torture, cli, wks_creds),
1358                         "auth2 failed");
1359
1360                 for (j=0; j<2; j++) {
1361                         torture_assert(torture,
1362                                 schan(torture, cli, wks_creds, cmdline_credentials),
1363                                 "schan failed");
1364                 }
1365         }
1366
1367         torture_assert(torture,
1368                 leave(torture, cli, cmdline_credentials, wks_creds),
1369                 "leave failed");
1370
1371         return true;
1372 }
1373
1374 /*
1375  * Do a simple join, testjoin and leave using specified smb and samr
1376  * credentials
1377  */
1378
1379 static bool test_join3(struct torture_context *tctx,
1380                        bool use_level25,
1381                        struct cli_credentials *smb_creds,
1382                        struct cli_credentials *samr_creds,
1383                        const char *wks_name)
1384 {
1385         NTSTATUS status;
1386         struct smbcli_state *cli;
1387         struct cli_credentials *wks_creds;
1388         struct smbcli_options options;
1389         struct smbcli_session_options session_options;
1390
1391         lpcfg_smbcli_options(tctx->lp_ctx, &options);
1392         lpcfg_smbcli_session_options(tctx->lp_ctx, &session_options);
1393
1394         status = smbcli_full_connection(tctx, &cli,
1395                                         torture_setting_string(tctx, "host", NULL),
1396                                         lpcfg_smb_ports(tctx->lp_ctx),
1397                                         "IPC$", NULL, lpcfg_socket_options(tctx->lp_ctx),
1398                                         smb_creds, lpcfg_resolve_context(tctx->lp_ctx),
1399                                         tctx->ev, &options, &session_options,
1400                                         lpcfg_gensec_settings(tctx, tctx->lp_ctx));
1401         torture_assert_ntstatus_ok(tctx, status,
1402                 "smbcli_full_connection failed");
1403
1404         wks_creds = cli_credentials_init(cli);
1405         torture_assert(tctx, wks_creds, "cli_credentials_init failed");
1406
1407         cli_credentials_set_conf(wks_creds, tctx->lp_ctx);
1408         cli_credentials_set_secure_channel_type(wks_creds, SEC_CHAN_WKSTA);
1409         cli_credentials_set_username(wks_creds, wks_name, CRED_SPECIFIED);
1410         cli_credentials_set_workstation(wks_creds, wks_name, CRED_SPECIFIED);
1411         cli_credentials_set_password(wks_creds,
1412                                      generate_random_password(wks_creds, 8, 255),
1413                                      CRED_SPECIFIED);
1414
1415         torture_assert(tctx,
1416                 join3(tctx, cli, use_level25, samr_creds, wks_creds),
1417                 "join failed");
1418
1419         cli_credentials_set_domain(
1420                 cmdline_credentials, cli_credentials_get_domain(wks_creds),
1421                 CRED_SPECIFIED);
1422
1423         torture_assert(tctx,
1424                 auth2(tctx, cli, wks_creds),
1425                 "auth2 failed");
1426
1427         torture_assert(tctx,
1428                 leave(tctx, cli, samr_creds, wks_creds),
1429                 "leave failed");
1430
1431         talloc_free(cli);
1432
1433         return true;
1434 }
1435
1436 /*
1437  * Test the different session key variants. Do it by joining, this uses the
1438  * session key in the setpassword routine. Test the join by doing the auth2.
1439  */
1440
1441 static bool torture_samba3_sessionkey(struct torture_context *torture)
1442 {
1443         struct cli_credentials *anon_creds;
1444         const char *wks_name;
1445
1446         wks_name = torture_setting_string(torture, "wksname", get_myname(torture));
1447
1448         if (!(anon_creds = cli_credentials_init_anon(torture))) {
1449                 torture_fail(torture, "create_anon_creds failed\n");
1450         }
1451
1452         cli_credentials_set_workstation(anon_creds, wks_name, CRED_SPECIFIED);
1453
1454
1455         if (!torture_setting_bool(torture, "samba3", false)) {
1456
1457                 /* Samba3 in the build farm right now does this happily. Need
1458                  * to fix :-) */
1459
1460                 if (test_join3(torture, false, anon_creds, NULL, wks_name)) {
1461                         torture_fail(torture, "join using anonymous bind on an anonymous smb "
1462                                  "connection succeeded -- HUH??\n");
1463                 }
1464         }
1465
1466         torture_assert(torture,
1467                 test_join3(torture, false, anon_creds, cmdline_credentials, wks_name),
1468                 "join using ntlmssp bind on an anonymous smb connection failed");
1469
1470         torture_assert(torture,
1471                 test_join3(torture, false, cmdline_credentials, NULL, wks_name),
1472                 "join using anonymous bind on an authenticated smb connection failed");
1473
1474         torture_assert(torture,
1475                 test_join3(torture, false, cmdline_credentials, cmdline_credentials, wks_name),
1476                 "join using ntlmssp bind on an authenticated smb connection failed");
1477
1478         /*
1479          * The following two are tests for setuserinfolevel 25
1480          */
1481
1482         torture_assert(torture,
1483                 test_join3(torture, true, anon_creds, cmdline_credentials, wks_name),
1484                 "join using ntlmssp bind on an anonymous smb connection failed");
1485
1486         torture_assert(torture,
1487                 test_join3(torture, true, cmdline_credentials, NULL, wks_name),
1488                 "join using anonymous bind on an authenticated smb connection failed");
1489
1490         return true;
1491 }
1492
1493 /*
1494  * open pipe and bind, given an IPC$ context
1495  */
1496
1497 static NTSTATUS pipe_bind_smb(struct torture_context *tctx,
1498                               TALLOC_CTX *mem_ctx,
1499                               struct smbcli_tree *tree,
1500                               const char *pipe_name,
1501                               const struct ndr_interface_table *iface,
1502                               struct dcerpc_pipe **p)
1503 {
1504         struct dcerpc_pipe *result;
1505         NTSTATUS status;
1506
1507         if (!(result = dcerpc_pipe_init(mem_ctx, tctx->ev))) {
1508                 return NT_STATUS_NO_MEMORY;
1509         }
1510
1511         status = dcerpc_pipe_open_smb(result, tree, pipe_name);
1512         if (!NT_STATUS_IS_OK(status)) {
1513                 torture_comment(tctx, "dcerpc_pipe_open_smb failed: %s\n",
1514                          nt_errstr(status));
1515                 talloc_free(result);
1516                 return status;
1517         }
1518
1519         status = dcerpc_bind_auth_none(result, iface);
1520         if (!NT_STATUS_IS_OK(status)) {
1521                 torture_comment(tctx, "schannel bind failed: %s\n", nt_errstr(status));
1522                 talloc_free(result);
1523                 return status;
1524         }
1525
1526         *p = result;
1527         return NT_STATUS_OK;
1528 }
1529
1530 /*
1531  * Sane wrapper around lsa_LookupNames
1532  */
1533
1534 static struct dom_sid *name2sid(struct torture_context *tctx,
1535                                 TALLOC_CTX *mem_ctx,
1536                                 struct dcerpc_pipe *p,
1537                                 const char *name,
1538                                 const char *domain)
1539 {
1540         struct lsa_ObjectAttribute attr;
1541         struct lsa_QosInfo qos;
1542         struct lsa_OpenPolicy2 r;
1543         struct lsa_Close c;
1544         NTSTATUS status;
1545         struct policy_handle handle;
1546         struct lsa_LookupNames l;
1547         struct lsa_TransSidArray sids;
1548         struct lsa_RefDomainList *domains = NULL;
1549         struct lsa_String lsa_name;
1550         uint32_t count = 0;
1551         struct dom_sid *result;
1552         TALLOC_CTX *tmp_ctx;
1553         struct dcerpc_binding_handle *b = p->binding_handle;
1554
1555         if (!(tmp_ctx = talloc_new(mem_ctx))) {
1556                 return NULL;
1557         }
1558
1559         qos.len = 0;
1560         qos.impersonation_level = 2;
1561         qos.context_mode = 1;
1562         qos.effective_only = 0;
1563
1564         attr.len = 0;
1565         attr.root_dir = NULL;
1566         attr.object_name = NULL;
1567         attr.attributes = 0;
1568         attr.sec_desc = NULL;
1569         attr.sec_qos = &qos;
1570
1571         r.in.system_name = "\\";
1572         r.in.attr = &attr;
1573         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1574         r.out.handle = &handle;
1575
1576         status = dcerpc_lsa_OpenPolicy2_r(b, tmp_ctx, &r);
1577         if (!NT_STATUS_IS_OK(status)) {
1578                 torture_comment(tctx, "OpenPolicy2 failed - %s\n", nt_errstr(status));
1579                 talloc_free(tmp_ctx);
1580                 return NULL;
1581         }
1582         if (!NT_STATUS_IS_OK(r.out.result)) {
1583                 torture_comment(tctx, "OpenPolicy2 failed - %s\n", nt_errstr(r.out.result));
1584                 talloc_free(tmp_ctx);
1585                 return NULL;
1586         }
1587
1588         sids.count = 0;
1589         sids.sids = NULL;
1590
1591         lsa_name.string = talloc_asprintf(tmp_ctx, "%s\\%s", domain, name);
1592
1593         l.in.handle = &handle;
1594         l.in.num_names = 1;
1595         l.in.names = &lsa_name;
1596         l.in.sids = &sids;
1597         l.in.level = 1;
1598         l.in.count = &count;
1599         l.out.count = &count;
1600         l.out.sids = &sids;
1601         l.out.domains = &domains;
1602
1603         status = dcerpc_lsa_LookupNames_r(b, tmp_ctx, &l);
1604         if (!NT_STATUS_IS_OK(status)) {
1605                 torture_comment(tctx, "LookupNames of %s failed - %s\n", lsa_name.string,
1606                        nt_errstr(status));
1607                 talloc_free(tmp_ctx);
1608                 return NULL;
1609         }
1610         if (!NT_STATUS_IS_OK(l.out.result)) {
1611                 torture_comment(tctx, "LookupNames of %s failed - %s\n", lsa_name.string,
1612                        nt_errstr(l.out.result));
1613                 talloc_free(tmp_ctx);
1614                 return NULL;
1615         }
1616
1617         result = dom_sid_add_rid(mem_ctx, domains->domains[0].sid,
1618                                  l.out.sids->sids[0].rid);
1619
1620         c.in.handle = &handle;
1621         c.out.handle = &handle;
1622
1623         status = dcerpc_lsa_Close_r(b, tmp_ctx, &c);
1624         if (!NT_STATUS_IS_OK(status)) {
1625                 torture_comment(tctx, "dcerpc_lsa_Close failed - %s\n", nt_errstr(status));
1626                 talloc_free(tmp_ctx);
1627                 return NULL;
1628         }
1629         if (!NT_STATUS_IS_OK(c.out.result)) {
1630                 torture_comment(tctx, "dcerpc_lsa_Close failed - %s\n", nt_errstr(c.out.result));
1631                 talloc_free(tmp_ctx);
1632                 return NULL;
1633         }
1634
1635         talloc_free(tmp_ctx);
1636         return result;
1637 }
1638
1639 /*
1640  * Find out the user SID on this connection
1641  */
1642
1643 static struct dom_sid *whoami(struct torture_context *tctx,
1644                               TALLOC_CTX *mem_ctx,
1645                               struct smbcli_tree *tree)
1646 {
1647         struct dcerpc_pipe *lsa;
1648         struct dcerpc_binding_handle *lsa_handle;
1649         struct lsa_GetUserName r;
1650         NTSTATUS status;
1651         struct lsa_String *authority_name_p = NULL;
1652         struct lsa_String *account_name_p = NULL;
1653         struct dom_sid *result;
1654
1655         status = pipe_bind_smb(tctx, mem_ctx, tree, "\\pipe\\lsarpc",
1656                                &ndr_table_lsarpc, &lsa);
1657         if (!NT_STATUS_IS_OK(status)) {
1658                 torture_warning(tctx, "Could not bind to LSA: %s\n",
1659                          nt_errstr(status));
1660                 return NULL;
1661         }
1662         lsa_handle = lsa->binding_handle;
1663
1664         r.in.system_name = "\\";
1665         r.in.account_name = &account_name_p;
1666         r.in.authority_name = &authority_name_p;
1667         r.out.account_name = &account_name_p;
1668
1669         status = dcerpc_lsa_GetUserName_r(lsa_handle, mem_ctx, &r);
1670
1671         authority_name_p = *r.out.authority_name;
1672
1673         if (!NT_STATUS_IS_OK(status)) {
1674                 torture_warning(tctx, "GetUserName failed - %s\n",
1675                        nt_errstr(status));
1676                 talloc_free(lsa);
1677                 return NULL;
1678         }
1679         if (!NT_STATUS_IS_OK(r.out.result)) {
1680                 torture_warning(tctx, "GetUserName failed - %s\n",
1681                        nt_errstr(r.out.result));
1682                 talloc_free(lsa);
1683                 return NULL;
1684         }
1685
1686         result = name2sid(tctx, mem_ctx, lsa, account_name_p->string,
1687                           authority_name_p->string);
1688
1689         talloc_free(lsa);
1690         return result;
1691 }
1692
1693 static int destroy_tree(struct smbcli_tree *tree)
1694 {
1695         smb_tree_disconnect(tree);
1696         return 0;
1697 }
1698
1699 /*
1700  * Do a tcon, given a session
1701  */
1702
1703 static NTSTATUS secondary_tcon(struct torture_context *tctx,
1704                                TALLOC_CTX *mem_ctx,
1705                                struct smbcli_session *session,
1706                                const char *sharename,
1707                                struct smbcli_tree **res)
1708 {
1709         struct smbcli_tree *result;
1710         TALLOC_CTX *tmp_ctx;
1711         union smb_tcon tcon;
1712         NTSTATUS status;
1713
1714         if (!(tmp_ctx = talloc_new(mem_ctx))) {
1715                 return NT_STATUS_NO_MEMORY;
1716         }
1717
1718         if (!(result = smbcli_tree_init(session, mem_ctx, false))) {
1719                 talloc_free(tmp_ctx);
1720                 return NT_STATUS_NO_MEMORY;
1721         }
1722
1723         tcon.generic.level = RAW_TCON_TCONX;
1724         tcon.tconx.in.flags = 0;
1725         tcon.tconx.in.password = data_blob(NULL, 0);
1726         tcon.tconx.in.path = sharename;
1727         tcon.tconx.in.device = "?????";
1728
1729         status = smb_raw_tcon(result, tmp_ctx, &tcon);
1730         if (!NT_STATUS_IS_OK(status)) {
1731                 torture_warning(tctx, "smb_raw_tcon failed: %s\n",
1732                          nt_errstr(status));
1733                 talloc_free(tmp_ctx);
1734                 return status;
1735         }
1736
1737         result->tid = tcon.tconx.out.tid;
1738         result = talloc_steal(mem_ctx, result);
1739         talloc_set_destructor(result, destroy_tree);
1740         talloc_free(tmp_ctx);
1741         *res = result;
1742         return NT_STATUS_OK;
1743 }
1744
1745 /*
1746  * Test the getusername behaviour
1747  */
1748
1749 static bool torture_samba3_rpc_getusername(struct torture_context *torture)
1750 {
1751         NTSTATUS status;
1752         struct smbcli_state *cli;
1753         bool ret = true;
1754         struct dom_sid *user_sid;
1755         struct dom_sid *created_sid;
1756         struct cli_credentials *anon_creds;
1757         struct cli_credentials *user_creds;
1758         char *domain_name;
1759         struct smbcli_options options;
1760         struct smbcli_session_options session_options;
1761
1762         lpcfg_smbcli_options(torture->lp_ctx, &options);
1763         lpcfg_smbcli_session_options(torture->lp_ctx, &session_options);
1764
1765         status = smbcli_full_connection(
1766                 torture, &cli, torture_setting_string(torture, "host", NULL),
1767                 lpcfg_smb_ports(torture->lp_ctx),
1768                 "IPC$", NULL, lpcfg_socket_options(torture->lp_ctx), cmdline_credentials,
1769                 lpcfg_resolve_context(torture->lp_ctx), torture->ev, &options,
1770                 &session_options, lpcfg_gensec_settings(torture, torture->lp_ctx));
1771         torture_assert_ntstatus_ok(torture, status, "smbcli_full_connection failed\n");
1772
1773         if (!(user_sid = whoami(torture, torture, cli->tree))) {
1774                 torture_fail(torture, "whoami on auth'ed connection failed\n");
1775         }
1776
1777         talloc_free(cli);
1778
1779         if (!(anon_creds = cli_credentials_init_anon(torture))) {
1780                 torture_fail(torture, "create_anon_creds failed\n");
1781         }
1782
1783         status = smbcli_full_connection(
1784                 torture, &cli, torture_setting_string(torture, "host", NULL),
1785                 lpcfg_smb_ports(torture->lp_ctx), "IPC$", NULL,
1786                 lpcfg_socket_options(torture->lp_ctx), anon_creds,
1787                 lpcfg_resolve_context(torture->lp_ctx),
1788                 torture->ev, &options, &session_options,
1789                 lpcfg_gensec_settings(torture, torture->lp_ctx));
1790         torture_assert_ntstatus_ok(torture, status, "anon smbcli_full_connection failed\n");
1791
1792         if (!(user_sid = whoami(torture, torture, cli->tree))) {
1793                 torture_fail(torture, "whoami on anon connection failed\n");
1794         }
1795
1796         torture_assert_sid_equal(torture, user_sid, dom_sid_parse_talloc(torture, "s-1-5-7"),
1797                 "Anon lsa_GetUserName returned unexpected SID");
1798
1799         if (!(user_creds = cli_credentials_init(torture))) {
1800                 torture_fail(torture, "cli_credentials_init failed\n");
1801         }
1802
1803         cli_credentials_set_conf(user_creds, torture->lp_ctx);
1804         cli_credentials_set_username(user_creds, "torture_username",
1805                                      CRED_SPECIFIED);
1806         cli_credentials_set_password(user_creds,
1807                                      generate_random_password(user_creds, 8, 255),
1808                                      CRED_SPECIFIED);
1809
1810         if (!create_user(torture, torture, cli, cmdline_credentials,
1811                          cli_credentials_get_username(user_creds),
1812                          cli_credentials_get_password(user_creds),
1813                          &domain_name, &created_sid)) {
1814                 torture_fail(torture, "create_user failed\n");
1815         }
1816
1817         cli_credentials_set_domain(user_creds, domain_name,
1818                                    CRED_SPECIFIED);
1819
1820         {
1821                 struct smbcli_session *session2;
1822                 struct smb_composite_sesssetup setup;
1823                 struct smbcli_tree *tree;
1824
1825                 session2 = smbcli_session_init(cli->transport, torture, false, session_options);
1826                 if (session2 == NULL) {
1827                         torture_fail(torture, "smbcli_session_init failed\n");
1828                 }
1829
1830                 setup.in.sesskey = cli->transport->negotiate.sesskey;
1831                 setup.in.capabilities = cli->transport->negotiate.capabilities;
1832                 setup.in.workgroup = "";
1833                 setup.in.credentials = user_creds;
1834                 setup.in.gensec_settings = lpcfg_gensec_settings(torture, torture->lp_ctx);
1835
1836                 status = smb_composite_sesssetup(session2, &setup);
1837                 torture_assert_ntstatus_ok(torture, status, "session setup with new user failed");
1838
1839                 session2->vuid = setup.out.vuid;
1840
1841                 if (!NT_STATUS_IS_OK(secondary_tcon(torture, torture, session2,
1842                                                     "IPC$", &tree))) {
1843                         torture_fail(torture, "secondary_tcon failed\n");
1844                 }
1845
1846                 if (!(user_sid = whoami(torture, torture, tree))) {
1847                         torture_fail_goto(torture, del, "whoami on user connection failed\n");
1848                         ret = false;
1849                         goto del;
1850                 }
1851
1852                 talloc_free(tree);
1853         }
1854
1855         torture_comment(torture, "Created %s, found %s\n",
1856                  dom_sid_string(torture, created_sid),
1857                  dom_sid_string(torture, user_sid));
1858
1859         if (!dom_sid_equal(created_sid, user_sid)) {
1860                 ret = false;
1861         }
1862
1863  del:
1864         if (!delete_user(torture, cli,
1865                          cmdline_credentials,
1866                          cli_credentials_get_username(user_creds))) {
1867                 torture_fail(torture, "delete_user failed\n");
1868         }
1869
1870         return ret;
1871 }
1872
1873 static bool test_NetShareGetInfo(struct torture_context *tctx,
1874                                  struct dcerpc_pipe *p,
1875                                  const char *sharename)
1876 {
1877         NTSTATUS status;
1878         struct srvsvc_NetShareGetInfo r;
1879         union srvsvc_NetShareInfo info;
1880         uint32_t levels[] = { 0, 1, 2, 501, 502, 1004, 1005, 1006, 1007, 1501 };
1881         int i;
1882         bool ret = true;
1883         struct dcerpc_binding_handle *b = p->binding_handle;
1884
1885         r.in.server_unc = talloc_asprintf(tctx, "\\\\%s",
1886                                           dcerpc_server_name(p));
1887         r.in.share_name = sharename;
1888         r.out.info = &info;
1889
1890         for (i=0;i<ARRAY_SIZE(levels);i++) {
1891                 r.in.level = levels[i];
1892
1893                 torture_comment(tctx, "Testing NetShareGetInfo level %u on share '%s'\n",
1894                        r.in.level, r.in.share_name);
1895
1896                 status = dcerpc_srvsvc_NetShareGetInfo_r(b, tctx, &r);
1897                 if (!NT_STATUS_IS_OK(status)) {
1898                         torture_warning(tctx, "NetShareGetInfo level %u on share '%s' failed"
1899                                " - %s\n", r.in.level, r.in.share_name,
1900                                nt_errstr(status));
1901                         ret = false;
1902                         continue;
1903                 }
1904                 if (!W_ERROR_IS_OK(r.out.result)) {
1905                         torture_warning(tctx, "NetShareGetInfo level %u on share '%s' failed "
1906                                "- %s\n", r.in.level, r.in.share_name,
1907                                win_errstr(r.out.result));
1908                         ret = false;
1909                         continue;
1910                 }
1911         }
1912
1913         return ret;
1914 }
1915
1916 static bool test_NetShareEnum(struct torture_context *tctx,
1917                               struct dcerpc_pipe *p,
1918                               const char **one_sharename)
1919 {
1920         NTSTATUS status;
1921         struct srvsvc_NetShareEnum r;
1922         struct srvsvc_NetShareInfoCtr info_ctr;
1923         struct srvsvc_NetShareCtr0 c0;
1924         struct srvsvc_NetShareCtr1 c1;
1925         struct srvsvc_NetShareCtr2 c2;
1926         struct srvsvc_NetShareCtr501 c501;
1927         struct srvsvc_NetShareCtr502 c502;
1928         struct srvsvc_NetShareCtr1004 c1004;
1929         struct srvsvc_NetShareCtr1005 c1005;
1930         struct srvsvc_NetShareCtr1006 c1006;
1931         struct srvsvc_NetShareCtr1007 c1007;
1932         uint32_t totalentries = 0;
1933         uint32_t levels[] = { 0, 1, 2, 501, 502, 1004, 1005, 1006, 1007 };
1934         int i;
1935         bool ret = true;
1936         struct dcerpc_binding_handle *b = p->binding_handle;
1937
1938         ZERO_STRUCT(info_ctr);
1939
1940         r.in.server_unc = talloc_asprintf(tctx,"\\\\%s",dcerpc_server_name(p));
1941         r.in.info_ctr = &info_ctr;
1942         r.in.max_buffer = (uint32_t)-1;
1943         r.in.resume_handle = NULL;
1944         r.out.totalentries = &totalentries;
1945         r.out.info_ctr = &info_ctr;
1946
1947         for (i=0;i<ARRAY_SIZE(levels);i++) {
1948                 info_ctr.level = levels[i];
1949
1950                 switch (info_ctr.level) {
1951                 case 0:
1952                         ZERO_STRUCT(c0);
1953                         info_ctr.ctr.ctr0 = &c0;
1954                         break;
1955                 case 1:
1956                         ZERO_STRUCT(c1);
1957                         info_ctr.ctr.ctr1 = &c1;
1958                         break;
1959                 case 2:
1960                         ZERO_STRUCT(c2);
1961                         info_ctr.ctr.ctr2 = &c2;
1962                         break;
1963                 case 501:
1964                         ZERO_STRUCT(c501);
1965                         info_ctr.ctr.ctr501 = &c501;
1966                         break;
1967                 case 502:
1968                         ZERO_STRUCT(c502);
1969                         info_ctr.ctr.ctr502 = &c502;
1970                         break;
1971                 case 1004:
1972                         ZERO_STRUCT(c1004);
1973                         info_ctr.ctr.ctr1004 = &c1004;
1974                         break;
1975                 case 1005:
1976                         ZERO_STRUCT(c1005);
1977                         info_ctr.ctr.ctr1005 = &c1005;
1978                         break;
1979                 case 1006:
1980                         ZERO_STRUCT(c1006);
1981                         info_ctr.ctr.ctr1006 = &c1006;
1982                         break;
1983                 case 1007:
1984                         ZERO_STRUCT(c1007);
1985                         info_ctr.ctr.ctr1007 = &c1007;
1986                         break;
1987                 }
1988
1989                 torture_comment(tctx, "Testing NetShareEnum level %u\n", info_ctr.level);
1990
1991                 status = dcerpc_srvsvc_NetShareEnum_r(b, tctx, &r);
1992                 if (!NT_STATUS_IS_OK(status)) {
1993                         torture_warning(tctx, "NetShareEnum level %u failed - %s\n",
1994                                info_ctr.level, nt_errstr(status));
1995                         ret = false;
1996                         continue;
1997                 }
1998                 if (!W_ERROR_IS_OK(r.out.result)) {
1999                         torture_warning(tctx, "NetShareEnum level %u failed - %s\n",
2000                                info_ctr.level, win_errstr(r.out.result));
2001                         continue;
2002                 }
2003                 if (info_ctr.level == 0) {
2004                         struct srvsvc_NetShareCtr0 *ctr = r.out.info_ctr->ctr.ctr0;
2005                         if (ctr->count > 0) {
2006                                 *one_sharename = ctr->array[0].name;
2007                         }
2008                 }
2009         }
2010
2011         return ret;
2012 }
2013
2014 static bool torture_samba3_rpc_srvsvc(struct torture_context *torture)
2015 {
2016         struct dcerpc_pipe *p;
2017         const char *sharename = NULL;
2018         bool ret = true;
2019
2020         torture_assert_ntstatus_ok(torture,
2021                 torture_rpc_connection(torture, &p, &ndr_table_srvsvc),
2022                 "failed to open srvsvc");
2023
2024         ret &= test_NetShareEnum(torture, p, &sharename);
2025         if (sharename == NULL) {
2026                 torture_comment(torture, "did not get sharename\n");
2027         } else {
2028                 ret &= test_NetShareGetInfo(torture, p, sharename);
2029         }
2030
2031         return ret;
2032 }
2033
2034 /*
2035  * Do a ReqChallenge/Auth2 with a random wks name, make sure it returns
2036  * NT_STATUS_NO_SAM_ACCOUNT
2037  */
2038
2039 static bool torture_samba3_rpc_randomauth2(struct torture_context *torture)
2040 {
2041         TALLOC_CTX *mem_ctx;
2042         struct dcerpc_pipe *net_pipe;
2043         struct dcerpc_binding_handle *net_handle;
2044         char *wksname;
2045         bool result = false;
2046         NTSTATUS status;
2047         struct netr_ServerReqChallenge r;
2048         struct netr_Credential netr_cli_creds;
2049         struct netr_Credential netr_srv_creds;
2050         uint32_t negotiate_flags;
2051         struct netr_ServerAuthenticate2 a;
2052         struct netlogon_creds_CredentialState *creds_state;
2053         struct netr_Credential netr_cred;
2054         struct samr_Password mach_pw;
2055         struct smbcli_state *cli;
2056
2057         if (!(mem_ctx = talloc_new(torture))) {
2058                 torture_comment(torture, "talloc_new failed\n");
2059                 return false;
2060         }
2061
2062         if (!(wksname = generate_random_str_list(
2063                       mem_ctx, 14, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"))) {
2064                 torture_comment(torture, "generate_random_str_list failed\n");
2065                 goto done;
2066         }
2067
2068         if (!(torture_open_connection_share(
2069                       mem_ctx, &cli,
2070                       torture, torture_setting_string(torture, "host", NULL),
2071                       "IPC$", torture->ev))) {
2072                 torture_comment(torture, "IPC$ connection failed\n");
2073                 goto done;
2074         }
2075
2076         if (!(net_pipe = dcerpc_pipe_init(mem_ctx, torture->ev))) {
2077                 torture_comment(torture, "dcerpc_pipe_init failed\n");
2078                 goto done;
2079         }
2080         net_handle = net_pipe->binding_handle;
2081
2082         status = dcerpc_pipe_open_smb(net_pipe, cli->tree, "\\netlogon");
2083         if (!NT_STATUS_IS_OK(status)) {
2084                 torture_comment(torture, "dcerpc_pipe_open_smb failed: %s\n",
2085                          nt_errstr(status));
2086                 goto done;
2087         }
2088
2089         status = dcerpc_bind_auth_none(net_pipe, &ndr_table_netlogon);
2090         if (!NT_STATUS_IS_OK(status)) {
2091                 torture_comment(torture, "dcerpc_bind_auth_none failed: %s\n",
2092                          nt_errstr(status));
2093                 goto done;
2094         }
2095
2096         r.in.computer_name = wksname;
2097         r.in.server_name = talloc_asprintf(
2098                 mem_ctx, "\\\\%s", dcerpc_server_name(net_pipe));
2099         if (r.in.server_name == NULL) {
2100                 torture_comment(torture, "talloc_asprintf failed\n");
2101                 goto done;
2102         }
2103         generate_random_buffer(netr_cli_creds.data,
2104                                sizeof(netr_cli_creds.data));
2105         r.in.credentials = &netr_cli_creds;
2106         r.out.return_credentials = &netr_srv_creds;
2107
2108         status = dcerpc_netr_ServerReqChallenge_r(net_handle, mem_ctx, &r);
2109         if (!NT_STATUS_IS_OK(status)) {
2110                 torture_comment(torture, "netr_ServerReqChallenge failed: %s\n",
2111                          nt_errstr(status));
2112                 goto done;
2113         }
2114         if (!NT_STATUS_IS_OK(r.out.result)) {
2115                 torture_comment(torture, "netr_ServerReqChallenge failed: %s\n",
2116                          nt_errstr(r.out.result));
2117                 goto done;
2118         }
2119
2120         negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS;
2121         E_md4hash("foobar", mach_pw.hash);
2122
2123         a.in.server_name = talloc_asprintf(
2124                 mem_ctx, "\\\\%s", dcerpc_server_name(net_pipe));
2125         a.in.account_name = talloc_asprintf(
2126                 mem_ctx, "%s$", wksname);
2127         a.in.computer_name = wksname;
2128         a.in.secure_channel_type = SEC_CHAN_WKSTA;
2129         a.in.negotiate_flags = &negotiate_flags;
2130         a.out.negotiate_flags = &negotiate_flags;
2131         a.in.credentials = &netr_cred;
2132         a.out.return_credentials = &netr_cred;
2133
2134         creds_state = netlogon_creds_client_init(mem_ctx,
2135                                                  a.in.account_name,
2136                                                  a.in.computer_name,
2137                                                  r.in.credentials,
2138                                                  r.out.return_credentials, &mach_pw,
2139                                                  &netr_cred, negotiate_flags);
2140
2141
2142         status = dcerpc_netr_ServerAuthenticate2_r(net_handle, mem_ctx, &a);
2143         if (!NT_STATUS_IS_OK(status)) {
2144                 goto done;
2145         }
2146         if (!NT_STATUS_EQUAL(a.out.result, NT_STATUS_NO_TRUST_SAM_ACCOUNT)) {
2147                 torture_comment(torture, "dcerpc_netr_ServerAuthenticate2 returned %s, "
2148                          "expected NT_STATUS_NO_TRUST_SAM_ACCOUNT\n",
2149                          nt_errstr(a.out.result));
2150                 goto done;
2151         }
2152
2153         result = true;
2154  done:
2155         talloc_free(mem_ctx);
2156         return result;
2157 }
2158
2159 static struct security_descriptor *get_sharesec(struct torture_context *tctx,
2160                                                 TALLOC_CTX *mem_ctx,
2161                                                 struct smbcli_session *sess,
2162                                                 const char *sharename)
2163 {
2164         struct smbcli_tree *tree;
2165         TALLOC_CTX *tmp_ctx;
2166         struct dcerpc_pipe *p;
2167         struct dcerpc_binding_handle *b;
2168         NTSTATUS status;
2169         struct srvsvc_NetShareGetInfo r;
2170         union srvsvc_NetShareInfo info;
2171         struct security_descriptor *result;
2172
2173         if (!(tmp_ctx = talloc_new(mem_ctx))) {
2174                 torture_comment(tctx, "talloc_new failed\n");
2175                 return NULL;
2176         }
2177
2178         if (!NT_STATUS_IS_OK(secondary_tcon(tctx, tmp_ctx, sess, "IPC$", &tree))) {
2179                 torture_comment(tctx, "secondary_tcon failed\n");
2180                 talloc_free(tmp_ctx);
2181                 return NULL;
2182         }
2183
2184         status = pipe_bind_smb(tctx, mem_ctx, tree, "\\pipe\\srvsvc",
2185                                &ndr_table_srvsvc, &p);
2186         if (!NT_STATUS_IS_OK(status)) {
2187                 torture_warning(tctx, "could not bind to srvsvc pipe: %s\n",
2188                          nt_errstr(status));
2189                 talloc_free(tmp_ctx);
2190                 return NULL;
2191         }
2192         b = p->binding_handle;
2193
2194 #if 0
2195         p->conn->flags |= DCERPC_DEBUG_PRINT_IN | DCERPC_DEBUG_PRINT_OUT;
2196 #endif
2197
2198         r.in.server_unc = talloc_asprintf(tmp_ctx, "\\\\%s",
2199                                           dcerpc_server_name(p));
2200         r.in.share_name = sharename;
2201         r.in.level = 502;
2202         r.out.info = &info;
2203
2204         status = dcerpc_srvsvc_NetShareGetInfo_r(b, tmp_ctx, &r);
2205         if (!NT_STATUS_IS_OK(status)) {
2206                 torture_comment(tctx, "srvsvc_NetShareGetInfo failed: %s\n",
2207                          nt_errstr(status));
2208                 talloc_free(tmp_ctx);
2209                 return NULL;
2210         }
2211         if (!W_ERROR_IS_OK(r.out.result)) {
2212                 torture_comment(tctx, "srvsvc_NetShareGetInfo failed: %s\n",
2213                          win_errstr(r.out.result));
2214                 talloc_free(tmp_ctx);
2215                 return NULL;
2216         }
2217
2218         result = talloc_steal(mem_ctx, info.info502->sd_buf.sd);
2219         talloc_free(tmp_ctx);
2220         return result;
2221 }
2222
2223 static NTSTATUS set_sharesec(struct torture_context *tctx,
2224                              TALLOC_CTX *mem_ctx,
2225                              struct smbcli_session *sess,
2226                              const char *sharename,
2227                              struct security_descriptor *sd)
2228 {
2229         struct smbcli_tree *tree;
2230         TALLOC_CTX *tmp_ctx;
2231         struct dcerpc_pipe *p;
2232         struct dcerpc_binding_handle *b;
2233         NTSTATUS status;
2234         struct sec_desc_buf i;
2235         struct srvsvc_NetShareSetInfo r;
2236         union srvsvc_NetShareInfo info;
2237         uint32_t error = 0;
2238
2239         if (!(tmp_ctx = talloc_new(mem_ctx))) {
2240                 torture_comment(tctx, "talloc_new failed\n");
2241                 return NT_STATUS_NO_MEMORY;
2242         }
2243
2244         if (!NT_STATUS_IS_OK(secondary_tcon(tctx, tmp_ctx, sess, "IPC$", &tree))) {
2245                 torture_comment(tctx, "secondary_tcon failed\n");
2246                 talloc_free(tmp_ctx);
2247                 return NT_STATUS_UNSUCCESSFUL;
2248         }
2249
2250         status = pipe_bind_smb(tctx, mem_ctx, tree, "\\pipe\\srvsvc",
2251                                &ndr_table_srvsvc, &p);
2252         if (!NT_STATUS_IS_OK(status)) {
2253                 torture_warning(tctx, "could not bind to srvsvc pipe: %s\n",
2254                          nt_errstr(status));
2255                 talloc_free(tmp_ctx);
2256                 return NT_STATUS_UNSUCCESSFUL;
2257         }
2258         b = p->binding_handle;
2259
2260 #if 0
2261         p->conn->flags |= DCERPC_DEBUG_PRINT_IN | DCERPC_DEBUG_PRINT_OUT;
2262 #endif
2263
2264         r.in.server_unc = talloc_asprintf(tmp_ctx, "\\\\%s",
2265                                           dcerpc_server_name(p));
2266         r.in.share_name = sharename;
2267         r.in.level = 1501;
2268         i.sd = sd;
2269         info.info1501 = &i;
2270         r.in.info = &info;
2271         r.in.parm_error = &error;
2272
2273         status = dcerpc_srvsvc_NetShareSetInfo_r(b, tmp_ctx, &r);
2274         if (!NT_STATUS_IS_OK(status)) {
2275                 torture_comment(tctx, "srvsvc_NetShareSetInfo failed: %s\n",
2276                          nt_errstr(status));
2277         }
2278         if (!W_ERROR_IS_OK(r.out.result)) {
2279                 torture_comment(tctx, "srvsvc_NetShareSetInfo failed: %s\n",
2280                         win_errstr(r.out.result));
2281                 status = werror_to_ntstatus(r.out.result);
2282         }
2283         talloc_free(tmp_ctx);
2284         return status;
2285 }
2286
2287 bool try_tcon(struct torture_context *tctx,
2288               TALLOC_CTX *mem_ctx,
2289               struct security_descriptor *orig_sd,
2290               struct smbcli_session *session,
2291               const char *sharename, const struct dom_sid *user_sid,
2292               unsigned int access_mask, NTSTATUS expected_tcon,
2293               NTSTATUS expected_mkdir)
2294 {
2295         TALLOC_CTX *tmp_ctx;
2296         struct smbcli_tree *rmdir_tree, *tree;
2297         struct dom_sid *domain_sid;
2298         uint32_t rid;
2299         struct security_descriptor *sd;
2300         NTSTATUS status;
2301         bool ret = true;
2302
2303         if (!(tmp_ctx = talloc_new(mem_ctx))) {
2304                 torture_comment(tctx, "talloc_new failed\n");
2305                 return false;
2306         }
2307
2308         status = secondary_tcon(tctx, tmp_ctx, session, sharename, &rmdir_tree);
2309         if (!NT_STATUS_IS_OK(status)) {
2310                 torture_comment(tctx, "first tcon to delete dir failed\n");
2311                 talloc_free(tmp_ctx);
2312                 return false;
2313         }
2314
2315         smbcli_rmdir(rmdir_tree, "sharesec_testdir");
2316
2317         if (!NT_STATUS_IS_OK(dom_sid_split_rid(tmp_ctx, user_sid,
2318                                                &domain_sid, &rid))) {
2319                 torture_comment(tctx, "dom_sid_split_rid failed\n");
2320                 talloc_free(tmp_ctx);
2321                 return false;
2322         }
2323
2324         sd = security_descriptor_dacl_create(
2325                 tmp_ctx, 0, "S-1-5-32-544",
2326                 dom_sid_string(mem_ctx, dom_sid_add_rid(mem_ctx, domain_sid,
2327                                                         DOMAIN_RID_USERS)),
2328                 dom_sid_string(mem_ctx, user_sid),
2329                 SEC_ACE_TYPE_ACCESS_ALLOWED, access_mask, 0, NULL);
2330         if (sd == NULL) {
2331                 torture_comment(tctx, "security_descriptor_dacl_create failed\n");
2332                 talloc_free(tmp_ctx);
2333                 return false;
2334         }
2335
2336         status = set_sharesec(tctx, mem_ctx, session, sharename, sd);
2337         if (!NT_STATUS_IS_OK(status)) {
2338                 torture_comment(tctx, "custom set_sharesec failed: %s\n",
2339                          nt_errstr(status));
2340                 talloc_free(tmp_ctx);
2341                 return false;
2342         }
2343
2344         status = secondary_tcon(tctx, tmp_ctx, session, sharename, &tree);
2345         if (!NT_STATUS_EQUAL(status, expected_tcon)) {
2346                 torture_comment(tctx, "Expected %s, got %s\n", nt_errstr(expected_tcon),
2347                          nt_errstr(status));
2348                 ret = false;
2349                 goto done;
2350         }
2351
2352         if (!NT_STATUS_IS_OK(status)) {
2353                 /* An expected non-access, no point in trying to write */
2354                 goto done;
2355         }
2356
2357         status = smbcli_mkdir(tree, "sharesec_testdir");
2358         if (!NT_STATUS_EQUAL(status, expected_mkdir)) {
2359                 torture_warning(tctx, "Expected %s, got %s\n",
2360                          nt_errstr(expected_mkdir), nt_errstr(status));
2361                 ret = false;
2362         }
2363
2364  done:
2365         smbcli_rmdir(rmdir_tree, "sharesec_testdir");
2366
2367         status = set_sharesec(tctx, mem_ctx, session, sharename, orig_sd);
2368         if (!NT_STATUS_IS_OK(status)) {
2369                 torture_comment(tctx, "custom set_sharesec failed: %s\n",
2370                          nt_errstr(status));
2371                 talloc_free(tmp_ctx);
2372                 return false;
2373         }
2374
2375         talloc_free(tmp_ctx);
2376         return ret;
2377 }
2378
2379 static bool torture_samba3_rpc_sharesec(struct torture_context *torture)
2380 {
2381         struct smbcli_state *cli;
2382         struct security_descriptor *sd;
2383         struct dom_sid *user_sid;
2384
2385         if (!(torture_open_connection_share(
2386                       torture, &cli, torture, torture_setting_string(torture, "host", NULL),
2387                       "IPC$", torture->ev))) {
2388                 torture_fail(torture, "IPC$ connection failed\n");
2389         }
2390
2391         if (!(user_sid = whoami(torture, torture, cli->tree))) {
2392                 torture_fail(torture, "whoami failed\n");
2393         }
2394
2395         sd = get_sharesec(torture, torture, cli->session,
2396                           torture_setting_string(torture, "share", NULL));
2397
2398         torture_assert(torture, try_tcon(
2399                         torture, torture, sd, cli->session,
2400                         torture_setting_string(torture, "share", NULL),
2401                         user_sid, 0, NT_STATUS_ACCESS_DENIED, NT_STATUS_OK),
2402                         "failed to test tcon with 0 access_mask");
2403
2404         torture_assert(torture, try_tcon(
2405                         torture, torture, sd, cli->session,
2406                         torture_setting_string(torture, "share", NULL),
2407                         user_sid, SEC_FILE_READ_DATA, NT_STATUS_OK,
2408                         NT_STATUS_MEDIA_WRITE_PROTECTED),
2409                         "failed to test tcon with SEC_FILE_READ_DATA access_mask");
2410
2411         torture_assert(torture, try_tcon(
2412                         torture, torture, sd, cli->session,
2413                         torture_setting_string(torture, "share", NULL),
2414                         user_sid, SEC_FILE_ALL, NT_STATUS_OK, NT_STATUS_OK),
2415                         "failed to test tcon with SEC_FILE_ALL access_mask")
2416
2417         return true;
2418 }
2419
2420 static bool torture_samba3_rpc_lsa(struct torture_context *torture)
2421 {
2422         struct dcerpc_pipe *p;
2423         struct dcerpc_binding_handle *b;
2424         struct policy_handle lsa_handle;
2425
2426         torture_assert_ntstatus_ok(torture,
2427                 torture_rpc_connection(torture, &p, &ndr_table_lsarpc),
2428                 "failed to setup lsarpc");
2429
2430         b = p->binding_handle;
2431
2432         {
2433                 struct lsa_ObjectAttribute attr;
2434                 struct lsa_OpenPolicy2 o;
2435                 o.in.system_name = talloc_asprintf(
2436                         torture, "\\\\%s", dcerpc_server_name(p));
2437                 ZERO_STRUCT(attr);
2438                 o.in.attr = &attr;
2439                 o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2440                 o.out.handle = &lsa_handle;
2441
2442                 torture_assert_ntstatus_ok(torture,
2443                         dcerpc_lsa_OpenPolicy2_r(b, torture, &o),
2444                         "dcerpc_lsa_OpenPolicy2 failed");
2445                 torture_assert_ntstatus_ok(torture, o.out.result,
2446                         "dcerpc_lsa_OpenPolicy2 failed");
2447         }
2448
2449         {
2450                 int i;
2451                 int levels[] = { 2,3,5,6 };
2452
2453                 for (i=0; i<ARRAY_SIZE(levels); i++) {
2454                         struct lsa_QueryInfoPolicy r;
2455                         union lsa_PolicyInformation *info = NULL;
2456                         r.in.handle = &lsa_handle;
2457                         r.in.level = levels[i];
2458                         r.out.info = &info;
2459
2460                         torture_assert_ntstatus_ok(torture,
2461                                 dcerpc_lsa_QueryInfoPolicy_r(b, torture, &r),
2462                                 talloc_asprintf(torture, "dcerpc_lsa_QueryInfoPolicy level %d failed", levels[i]));
2463                         torture_assert_ntstatus_ok(torture, r.out.result,
2464                                 talloc_asprintf(torture, "dcerpc_lsa_QueryInfoPolicy level %d failed", levels[i]));
2465                 }
2466         }
2467
2468         return true;
2469 }
2470
2471 static NTSTATUS get_servername(TALLOC_CTX *mem_ctx, struct smbcli_tree *tree,
2472                                char **name)
2473 {
2474         struct rap_WserverGetInfo r;
2475         NTSTATUS status;
2476         char servername[17];
2477         size_t converted_size;
2478
2479         r.in.level = 0;
2480         r.in.bufsize = 0xffff;
2481
2482         status = smbcli_rap_netservergetinfo(tree, mem_ctx, &r);
2483         if (!NT_STATUS_IS_OK(status)) {
2484                 return status;
2485         }
2486
2487         memcpy(servername, r.out.info.info0.name, 16);
2488         servername[16] = '\0';
2489
2490         if (!pull_ascii_talloc(mem_ctx, name, servername, &converted_size)) {
2491                 return NT_STATUS_NO_MEMORY;
2492         }
2493
2494         return NT_STATUS_OK;
2495 }
2496
2497 static bool rap_get_servername(struct torture_context *tctx,
2498                                char **servername)
2499 {
2500         struct smbcli_state *cli;
2501
2502         torture_assert(tctx,
2503                 torture_open_connection_share(tctx, &cli, tctx, torture_setting_string(tctx, "host", NULL),
2504                                               "IPC$", tctx->ev),
2505                 "IPC$ connection failed");
2506
2507         torture_assert_ntstatus_ok(tctx,
2508                 get_servername(tctx, cli->tree, servername),
2509                 "get_servername failed");
2510
2511         talloc_free(cli);
2512
2513         return true;
2514 }
2515
2516 static bool find_printers(struct torture_context *tctx,
2517                           struct dcerpc_pipe *p,
2518                           const char ***printers,
2519                           int *num_printers)
2520 {
2521         struct srvsvc_NetShareEnum r;
2522         struct srvsvc_NetShareInfoCtr info_ctr;
2523         struct srvsvc_NetShareCtr1 c1_in;
2524         struct srvsvc_NetShareCtr1 *c1;
2525         uint32_t totalentries = 0;
2526         int i;
2527         struct dcerpc_binding_handle *b = p->binding_handle;
2528
2529         ZERO_STRUCT(c1_in);
2530         info_ctr.level = 1;
2531         info_ctr.ctr.ctr1 = &c1_in;
2532
2533         r.in.server_unc = talloc_asprintf(
2534                 tctx, "\\\\%s", dcerpc_server_name(p));
2535         r.in.info_ctr = &info_ctr;
2536         r.in.max_buffer = (uint32_t)-1;
2537         r.in.resume_handle = NULL;
2538         r.out.totalentries = &totalentries;
2539         r.out.info_ctr = &info_ctr;
2540
2541         torture_assert_ntstatus_ok(tctx,
2542                 dcerpc_srvsvc_NetShareEnum_r(b, tctx, &r),
2543                 "NetShareEnum level 1 failed");
2544         torture_assert_werr_ok(tctx, r.out.result,
2545                 "NetShareEnum level 1 failed");
2546
2547         *printers = NULL;
2548         *num_printers = 0;
2549         c1 = r.out.info_ctr->ctr.ctr1;
2550         for (i=0; i<c1->count; i++) {
2551                 if (c1->array[i].type != STYPE_PRINTQ) {
2552                         continue;
2553                 }
2554                 if (!add_string_to_array(tctx, c1->array[i].name,
2555                                          printers, num_printers)) {
2556                         return false;
2557                 }
2558         }
2559
2560         return true;
2561 }
2562
2563 static bool enumprinters(struct torture_context *tctx,
2564                          struct dcerpc_binding_handle *b,
2565                          const char *servername, int level, int *num_printers)
2566 {
2567         struct spoolss_EnumPrinters r;
2568         DATA_BLOB blob;
2569         uint32_t needed;
2570         uint32_t count;
2571         union spoolss_PrinterInfo *info;
2572
2573         r.in.flags = PRINTER_ENUM_LOCAL;
2574         r.in.server = talloc_asprintf(tctx, "\\\\%s", servername);
2575         r.in.level = level;
2576         r.in.buffer = NULL;
2577         r.in.offered = 0;
2578         r.out.needed = &needed;
2579         r.out.count = &count;
2580         r.out.info = &info;
2581
2582         torture_assert_ntstatus_ok(tctx,
2583                 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
2584                 "dcerpc_spoolss_EnumPrinters failed");
2585         torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
2586                 "EnumPrinters unexpected return code should be WERR_INSUFFICIENT_BUFFER");
2587
2588         blob = data_blob_talloc_zero(tctx, needed);
2589         if (blob.data == NULL) {
2590                 return false;
2591         }
2592
2593         r.in.buffer = &blob;
2594         r.in.offered = needed;
2595
2596         torture_assert_ntstatus_ok(tctx,
2597                 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
2598                 "dcerpc_spoolss_EnumPrinters failed");
2599         torture_assert_werr_ok(tctx, r.out.result,
2600                 "dcerpc_spoolss_EnumPrinters failed");
2601
2602         *num_printers = count;
2603
2604         return true;
2605 }
2606
2607 static bool getprinterinfo(struct torture_context *tctx,
2608                            struct dcerpc_binding_handle *b,
2609                            struct policy_handle *handle, int level,
2610                            union spoolss_PrinterInfo **res)
2611 {
2612         struct spoolss_GetPrinter r;
2613         DATA_BLOB blob;
2614         uint32_t needed;
2615
2616         r.in.handle = handle;
2617         r.in.level = level;
2618         r.in.buffer = NULL;
2619         r.in.offered = 0;
2620         r.out.needed = &needed;
2621
2622         torture_assert_ntstatus_ok(tctx,
2623                 dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
2624                 "dcerpc_spoolss_GetPrinter failed");
2625         torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
2626                 "GetPrinter unexpected return code should be WERR_INSUFFICIENT_BUFFER");
2627
2628         r.in.handle = handle;
2629         r.in.level = level;
2630         blob = data_blob_talloc_zero(tctx, needed);
2631         if (blob.data == NULL) {
2632                 return false;
2633         }
2634         r.in.buffer = &blob;
2635         r.in.offered = needed;
2636
2637         torture_assert_ntstatus_ok(tctx,
2638                 dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
2639                 "dcerpc_spoolss_GetPrinter failed");
2640         torture_assert_werr_ok(tctx, r.out.result,
2641                 "dcerpc_spoolss_GetPrinter failed");
2642
2643         if (res != NULL) {
2644                 *res = talloc_steal(tctx, r.out.info);
2645         }
2646
2647         return true;
2648 }
2649
2650 static bool torture_samba3_rpc_spoolss(struct torture_context *torture)
2651 {
2652         struct dcerpc_pipe *p, *p2;
2653         struct dcerpc_binding_handle *b;
2654         struct policy_handle server_handle, printer_handle;
2655         const char **printers;
2656         int num_printers;
2657         struct spoolss_UserLevel1 userlevel1;
2658         char *servername;
2659
2660         torture_assert(torture,
2661                 rap_get_servername(torture, &servername),
2662                 "failed to rap servername");
2663
2664         torture_assert_ntstatus_ok(torture,
2665                 torture_rpc_connection(torture, &p2, &ndr_table_srvsvc),
2666                 "failed to setup srvsvc");
2667
2668         torture_assert(torture,
2669                 find_printers(torture, p2, &printers, &num_printers),
2670                 "failed to find printers via srvsvc");
2671
2672         talloc_free(p2);
2673
2674         if (num_printers == 0) {
2675                 torture_skip(torture, "Did not find printers\n");
2676                 return true;
2677         }
2678
2679         torture_assert_ntstatus_ok(torture,
2680                 torture_rpc_connection(torture, &p, &ndr_table_spoolss),
2681                 "failed to setup spoolss");
2682
2683         b = p->binding_handle;
2684
2685         ZERO_STRUCT(userlevel1);
2686         userlevel1.client = talloc_asprintf(
2687                 torture, "\\\\%s", lpcfg_netbios_name(torture->lp_ctx));
2688         userlevel1.user = cli_credentials_get_username(cmdline_credentials);
2689         userlevel1.build = 2600;
2690         userlevel1.major = 3;
2691         userlevel1.minor = 0;
2692         userlevel1.processor = 0;
2693
2694         {
2695                 struct spoolss_OpenPrinterEx r;
2696
2697                 ZERO_STRUCT(r);
2698                 r.in.printername = talloc_asprintf(torture, "\\\\%s",
2699                                                    servername);
2700                 r.in.datatype = NULL;
2701                 r.in.access_mask = 0;
2702                 r.in.level = 1;
2703                 r.in.userlevel.level1 = &userlevel1;
2704                 r.out.handle = &server_handle;
2705
2706                 torture_assert_ntstatus_ok(torture,
2707                         dcerpc_spoolss_OpenPrinterEx_r(b, torture, &r),
2708                         "dcerpc_spoolss_OpenPrinterEx failed");
2709                 torture_assert_werr_ok(torture, r.out.result,
2710                         "dcerpc_spoolss_OpenPrinterEx failed");
2711         }
2712
2713         {
2714                 struct spoolss_ClosePrinter r;
2715
2716                 r.in.handle = &server_handle;
2717                 r.out.handle = &server_handle;
2718
2719                 torture_assert_ntstatus_ok(torture,
2720                         dcerpc_spoolss_ClosePrinter_r(b, torture, &r),
2721                         "dcerpc_spoolss_ClosePrinter failed");
2722                 torture_assert_werr_ok(torture, r.out.result,
2723                         "dcerpc_spoolss_ClosePrinter failed");
2724         }
2725
2726         {
2727                 struct spoolss_OpenPrinterEx r;
2728
2729                 ZERO_STRUCT(r);
2730                 r.in.printername = talloc_asprintf(
2731                         torture, "\\\\%s\\%s", servername, printers[0]);
2732                 r.in.datatype = NULL;
2733                 r.in.access_mask = 0;
2734                 r.in.level = 1;
2735                 r.in.userlevel.level1 = &userlevel1;
2736                 r.out.handle = &printer_handle;
2737
2738                 torture_assert_ntstatus_ok(torture,
2739                         dcerpc_spoolss_OpenPrinterEx_r(b, torture, &r),
2740                         "dcerpc_spoolss_OpenPrinterEx failed");
2741                 torture_assert_werr_ok(torture, r.out.result,
2742                         "dcerpc_spoolss_OpenPrinterEx failed");
2743         }
2744
2745         {
2746                 int i;
2747
2748                 for (i=0; i<8; i++) {
2749                         torture_assert(torture,
2750                                 getprinterinfo(torture, b, &printer_handle, i, NULL),
2751                                 talloc_asprintf(torture, "getprinterinfo %d failed", i));
2752                 }
2753         }
2754
2755         {
2756                 struct spoolss_ClosePrinter r;
2757
2758                 r.in.handle = &printer_handle;
2759                 r.out.handle = &printer_handle;
2760
2761                 torture_assert_ntstatus_ok(torture,
2762                         dcerpc_spoolss_ClosePrinter_r(b, torture, &r),
2763                         "dcerpc_spoolss_ClosePrinter failed");
2764                 torture_assert_werr_ok(torture, r.out.result,
2765                         "dcerpc_spoolss_ClosePrinter failed");
2766         }
2767
2768         {
2769                 int num_enumerated;
2770
2771                 torture_assert(torture,
2772                         enumprinters(torture, b, servername, 1, &num_enumerated),
2773                         "enumprinters failed");
2774
2775                 torture_assert_int_equal(torture, num_printers, num_enumerated,
2776                         "netshareenum / enumprinters lvl 1 numprinter mismatch");
2777         }
2778
2779         {
2780                 int num_enumerated;
2781
2782                 torture_assert(torture,
2783                         enumprinters(torture, b, servername, 2, &num_enumerated),
2784                         "enumprinters failed");
2785
2786                 torture_assert_int_equal(torture, num_printers, num_enumerated,
2787                         "netshareenum / enumprinters lvl 2 numprinter mismatch");
2788         }
2789
2790         return true;
2791 }
2792
2793 static bool torture_samba3_rpc_wkssvc(struct torture_context *torture)
2794 {
2795         struct dcerpc_pipe *p;
2796         struct dcerpc_binding_handle *b;
2797         char *servername;
2798
2799         torture_assert(torture,
2800                 rap_get_servername(torture, &servername),
2801                 "failed to rap servername");
2802
2803         torture_assert_ntstatus_ok(torture,
2804                 torture_rpc_connection(torture, &p, &ndr_table_wkssvc),
2805                 "failed to setup wkssvc");
2806
2807         b = p->binding_handle;
2808
2809         {
2810                 struct wkssvc_NetWkstaInfo100 wks100;
2811                 union wkssvc_NetWkstaInfo info;
2812                 struct wkssvc_NetWkstaGetInfo r;
2813
2814                 r.in.server_name = "\\foo";
2815                 r.in.level = 100;
2816                 info.info100 = &wks100;
2817                 r.out.info = &info;
2818
2819                 torture_assert_ntstatus_ok(torture,
2820                         dcerpc_wkssvc_NetWkstaGetInfo_r(b, torture, &r),
2821                         "dcerpc_wkssvc_NetWksGetInfo failed");
2822                 torture_assert_werr_ok(torture, r.out.result,
2823                         "dcerpc_wkssvc_NetWksGetInfo failed");
2824
2825                 torture_assert_str_equal(torture, servername, r.out.info->info100->server_name,
2826                         "servername RAP / DCERPC inconsistency");
2827         }
2828
2829         return true;
2830 }
2831
2832 static bool winreg_close(struct torture_context *tctx,
2833                          struct dcerpc_binding_handle *b,
2834                          struct policy_handle *handle)
2835 {
2836         struct winreg_CloseKey c;
2837
2838         c.in.handle = c.out.handle = handle;
2839
2840         torture_assert_ntstatus_ok(tctx,
2841                 dcerpc_winreg_CloseKey_r(b, tctx, &c),
2842                 "winreg_CloseKey failed");
2843         torture_assert_werr_ok(tctx, c.out.result,
2844                 "winreg_CloseKey failed");
2845
2846         return true;
2847 }
2848
2849 static bool enumvalues(struct torture_context *tctx,
2850                        struct dcerpc_binding_handle *b,
2851                        struct policy_handle *handle)
2852 {
2853         uint32_t enum_index = 0;
2854
2855         while (1) {
2856                 struct winreg_EnumValue r;
2857                 struct winreg_ValNameBuf name;
2858                 enum winreg_Type type = 0;
2859                 uint8_t buf8[1024];
2860                 NTSTATUS status;
2861                 uint32_t size, length;
2862
2863                 r.in.handle = handle;
2864                 r.in.enum_index = enum_index;
2865                 name.name = "";
2866                 name.size = 1024;
2867                 r.in.name = r.out.name = &name;
2868                 size = 1024;
2869                 length = 5;
2870                 r.in.type = &type;
2871                 r.in.value = buf8;
2872                 r.in.size = &size;
2873                 r.in.length = &length;
2874
2875                 status = dcerpc_winreg_EnumValue_r(b, tctx, &r);
2876                 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
2877                         return true;
2878                 }
2879                 enum_index += 1;
2880         }
2881 }
2882
2883 static bool enumkeys(struct torture_context *tctx,
2884                      struct dcerpc_binding_handle *b,
2885                      struct policy_handle *handle,
2886                      int depth)
2887 {
2888         struct winreg_EnumKey r;
2889         struct winreg_StringBuf kclass, name;
2890         NTSTATUS status;
2891         NTTIME t = 0;
2892
2893         if (depth <= 0) {
2894                 return true;
2895         }
2896
2897         kclass.name   = "";
2898         kclass.size   = 1024;
2899
2900         r.in.handle = handle;
2901         r.in.enum_index = 0;
2902         r.in.name = &name;
2903         r.in.keyclass = &kclass;
2904         r.out.name = &name;
2905         r.in.last_changed_time = &t;
2906
2907         do {
2908                 struct winreg_OpenKey o;
2909                 struct policy_handle key_handle;
2910                 int i;
2911
2912                 name.name = NULL;
2913                 name.size = 1024;
2914
2915                 status = dcerpc_winreg_EnumKey_r(b, tctx, &r);
2916                 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
2917                         /* We're done enumerating */
2918                         return true;
2919                 }
2920
2921                 for (i=0; i<10-depth; i++) {
2922                         torture_comment(tctx, " ");
2923                 }
2924                 torture_comment(tctx, "%s\n", r.out.name->name);
2925
2926                 o.in.parent_handle = handle;
2927                 o.in.keyname.name = r.out.name->name;
2928                 o.in.options = 0;
2929                 o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2930                 o.out.handle = &key_handle;
2931
2932                 status = dcerpc_winreg_OpenKey_r(b, tctx, &o);
2933                 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(o.out.result)) {
2934                         enumkeys(tctx, b, &key_handle, depth-1);
2935                         enumvalues(tctx, b, &key_handle);
2936                         torture_assert(tctx, winreg_close(tctx, b, &key_handle), "");
2937                 }
2938
2939                 r.in.enum_index += 1;
2940         } while(true);
2941
2942         return true;
2943 }
2944
2945 typedef NTSTATUS (*winreg_open_fn)(struct dcerpc_binding_handle *, TALLOC_CTX *, void *);
2946
2947 static bool test_Open3(struct torture_context *tctx,
2948                        struct dcerpc_binding_handle *b,
2949                        const char *name, winreg_open_fn open_fn)
2950 {
2951         struct policy_handle handle;
2952         struct winreg_OpenHKLM r;
2953
2954         r.in.system_name = 0;
2955         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2956         r.out.handle = &handle;
2957
2958         torture_assert_ntstatus_ok(tctx,
2959                 open_fn(b, tctx, &r),
2960                 talloc_asprintf(tctx, "%s failed", name));
2961         torture_assert_werr_ok(tctx, r.out.result,
2962                 talloc_asprintf(tctx, "%s failed", name));
2963
2964         enumkeys(tctx, b, &handle, 4);
2965
2966         torture_assert(tctx,
2967                 winreg_close(tctx, b, &handle),
2968                 "dcerpc_CloseKey failed");
2969
2970         return true;
2971 }
2972
2973 static bool torture_samba3_rpc_winreg(struct torture_context *torture)
2974 {
2975         struct dcerpc_pipe *p;
2976         struct dcerpc_binding_handle *b;
2977         bool ret = true;
2978         struct {
2979                 const char *name;
2980                 winreg_open_fn fn;
2981         } open_fns[] = {
2982                 {"OpenHKLM", (winreg_open_fn)dcerpc_winreg_OpenHKLM_r },
2983                 {"OpenHKU",  (winreg_open_fn)dcerpc_winreg_OpenHKU_r },
2984                 {"OpenHKPD", (winreg_open_fn)dcerpc_winreg_OpenHKPD_r },
2985                 {"OpenHKPT", (winreg_open_fn)dcerpc_winreg_OpenHKPT_r },
2986                 {"OpenHKCR", (winreg_open_fn)dcerpc_winreg_OpenHKCR_r }};
2987 #if 0
2988         int i;
2989 #endif
2990
2991         torture_assert_ntstatus_ok(torture,
2992                 torture_rpc_connection(torture, &p, &ndr_table_winreg),
2993                 "failed to setup winreg");
2994
2995         b = p->binding_handle;
2996
2997 #if 1
2998         ret = test_Open3(torture, b, open_fns[0].name, open_fns[0].fn);
2999 #else
3000         for (i = 0; i < ARRAY_SIZE(open_fns); i++) {
3001                 if (!test_Open3(torture, b, open_fns[i].name, open_fns[i].fn))
3002                         ret = false;
3003         }
3004 #endif
3005         return ret;
3006 }
3007
3008 static bool get_shareinfo(struct torture_context *tctx,
3009                           struct dcerpc_binding_handle *b,
3010                           const char *servername,
3011                           const char *share,
3012                           struct srvsvc_NetShareInfo502 **info502)
3013 {
3014         struct srvsvc_NetShareGetInfo r;
3015         union srvsvc_NetShareInfo info;
3016
3017         r.in.server_unc = talloc_asprintf(tctx, "\\\\%s", servername);
3018         r.in.share_name = share;
3019         r.in.level = 502;
3020         r.out.info = &info;
3021
3022         torture_assert_ntstatus_ok(tctx,
3023                 dcerpc_srvsvc_NetShareGetInfo_r(b, tctx, &r),
3024                 "srvsvc_NetShareGetInfo failed");
3025         torture_assert_werr_ok(tctx, r.out.result,
3026                 "srvsvc_NetShareGetInfo failed");
3027
3028         *info502 = talloc_move(tctx, &info.info502);
3029
3030         return true;
3031 }
3032
3033 /*
3034  * Get us a handle on HKLM\
3035  */
3036
3037 static bool get_hklm_handle(struct torture_context *tctx,
3038                             struct dcerpc_binding_handle *b,
3039                             struct policy_handle *handle)
3040 {
3041         struct winreg_OpenHKLM r;
3042         struct policy_handle result;
3043
3044         r.in.system_name = 0;
3045         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3046         r.out.handle = &result;
3047
3048         torture_assert_ntstatus_ok(tctx,
3049                 dcerpc_winreg_OpenHKLM_r(b, tctx, &r),
3050                 "OpenHKLM failed");
3051         torture_assert_werr_ok(tctx, r.out.result,
3052                 "OpenHKLM failed");
3053
3054         *handle = result;
3055
3056         return true;
3057 }
3058
3059 static bool torture_samba3_createshare(struct torture_context *tctx,
3060                                        struct dcerpc_binding_handle *b,
3061                                        const char *sharename)
3062 {
3063         struct policy_handle hklm;
3064         struct policy_handle new_handle;
3065         struct winreg_CreateKey c;
3066         struct winreg_CloseKey cl;
3067         enum winreg_CreateAction action_taken;
3068
3069         c.in.handle = &hklm;
3070         c.in.name.name = talloc_asprintf(
3071                 tctx, "software\\samba\\smbconf\\%s", sharename);
3072         torture_assert(tctx, c.in.name.name, "talloc_asprintf failed");
3073
3074         c.in.keyclass.name = "";
3075         c.in.options = 0;
3076         c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3077         c.in.secdesc = NULL;
3078         c.in.action_taken = &action_taken;
3079         c.out.new_handle = &new_handle;
3080         c.out.action_taken = &action_taken;
3081
3082         torture_assert_ntstatus_ok(tctx,
3083                 dcerpc_winreg_CreateKey_r(b, tctx, &c),
3084                 "OpenKey failed");
3085         torture_assert_werr_ok(tctx, c.out.result,
3086                 "OpenKey failed");
3087
3088         cl.in.handle = &new_handle;
3089         cl.out.handle = &new_handle;
3090
3091         torture_assert_ntstatus_ok(tctx,
3092                 dcerpc_winreg_CloseKey_r(b, tctx, &cl),
3093                 "CloseKey failed");
3094         torture_assert_werr_ok(tctx, cl.out.result,
3095                 "CloseKey failed");
3096
3097         return true;
3098 }
3099
3100 static bool torture_samba3_deleteshare(struct torture_context *tctx,
3101                                        struct dcerpc_binding_handle *b,
3102                                        const char *sharename)
3103 {
3104         struct policy_handle hklm;
3105         struct winreg_DeleteKey d;
3106
3107         torture_assert(tctx,
3108                 get_hklm_handle(tctx, b, &hklm),
3109                 "get_hklm_handle failed");
3110
3111         d.in.handle = &hklm;
3112         d.in.key.name = talloc_asprintf(
3113                 tctx, "software\\samba\\smbconf\\%s", sharename);
3114         torture_assert(tctx, d.in.key.name, "talloc_asprintf failed");
3115
3116         torture_assert_ntstatus_ok(tctx,
3117                 dcerpc_winreg_DeleteKey_r(b, tctx, &d),
3118                 "DeleteKey failed");
3119         torture_assert_werr_ok(tctx, d.out.result,
3120                 "DeleteKey failed");
3121
3122         return true;
3123 }
3124
3125 static bool torture_samba3_setconfig(struct torture_context *tctx,
3126                                      struct dcerpc_binding_handle *b,
3127                                      const char *sharename,
3128                                      const char *parameter,
3129                                      const char *value)
3130 {
3131         struct policy_handle hklm, key_handle;
3132         struct winreg_OpenKey o;
3133         struct winreg_SetValue s;
3134         uint32_t type;
3135         DATA_BLOB val;
3136
3137         torture_assert(tctx,
3138                 get_hklm_handle(tctx, b, &hklm),
3139                 "get_hklm_handle failed");
3140
3141         o.in.parent_handle = &hklm;
3142         o.in.keyname.name = talloc_asprintf(
3143                 tctx, "software\\samba\\smbconf\\%s", sharename);
3144         torture_assert(tctx, o.in.keyname.name, "talloc_asprintf failed");
3145
3146         o.in.options = 0;
3147         o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3148         o.out.handle = &key_handle;
3149
3150         torture_assert_ntstatus_ok(tctx,
3151                 dcerpc_winreg_OpenKey_r(b, tctx, &o),
3152                 "OpenKey failed");
3153         torture_assert_werr_ok(tctx, o.out.result,
3154                 "OpenKey failed");
3155
3156         torture_assert(tctx,
3157                 reg_string_to_val(tctx, "REG_SZ", value, &type, &val),
3158                 "reg_string_to_val failed");
3159
3160         s.in.handle = &key_handle;
3161         s.in.name.name = parameter;
3162         s.in.type = type;
3163         s.in.data = val.data;
3164         s.in.size = val.length;
3165
3166         torture_assert_ntstatus_ok(tctx,
3167                 dcerpc_winreg_SetValue_r(b, tctx, &s),
3168                 "SetValue failed");
3169         torture_assert_werr_ok(tctx, s.out.result,
3170                 "SetValue failed");
3171
3172         return true;
3173 }
3174
3175 static bool torture_samba3_regconfig(struct torture_context *torture)
3176 {
3177         struct srvsvc_NetShareInfo502 *i = NULL;
3178         const char *comment = "Dummer Kommentar";
3179         struct dcerpc_pipe *srvsvc_pipe, *winreg_pipe;
3180
3181         torture_assert_ntstatus_ok(torture,
3182                 torture_rpc_connection(torture, &srvsvc_pipe, &ndr_table_srvsvc),
3183                 "failed to setup srvsvc");
3184
3185         torture_assert_ntstatus_ok(torture,
3186                 torture_rpc_connection(torture, &winreg_pipe, &ndr_table_winreg),
3187                 "failed to setup winreg");
3188
3189         torture_assert(torture,
3190                 torture_samba3_createshare(torture, winreg_pipe->binding_handle, "blubber"),
3191                 "torture_samba3_createshare failed");
3192
3193         torture_assert(torture,
3194                 torture_samba3_setconfig(torture, winreg_pipe->binding_handle, "blubber", "comment", comment),
3195                 "torture_samba3_setconfig failed");
3196
3197         torture_assert(torture,
3198                 get_shareinfo(torture, srvsvc_pipe->binding_handle, dcerpc_server_name(srvsvc_pipe), "blubber", &i),
3199                 "get_shareinfo failed");
3200
3201         torture_assert_str_equal(torture, comment, i->comment,
3202                 "got unexpected comment");
3203
3204         torture_assert(torture,
3205                 torture_samba3_deleteshare(torture, winreg_pipe->binding_handle, "blubber"),
3206                 "torture_samba3_deleteshare failed");
3207
3208         return true;
3209 }
3210
3211 /*
3212  * Test that even with a result of 0 rids the array is returned as a
3213  * non-NULL pointer. Yes, XP does notice.
3214  */
3215
3216 bool torture_samba3_getaliasmembership_0(struct torture_context *torture)
3217 {
3218         struct dcerpc_pipe *p;
3219         struct dcerpc_binding_handle *b;
3220         struct samr_Connect2 c;
3221         struct samr_OpenDomain o;
3222         struct dom_sid sid;
3223         struct lsa_SidPtr ptr;
3224         struct lsa_SidArray sids;
3225         struct samr_GetAliasMembership g;
3226         struct samr_Ids rids;
3227         struct policy_handle samr, domain;
3228
3229         torture_assert_ntstatus_ok(torture,
3230                 torture_rpc_connection(torture, &p, &ndr_table_samr),
3231                 "failed to setup samr");
3232
3233         b = p->binding_handle;
3234
3235         c.in.system_name = NULL;
3236         c.in.access_mask = SAMR_ACCESS_LOOKUP_DOMAIN;
3237         c.out.connect_handle = &samr;
3238         torture_assert_ntstatus_ok(torture,
3239                 dcerpc_samr_Connect2_r(b, torture, &c),
3240                 "");
3241         torture_assert_ntstatus_ok(torture, c.out.result,
3242                 "");
3243         dom_sid_parse("S-1-5-32", &sid);
3244         o.in.connect_handle = &samr;
3245         o.in.access_mask = SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS;
3246         o.in.sid = &sid;
3247         o.out.domain_handle = &domain;
3248         torture_assert_ntstatus_ok(torture,
3249                 dcerpc_samr_OpenDomain_r(b, torture, &o),
3250                 "");
3251         torture_assert_ntstatus_ok(torture, o.out.result,
3252                 "");
3253         dom_sid_parse("S-1-2-3-4-5", &sid);
3254         ptr.sid = &sid;
3255         sids.num_sids = 1;
3256         sids.sids = &ptr;
3257         g.in.domain_handle = &domain;
3258         g.in.sids = &sids;
3259         g.out.rids = &rids;
3260         torture_assert_ntstatus_ok(torture,
3261                 dcerpc_samr_GetAliasMembership_r(b, torture, &g),
3262                 "");
3263         torture_assert_ntstatus_ok(torture, g.out.result,
3264                 "");
3265         if (rids.ids == NULL) {
3266                 /* This is the piece to test here */
3267                 torture_fail(torture,
3268                         "torture_samba3_getaliasmembership_0: "
3269                         "Server returns NULL rids array\n");
3270         }
3271
3272         return true;
3273 }
3274
3275 struct torture_suite *torture_rpc_samba3(TALLOC_CTX *mem_ctx)
3276 {
3277         struct torture_suite *suite = torture_suite_create(mem_ctx, "samba3");
3278
3279         torture_suite_add_simple_test(suite, "bind", torture_bind_samba3);
3280         torture_suite_add_simple_test(suite, "netlogon", torture_netlogon_samba3);
3281         torture_suite_add_simple_test(suite, "sessionkey", torture_samba3_sessionkey);
3282         torture_suite_add_simple_test(suite, "srvsvc", torture_samba3_rpc_srvsvc);
3283         torture_suite_add_simple_test(suite, "sharesec", torture_samba3_rpc_sharesec);
3284         torture_suite_add_simple_test(suite, "getusername", torture_samba3_rpc_getusername);
3285         torture_suite_add_simple_test(suite, "randomauth2", torture_samba3_rpc_randomauth2);
3286         torture_suite_add_simple_test(suite, "lsa", torture_samba3_rpc_lsa);
3287         torture_suite_add_simple_test(suite, "spoolss", torture_samba3_rpc_spoolss);
3288         torture_suite_add_simple_test(suite, "wkssvc", torture_samba3_rpc_wkssvc);
3289         torture_suite_add_simple_test(suite, "winreg", torture_samba3_rpc_winreg);
3290         torture_suite_add_simple_test(suite, "getaliasmembership-0", torture_samba3_getaliasmembership_0);
3291         torture_suite_add_simple_test(suite, "regconfig", torture_samba3_regconfig);
3292
3293         suite->description = talloc_strdup(suite, "samba3 DCERPC interface tests");
3294
3295         return suite;
3296 }