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