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