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