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