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