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