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