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