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