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