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