• 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/source3/lib/netapi/
1/*
2 *  Unix SMB/CIFS implementation.
3 *  NetApi User Support
4 *  Copyright (C) Guenther Deschner 2008
5 *
6 *  This program is free software; you can redistribute it and/or modify
7 *  it under the terms of the GNU General Public License as published by
8 *  the Free Software Foundation; either version 3 of the License, or
9 *  (at your option) any later version.
10 *
11 *  This program is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *  GNU General Public License for more details.
15 *
16 *  You should have received a copy of the GNU General Public License
17 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "includes.h"
21
22#include "librpc/gen_ndr/libnetapi.h"
23#include "lib/netapi/netapi.h"
24#include "lib/netapi/netapi_private.h"
25#include "lib/netapi/libnetapi.h"
26#include "../librpc/gen_ndr/cli_samr.h"
27
28/****************************************************************
29****************************************************************/
30
31static void convert_USER_INFO_X_to_samr_user_info21(struct USER_INFO_X *infoX,
32						    struct samr_UserInfo21 *info21)
33{
34	uint32_t fields_present = 0;
35	struct samr_LogonHours zero_logon_hours;
36	struct lsa_BinaryString zero_parameters;
37	NTTIME password_age;
38
39	ZERO_STRUCTP(info21);
40	ZERO_STRUCT(zero_logon_hours);
41	ZERO_STRUCT(zero_parameters);
42
43	if (infoX->usriX_flags) {
44		fields_present |= SAMR_FIELD_ACCT_FLAGS;
45	}
46	if (infoX->usriX_name) {
47		fields_present |= SAMR_FIELD_ACCOUNT_NAME;
48	}
49	if (infoX->usriX_password) {
50		fields_present |= SAMR_FIELD_NT_PASSWORD_PRESENT;
51	}
52	if (infoX->usriX_flags) {
53		fields_present |= SAMR_FIELD_ACCT_FLAGS;
54	}
55	if (infoX->usriX_home_dir) {
56		fields_present |= SAMR_FIELD_HOME_DIRECTORY;
57	}
58	if (infoX->usriX_script_path) {
59		fields_present |= SAMR_FIELD_LOGON_SCRIPT;
60	}
61	if (infoX->usriX_comment) {
62		fields_present |= SAMR_FIELD_DESCRIPTION;
63	}
64	if (infoX->usriX_password_age) {
65		fields_present |= SAMR_FIELD_FORCE_PWD_CHANGE;
66	}
67	if (infoX->usriX_full_name) {
68		fields_present |= SAMR_FIELD_FULL_NAME;
69	}
70	if (infoX->usriX_usr_comment) {
71		fields_present |= SAMR_FIELD_COMMENT;
72	}
73	if (infoX->usriX_profile) {
74		fields_present |= SAMR_FIELD_PROFILE_PATH;
75	}
76	if (infoX->usriX_home_dir_drive) {
77		fields_present |= SAMR_FIELD_HOME_DRIVE;
78	}
79	if (infoX->usriX_primary_group_id) {
80		fields_present |= SAMR_FIELD_PRIMARY_GID;
81	}
82	if (infoX->usriX_country_code) {
83		fields_present |= SAMR_FIELD_COUNTRY_CODE;
84	}
85	if (infoX->usriX_workstations) {
86		fields_present |= SAMR_FIELD_WORKSTATIONS;
87	}
88
89	unix_to_nt_time_abs(&password_age, infoX->usriX_password_age);
90
91	/* TODO: infoX->usriX_priv */
92
93	info21->last_logon		= 0;
94	info21->last_logoff		= 0;
95	info21->last_password_change	= 0;
96	info21->acct_expiry		= 0;
97	info21->allow_password_change	= 0;
98	info21->force_password_change	= 0;
99	info21->account_name.string	= infoX->usriX_name;
100	info21->full_name.string	= infoX->usriX_full_name;
101	info21->home_directory.string	= infoX->usriX_home_dir;
102	info21->home_drive.string	= infoX->usriX_home_dir_drive;
103	info21->logon_script.string	= infoX->usriX_script_path;
104	info21->profile_path.string	= infoX->usriX_profile;
105	info21->description.string	= infoX->usriX_comment;
106	info21->workstations.string	= infoX->usriX_workstations;
107	info21->comment.string		= infoX->usriX_usr_comment;
108	info21->parameters		= zero_parameters;
109	info21->lm_owf_password		= zero_parameters;
110	info21->nt_owf_password		= zero_parameters;
111	info21->unknown3.string		= NULL;
112	info21->buf_count		= 0;
113	info21->buffer			= NULL;
114	info21->rid			= infoX->usriX_user_id;
115	info21->primary_gid		= infoX->usriX_primary_group_id;
116	info21->acct_flags		= infoX->usriX_flags;
117	info21->fields_present		= fields_present;
118	info21->logon_hours		= zero_logon_hours;
119	info21->bad_password_count	= infoX->usriX_bad_pw_count;
120	info21->logon_count		= infoX->usriX_num_logons;
121	info21->country_code		= infoX->usriX_country_code;
122	info21->code_page		= infoX->usriX_code_page;
123	info21->lm_password_set		= 0;
124	info21->nt_password_set		= 0;
125	info21->password_expired	= infoX->usriX_password_expired;
126	info21->unknown4		= 0;
127}
128
129/****************************************************************
130****************************************************************/
131
132static NTSTATUS construct_USER_INFO_X(uint32_t level,
133				      uint8_t *buffer,
134				      struct USER_INFO_X *uX)
135{
136	struct USER_INFO_0 *u0 = NULL;
137	struct USER_INFO_1 *u1 = NULL;
138	struct USER_INFO_2 *u2 = NULL;
139	struct USER_INFO_3 *u3 = NULL;
140	struct USER_INFO_1003 *u1003 = NULL;
141	struct USER_INFO_1006 *u1006 = NULL;
142	struct USER_INFO_1007 *u1007 = NULL;
143	struct USER_INFO_1009 *u1009 = NULL;
144	struct USER_INFO_1011 *u1011 = NULL;
145	struct USER_INFO_1012 *u1012 = NULL;
146	struct USER_INFO_1014 *u1014 = NULL;
147	struct USER_INFO_1024 *u1024 = NULL;
148	struct USER_INFO_1051 *u1051 = NULL;
149	struct USER_INFO_1052 *u1052 = NULL;
150	struct USER_INFO_1053 *u1053 = NULL;
151
152	if (!buffer || !uX) {
153		return NT_STATUS_INVALID_PARAMETER;
154	}
155
156	ZERO_STRUCTP(uX);
157
158	switch (level) {
159		case 0:
160			u0 = (struct USER_INFO_0 *)buffer;
161			uX->usriX_name		= u0->usri0_name;
162			break;
163		case 1:
164			u1 = (struct USER_INFO_1 *)buffer;
165			uX->usriX_name		= u1->usri1_name;
166			uX->usriX_password	= u1->usri1_password;
167			uX->usriX_password_age	= u1->usri1_password_age;
168			uX->usriX_priv		= u1->usri1_priv;
169			uX->usriX_home_dir	= u1->usri1_home_dir;
170			uX->usriX_comment	= u1->usri1_comment;
171			uX->usriX_flags		= u1->usri1_flags;
172			uX->usriX_script_path	= u1->usri1_script_path;
173			break;
174		case 2:
175			u2 = (struct USER_INFO_2 *)buffer;
176			uX->usriX_name		= u2->usri2_name;
177			uX->usriX_password	= u2->usri2_password;
178			uX->usriX_password_age	= u2->usri2_password_age;
179			uX->usriX_priv		= u2->usri2_priv;
180			uX->usriX_home_dir	= u2->usri2_home_dir;
181			uX->usriX_comment	= u2->usri2_comment;
182			uX->usriX_flags		= u2->usri2_flags;
183			uX->usriX_script_path	= u2->usri2_script_path;
184			uX->usriX_auth_flags	= u2->usri2_auth_flags;
185			uX->usriX_full_name	= u2->usri2_full_name;
186			uX->usriX_usr_comment	= u2->usri2_usr_comment;
187			uX->usriX_parms		= u2->usri2_parms;
188			uX->usriX_workstations	= u2->usri2_workstations;
189			uX->usriX_last_logon	= u2->usri2_last_logon;
190			uX->usriX_last_logoff	= u2->usri2_last_logoff;
191			uX->usriX_acct_expires	= u2->usri2_acct_expires;
192			uX->usriX_max_storage	= u2->usri2_max_storage;
193			uX->usriX_units_per_week= u2->usri2_units_per_week;
194			uX->usriX_logon_hours	= u2->usri2_logon_hours;
195			uX->usriX_bad_pw_count	= u2->usri2_bad_pw_count;
196			uX->usriX_num_logons	= u2->usri2_num_logons;
197			uX->usriX_logon_server	= u2->usri2_logon_server;
198			uX->usriX_country_code	= u2->usri2_country_code;
199			uX->usriX_code_page	= u2->usri2_code_page;
200			break;
201		case 3:
202			u3 = (struct USER_INFO_3 *)buffer;
203			uX->usriX_name		= u3->usri3_name;
204			uX->usriX_password_age	= u3->usri3_password_age;
205			uX->usriX_priv		= u3->usri3_priv;
206			uX->usriX_home_dir	= u3->usri3_home_dir;
207			uX->usriX_comment	= u3->usri3_comment;
208			uX->usriX_flags		= u3->usri3_flags;
209			uX->usriX_script_path	= u3->usri3_script_path;
210			uX->usriX_auth_flags	= u3->usri3_auth_flags;
211			uX->usriX_full_name	= u3->usri3_full_name;
212			uX->usriX_usr_comment	= u3->usri3_usr_comment;
213			uX->usriX_parms		= u3->usri3_parms;
214			uX->usriX_workstations	= u3->usri3_workstations;
215			uX->usriX_last_logon	= u3->usri3_last_logon;
216			uX->usriX_last_logoff	= u3->usri3_last_logoff;
217			uX->usriX_acct_expires	= u3->usri3_acct_expires;
218			uX->usriX_max_storage	= u3->usri3_max_storage;
219			uX->usriX_units_per_week= u3->usri3_units_per_week;
220			uX->usriX_logon_hours	= u3->usri3_logon_hours;
221			uX->usriX_bad_pw_count	= u3->usri3_bad_pw_count;
222			uX->usriX_num_logons	= u3->usri3_num_logons;
223			uX->usriX_logon_server	= u3->usri3_logon_server;
224			uX->usriX_country_code	= u3->usri3_country_code;
225			uX->usriX_code_page	= u3->usri3_code_page;
226			uX->usriX_user_id	= u3->usri3_user_id;
227			uX->usriX_primary_group_id = u3->usri3_primary_group_id;
228			uX->usriX_profile	= u3->usri3_profile;
229			uX->usriX_home_dir_drive = u3->usri3_home_dir_drive;
230			uX->usriX_password_expired = u3->usri3_password_expired;
231			break;
232		case 1003:
233			u1003 = (struct USER_INFO_1003 *)buffer;
234			uX->usriX_password	= u1003->usri1003_password;
235			break;
236		case 1006:
237			u1006 = (struct USER_INFO_1006 *)buffer;
238			uX->usriX_home_dir	= u1006->usri1006_home_dir;
239			break;
240		case 1007:
241			u1007 = (struct USER_INFO_1007 *)buffer;
242			uX->usriX_comment	= u1007->usri1007_comment;
243			break;
244		case 1009:
245			u1009 = (struct USER_INFO_1009 *)buffer;
246			uX->usriX_script_path	= u1009->usri1009_script_path;
247			break;
248		case 1011:
249			u1011 = (struct USER_INFO_1011 *)buffer;
250			uX->usriX_full_name	= u1011->usri1011_full_name;
251			break;
252		case 1012:
253			u1012 = (struct USER_INFO_1012 *)buffer;
254			uX->usriX_usr_comment	= u1012->usri1012_usr_comment;
255			break;
256		case 1014:
257			u1014 = (struct USER_INFO_1014 *)buffer;
258			uX->usriX_workstations	= u1014->usri1014_workstations;
259			break;
260		case 1024:
261			u1024 = (struct USER_INFO_1024 *)buffer;
262			uX->usriX_country_code	= u1024->usri1024_country_code;
263			break;
264		case 1051:
265			u1051 = (struct USER_INFO_1051 *)buffer;
266			uX->usriX_primary_group_id = u1051->usri1051_primary_group_id;
267			break;
268		case 1052:
269			u1052 = (struct USER_INFO_1052 *)buffer;
270			uX->usriX_profile	= u1052->usri1052_profile;
271			break;
272		case 1053:
273			u1053 = (struct USER_INFO_1053 *)buffer;
274			uX->usriX_home_dir_drive = u1053->usri1053_home_dir_drive;
275			break;
276		case 4:
277		default:
278			return NT_STATUS_INVALID_INFO_CLASS;
279	}
280
281	return NT_STATUS_OK;
282}
283
284/****************************************************************
285****************************************************************/
286
287static NTSTATUS set_user_info_USER_INFO_X(TALLOC_CTX *ctx,
288					  struct rpc_pipe_client *pipe_cli,
289					  DATA_BLOB *session_key,
290					  struct policy_handle *user_handle,
291					  struct USER_INFO_X *uX)
292{
293	union samr_UserInfo user_info;
294	struct samr_UserInfo21 info21;
295	NTSTATUS status;
296
297	if (!uX) {
298		return NT_STATUS_INVALID_PARAMETER;
299	}
300
301	convert_USER_INFO_X_to_samr_user_info21(uX, &info21);
302
303	ZERO_STRUCT(user_info);
304
305	if (uX->usriX_password) {
306
307		user_info.info25.info = info21;
308
309		init_samr_CryptPasswordEx(uX->usriX_password,
310					  session_key,
311					  &user_info.info25.password);
312
313		status = rpccli_samr_SetUserInfo2(pipe_cli, talloc_tos(),
314						  user_handle,
315						  25,
316						  &user_info);
317
318		if (NT_STATUS_EQUAL(status, NT_STATUS(DCERPC_FAULT_INVALID_TAG))) {
319
320			user_info.info23.info = info21;
321
322			init_samr_CryptPassword(uX->usriX_password,
323						session_key,
324						&user_info.info23.password);
325
326			status = rpccli_samr_SetUserInfo2(pipe_cli, talloc_tos(),
327							  user_handle,
328							  23,
329							  &user_info);
330		}
331	} else {
332
333		user_info.info21 = info21;
334
335		status = rpccli_samr_SetUserInfo(pipe_cli, talloc_tos(),
336						 user_handle,
337						 21,
338						 &user_info);
339	}
340
341	return status;
342}
343
344/****************************************************************
345****************************************************************/
346
347WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
348		    struct NetUserAdd *r)
349{
350	struct rpc_pipe_client *pipe_cli = NULL;
351	NTSTATUS status;
352	WERROR werr;
353	struct policy_handle connect_handle, domain_handle, user_handle;
354	struct lsa_String lsa_account_name;
355	struct dom_sid2 *domain_sid = NULL;
356	union samr_UserInfo *user_info = NULL;
357	struct samr_PwInfo pw_info;
358	uint32_t access_granted = 0;
359	uint32_t rid = 0;
360	struct USER_INFO_X uX;
361
362	ZERO_STRUCT(connect_handle);
363	ZERO_STRUCT(domain_handle);
364	ZERO_STRUCT(user_handle);
365
366	if (!r->in.buffer) {
367		return WERR_INVALID_PARAM;
368	}
369
370	switch (r->in.level) {
371		case 1:
372			break;
373		case 2:
374		case 3:
375		case 4:
376		default:
377			werr = WERR_NOT_SUPPORTED;
378			goto done;
379	}
380
381	werr = libnetapi_open_pipe(ctx, r->in.server_name,
382				   &ndr_table_samr.syntax_id,
383				   &pipe_cli);
384	if (!W_ERROR_IS_OK(werr)) {
385		goto done;
386	}
387
388	status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
389	if (!NT_STATUS_IS_OK(status)) {
390		werr = ntstatus_to_werror(status);
391		goto done;
392	}
393
394	werr = libnetapi_samr_open_domain(ctx, pipe_cli,
395					  SAMR_ACCESS_ENUM_DOMAINS |
396					  SAMR_ACCESS_LOOKUP_DOMAIN,
397					  SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
398					  SAMR_DOMAIN_ACCESS_CREATE_USER |
399					  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
400					  &connect_handle,
401					  &domain_handle,
402					  &domain_sid);
403	if (!W_ERROR_IS_OK(werr)) {
404		goto done;
405	}
406
407	init_lsa_String(&lsa_account_name, uX.usriX_name);
408
409	status = rpccli_samr_CreateUser2(pipe_cli, talloc_tos(),
410					 &domain_handle,
411					 &lsa_account_name,
412					 ACB_NORMAL,
413					 SEC_STD_WRITE_DAC |
414					 SEC_STD_DELETE |
415					 SAMR_USER_ACCESS_SET_PASSWORD |
416					 SAMR_USER_ACCESS_SET_ATTRIBUTES |
417					 SAMR_USER_ACCESS_GET_ATTRIBUTES,
418					 &user_handle,
419					 &access_granted,
420					 &rid);
421	if (!NT_STATUS_IS_OK(status)) {
422		werr = ntstatus_to_werror(status);
423		goto done;
424	}
425
426	status = rpccli_samr_QueryUserInfo(pipe_cli, talloc_tos(),
427					   &user_handle,
428					   16,
429					   &user_info);
430	if (!NT_STATUS_IS_OK(status)) {
431		werr = ntstatus_to_werror(status);
432		goto done;
433	}
434
435	if (!(user_info->info16.acct_flags & ACB_NORMAL)) {
436		werr = WERR_INVALID_PARAM;
437		goto done;
438	}
439
440	status = rpccli_samr_GetUserPwInfo(pipe_cli, talloc_tos(),
441					   &user_handle,
442					   &pw_info);
443	if (!NT_STATUS_IS_OK(status)) {
444		werr = ntstatus_to_werror(status);
445		goto done;
446	}
447
448	uX.usriX_flags |= ACB_NORMAL;
449
450	status = set_user_info_USER_INFO_X(ctx, pipe_cli,
451					   &pipe_cli->auth->user_session_key,
452					   &user_handle,
453					   &uX);
454	if (!NT_STATUS_IS_OK(status)) {
455		werr = ntstatus_to_werror(status);
456		goto failed;
457	}
458
459	werr = WERR_OK;
460	goto done;
461
462 failed:
463	rpccli_samr_DeleteUser(pipe_cli, talloc_tos(),
464			       &user_handle);
465
466 done:
467	if (is_valid_policy_hnd(&user_handle) && pipe_cli) {
468		rpccli_samr_Close(pipe_cli, talloc_tos(), &user_handle);
469	}
470
471	if (ctx->disable_policy_handle_cache) {
472		libnetapi_samr_close_domain_handle(ctx, &domain_handle);
473		libnetapi_samr_close_connect_handle(ctx, &connect_handle);
474	}
475
476	return werr;
477}
478
479/****************************************************************
480****************************************************************/
481
482WERROR NetUserAdd_l(struct libnetapi_ctx *ctx,
483		    struct NetUserAdd *r)
484{
485	LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserAdd);
486}
487
488/****************************************************************
489****************************************************************/
490
491WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
492		    struct NetUserDel *r)
493{
494	struct rpc_pipe_client *pipe_cli = NULL;
495	NTSTATUS status;
496	WERROR werr;
497	struct policy_handle connect_handle, builtin_handle, domain_handle, user_handle;
498	struct lsa_String lsa_account_name;
499	struct samr_Ids user_rids, name_types;
500	struct dom_sid2 *domain_sid = NULL;
501	struct dom_sid2 user_sid;
502
503	ZERO_STRUCT(connect_handle);
504	ZERO_STRUCT(builtin_handle);
505	ZERO_STRUCT(domain_handle);
506	ZERO_STRUCT(user_handle);
507
508	werr = libnetapi_open_pipe(ctx, r->in.server_name,
509				   &ndr_table_samr.syntax_id,
510				   &pipe_cli);
511
512	if (!W_ERROR_IS_OK(werr)) {
513		goto done;
514	}
515
516	werr = libnetapi_samr_open_domain(ctx, pipe_cli,
517					  SAMR_ACCESS_ENUM_DOMAINS |
518					  SAMR_ACCESS_LOOKUP_DOMAIN,
519					  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
520					  &connect_handle,
521					  &domain_handle,
522					  &domain_sid);
523	if (!W_ERROR_IS_OK(werr)) {
524		goto done;
525	}
526
527	status = rpccli_samr_OpenDomain(pipe_cli, talloc_tos(),
528					&connect_handle,
529					SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
530					CONST_DISCARD(DOM_SID *, &global_sid_Builtin),
531					&builtin_handle);
532	if (!NT_STATUS_IS_OK(status)) {
533		werr = ntstatus_to_werror(status);
534		goto done;
535	}
536
537	init_lsa_String(&lsa_account_name, r->in.user_name);
538
539	status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
540					 &domain_handle,
541					 1,
542					 &lsa_account_name,
543					 &user_rids,
544					 &name_types);
545	if (!NT_STATUS_IS_OK(status)) {
546		werr = ntstatus_to_werror(status);
547		goto done;
548	}
549
550	status = rpccli_samr_OpenUser(pipe_cli, talloc_tos(),
551				      &domain_handle,
552				      SEC_STD_DELETE,
553				      user_rids.ids[0],
554				      &user_handle);
555	if (!NT_STATUS_IS_OK(status)) {
556		werr = ntstatus_to_werror(status);
557		goto done;
558	}
559
560	sid_compose(&user_sid, domain_sid, user_rids.ids[0]);
561
562	status = rpccli_samr_RemoveMemberFromForeignDomain(pipe_cli, talloc_tos(),
563							   &builtin_handle,
564							   &user_sid);
565	if (!NT_STATUS_IS_OK(status)) {
566		werr = ntstatus_to_werror(status);
567		goto done;
568	}
569
570	status = rpccli_samr_DeleteUser(pipe_cli, talloc_tos(),
571					&user_handle);
572	if (!NT_STATUS_IS_OK(status)) {
573		werr = ntstatus_to_werror(status);
574		goto done;
575	}
576
577	werr = WERR_OK;
578
579 done:
580	if (is_valid_policy_hnd(&user_handle)) {
581		rpccli_samr_Close(pipe_cli, talloc_tos(), &user_handle);
582	}
583
584	if (ctx->disable_policy_handle_cache) {
585		libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
586		libnetapi_samr_close_domain_handle(ctx, &domain_handle);
587		libnetapi_samr_close_connect_handle(ctx, &connect_handle);
588	}
589
590	return werr;
591}
592
593/****************************************************************
594****************************************************************/
595
596WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
597		    struct NetUserDel *r)
598{
599	LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserDel);
600}
601
602/****************************************************************
603****************************************************************/
604
605static NTSTATUS libnetapi_samr_lookup_user(TALLOC_CTX *mem_ctx,
606					   struct rpc_pipe_client *pipe_cli,
607					   struct policy_handle *domain_handle,
608					   struct policy_handle *builtin_handle,
609					   const char *user_name,
610					   const struct dom_sid *domain_sid,
611					   uint32_t rid,
612					   uint32_t level,
613					   struct samr_UserInfo21 **info21,
614					   struct sec_desc_buf **sec_desc,
615					   uint32_t *auth_flag_p)
616{
617	NTSTATUS status;
618
619	struct policy_handle user_handle;
620	union samr_UserInfo *user_info = NULL;
621	struct samr_RidWithAttributeArray *rid_array = NULL;
622	uint32_t access_mask = SEC_STD_READ_CONTROL |
623			       SAMR_USER_ACCESS_GET_ATTRIBUTES |
624			       SAMR_USER_ACCESS_GET_NAME_ETC;
625
626	ZERO_STRUCT(user_handle);
627
628	switch (level) {
629		case 0:
630			break;
631		case 1:
632			access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
633				       SAMR_USER_ACCESS_GET_GROUPS;
634			break;
635		case 2:
636		case 3:
637		case 4:
638		case 11:
639			access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
640				       SAMR_USER_ACCESS_GET_GROUPS |
641				       SAMR_USER_ACCESS_GET_LOCALE;
642			break;
643		case 10:
644		case 20:
645		case 23:
646			break;
647		default:
648			return NT_STATUS_INVALID_LEVEL;
649	}
650
651	if (level == 0) {
652		return NT_STATUS_OK;
653	}
654
655	status = rpccli_samr_OpenUser(pipe_cli, mem_ctx,
656				      domain_handle,
657				      access_mask,
658				      rid,
659				      &user_handle);
660	if (!NT_STATUS_IS_OK(status)) {
661		goto done;
662	}
663
664	status = rpccli_samr_QueryUserInfo(pipe_cli, mem_ctx,
665					   &user_handle,
666					   21,
667					   &user_info);
668	if (!NT_STATUS_IS_OK(status)) {
669		goto done;
670	}
671
672	status = rpccli_samr_QuerySecurity(pipe_cli, mem_ctx,
673					   &user_handle,
674					   SECINFO_DACL,
675					   sec_desc);
676	if (!NT_STATUS_IS_OK(status)) {
677		goto done;
678	}
679
680	if (access_mask & SAMR_USER_ACCESS_GET_GROUPS) {
681
682		struct lsa_SidArray sid_array;
683		struct samr_Ids alias_rids;
684		int i;
685		uint32_t auth_flag = 0;
686		struct dom_sid sid;
687
688		status = rpccli_samr_GetGroupsForUser(pipe_cli, mem_ctx,
689						      &user_handle,
690						      &rid_array);
691		if (!NT_STATUS_IS_OK(status)) {
692			goto done;
693		}
694
695		sid_array.num_sids = rid_array->count + 1;
696		sid_array.sids = talloc_array(mem_ctx, struct lsa_SidPtr,
697					      sid_array.num_sids);
698		NT_STATUS_HAVE_NO_MEMORY(sid_array.sids);
699
700		for (i=0; i<rid_array->count; i++) {
701			sid_compose(&sid, domain_sid, rid_array->rids[i].rid);
702			sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sid);
703			NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
704		}
705
706		sid_compose(&sid, domain_sid, rid);
707		sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sid);
708		NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
709
710		status = rpccli_samr_GetAliasMembership(pipe_cli, mem_ctx,
711							builtin_handle,
712							&sid_array,
713							&alias_rids);
714		if (!NT_STATUS_IS_OK(status)) {
715			goto done;
716		}
717
718		for (i=0; i<alias_rids.count; i++) {
719			switch (alias_rids.ids[i]) {
720				case 550: /* Print Operators */
721					auth_flag |= AF_OP_PRINT;
722					break;
723				case 549: /* Server Operators */
724					auth_flag |= AF_OP_SERVER;
725					break;
726				case 548: /* Account Operators */
727					auth_flag |= AF_OP_ACCOUNTS;
728					break;
729				default:
730					break;
731			}
732		}
733
734		if (auth_flag_p) {
735			*auth_flag_p = auth_flag;
736		}
737	}
738
739	*info21 = &user_info->info21;
740
741 done:
742	if (is_valid_policy_hnd(&user_handle)) {
743		rpccli_samr_Close(pipe_cli, mem_ctx, &user_handle);
744	}
745
746	return status;
747}
748
749/****************************************************************
750****************************************************************/
751
752static uint32_t samr_rid_to_priv_level(uint32_t rid)
753{
754	switch (rid) {
755		case DOMAIN_RID_ADMINISTRATOR:
756			return USER_PRIV_ADMIN;
757		case DOMAIN_RID_GUEST:
758			return USER_PRIV_GUEST;
759		default:
760			return USER_PRIV_USER;
761	}
762}
763
764/****************************************************************
765****************************************************************/
766
767static uint32_t samr_acb_flags_to_netapi_flags(uint32_t acb)
768{
769	uint32_t fl = UF_SCRIPT; /* god knows why */
770
771	fl |= ds_acb2uf(acb);
772
773	return fl;
774}
775
776/****************************************************************
777****************************************************************/
778
779static NTSTATUS info21_to_USER_INFO_1(TALLOC_CTX *mem_ctx,
780				      const struct samr_UserInfo21 *i21,
781				      struct USER_INFO_1 *i)
782{
783	ZERO_STRUCTP(i);
784	i->usri1_name		= talloc_strdup(mem_ctx, i21->account_name.string);
785	NT_STATUS_HAVE_NO_MEMORY(i->usri1_name);
786	i->usri1_password	= NULL;
787	i->usri1_password_age	= time(NULL) - nt_time_to_unix(i21->last_password_change);
788	i->usri1_priv		= samr_rid_to_priv_level(i21->rid);
789	i->usri1_home_dir	= talloc_strdup(mem_ctx, i21->home_directory.string);
790	i->usri1_comment	= talloc_strdup(mem_ctx, i21->description.string);
791	i->usri1_flags		= samr_acb_flags_to_netapi_flags(i21->acct_flags);
792	i->usri1_script_path	= talloc_strdup(mem_ctx, i21->logon_script.string);
793
794	return NT_STATUS_OK;
795}
796
797/****************************************************************
798****************************************************************/
799
800static NTSTATUS info21_to_USER_INFO_2(TALLOC_CTX *mem_ctx,
801				      const struct samr_UserInfo21 *i21,
802				      uint32_t auth_flag,
803				      struct USER_INFO_2 *i)
804{
805	ZERO_STRUCTP(i);
806
807	i->usri2_name		= talloc_strdup(mem_ctx, i21->account_name.string);
808	NT_STATUS_HAVE_NO_MEMORY(i->usri2_name);
809	i->usri2_password	= NULL;
810	i->usri2_password_age	= time(NULL) - nt_time_to_unix(i21->last_password_change);
811	i->usri2_priv		= samr_rid_to_priv_level(i21->rid);
812	i->usri2_home_dir	= talloc_strdup(mem_ctx, i21->home_directory.string);
813	i->usri2_comment	= talloc_strdup(mem_ctx, i21->description.string);
814	i->usri2_flags		= samr_acb_flags_to_netapi_flags(i21->acct_flags);
815	i->usri2_script_path	= talloc_strdup(mem_ctx, i21->logon_script.string);
816	i->usri2_auth_flags	= auth_flag;
817	i->usri2_full_name	= talloc_strdup(mem_ctx, i21->full_name.string);
818	i->usri2_usr_comment	= talloc_strdup(mem_ctx, i21->comment.string);
819	i->usri2_parms		= talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
820	i->usri2_workstations	= talloc_strdup(mem_ctx, i21->workstations.string);
821	i->usri2_last_logon	= nt_time_to_unix(i21->last_logon);
822	i->usri2_last_logoff	= nt_time_to_unix(i21->last_logoff);
823	i->usri2_acct_expires	= nt_time_to_unix(i21->acct_expiry);
824	i->usri2_max_storage	= USER_MAXSTORAGE_UNLIMITED; /* FIXME */
825	i->usri2_units_per_week	= i21->logon_hours.units_per_week;
826	i->usri2_logon_hours	= (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
827	i->usri2_bad_pw_count	= i21->bad_password_count;
828	i->usri2_num_logons	= i21->logon_count;
829	i->usri2_logon_server	= talloc_strdup(mem_ctx, "\\\\*");
830	i->usri2_country_code	= i21->country_code;
831	i->usri2_code_page	= i21->code_page;
832
833	return NT_STATUS_OK;
834}
835
836/****************************************************************
837****************************************************************/
838
839static NTSTATUS info21_to_USER_INFO_3(TALLOC_CTX *mem_ctx,
840				      const struct samr_UserInfo21 *i21,
841				      uint32_t auth_flag,
842				      struct USER_INFO_3 *i)
843{
844	ZERO_STRUCTP(i);
845
846	i->usri3_name		= talloc_strdup(mem_ctx, i21->account_name.string);
847	NT_STATUS_HAVE_NO_MEMORY(i->usri3_name);
848	i->usri3_password_age	= time(NULL) - nt_time_to_unix(i21->last_password_change);
849	i->usri3_priv		= samr_rid_to_priv_level(i21->rid);
850	i->usri3_home_dir	= talloc_strdup(mem_ctx, i21->home_directory.string);
851	i->usri3_comment	= talloc_strdup(mem_ctx, i21->description.string);
852	i->usri3_flags		= samr_acb_flags_to_netapi_flags(i21->acct_flags);
853	i->usri3_script_path	= talloc_strdup(mem_ctx, i21->logon_script.string);
854	i->usri3_auth_flags	= auth_flag;
855	i->usri3_full_name	= talloc_strdup(mem_ctx, i21->full_name.string);
856	i->usri3_usr_comment	= talloc_strdup(mem_ctx, i21->comment.string);
857	i->usri3_parms		= talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
858	i->usri3_workstations	= talloc_strdup(mem_ctx, i21->workstations.string);
859	i->usri3_last_logon	= nt_time_to_unix(i21->last_logon);
860	i->usri3_last_logoff	= nt_time_to_unix(i21->last_logoff);
861	i->usri3_acct_expires	= nt_time_to_unix(i21->acct_expiry);
862	i->usri3_max_storage	= USER_MAXSTORAGE_UNLIMITED; /* FIXME */
863	i->usri3_units_per_week	= i21->logon_hours.units_per_week;
864	i->usri3_logon_hours	= (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
865	i->usri3_bad_pw_count	= i21->bad_password_count;
866	i->usri3_num_logons	= i21->logon_count;
867	i->usri3_logon_server	= talloc_strdup(mem_ctx, "\\\\*");
868	i->usri3_country_code	= i21->country_code;
869	i->usri3_code_page	= i21->code_page;
870	i->usri3_user_id	= i21->rid;
871	i->usri3_primary_group_id = i21->primary_gid;
872	i->usri3_profile	= talloc_strdup(mem_ctx, i21->profile_path.string);
873	i->usri3_home_dir_drive	= talloc_strdup(mem_ctx, i21->home_drive.string);
874	i->usri3_password_expired = i21->password_expired;
875
876	return NT_STATUS_OK;
877}
878
879/****************************************************************
880****************************************************************/
881
882static NTSTATUS info21_to_USER_INFO_4(TALLOC_CTX *mem_ctx,
883				      const struct samr_UserInfo21 *i21,
884				      uint32_t auth_flag,
885				      struct dom_sid *domain_sid,
886				      struct USER_INFO_4 *i)
887{
888	struct dom_sid sid;
889
890	ZERO_STRUCTP(i);
891
892	i->usri4_name		= talloc_strdup(mem_ctx, i21->account_name.string);
893	NT_STATUS_HAVE_NO_MEMORY(i->usri4_name);
894	i->usri4_password_age	= time(NULL) - nt_time_to_unix(i21->last_password_change);
895	i->usri4_password	= NULL;
896	i->usri4_priv		= samr_rid_to_priv_level(i21->rid);
897	i->usri4_home_dir	= talloc_strdup(mem_ctx, i21->home_directory.string);
898	i->usri4_comment	= talloc_strdup(mem_ctx, i21->description.string);
899	i->usri4_flags		= samr_acb_flags_to_netapi_flags(i21->acct_flags);
900	i->usri4_script_path	= talloc_strdup(mem_ctx, i21->logon_script.string);
901	i->usri4_auth_flags	= auth_flag;
902	i->usri4_full_name	= talloc_strdup(mem_ctx, i21->full_name.string);
903	i->usri4_usr_comment	= talloc_strdup(mem_ctx, i21->comment.string);
904	i->usri4_parms		= talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
905	i->usri4_workstations	= talloc_strdup(mem_ctx, i21->workstations.string);
906	i->usri4_last_logon	= nt_time_to_unix(i21->last_logon);
907	i->usri4_last_logoff	= nt_time_to_unix(i21->last_logoff);
908	i->usri4_acct_expires	= nt_time_to_unix(i21->acct_expiry);
909	i->usri4_max_storage	= USER_MAXSTORAGE_UNLIMITED; /* FIXME */
910	i->usri4_units_per_week	= i21->logon_hours.units_per_week;
911	i->usri4_logon_hours	= (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
912	i->usri4_bad_pw_count	= i21->bad_password_count;
913	i->usri4_num_logons	= i21->logon_count;
914	i->usri4_logon_server	= talloc_strdup(mem_ctx, "\\\\*");
915	i->usri4_country_code	= i21->country_code;
916	i->usri4_code_page	= i21->code_page;
917	if (!sid_compose(&sid, domain_sid, i21->rid)) {
918		return NT_STATUS_NO_MEMORY;
919	}
920	i->usri4_user_sid	= (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
921	i->usri4_primary_group_id = i21->primary_gid;
922	i->usri4_profile	= talloc_strdup(mem_ctx, i21->profile_path.string);
923	i->usri4_home_dir_drive	= talloc_strdup(mem_ctx, i21->home_drive.string);
924	i->usri4_password_expired = i21->password_expired;
925
926	return NT_STATUS_OK;
927}
928
929/****************************************************************
930****************************************************************/
931
932static NTSTATUS info21_to_USER_INFO_10(TALLOC_CTX *mem_ctx,
933				       const struct samr_UserInfo21 *i21,
934				       struct USER_INFO_10 *i)
935{
936	ZERO_STRUCTP(i);
937
938	i->usri10_name		= talloc_strdup(mem_ctx, i21->account_name.string);
939	NT_STATUS_HAVE_NO_MEMORY(i->usri10_name);
940	i->usri10_comment	= talloc_strdup(mem_ctx, i21->description.string);
941	i->usri10_full_name	= talloc_strdup(mem_ctx, i21->full_name.string);
942	i->usri10_usr_comment	= talloc_strdup(mem_ctx, i21->comment.string);
943
944	return NT_STATUS_OK;
945}
946
947/****************************************************************
948****************************************************************/
949
950static NTSTATUS info21_to_USER_INFO_11(TALLOC_CTX *mem_ctx,
951				       const struct samr_UserInfo21 *i21,
952				       uint32_t auth_flag,
953				       struct USER_INFO_11 *i)
954{
955	ZERO_STRUCTP(i);
956
957	i->usri11_name		= talloc_strdup(mem_ctx, i21->account_name.string);
958	NT_STATUS_HAVE_NO_MEMORY(i->usri11_name);
959	i->usri11_comment	= talloc_strdup(mem_ctx, i21->description.string);
960	i->usri11_usr_comment	= talloc_strdup(mem_ctx, i21->comment.string);
961	i->usri11_full_name	= talloc_strdup(mem_ctx, i21->full_name.string);
962	i->usri11_priv		= samr_rid_to_priv_level(i21->rid);
963	i->usri11_auth_flags	= auth_flag;
964	i->usri11_password_age	= time(NULL) - nt_time_to_unix(i21->last_password_change);
965	i->usri11_home_dir	= talloc_strdup(mem_ctx, i21->home_directory.string);
966	i->usri11_parms		= talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
967	i->usri11_last_logon	= nt_time_to_unix(i21->last_logon);
968	i->usri11_last_logoff	= nt_time_to_unix(i21->last_logoff);
969	i->usri11_bad_pw_count	= i21->bad_password_count;
970	i->usri11_num_logons	= i21->logon_count;
971	i->usri11_logon_server	= talloc_strdup(mem_ctx, "\\\\*");
972	i->usri11_country_code	= i21->country_code;
973	i->usri11_workstations	= talloc_strdup(mem_ctx, i21->workstations.string);
974	i->usri11_max_storage	= USER_MAXSTORAGE_UNLIMITED; /* FIXME */
975	i->usri11_units_per_week = i21->logon_hours.units_per_week;
976	i->usri11_logon_hours	= (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
977	i->usri11_code_page	= i21->code_page;
978
979	return NT_STATUS_OK;
980}
981
982/****************************************************************
983****************************************************************/
984
985static NTSTATUS info21_to_USER_INFO_20(TALLOC_CTX *mem_ctx,
986				       const struct samr_UserInfo21 *i21,
987				       struct USER_INFO_20 *i)
988{
989	ZERO_STRUCTP(i);
990
991	i->usri20_name		= talloc_strdup(mem_ctx, i21->account_name.string);
992	NT_STATUS_HAVE_NO_MEMORY(i->usri20_name);
993	i->usri20_comment	= talloc_strdup(mem_ctx, i21->description.string);
994	i->usri20_full_name	= talloc_strdup(mem_ctx, i21->full_name.string);
995	i->usri20_flags		= samr_acb_flags_to_netapi_flags(i21->acct_flags);
996	i->usri20_user_id	= i21->rid;
997
998	return NT_STATUS_OK;
999}
1000
1001/****************************************************************
1002****************************************************************/
1003
1004static NTSTATUS info21_to_USER_INFO_23(TALLOC_CTX *mem_ctx,
1005				       const struct samr_UserInfo21 *i21,
1006				       struct dom_sid *domain_sid,
1007				       struct USER_INFO_23 *i)
1008{
1009	struct dom_sid sid;
1010
1011	ZERO_STRUCTP(i);
1012
1013	i->usri23_name		= talloc_strdup(mem_ctx, i21->account_name.string);
1014	NT_STATUS_HAVE_NO_MEMORY(i->usri23_name);
1015	i->usri23_comment	= talloc_strdup(mem_ctx, i21->description.string);
1016	i->usri23_full_name	= talloc_strdup(mem_ctx, i21->full_name.string);
1017	i->usri23_flags		= samr_acb_flags_to_netapi_flags(i21->acct_flags);
1018	if (!sid_compose(&sid, domain_sid, i21->rid)) {
1019		return NT_STATUS_NO_MEMORY;
1020	}
1021	i->usri23_user_sid	= (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
1022
1023	return NT_STATUS_OK;
1024}
1025
1026/****************************************************************
1027****************************************************************/
1028
1029static NTSTATUS libnetapi_samr_lookup_user_map_USER_INFO(TALLOC_CTX *mem_ctx,
1030							 struct rpc_pipe_client *pipe_cli,
1031							 struct dom_sid *domain_sid,
1032							 struct policy_handle *domain_handle,
1033							 struct policy_handle *builtin_handle,
1034							 const char *user_name,
1035							 uint32_t rid,
1036							 uint32_t level,
1037							 uint8_t **buffer,
1038							 uint32_t *num_entries)
1039{
1040	NTSTATUS status;
1041
1042	struct samr_UserInfo21 *info21 = NULL;
1043	struct sec_desc_buf *sec_desc = NULL;
1044	uint32_t auth_flag = 0;
1045
1046	struct USER_INFO_0 info0;
1047	struct USER_INFO_1 info1;
1048	struct USER_INFO_2 info2;
1049	struct USER_INFO_3 info3;
1050	struct USER_INFO_4 info4;
1051	struct USER_INFO_10 info10;
1052	struct USER_INFO_11 info11;
1053	struct USER_INFO_20 info20;
1054	struct USER_INFO_23 info23;
1055
1056	switch (level) {
1057		case 0:
1058		case 1:
1059		case 2:
1060		case 3:
1061		case 4:
1062		case 10:
1063		case 11:
1064		case 20:
1065		case 23:
1066			break;
1067		default:
1068			return NT_STATUS_INVALID_LEVEL;
1069	}
1070
1071	if (level == 0) {
1072		info0.usri0_name = talloc_strdup(mem_ctx, user_name);
1073		NT_STATUS_HAVE_NO_MEMORY(info0.usri0_name);
1074
1075		ADD_TO_ARRAY(mem_ctx, struct USER_INFO_0, info0,
1076			     (struct USER_INFO_0 **)buffer, num_entries);
1077
1078		return NT_STATUS_OK;
1079	}
1080
1081	status = libnetapi_samr_lookup_user(mem_ctx, pipe_cli,
1082					    domain_handle,
1083					    builtin_handle,
1084					    user_name,
1085					    domain_sid,
1086					    rid,
1087					    level,
1088					    &info21,
1089					    &sec_desc,
1090					    &auth_flag);
1091
1092	if (!NT_STATUS_IS_OK(status)) {
1093		goto done;
1094	}
1095
1096	switch (level) {
1097		case 0:
1098			/* already returned above */
1099			break;
1100		case 1:
1101			status = info21_to_USER_INFO_1(mem_ctx, info21, &info1);
1102			NT_STATUS_NOT_OK_RETURN(status);
1103
1104			ADD_TO_ARRAY(mem_ctx, struct USER_INFO_1, info1,
1105				     (struct USER_INFO_1 **)buffer, num_entries);
1106
1107			break;
1108		case 2:
1109			status = info21_to_USER_INFO_2(mem_ctx, info21, auth_flag, &info2);
1110			NT_STATUS_NOT_OK_RETURN(status);
1111
1112			ADD_TO_ARRAY(mem_ctx, struct USER_INFO_2, info2,
1113				     (struct USER_INFO_2 **)buffer, num_entries);
1114
1115			break;
1116		case 3:
1117			status = info21_to_USER_INFO_3(mem_ctx, info21, auth_flag, &info3);
1118			NT_STATUS_NOT_OK_RETURN(status);
1119
1120			ADD_TO_ARRAY(mem_ctx, struct USER_INFO_3, info3,
1121				     (struct USER_INFO_3 **)buffer, num_entries);
1122
1123			break;
1124		case 4:
1125			status = info21_to_USER_INFO_4(mem_ctx, info21, auth_flag, domain_sid, &info4);
1126			NT_STATUS_NOT_OK_RETURN(status);
1127
1128			ADD_TO_ARRAY(mem_ctx, struct USER_INFO_4, info4,
1129				     (struct USER_INFO_4 **)buffer, num_entries);
1130
1131			break;
1132		case 10:
1133			status = info21_to_USER_INFO_10(mem_ctx, info21, &info10);
1134			NT_STATUS_NOT_OK_RETURN(status);
1135
1136			ADD_TO_ARRAY(mem_ctx, struct USER_INFO_10, info10,
1137				     (struct USER_INFO_10 **)buffer, num_entries);
1138
1139			break;
1140		case 11:
1141			status = info21_to_USER_INFO_11(mem_ctx, info21, auth_flag, &info11);
1142			NT_STATUS_NOT_OK_RETURN(status);
1143
1144			ADD_TO_ARRAY(mem_ctx, struct USER_INFO_11, info11,
1145				     (struct USER_INFO_11 **)buffer, num_entries);
1146
1147			break;
1148		case 20:
1149			status = info21_to_USER_INFO_20(mem_ctx, info21, &info20);
1150			NT_STATUS_NOT_OK_RETURN(status);
1151
1152			ADD_TO_ARRAY(mem_ctx, struct USER_INFO_20, info20,
1153				     (struct USER_INFO_20 **)buffer, num_entries);
1154
1155			break;
1156		case 23:
1157			status = info21_to_USER_INFO_23(mem_ctx, info21, domain_sid, &info23);
1158			NT_STATUS_NOT_OK_RETURN(status);
1159
1160			ADD_TO_ARRAY(mem_ctx, struct USER_INFO_23, info23,
1161				     (struct USER_INFO_23 **)buffer, num_entries);
1162			break;
1163		default:
1164			return NT_STATUS_INVALID_LEVEL;
1165	}
1166
1167 done:
1168	return status;
1169}
1170
1171/****************************************************************
1172****************************************************************/
1173
1174WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
1175		     struct NetUserEnum *r)
1176{
1177	struct rpc_pipe_client *pipe_cli = NULL;
1178	struct policy_handle connect_handle;
1179	struct dom_sid2 *domain_sid = NULL;
1180	struct policy_handle domain_handle, builtin_handle;
1181	struct samr_SamArray *sam = NULL;
1182	uint32_t filter = ACB_NORMAL;
1183	int i;
1184	uint32_t entries_read = 0;
1185
1186	NTSTATUS status = NT_STATUS_OK;
1187	WERROR werr;
1188
1189	ZERO_STRUCT(connect_handle);
1190	ZERO_STRUCT(domain_handle);
1191	ZERO_STRUCT(builtin_handle);
1192
1193	if (!r->out.buffer) {
1194		return WERR_INVALID_PARAM;
1195	}
1196
1197	*r->out.buffer = NULL;
1198	*r->out.entries_read = 0;
1199
1200	switch (r->in.level) {
1201		case 0:
1202		case 1:
1203		case 2:
1204		case 3:
1205		case 4:
1206		case 10:
1207		case 11:
1208		case 20:
1209		case 23:
1210			break;
1211		default:
1212			return WERR_UNKNOWN_LEVEL;
1213	}
1214
1215	werr = libnetapi_open_pipe(ctx, r->in.server_name,
1216				   &ndr_table_samr.syntax_id,
1217				   &pipe_cli);
1218	if (!W_ERROR_IS_OK(werr)) {
1219		goto done;
1220	}
1221
1222	werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1223						  SAMR_ACCESS_ENUM_DOMAINS |
1224						  SAMR_ACCESS_LOOKUP_DOMAIN,
1225						  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1226						  SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1227						  &connect_handle,
1228						  &builtin_handle);
1229	if (!W_ERROR_IS_OK(werr)) {
1230		goto done;
1231	}
1232
1233	werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1234					  SAMR_ACCESS_ENUM_DOMAINS |
1235					  SAMR_ACCESS_LOOKUP_DOMAIN,
1236					  SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1237					  SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1238					  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1239					  &connect_handle,
1240					  &domain_handle,
1241					  &domain_sid);
1242	if (!W_ERROR_IS_OK(werr)) {
1243		goto done;
1244	}
1245
1246	switch (r->in.filter) {
1247		case FILTER_NORMAL_ACCOUNT:
1248			filter = ACB_NORMAL;
1249			break;
1250		case FILTER_TEMP_DUPLICATE_ACCOUNT:
1251			filter = ACB_TEMPDUP;
1252			break;
1253		case FILTER_INTERDOMAIN_TRUST_ACCOUNT:
1254			filter = ACB_DOMTRUST;
1255			break;
1256		case FILTER_WORKSTATION_TRUST_ACCOUNT:
1257			filter = ACB_WSTRUST;
1258			break;
1259		case FILTER_SERVER_TRUST_ACCOUNT:
1260			filter = ACB_SVRTRUST;
1261			break;
1262		default:
1263			break;
1264	}
1265
1266	status = rpccli_samr_EnumDomainUsers(pipe_cli,
1267					     ctx,
1268					     &domain_handle,
1269					     r->in.resume_handle,
1270					     filter,
1271					     &sam,
1272					     r->in.prefmaxlen,
1273					     &entries_read);
1274	werr = ntstatus_to_werror(status);
1275	if (NT_STATUS_IS_ERR(status)) {
1276		goto done;
1277	}
1278
1279	for (i=0; i < sam->count; i++) {
1280
1281		status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1282								  domain_sid,
1283								  &domain_handle,
1284								  &builtin_handle,
1285								  sam->entries[i].name.string,
1286								  sam->entries[i].idx,
1287								  r->in.level,
1288								  r->out.buffer,
1289								  r->out.entries_read);
1290		if (!NT_STATUS_IS_OK(status)) {
1291			werr = ntstatus_to_werror(status);
1292			goto done;
1293		}
1294	}
1295
1296 done:
1297	/* if last query */
1298	if (NT_STATUS_IS_OK(status) ||
1299	    NT_STATUS_IS_ERR(status)) {
1300
1301		if (ctx->disable_policy_handle_cache) {
1302			libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1303			libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1304			libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1305		}
1306	}
1307
1308	return werr;
1309}
1310
1311/****************************************************************
1312****************************************************************/
1313
1314WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
1315		     struct NetUserEnum *r)
1316{
1317	LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserEnum);
1318}
1319
1320/****************************************************************
1321****************************************************************/
1322
1323static WERROR convert_samr_dispinfo_to_NET_DISPLAY_USER(TALLOC_CTX *mem_ctx,
1324							struct samr_DispInfoGeneral *info,
1325							uint32_t *entries_read,
1326							void **buffer)
1327{
1328	struct NET_DISPLAY_USER *user = NULL;
1329	int i;
1330
1331	user = TALLOC_ZERO_ARRAY(mem_ctx,
1332				 struct NET_DISPLAY_USER,
1333				 info->count);
1334	W_ERROR_HAVE_NO_MEMORY(user);
1335
1336	for (i = 0; i < info->count; i++) {
1337		user[i].usri1_name = talloc_strdup(mem_ctx,
1338			info->entries[i].account_name.string);
1339		user[i].usri1_comment = talloc_strdup(mem_ctx,
1340			info->entries[i].description.string);
1341		user[i].usri1_flags =
1342			info->entries[i].acct_flags;
1343		user[i].usri1_full_name = talloc_strdup(mem_ctx,
1344			info->entries[i].full_name.string);
1345		user[i].usri1_user_id =
1346			info->entries[i].rid;
1347		user[i].usri1_next_index =
1348			info->entries[i].idx;
1349
1350		if (!user[i].usri1_name) {
1351			return WERR_NOMEM;
1352		}
1353	}
1354
1355	*buffer = talloc_memdup(mem_ctx, user,
1356		sizeof(struct NET_DISPLAY_USER) * info->count);
1357	W_ERROR_HAVE_NO_MEMORY(*buffer);
1358
1359	*entries_read = info->count;
1360
1361	return WERR_OK;
1362}
1363
1364/****************************************************************
1365****************************************************************/
1366
1367static WERROR convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(TALLOC_CTX *mem_ctx,
1368							   struct samr_DispInfoFull *info,
1369							   uint32_t *entries_read,
1370							   void **buffer)
1371{
1372	struct NET_DISPLAY_MACHINE *machine = NULL;
1373	int i;
1374
1375	machine = TALLOC_ZERO_ARRAY(mem_ctx,
1376				    struct NET_DISPLAY_MACHINE,
1377				    info->count);
1378	W_ERROR_HAVE_NO_MEMORY(machine);
1379
1380	for (i = 0; i < info->count; i++) {
1381		machine[i].usri2_name = talloc_strdup(mem_ctx,
1382			info->entries[i].account_name.string);
1383		machine[i].usri2_comment = talloc_strdup(mem_ctx,
1384			info->entries[i].description.string);
1385		machine[i].usri2_flags =
1386			info->entries[i].acct_flags;
1387		machine[i].usri2_user_id =
1388			info->entries[i].rid;
1389		machine[i].usri2_next_index =
1390			info->entries[i].idx;
1391
1392		if (!machine[i].usri2_name) {
1393			return WERR_NOMEM;
1394		}
1395	}
1396
1397	*buffer = talloc_memdup(mem_ctx, machine,
1398		sizeof(struct NET_DISPLAY_MACHINE) * info->count);
1399	W_ERROR_HAVE_NO_MEMORY(*buffer);
1400
1401	*entries_read = info->count;
1402
1403	return WERR_OK;
1404}
1405
1406/****************************************************************
1407****************************************************************/
1408
1409static WERROR convert_samr_dispinfo_to_NET_DISPLAY_GROUP(TALLOC_CTX *mem_ctx,
1410							 struct samr_DispInfoFullGroups *info,
1411							 uint32_t *entries_read,
1412							 void **buffer)
1413{
1414	struct NET_DISPLAY_GROUP *group = NULL;
1415	int i;
1416
1417	group = TALLOC_ZERO_ARRAY(mem_ctx,
1418				  struct NET_DISPLAY_GROUP,
1419				  info->count);
1420	W_ERROR_HAVE_NO_MEMORY(group);
1421
1422	for (i = 0; i < info->count; i++) {
1423		group[i].grpi3_name = talloc_strdup(mem_ctx,
1424			info->entries[i].account_name.string);
1425		group[i].grpi3_comment = talloc_strdup(mem_ctx,
1426			info->entries[i].description.string);
1427		group[i].grpi3_group_id =
1428			info->entries[i].rid;
1429		group[i].grpi3_attributes =
1430			info->entries[i].acct_flags;
1431		group[i].grpi3_next_index =
1432			info->entries[i].idx;
1433
1434		if (!group[i].grpi3_name) {
1435			return WERR_NOMEM;
1436		}
1437	}
1438
1439	*buffer = talloc_memdup(mem_ctx, group,
1440		sizeof(struct NET_DISPLAY_GROUP) * info->count);
1441	W_ERROR_HAVE_NO_MEMORY(*buffer);
1442
1443	*entries_read = info->count;
1444
1445	return WERR_OK;
1446
1447}
1448
1449/****************************************************************
1450****************************************************************/
1451
1452static WERROR convert_samr_dispinfo_to_NET_DISPLAY(TALLOC_CTX *mem_ctx,
1453						   union samr_DispInfo *info,
1454						   uint32_t level,
1455						   uint32_t *entries_read,
1456						   void **buffer)
1457{
1458	switch (level) {
1459		case 1:
1460			return convert_samr_dispinfo_to_NET_DISPLAY_USER(mem_ctx,
1461									 &info->info1,
1462									 entries_read,
1463									 buffer);
1464		case 2:
1465			return convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(mem_ctx,
1466									    &info->info2,
1467									    entries_read,
1468									    buffer);
1469		case 3:
1470			return convert_samr_dispinfo_to_NET_DISPLAY_GROUP(mem_ctx,
1471									  &info->info3,
1472									  entries_read,
1473									  buffer);
1474		default:
1475			break;
1476	}
1477
1478	return WERR_UNKNOWN_LEVEL;
1479}
1480
1481/****************************************************************
1482****************************************************************/
1483
1484WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
1485				    struct NetQueryDisplayInformation *r)
1486{
1487	struct rpc_pipe_client *pipe_cli = NULL;
1488	struct policy_handle connect_handle;
1489	struct dom_sid2 *domain_sid = NULL;
1490	struct policy_handle domain_handle;
1491	union samr_DispInfo info;
1492
1493	uint32_t total_size = 0;
1494	uint32_t returned_size = 0;
1495
1496	NTSTATUS status = NT_STATUS_OK;
1497	WERROR werr;
1498	WERROR werr_tmp;
1499
1500	*r->out.entries_read = 0;
1501
1502	ZERO_STRUCT(connect_handle);
1503	ZERO_STRUCT(domain_handle);
1504
1505	switch (r->in.level) {
1506		case 1:
1507		case 2:
1508		case 3:
1509			break;
1510		default:
1511			return WERR_UNKNOWN_LEVEL;
1512	}
1513
1514	werr = libnetapi_open_pipe(ctx, r->in.server_name,
1515				   &ndr_table_samr.syntax_id,
1516				   &pipe_cli);
1517	if (!W_ERROR_IS_OK(werr)) {
1518		goto done;
1519	}
1520
1521	werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1522					  SAMR_ACCESS_ENUM_DOMAINS |
1523					  SAMR_ACCESS_LOOKUP_DOMAIN,
1524					  SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1525					  SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1526					  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1527					  &connect_handle,
1528					  &domain_handle,
1529					  &domain_sid);
1530	if (!W_ERROR_IS_OK(werr)) {
1531		goto done;
1532	}
1533
1534	status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
1535					       ctx,
1536					       &domain_handle,
1537					       r->in.level,
1538					       r->in.idx,
1539					       r->in.entries_requested,
1540					       r->in.prefmaxlen,
1541					       &total_size,
1542					       &returned_size,
1543					       &info);
1544	werr = ntstatus_to_werror(status);
1545	if (NT_STATUS_IS_ERR(status)) {
1546		goto done;
1547	}
1548
1549	werr_tmp = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info,
1550							r->in.level,
1551							r->out.entries_read,
1552							r->out.buffer);
1553	if (!W_ERROR_IS_OK(werr_tmp)) {
1554		werr = werr_tmp;
1555	}
1556 done:
1557	/* if last query */
1558	if (NT_STATUS_IS_OK(status) ||
1559	    NT_STATUS_IS_ERR(status)) {
1560
1561		if (ctx->disable_policy_handle_cache) {
1562			libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1563			libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1564		}
1565	}
1566
1567	return werr;
1568
1569}
1570
1571/****************************************************************
1572****************************************************************/
1573
1574
1575WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
1576				    struct NetQueryDisplayInformation *r)
1577{
1578	LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetQueryDisplayInformation);
1579}
1580
1581/****************************************************************
1582****************************************************************/
1583
1584WERROR NetUserChangePassword_r(struct libnetapi_ctx *ctx,
1585			       struct NetUserChangePassword *r)
1586{
1587	return WERR_NOT_SUPPORTED;
1588}
1589
1590/****************************************************************
1591****************************************************************/
1592
1593WERROR NetUserChangePassword_l(struct libnetapi_ctx *ctx,
1594			       struct NetUserChangePassword *r)
1595{
1596	return WERR_NOT_SUPPORTED;
1597}
1598
1599/****************************************************************
1600****************************************************************/
1601
1602WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx,
1603			struct NetUserGetInfo *r)
1604{
1605	struct rpc_pipe_client *pipe_cli = NULL;
1606	NTSTATUS status;
1607	WERROR werr;
1608
1609	struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1610	struct lsa_String lsa_account_name;
1611	struct dom_sid2 *domain_sid = NULL;
1612	struct samr_Ids user_rids, name_types;
1613	uint32_t num_entries = 0;
1614
1615	ZERO_STRUCT(connect_handle);
1616	ZERO_STRUCT(domain_handle);
1617	ZERO_STRUCT(builtin_handle);
1618	ZERO_STRUCT(user_handle);
1619
1620	if (!r->out.buffer) {
1621		return WERR_INVALID_PARAM;
1622	}
1623
1624	switch (r->in.level) {
1625		case 0:
1626		case 1:
1627		case 2:
1628		case 3:
1629		case 4:
1630		case 10:
1631		case 11:
1632		case 20:
1633		case 23:
1634			break;
1635		default:
1636			werr = WERR_UNKNOWN_LEVEL;
1637			goto done;
1638	}
1639
1640	werr = libnetapi_open_pipe(ctx, r->in.server_name,
1641				   &ndr_table_samr.syntax_id,
1642				   &pipe_cli);
1643	if (!W_ERROR_IS_OK(werr)) {
1644		goto done;
1645	}
1646
1647	werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1648					  SAMR_ACCESS_ENUM_DOMAINS |
1649					  SAMR_ACCESS_LOOKUP_DOMAIN,
1650					  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1651					  &connect_handle,
1652					  &domain_handle,
1653					  &domain_sid);
1654	if (!W_ERROR_IS_OK(werr)) {
1655		goto done;
1656	}
1657
1658	werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1659						  SAMR_ACCESS_ENUM_DOMAINS |
1660						  SAMR_ACCESS_LOOKUP_DOMAIN,
1661						  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1662						  SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1663						  &connect_handle,
1664						  &builtin_handle);
1665	if (!W_ERROR_IS_OK(werr)) {
1666		goto done;
1667	}
1668
1669	init_lsa_String(&lsa_account_name, r->in.user_name);
1670
1671	status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
1672					 &domain_handle,
1673					 1,
1674					 &lsa_account_name,
1675					 &user_rids,
1676					 &name_types);
1677	if (!NT_STATUS_IS_OK(status)) {
1678		werr = ntstatus_to_werror(status);
1679		goto done;
1680	}
1681
1682	status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1683							  domain_sid,
1684							  &domain_handle,
1685							  &builtin_handle,
1686							  r->in.user_name,
1687							  user_rids.ids[0],
1688							  r->in.level,
1689							  r->out.buffer,
1690							  &num_entries);
1691	if (!NT_STATUS_IS_OK(status)) {
1692		werr = ntstatus_to_werror(status);
1693		goto done;
1694	}
1695
1696 done:
1697	if (is_valid_policy_hnd(&user_handle) && pipe_cli) {
1698		rpccli_samr_Close(pipe_cli, talloc_tos(), &user_handle);
1699	}
1700
1701	if (ctx->disable_policy_handle_cache) {
1702		libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1703		libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1704	}
1705
1706	return werr;
1707}
1708
1709/****************************************************************
1710****************************************************************/
1711
1712WERROR NetUserGetInfo_l(struct libnetapi_ctx *ctx,
1713			struct NetUserGetInfo *r)
1714{
1715	LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetInfo);
1716}
1717
1718/****************************************************************
1719****************************************************************/
1720
1721WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
1722			struct NetUserSetInfo *r)
1723{
1724	struct rpc_pipe_client *pipe_cli = NULL;
1725	NTSTATUS status;
1726	WERROR werr;
1727
1728	struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1729	struct lsa_String lsa_account_name;
1730	struct dom_sid2 *domain_sid = NULL;
1731	struct samr_Ids user_rids, name_types;
1732	uint32_t user_mask = 0;
1733
1734	struct USER_INFO_X uX;
1735
1736	ZERO_STRUCT(connect_handle);
1737	ZERO_STRUCT(domain_handle);
1738	ZERO_STRUCT(builtin_handle);
1739	ZERO_STRUCT(user_handle);
1740
1741	if (!r->in.buffer) {
1742		return WERR_INVALID_PARAM;
1743	}
1744
1745	switch (r->in.level) {
1746		case 0:
1747			user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
1748			break;
1749		case 1003:
1750			user_mask = SAMR_USER_ACCESS_SET_PASSWORD;
1751			break;
1752		case 1006:
1753		case 1007:
1754		case 1009:
1755		case 1011:
1756		case 1014:
1757		case 1052:
1758		case 1053:
1759			user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
1760			break;
1761		case 1012:
1762		case 1024:
1763			user_mask = SAMR_USER_ACCESS_SET_LOC_COM;
1764		case 1051:
1765			user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES |
1766				    SAMR_USER_ACCESS_GET_GROUPS;
1767			break;
1768		case 3:
1769			user_mask = STD_RIGHT_READ_CONTROL_ACCESS |
1770				    STD_RIGHT_WRITE_DAC_ACCESS |
1771				    SAMR_USER_ACCESS_GET_GROUPS |
1772				    SAMR_USER_ACCESS_SET_PASSWORD |
1773				    SAMR_USER_ACCESS_SET_ATTRIBUTES |
1774				    SAMR_USER_ACCESS_GET_ATTRIBUTES |
1775				    SAMR_USER_ACCESS_SET_LOC_COM;
1776			break;
1777		case 1:
1778		case 2:
1779		case 4:
1780		case 21:
1781		case 22:
1782		case 1005:
1783		case 1008:
1784		case 1010:
1785		case 1017:
1786		case 1020:
1787			werr = WERR_NOT_SUPPORTED;
1788			goto done;
1789		default:
1790			werr = WERR_UNKNOWN_LEVEL;
1791			goto done;
1792	}
1793
1794	werr = libnetapi_open_pipe(ctx, r->in.server_name,
1795				   &ndr_table_samr.syntax_id,
1796				   &pipe_cli);
1797	if (!W_ERROR_IS_OK(werr)) {
1798		goto done;
1799	}
1800
1801	werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1802					  SAMR_ACCESS_ENUM_DOMAINS |
1803					  SAMR_ACCESS_LOOKUP_DOMAIN,
1804					  SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
1805					  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1806					  &connect_handle,
1807					  &domain_handle,
1808					  &domain_sid);
1809	if (!W_ERROR_IS_OK(werr)) {
1810		goto done;
1811	}
1812
1813	werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1814						  SAMR_ACCESS_ENUM_DOMAINS |
1815						  SAMR_ACCESS_LOOKUP_DOMAIN,
1816						  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1817						  SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1818						  &connect_handle,
1819						  &builtin_handle);
1820	if (!W_ERROR_IS_OK(werr)) {
1821		goto done;
1822	}
1823
1824	init_lsa_String(&lsa_account_name, r->in.user_name);
1825
1826	status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
1827					 &domain_handle,
1828					 1,
1829					 &lsa_account_name,
1830					 &user_rids,
1831					 &name_types);
1832	if (!NT_STATUS_IS_OK(status)) {
1833		werr = ntstatus_to_werror(status);
1834		goto done;
1835	}
1836
1837	status = rpccli_samr_OpenUser(pipe_cli, talloc_tos(),
1838				      &domain_handle,
1839				      user_mask,
1840				      user_rids.ids[0],
1841				      &user_handle);
1842	if (!NT_STATUS_IS_OK(status)) {
1843		werr = ntstatus_to_werror(status);
1844		goto done;
1845	}
1846
1847	status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
1848	if (!NT_STATUS_IS_OK(status)) {
1849		werr = ntstatus_to_werror(status);
1850		goto done;
1851	}
1852
1853	status = set_user_info_USER_INFO_X(ctx, pipe_cli,
1854					   &pipe_cli->auth->user_session_key,
1855					   &user_handle,
1856					   &uX);
1857	if (!NT_STATUS_IS_OK(status)) {
1858		werr = ntstatus_to_werror(status);
1859		goto done;
1860	}
1861
1862	werr = WERR_OK;
1863
1864 done:
1865	if (is_valid_policy_hnd(&user_handle) && pipe_cli) {
1866		rpccli_samr_Close(pipe_cli, talloc_tos(), &user_handle);
1867	}
1868
1869	if (ctx->disable_policy_handle_cache) {
1870		libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1871		libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1872		libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1873	}
1874
1875	return werr;
1876}
1877
1878/****************************************************************
1879****************************************************************/
1880
1881WERROR NetUserSetInfo_l(struct libnetapi_ctx *ctx,
1882			struct NetUserSetInfo *r)
1883{
1884	LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetInfo);
1885}
1886
1887/****************************************************************
1888****************************************************************/
1889
1890static NTSTATUS query_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
1891					   struct rpc_pipe_client *pipe_cli,
1892					   struct policy_handle *domain_handle,
1893					   struct samr_DomInfo1 *info1,
1894					   struct samr_DomInfo3 *info3,
1895					   struct samr_DomInfo5 *info5,
1896					   struct samr_DomInfo6 *info6,
1897					   struct samr_DomInfo7 *info7,
1898					   struct samr_DomInfo12 *info12)
1899{
1900	NTSTATUS status;
1901	union samr_DomainInfo *dom_info = NULL;
1902
1903	if (info1) {
1904		status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1905						     domain_handle,
1906						     1,
1907						     &dom_info);
1908		NT_STATUS_NOT_OK_RETURN(status);
1909
1910		*info1 = dom_info->info1;
1911	}
1912
1913	if (info3) {
1914		status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1915						     domain_handle,
1916						     3,
1917						     &dom_info);
1918		NT_STATUS_NOT_OK_RETURN(status);
1919
1920		*info3 = dom_info->info3;
1921	}
1922
1923	if (info5) {
1924		status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1925						     domain_handle,
1926						     5,
1927						     &dom_info);
1928		NT_STATUS_NOT_OK_RETURN(status);
1929
1930		*info5 = dom_info->info5;
1931	}
1932
1933	if (info6) {
1934		status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1935						     domain_handle,
1936						     6,
1937						     &dom_info);
1938		NT_STATUS_NOT_OK_RETURN(status);
1939
1940		*info6 = dom_info->info6;
1941	}
1942
1943	if (info7) {
1944		status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1945						     domain_handle,
1946						     7,
1947						     &dom_info);
1948		NT_STATUS_NOT_OK_RETURN(status);
1949
1950		*info7 = dom_info->info7;
1951	}
1952
1953	if (info12) {
1954		status = rpccli_samr_QueryDomainInfo2(pipe_cli, mem_ctx,
1955						      domain_handle,
1956						      12,
1957						      &dom_info);
1958		NT_STATUS_NOT_OK_RETURN(status);
1959
1960		*info12 = dom_info->info12;
1961	}
1962
1963	return NT_STATUS_OK;
1964}
1965
1966/****************************************************************
1967****************************************************************/
1968
1969static NTSTATUS query_USER_MODALS_INFO_0(TALLOC_CTX *mem_ctx,
1970					 struct rpc_pipe_client *pipe_cli,
1971					 struct policy_handle *domain_handle,
1972					 struct USER_MODALS_INFO_0 *info0)
1973{
1974	NTSTATUS status;
1975	struct samr_DomInfo1 dom_info1;
1976	struct samr_DomInfo3 dom_info3;
1977
1978	ZERO_STRUCTP(info0);
1979
1980	status = query_USER_MODALS_INFO_rpc(mem_ctx,
1981					    pipe_cli,
1982					    domain_handle,
1983					    &dom_info1,
1984					    &dom_info3,
1985					    NULL,
1986					    NULL,
1987					    NULL,
1988					    NULL);
1989	NT_STATUS_NOT_OK_RETURN(status);
1990
1991	info0->usrmod0_min_passwd_len =
1992		dom_info1.min_password_length;
1993	info0->usrmod0_max_passwd_age =
1994		nt_time_to_unix_abs((NTTIME *)&dom_info1.max_password_age);
1995	info0->usrmod0_min_passwd_age =
1996		nt_time_to_unix_abs((NTTIME *)&dom_info1.min_password_age);
1997	info0->usrmod0_password_hist_len =
1998		dom_info1.password_history_length;
1999
2000	info0->usrmod0_force_logoff =
2001		nt_time_to_unix_abs(&dom_info3.force_logoff_time);
2002
2003	return NT_STATUS_OK;
2004}
2005
2006/****************************************************************
2007****************************************************************/
2008
2009static NTSTATUS query_USER_MODALS_INFO_1(TALLOC_CTX *mem_ctx,
2010					 struct rpc_pipe_client *pipe_cli,
2011					 struct policy_handle *domain_handle,
2012					 struct USER_MODALS_INFO_1 *info1)
2013{
2014	NTSTATUS status;
2015	struct samr_DomInfo6 dom_info6;
2016	struct samr_DomInfo7 dom_info7;
2017
2018	status = query_USER_MODALS_INFO_rpc(mem_ctx,
2019					    pipe_cli,
2020					    domain_handle,
2021					    NULL,
2022					    NULL,
2023					    NULL,
2024					    &dom_info6,
2025					    &dom_info7,
2026					    NULL);
2027	NT_STATUS_NOT_OK_RETURN(status);
2028
2029	info1->usrmod1_primary =
2030		talloc_strdup(mem_ctx, dom_info6.primary.string);
2031
2032	info1->usrmod1_role = dom_info7.role;
2033
2034	return NT_STATUS_OK;
2035}
2036
2037/****************************************************************
2038****************************************************************/
2039
2040static NTSTATUS query_USER_MODALS_INFO_2(TALLOC_CTX *mem_ctx,
2041					 struct rpc_pipe_client *pipe_cli,
2042					 struct policy_handle *domain_handle,
2043					 struct dom_sid *domain_sid,
2044					 struct USER_MODALS_INFO_2 *info2)
2045{
2046	NTSTATUS status;
2047	struct samr_DomInfo5 dom_info5;
2048
2049	status = query_USER_MODALS_INFO_rpc(mem_ctx,
2050					    pipe_cli,
2051					    domain_handle,
2052					    NULL,
2053					    NULL,
2054					    &dom_info5,
2055					    NULL,
2056					    NULL,
2057					    NULL);
2058	NT_STATUS_NOT_OK_RETURN(status);
2059
2060	info2->usrmod2_domain_name =
2061		talloc_strdup(mem_ctx, dom_info5.domain_name.string);
2062	info2->usrmod2_domain_id =
2063		(struct domsid *)sid_dup_talloc(mem_ctx, domain_sid);
2064
2065	NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_name);
2066	NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_id);
2067
2068	return NT_STATUS_OK;
2069}
2070
2071/****************************************************************
2072****************************************************************/
2073
2074static NTSTATUS query_USER_MODALS_INFO_3(TALLOC_CTX *mem_ctx,
2075					 struct rpc_pipe_client *pipe_cli,
2076					 struct policy_handle *domain_handle,
2077					 struct USER_MODALS_INFO_3 *info3)
2078{
2079	NTSTATUS status;
2080	struct samr_DomInfo12 dom_info12;
2081
2082	status = query_USER_MODALS_INFO_rpc(mem_ctx,
2083					    pipe_cli,
2084					    domain_handle,
2085					    NULL,
2086					    NULL,
2087					    NULL,
2088					    NULL,
2089					    NULL,
2090					    &dom_info12);
2091	NT_STATUS_NOT_OK_RETURN(status);
2092
2093	info3->usrmod3_lockout_duration =
2094		nt_time_to_unix_abs(&dom_info12.lockout_duration);
2095	info3->usrmod3_lockout_observation_window =
2096		nt_time_to_unix_abs(&dom_info12.lockout_window);
2097	info3->usrmod3_lockout_threshold =
2098		dom_info12.lockout_threshold;
2099
2100	return NT_STATUS_OK;
2101}
2102
2103/****************************************************************
2104****************************************************************/
2105
2106static NTSTATUS query_USER_MODALS_INFO_to_buffer(TALLOC_CTX *mem_ctx,
2107						 struct rpc_pipe_client *pipe_cli,
2108						 uint32_t level,
2109						 struct policy_handle *domain_handle,
2110						 struct dom_sid *domain_sid,
2111						 uint8_t **buffer)
2112{
2113	NTSTATUS status;
2114
2115	struct USER_MODALS_INFO_0 info0;
2116	struct USER_MODALS_INFO_1 info1;
2117	struct USER_MODALS_INFO_2 info2;
2118	struct USER_MODALS_INFO_3 info3;
2119
2120	if (!buffer) {
2121		return ERROR_INSUFFICIENT_BUFFER;
2122	}
2123
2124	switch (level) {
2125		case 0:
2126			status = query_USER_MODALS_INFO_0(mem_ctx,
2127							  pipe_cli,
2128							  domain_handle,
2129							  &info0);
2130			NT_STATUS_NOT_OK_RETURN(status);
2131
2132			*buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0,
2133							   sizeof(info0));
2134			break;
2135
2136		case 1:
2137			status = query_USER_MODALS_INFO_1(mem_ctx,
2138							  pipe_cli,
2139							  domain_handle,
2140							  &info1);
2141			NT_STATUS_NOT_OK_RETURN(status);
2142
2143			*buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1,
2144							   sizeof(info1));
2145			break;
2146		case 2:
2147			status = query_USER_MODALS_INFO_2(mem_ctx,
2148							  pipe_cli,
2149							  domain_handle,
2150							  domain_sid,
2151							  &info2);
2152			NT_STATUS_NOT_OK_RETURN(status);
2153
2154			*buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2,
2155							   sizeof(info2));
2156			break;
2157		case 3:
2158			status = query_USER_MODALS_INFO_3(mem_ctx,
2159							  pipe_cli,
2160							  domain_handle,
2161							  &info3);
2162			NT_STATUS_NOT_OK_RETURN(status);
2163
2164			*buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3,
2165							   sizeof(info3));
2166			break;
2167		default:
2168			break;
2169	}
2170
2171	NT_STATUS_HAVE_NO_MEMORY(*buffer);
2172
2173	return NT_STATUS_OK;
2174}
2175
2176/****************************************************************
2177****************************************************************/
2178
2179WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx,
2180			  struct NetUserModalsGet *r)
2181{
2182	struct rpc_pipe_client *pipe_cli = NULL;
2183	NTSTATUS status;
2184	WERROR werr;
2185
2186	struct policy_handle connect_handle, domain_handle;
2187	struct dom_sid2 *domain_sid = NULL;
2188	uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2189
2190	ZERO_STRUCT(connect_handle);
2191	ZERO_STRUCT(domain_handle);
2192
2193	if (!r->out.buffer) {
2194		return WERR_INVALID_PARAM;
2195	}
2196
2197	switch (r->in.level) {
2198		case 0:
2199			access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2200				       SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2201			break;
2202		case 1:
2203		case 2:
2204			access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2205			break;
2206		case 3:
2207			access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1;
2208			break;
2209		default:
2210			werr = WERR_UNKNOWN_LEVEL;
2211			goto done;
2212	}
2213
2214	werr = libnetapi_open_pipe(ctx, r->in.server_name,
2215				   &ndr_table_samr.syntax_id,
2216				   &pipe_cli);
2217	if (!W_ERROR_IS_OK(werr)) {
2218		goto done;
2219	}
2220
2221	werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2222					  SAMR_ACCESS_ENUM_DOMAINS |
2223					  SAMR_ACCESS_LOOKUP_DOMAIN,
2224					  access_mask,
2225					  &connect_handle,
2226					  &domain_handle,
2227					  &domain_sid);
2228	if (!W_ERROR_IS_OK(werr)) {
2229		goto done;
2230	}
2231
2232	/* 0:  1 + 3 */
2233	/* 1:  6 + 7 */
2234	/* 2:  5 */
2235	/* 3: 12 (DomainInfo2) */
2236
2237	status = query_USER_MODALS_INFO_to_buffer(ctx,
2238						  pipe_cli,
2239						  r->in.level,
2240						  &domain_handle,
2241						  domain_sid,
2242						  r->out.buffer);
2243	if (!NT_STATUS_IS_OK(status)) {
2244		werr = ntstatus_to_werror(status);
2245		goto done;
2246	}
2247
2248 done:
2249	if (ctx->disable_policy_handle_cache) {
2250		libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2251		libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2252	}
2253
2254	return werr;
2255}
2256
2257/****************************************************************
2258****************************************************************/
2259
2260WERROR NetUserModalsGet_l(struct libnetapi_ctx *ctx,
2261			  struct NetUserModalsGet *r)
2262{
2263	LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsGet);
2264}
2265
2266/****************************************************************
2267****************************************************************/
2268
2269static NTSTATUS set_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
2270					 struct rpc_pipe_client *pipe_cli,
2271					 struct policy_handle *domain_handle,
2272					 struct samr_DomInfo1 *info1,
2273					 struct samr_DomInfo3 *info3,
2274					 struct samr_DomInfo12 *info12)
2275{
2276	NTSTATUS status;
2277	union samr_DomainInfo dom_info;
2278
2279	if (info1) {
2280
2281		ZERO_STRUCT(dom_info);
2282
2283		dom_info.info1 = *info1;
2284
2285		status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2286						   domain_handle,
2287						   1,
2288						   &dom_info);
2289		NT_STATUS_NOT_OK_RETURN(status);
2290	}
2291
2292	if (info3) {
2293
2294		ZERO_STRUCT(dom_info);
2295
2296		dom_info.info3 = *info3;
2297
2298		status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2299						   domain_handle,
2300						   3,
2301						   &dom_info);
2302
2303		NT_STATUS_NOT_OK_RETURN(status);
2304	}
2305
2306	if (info12) {
2307
2308		ZERO_STRUCT(dom_info);
2309
2310		dom_info.info12 = *info12;
2311
2312		status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2313						   domain_handle,
2314						   12,
2315						   &dom_info);
2316
2317		NT_STATUS_NOT_OK_RETURN(status);
2318	}
2319
2320	return NT_STATUS_OK;
2321}
2322
2323/****************************************************************
2324****************************************************************/
2325
2326static NTSTATUS set_USER_MODALS_INFO_0_buffer(TALLOC_CTX *mem_ctx,
2327					      struct rpc_pipe_client *pipe_cli,
2328					      struct policy_handle *domain_handle,
2329					      struct USER_MODALS_INFO_0 *info0)
2330{
2331	NTSTATUS status;
2332	struct samr_DomInfo1 dom_info_1;
2333	struct samr_DomInfo3 dom_info_3;
2334
2335	status = query_USER_MODALS_INFO_rpc(mem_ctx,
2336					    pipe_cli,
2337					    domain_handle,
2338					    &dom_info_1,
2339					    &dom_info_3,
2340					    NULL,
2341					    NULL,
2342					    NULL,
2343					    NULL);
2344	NT_STATUS_NOT_OK_RETURN(status);
2345
2346	dom_info_1.min_password_length =
2347		info0->usrmod0_min_passwd_len;
2348	dom_info_1.password_history_length =
2349		info0->usrmod0_password_hist_len;
2350
2351	unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2352		info0->usrmod0_max_passwd_age);
2353	unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2354		info0->usrmod0_min_passwd_age);
2355
2356	unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2357		info0->usrmod0_force_logoff);
2358
2359	return set_USER_MODALS_INFO_rpc(mem_ctx,
2360					pipe_cli,
2361					domain_handle,
2362					&dom_info_1,
2363					&dom_info_3,
2364					NULL);
2365}
2366
2367/****************************************************************
2368****************************************************************/
2369
2370static NTSTATUS set_USER_MODALS_INFO_3_buffer(TALLOC_CTX *mem_ctx,
2371					      struct rpc_pipe_client *pipe_cli,
2372					      struct policy_handle *domain_handle,
2373					      struct USER_MODALS_INFO_3 *info3)
2374{
2375	NTSTATUS status;
2376	struct samr_DomInfo12 dom_info_12;
2377
2378	status = query_USER_MODALS_INFO_rpc(mem_ctx,
2379					    pipe_cli,
2380					    domain_handle,
2381					    NULL,
2382					    NULL,
2383					    NULL,
2384					    NULL,
2385					    NULL,
2386					    &dom_info_12);
2387	NT_STATUS_NOT_OK_RETURN(status);
2388
2389	unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_duration,
2390		info3->usrmod3_lockout_duration);
2391	unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_window,
2392		info3->usrmod3_lockout_observation_window);
2393	dom_info_12.lockout_threshold = info3->usrmod3_lockout_threshold;
2394
2395	return set_USER_MODALS_INFO_rpc(mem_ctx,
2396					pipe_cli,
2397					domain_handle,
2398					NULL,
2399					NULL,
2400					&dom_info_12);
2401}
2402
2403/****************************************************************
2404****************************************************************/
2405
2406static NTSTATUS set_USER_MODALS_INFO_1001_buffer(TALLOC_CTX *mem_ctx,
2407						 struct rpc_pipe_client *pipe_cli,
2408						 struct policy_handle *domain_handle,
2409						 struct USER_MODALS_INFO_1001 *info1001)
2410{
2411	NTSTATUS status;
2412	struct samr_DomInfo1 dom_info_1;
2413
2414	status = query_USER_MODALS_INFO_rpc(mem_ctx,
2415					    pipe_cli,
2416					    domain_handle,
2417					    &dom_info_1,
2418					    NULL,
2419					    NULL,
2420					    NULL,
2421					    NULL,
2422					    NULL);
2423	NT_STATUS_NOT_OK_RETURN(status);
2424
2425	dom_info_1.min_password_length =
2426		info1001->usrmod1001_min_passwd_len;
2427
2428	return set_USER_MODALS_INFO_rpc(mem_ctx,
2429					pipe_cli,
2430					domain_handle,
2431					&dom_info_1,
2432					NULL,
2433					NULL);
2434}
2435
2436/****************************************************************
2437****************************************************************/
2438
2439static NTSTATUS set_USER_MODALS_INFO_1002_buffer(TALLOC_CTX *mem_ctx,
2440						 struct rpc_pipe_client *pipe_cli,
2441						 struct policy_handle *domain_handle,
2442						 struct USER_MODALS_INFO_1002 *info1002)
2443{
2444	NTSTATUS status;
2445	struct samr_DomInfo1 dom_info_1;
2446
2447	status = query_USER_MODALS_INFO_rpc(mem_ctx,
2448					    pipe_cli,
2449					    domain_handle,
2450					    &dom_info_1,
2451					    NULL,
2452					    NULL,
2453					    NULL,
2454					    NULL,
2455					    NULL);
2456	NT_STATUS_NOT_OK_RETURN(status);
2457
2458	unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2459		info1002->usrmod1002_max_passwd_age);
2460
2461	return set_USER_MODALS_INFO_rpc(mem_ctx,
2462					pipe_cli,
2463					domain_handle,
2464					&dom_info_1,
2465					NULL,
2466					NULL);
2467}
2468
2469/****************************************************************
2470****************************************************************/
2471
2472static NTSTATUS set_USER_MODALS_INFO_1003_buffer(TALLOC_CTX *mem_ctx,
2473						 struct rpc_pipe_client *pipe_cli,
2474						 struct policy_handle *domain_handle,
2475						 struct USER_MODALS_INFO_1003 *info1003)
2476{
2477	NTSTATUS status;
2478	struct samr_DomInfo1 dom_info_1;
2479
2480	status = query_USER_MODALS_INFO_rpc(mem_ctx,
2481					    pipe_cli,
2482					    domain_handle,
2483					    &dom_info_1,
2484					    NULL,
2485					    NULL,
2486					    NULL,
2487					    NULL,
2488					    NULL);
2489	NT_STATUS_NOT_OK_RETURN(status);
2490
2491	unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2492		info1003->usrmod1003_min_passwd_age);
2493
2494	return set_USER_MODALS_INFO_rpc(mem_ctx,
2495					pipe_cli,
2496					domain_handle,
2497					&dom_info_1,
2498					NULL,
2499					NULL);
2500}
2501
2502/****************************************************************
2503****************************************************************/
2504
2505static NTSTATUS set_USER_MODALS_INFO_1004_buffer(TALLOC_CTX *mem_ctx,
2506						 struct rpc_pipe_client *pipe_cli,
2507						 struct policy_handle *domain_handle,
2508						 struct USER_MODALS_INFO_1004 *info1004)
2509{
2510	NTSTATUS status;
2511	struct samr_DomInfo3 dom_info_3;
2512
2513	status = query_USER_MODALS_INFO_rpc(mem_ctx,
2514					    pipe_cli,
2515					    domain_handle,
2516					    NULL,
2517					    &dom_info_3,
2518					    NULL,
2519					    NULL,
2520					    NULL,
2521					    NULL);
2522	NT_STATUS_NOT_OK_RETURN(status);
2523
2524	unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2525		info1004->usrmod1004_force_logoff);
2526
2527	return set_USER_MODALS_INFO_rpc(mem_ctx,
2528					pipe_cli,
2529					domain_handle,
2530					NULL,
2531					&dom_info_3,
2532					NULL);
2533}
2534
2535/****************************************************************
2536****************************************************************/
2537
2538static NTSTATUS set_USER_MODALS_INFO_1005_buffer(TALLOC_CTX *mem_ctx,
2539						 struct rpc_pipe_client *pipe_cli,
2540						 struct policy_handle *domain_handle,
2541						 struct USER_MODALS_INFO_1005 *info1005)
2542{
2543	NTSTATUS status;
2544	struct samr_DomInfo1 dom_info_1;
2545
2546	status = query_USER_MODALS_INFO_rpc(mem_ctx,
2547					    pipe_cli,
2548					    domain_handle,
2549					    &dom_info_1,
2550					    NULL,
2551					    NULL,
2552					    NULL,
2553					    NULL,
2554					    NULL);
2555	NT_STATUS_NOT_OK_RETURN(status);
2556
2557	dom_info_1.password_history_length =
2558		info1005->usrmod1005_password_hist_len;
2559
2560	return set_USER_MODALS_INFO_rpc(mem_ctx,
2561					pipe_cli,
2562					domain_handle,
2563					&dom_info_1,
2564					NULL,
2565					NULL);
2566}
2567
2568/****************************************************************
2569****************************************************************/
2570
2571static NTSTATUS set_USER_MODALS_INFO_buffer(TALLOC_CTX *mem_ctx,
2572					    struct rpc_pipe_client *pipe_cli,
2573					    uint32_t level,
2574					    struct policy_handle *domain_handle,
2575					    struct dom_sid *domain_sid,
2576					    uint8_t *buffer)
2577{
2578	struct USER_MODALS_INFO_0 *info0;
2579	struct USER_MODALS_INFO_3 *info3;
2580	struct USER_MODALS_INFO_1001 *info1001;
2581	struct USER_MODALS_INFO_1002 *info1002;
2582	struct USER_MODALS_INFO_1003 *info1003;
2583	struct USER_MODALS_INFO_1004 *info1004;
2584	struct USER_MODALS_INFO_1005 *info1005;
2585
2586	if (!buffer) {
2587		return ERROR_INSUFFICIENT_BUFFER;
2588	}
2589
2590	switch (level) {
2591		case 0:
2592			info0 = (struct USER_MODALS_INFO_0 *)buffer;
2593			return set_USER_MODALS_INFO_0_buffer(mem_ctx,
2594							     pipe_cli,
2595							     domain_handle,
2596							     info0);
2597		case 3:
2598			info3 = (struct USER_MODALS_INFO_3 *)buffer;
2599			return set_USER_MODALS_INFO_3_buffer(mem_ctx,
2600							     pipe_cli,
2601							     domain_handle,
2602							     info3);
2603		case 1001:
2604			info1001 = (struct USER_MODALS_INFO_1001 *)buffer;
2605			return set_USER_MODALS_INFO_1001_buffer(mem_ctx,
2606								pipe_cli,
2607								domain_handle,
2608								info1001);
2609		case 1002:
2610			info1002 = (struct USER_MODALS_INFO_1002 *)buffer;
2611			return set_USER_MODALS_INFO_1002_buffer(mem_ctx,
2612								pipe_cli,
2613								domain_handle,
2614								info1002);
2615		case 1003:
2616			info1003 = (struct USER_MODALS_INFO_1003 *)buffer;
2617			return set_USER_MODALS_INFO_1003_buffer(mem_ctx,
2618								pipe_cli,
2619								domain_handle,
2620								info1003);
2621		case 1004:
2622			info1004 = (struct USER_MODALS_INFO_1004 *)buffer;
2623			return set_USER_MODALS_INFO_1004_buffer(mem_ctx,
2624								pipe_cli,
2625								domain_handle,
2626								info1004);
2627		case 1005:
2628			info1005 = (struct USER_MODALS_INFO_1005 *)buffer;
2629			return set_USER_MODALS_INFO_1005_buffer(mem_ctx,
2630								pipe_cli,
2631								domain_handle,
2632								info1005);
2633
2634		default:
2635			break;
2636	}
2637
2638	return NT_STATUS_OK;
2639}
2640
2641/****************************************************************
2642****************************************************************/
2643
2644WERROR NetUserModalsSet_r(struct libnetapi_ctx *ctx,
2645			  struct NetUserModalsSet *r)
2646{
2647	struct rpc_pipe_client *pipe_cli = NULL;
2648	NTSTATUS status;
2649	WERROR werr;
2650
2651	struct policy_handle connect_handle, domain_handle;
2652	struct dom_sid2 *domain_sid = NULL;
2653	uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2654
2655	ZERO_STRUCT(connect_handle);
2656	ZERO_STRUCT(domain_handle);
2657
2658	if (!r->in.buffer) {
2659		return WERR_INVALID_PARAM;
2660	}
2661
2662	switch (r->in.level) {
2663		case 0:
2664			access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2665				       SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2666				       SAMR_DOMAIN_ACCESS_SET_INFO_1 |
2667				       SAMR_DOMAIN_ACCESS_SET_INFO_2;
2668			break;
2669		case 3:
2670		case 1001:
2671		case 1002:
2672		case 1003:
2673		case 1005:
2674			access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2675				       SAMR_DOMAIN_ACCESS_SET_INFO_1;
2676			break;
2677		case 1004:
2678			access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2679				       SAMR_DOMAIN_ACCESS_SET_INFO_2;
2680			break;
2681		case 1:
2682		case 2:
2683		case 1006:
2684		case 1007:
2685			werr = WERR_NOT_SUPPORTED;
2686			break;
2687		default:
2688			werr = WERR_UNKNOWN_LEVEL;
2689			goto done;
2690	}
2691
2692	werr = libnetapi_open_pipe(ctx, r->in.server_name,
2693				   &ndr_table_samr.syntax_id,
2694				   &pipe_cli);
2695	if (!W_ERROR_IS_OK(werr)) {
2696		goto done;
2697	}
2698
2699	werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2700					  SAMR_ACCESS_ENUM_DOMAINS |
2701					  SAMR_ACCESS_LOOKUP_DOMAIN,
2702					  access_mask,
2703					  &connect_handle,
2704					  &domain_handle,
2705					  &domain_sid);
2706	if (!W_ERROR_IS_OK(werr)) {
2707		goto done;
2708	}
2709
2710	status = set_USER_MODALS_INFO_buffer(ctx,
2711					     pipe_cli,
2712					     r->in.level,
2713					     &domain_handle,
2714					     domain_sid,
2715					     r->in.buffer);
2716	if (!NT_STATUS_IS_OK(status)) {
2717		werr = ntstatus_to_werror(status);
2718		goto done;
2719	}
2720
2721 done:
2722	if (ctx->disable_policy_handle_cache) {
2723		libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2724		libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2725	}
2726
2727	return werr;
2728}
2729
2730/****************************************************************
2731****************************************************************/
2732
2733WERROR NetUserModalsSet_l(struct libnetapi_ctx *ctx,
2734			  struct NetUserModalsSet *r)
2735{
2736	LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsSet);
2737}
2738
2739/****************************************************************
2740****************************************************************/
2741
2742NTSTATUS add_GROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
2743				       uint32_t level,
2744				       const char *group_name,
2745				       uint32_t attributes,
2746				       uint8_t **buffer,
2747				       uint32_t *num_entries)
2748{
2749	struct GROUP_USERS_INFO_0 u0;
2750	struct GROUP_USERS_INFO_1 u1;
2751
2752	switch (level) {
2753		case 0:
2754			if (group_name) {
2755				u0.grui0_name = talloc_strdup(mem_ctx, group_name);
2756				NT_STATUS_HAVE_NO_MEMORY(u0.grui0_name);
2757			} else {
2758				u0.grui0_name = NULL;
2759			}
2760
2761			ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_0, u0,
2762				     (struct GROUP_USERS_INFO_0 **)buffer, num_entries);
2763			break;
2764		case 1:
2765			if (group_name) {
2766				u1.grui1_name = talloc_strdup(mem_ctx, group_name);
2767				NT_STATUS_HAVE_NO_MEMORY(u1.grui1_name);
2768			} else {
2769				u1.grui1_name = NULL;
2770			}
2771
2772			u1.grui1_attributes = attributes;
2773
2774			ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_1, u1,
2775				     (struct GROUP_USERS_INFO_1 **)buffer, num_entries);
2776			break;
2777		default:
2778			return NT_STATUS_INVALID_INFO_CLASS;
2779	}
2780
2781	return NT_STATUS_OK;
2782}
2783
2784/****************************************************************
2785****************************************************************/
2786
2787WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
2788			  struct NetUserGetGroups *r)
2789{
2790	struct rpc_pipe_client *pipe_cli = NULL;
2791	struct policy_handle connect_handle, domain_handle, user_handle;
2792	struct lsa_String lsa_account_name;
2793	struct dom_sid2 *domain_sid = NULL;
2794	struct samr_Ids user_rids, name_types;
2795	struct samr_RidWithAttributeArray *rid_array = NULL;
2796	struct lsa_Strings names;
2797	struct samr_Ids types;
2798	uint32_t *rids = NULL;
2799
2800	int i;
2801	uint32_t entries_read = 0;
2802
2803	NTSTATUS status = NT_STATUS_OK;
2804	WERROR werr;
2805
2806	ZERO_STRUCT(connect_handle);
2807	ZERO_STRUCT(domain_handle);
2808
2809	if (!r->out.buffer) {
2810		return WERR_INVALID_PARAM;
2811	}
2812
2813	*r->out.buffer = NULL;
2814	*r->out.entries_read = 0;
2815	*r->out.total_entries = 0;
2816
2817	switch (r->in.level) {
2818		case 0:
2819		case 1:
2820			break;
2821		default:
2822			return WERR_UNKNOWN_LEVEL;
2823	}
2824
2825	werr = libnetapi_open_pipe(ctx, r->in.server_name,
2826				   &ndr_table_samr.syntax_id,
2827				   &pipe_cli);
2828	if (!W_ERROR_IS_OK(werr)) {
2829		goto done;
2830	}
2831
2832	werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2833					  SAMR_ACCESS_ENUM_DOMAINS |
2834					  SAMR_ACCESS_LOOKUP_DOMAIN,
2835					  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2836					  &connect_handle,
2837					  &domain_handle,
2838					  &domain_sid);
2839	if (!W_ERROR_IS_OK(werr)) {
2840		goto done;
2841	}
2842
2843	init_lsa_String(&lsa_account_name, r->in.user_name);
2844
2845	status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
2846					 &domain_handle,
2847					 1,
2848					 &lsa_account_name,
2849					 &user_rids,
2850					 &name_types);
2851	if (!NT_STATUS_IS_OK(status)) {
2852		werr = ntstatus_to_werror(status);
2853		goto done;
2854	}
2855
2856	status = rpccli_samr_OpenUser(pipe_cli, talloc_tos(),
2857				      &domain_handle,
2858				      SAMR_USER_ACCESS_GET_GROUPS,
2859				      user_rids.ids[0],
2860				      &user_handle);
2861	if (!NT_STATUS_IS_OK(status)) {
2862		werr = ntstatus_to_werror(status);
2863		goto done;
2864	}
2865
2866	status = rpccli_samr_GetGroupsForUser(pipe_cli, talloc_tos(),
2867					      &user_handle,
2868					      &rid_array);
2869	if (!NT_STATUS_IS_OK(status)) {
2870		werr = ntstatus_to_werror(status);
2871		goto done;
2872	}
2873
2874	rids = talloc_array(ctx, uint32_t, rid_array->count);
2875	if (!rids) {
2876		werr = WERR_NOMEM;
2877		goto done;
2878	}
2879
2880	for (i=0; i < rid_array->count; i++) {
2881		rids[i] = rid_array->rids[i].rid;
2882	}
2883
2884	status = rpccli_samr_LookupRids(pipe_cli, talloc_tos(),
2885					&domain_handle,
2886					rid_array->count,
2887					rids,
2888					&names,
2889					&types);
2890	if (!NT_STATUS_IS_OK(status) &&
2891	    !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
2892		werr = ntstatus_to_werror(status);
2893		goto done;
2894	}
2895
2896	for (i=0; i < names.count; i++) {
2897		status = add_GROUP_USERS_INFO_X_buffer(ctx,
2898						       r->in.level,
2899						       names.names[i].string,
2900						       rid_array->rids[i].attributes,
2901						       r->out.buffer,
2902						       &entries_read);
2903		if (!NT_STATUS_IS_OK(status)) {
2904			werr = ntstatus_to_werror(status);
2905			goto done;
2906		}
2907	}
2908
2909	*r->out.entries_read = entries_read;
2910	*r->out.total_entries = entries_read;
2911
2912 done:
2913	if (ctx->disable_policy_handle_cache) {
2914		libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2915		libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2916	}
2917
2918	return werr;
2919}
2920
2921/****************************************************************
2922****************************************************************/
2923
2924WERROR NetUserGetGroups_l(struct libnetapi_ctx *ctx,
2925			  struct NetUserGetGroups *r)
2926{
2927	LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetGroups);
2928}
2929
2930/****************************************************************
2931****************************************************************/
2932
2933WERROR NetUserSetGroups_r(struct libnetapi_ctx *ctx,
2934			  struct NetUserSetGroups *r)
2935{
2936	struct rpc_pipe_client *pipe_cli = NULL;
2937	struct policy_handle connect_handle, domain_handle, user_handle, group_handle;
2938	struct lsa_String lsa_account_name;
2939	struct dom_sid2 *domain_sid = NULL;
2940	struct samr_Ids user_rids, name_types;
2941	struct samr_Ids group_rids;
2942	struct samr_RidWithAttributeArray *rid_array = NULL;
2943	struct lsa_String *lsa_names = NULL;
2944
2945	uint32_t *add_rids = NULL;
2946	uint32_t *del_rids = NULL;
2947	size_t num_add_rids = 0;
2948	size_t num_del_rids = 0;
2949
2950	uint32_t *member_rids = NULL;
2951	size_t num_member_rids = 0;
2952
2953	struct GROUP_USERS_INFO_0 *i0 = NULL;
2954	struct GROUP_USERS_INFO_1 *i1 = NULL;
2955
2956	int i, k;
2957
2958	NTSTATUS status = NT_STATUS_OK;
2959	WERROR werr;
2960
2961	ZERO_STRUCT(connect_handle);
2962	ZERO_STRUCT(domain_handle);
2963
2964	if (!r->in.buffer) {
2965		return WERR_INVALID_PARAM;
2966	}
2967
2968	switch (r->in.level) {
2969		case 0:
2970		case 1:
2971			break;
2972		default:
2973			return WERR_UNKNOWN_LEVEL;
2974	}
2975
2976	werr = libnetapi_open_pipe(ctx, r->in.server_name,
2977				   &ndr_table_samr.syntax_id,
2978				   &pipe_cli);
2979	if (!W_ERROR_IS_OK(werr)) {
2980		goto done;
2981	}
2982
2983	werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2984					  SAMR_ACCESS_ENUM_DOMAINS |
2985					  SAMR_ACCESS_LOOKUP_DOMAIN,
2986					  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2987					  &connect_handle,
2988					  &domain_handle,
2989					  &domain_sid);
2990	if (!W_ERROR_IS_OK(werr)) {
2991		goto done;
2992	}
2993
2994	init_lsa_String(&lsa_account_name, r->in.user_name);
2995
2996	status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
2997					 &domain_handle,
2998					 1,
2999					 &lsa_account_name,
3000					 &user_rids,
3001					 &name_types);
3002	if (!NT_STATUS_IS_OK(status)) {
3003		werr = ntstatus_to_werror(status);
3004		goto done;
3005	}
3006
3007	status = rpccli_samr_OpenUser(pipe_cli, talloc_tos(),
3008				      &domain_handle,
3009				      SAMR_USER_ACCESS_GET_GROUPS,
3010				      user_rids.ids[0],
3011				      &user_handle);
3012	if (!NT_STATUS_IS_OK(status)) {
3013		werr = ntstatus_to_werror(status);
3014		goto done;
3015	}
3016
3017	switch (r->in.level) {
3018		case 0:
3019			i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
3020			break;
3021		case 1:
3022			i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
3023			break;
3024	}
3025
3026	lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
3027	if (!lsa_names) {
3028		werr = WERR_NOMEM;
3029		goto done;
3030	}
3031
3032	for (i=0; i < r->in.num_entries; i++) {
3033
3034		switch (r->in.level) {
3035			case 0:
3036				init_lsa_String(&lsa_names[i], i0->grui0_name);
3037				i0++;
3038				break;
3039			case 1:
3040				init_lsa_String(&lsa_names[i], i1->grui1_name);
3041				i1++;
3042				break;
3043		}
3044	}
3045
3046	status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
3047					 &domain_handle,
3048					 r->in.num_entries,
3049					 lsa_names,
3050					 &group_rids,
3051					 &name_types);
3052	if (!NT_STATUS_IS_OK(status)) {
3053		werr = ntstatus_to_werror(status);
3054		goto done;
3055	}
3056
3057	member_rids = group_rids.ids;
3058	num_member_rids = group_rids.count;
3059
3060	status = rpccli_samr_GetGroupsForUser(pipe_cli, talloc_tos(),
3061					      &user_handle,
3062					      &rid_array);
3063	if (!NT_STATUS_IS_OK(status)) {
3064		werr = ntstatus_to_werror(status);
3065		goto done;
3066	}
3067
3068	/* add list */
3069
3070	for (i=0; i < r->in.num_entries; i++) {
3071		bool already_member = false;
3072		for (k=0; k < rid_array->count; k++) {
3073			if (member_rids[i] == rid_array->rids[k].rid) {
3074				already_member = true;
3075				break;
3076			}
3077		}
3078		if (!already_member) {
3079			if (!add_rid_to_array_unique(ctx,
3080						     member_rids[i],
3081						     &add_rids, &num_add_rids)) {
3082				werr = WERR_GENERAL_FAILURE;
3083				goto done;
3084			}
3085		}
3086	}
3087
3088	/* del list */
3089
3090	for (k=0; k < rid_array->count; k++) {
3091		bool keep_member = false;
3092		for (i=0; i < r->in.num_entries; i++) {
3093			if (member_rids[i] == rid_array->rids[k].rid) {
3094				keep_member = true;
3095				break;
3096			}
3097		}
3098		if (!keep_member) {
3099			if (!add_rid_to_array_unique(ctx,
3100						     rid_array->rids[k].rid,
3101						     &del_rids, &num_del_rids)) {
3102				werr = WERR_GENERAL_FAILURE;
3103				goto done;
3104			}
3105		}
3106	}
3107
3108	/* add list */
3109
3110	for (i=0; i < num_add_rids; i++) {
3111		status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(),
3112					       &domain_handle,
3113					       SAMR_GROUP_ACCESS_ADD_MEMBER,
3114					       add_rids[i],
3115					       &group_handle);
3116		if (!NT_STATUS_IS_OK(status)) {
3117			werr = ntstatus_to_werror(status);
3118			goto done;
3119		}
3120
3121		status = rpccli_samr_AddGroupMember(pipe_cli, talloc_tos(),
3122						    &group_handle,
3123						    user_rids.ids[0],
3124						    7 /* ? */);
3125		if (!NT_STATUS_IS_OK(status)) {
3126			werr = ntstatus_to_werror(status);
3127			goto done;
3128		}
3129
3130		if (is_valid_policy_hnd(&group_handle)) {
3131			rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle);
3132		}
3133	}
3134
3135	/* del list */
3136
3137	for (i=0; i < num_del_rids; i++) {
3138		status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(),
3139					       &domain_handle,
3140					       SAMR_GROUP_ACCESS_REMOVE_MEMBER,
3141					       del_rids[i],
3142					       &group_handle);
3143		if (!NT_STATUS_IS_OK(status)) {
3144			werr = ntstatus_to_werror(status);
3145			goto done;
3146		}
3147
3148		status = rpccli_samr_DeleteGroupMember(pipe_cli, talloc_tos(),
3149						       &group_handle,
3150						       user_rids.ids[0]);
3151		if (!NT_STATUS_IS_OK(status)) {
3152			werr = ntstatus_to_werror(status);
3153			goto done;
3154		}
3155
3156		if (is_valid_policy_hnd(&group_handle)) {
3157			rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle);
3158		}
3159	}
3160
3161	werr = WERR_OK;
3162
3163 done:
3164	if (is_valid_policy_hnd(&group_handle)) {
3165		rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle);
3166	}
3167
3168	if (ctx->disable_policy_handle_cache) {
3169		libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3170		libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3171	}
3172
3173	return werr;
3174}
3175
3176/****************************************************************
3177****************************************************************/
3178
3179WERROR NetUserSetGroups_l(struct libnetapi_ctx *ctx,
3180			  struct NetUserSetGroups *r)
3181{
3182	LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetGroups);
3183}
3184
3185/****************************************************************
3186****************************************************************/
3187
3188static NTSTATUS add_LOCALGROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
3189						   uint32_t level,
3190						   const char *group_name,
3191						   uint8_t **buffer,
3192						   uint32_t *num_entries)
3193{
3194	struct LOCALGROUP_USERS_INFO_0 u0;
3195
3196	switch (level) {
3197		case 0:
3198			u0.lgrui0_name = talloc_strdup(mem_ctx, group_name);
3199			NT_STATUS_HAVE_NO_MEMORY(u0.lgrui0_name);
3200
3201			ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_USERS_INFO_0, u0,
3202				     (struct LOCALGROUP_USERS_INFO_0 **)buffer, num_entries);
3203			break;
3204		default:
3205			return NT_STATUS_INVALID_INFO_CLASS;
3206	}
3207
3208	return NT_STATUS_OK;
3209}
3210
3211/****************************************************************
3212****************************************************************/
3213
3214WERROR NetUserGetLocalGroups_r(struct libnetapi_ctx *ctx,
3215			       struct NetUserGetLocalGroups *r)
3216{
3217	struct rpc_pipe_client *pipe_cli = NULL;
3218	struct policy_handle connect_handle, domain_handle, user_handle,
3219	builtin_handle;
3220	struct lsa_String lsa_account_name;
3221	struct dom_sid2 *domain_sid = NULL;
3222	struct samr_Ids user_rids, name_types;
3223	struct samr_RidWithAttributeArray *rid_array = NULL;
3224	struct lsa_Strings names;
3225	struct samr_Ids types;
3226	uint32_t *rids = NULL;
3227	size_t num_rids = 0;
3228	struct dom_sid user_sid;
3229	struct lsa_SidArray sid_array;
3230	struct samr_Ids domain_rids;
3231	struct samr_Ids builtin_rids;
3232
3233	int i;
3234	uint32_t entries_read = 0;
3235
3236	NTSTATUS status = NT_STATUS_OK;
3237	WERROR werr;
3238
3239	ZERO_STRUCT(connect_handle);
3240	ZERO_STRUCT(domain_handle);
3241
3242	if (!r->out.buffer) {
3243		return WERR_INVALID_PARAM;
3244	}
3245
3246	*r->out.buffer = NULL;
3247	*r->out.entries_read = 0;
3248	*r->out.total_entries = 0;
3249
3250	switch (r->in.level) {
3251		case 0:
3252		case 1:
3253			break;
3254		default:
3255			return WERR_UNKNOWN_LEVEL;
3256	}
3257
3258	werr = libnetapi_open_pipe(ctx, r->in.server_name,
3259				   &ndr_table_samr.syntax_id,
3260				   &pipe_cli);
3261	if (!W_ERROR_IS_OK(werr)) {
3262		goto done;
3263	}
3264
3265	werr = libnetapi_samr_open_domain(ctx, pipe_cli,
3266					  SAMR_ACCESS_ENUM_DOMAINS |
3267					  SAMR_ACCESS_LOOKUP_DOMAIN,
3268					  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
3269					  SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
3270					  &connect_handle,
3271					  &domain_handle,
3272					  &domain_sid);
3273	if (!W_ERROR_IS_OK(werr)) {
3274		goto done;
3275	}
3276
3277	werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
3278						  SAMR_ACCESS_ENUM_DOMAINS |
3279						  SAMR_ACCESS_LOOKUP_DOMAIN,
3280						  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
3281						  SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
3282						  &connect_handle,
3283						  &builtin_handle);
3284	if (!W_ERROR_IS_OK(werr)) {
3285		goto done;
3286	}
3287
3288	init_lsa_String(&lsa_account_name, r->in.user_name);
3289
3290	status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
3291					 &domain_handle,
3292					 1,
3293					 &lsa_account_name,
3294					 &user_rids,
3295					 &name_types);
3296	if (!NT_STATUS_IS_OK(status)) {
3297		werr = ntstatus_to_werror(status);
3298		goto done;
3299	}
3300
3301	status = rpccli_samr_OpenUser(pipe_cli, talloc_tos(),
3302				      &domain_handle,
3303				      SAMR_USER_ACCESS_GET_GROUPS,
3304				      user_rids.ids[0],
3305				      &user_handle);
3306	if (!NT_STATUS_IS_OK(status)) {
3307		werr = ntstatus_to_werror(status);
3308		goto done;
3309	}
3310
3311	status = rpccli_samr_GetGroupsForUser(pipe_cli, talloc_tos(),
3312					      &user_handle,
3313					      &rid_array);
3314	if (!NT_STATUS_IS_OK(status)) {
3315		werr = ntstatus_to_werror(status);
3316		goto done;
3317	}
3318
3319	if (!sid_compose(&user_sid, domain_sid, user_rids.ids[0])) {
3320		werr = WERR_NOMEM;
3321		goto done;
3322	}
3323
3324	sid_array.num_sids = rid_array->count + 1;
3325	sid_array.sids = TALLOC_ARRAY(ctx, struct lsa_SidPtr, sid_array.num_sids);
3326	if (!sid_array.sids) {
3327		werr = WERR_NOMEM;
3328		goto done;
3329	}
3330
3331	sid_array.sids[0].sid = sid_dup_talloc(ctx, &user_sid);
3332	if (!sid_array.sids[0].sid) {
3333		werr = WERR_NOMEM;
3334		goto done;
3335	}
3336
3337	for (i=0; i < rid_array->count; i++) {
3338		struct dom_sid sid;
3339
3340		if (!sid_compose(&sid, domain_sid, rid_array->rids[i].rid)) {
3341			werr = WERR_NOMEM;
3342			goto done;
3343		}
3344
3345		sid_array.sids[i+1].sid = sid_dup_talloc(ctx, &sid);
3346		if (!sid_array.sids[i+1].sid) {
3347			werr = WERR_NOMEM;
3348			goto done;
3349		}
3350	}
3351
3352	status = rpccli_samr_GetAliasMembership(pipe_cli, talloc_tos(),
3353						&domain_handle,
3354						&sid_array,
3355						&domain_rids);
3356	if (!NT_STATUS_IS_OK(status)) {
3357		werr = ntstatus_to_werror(status);
3358		goto done;
3359	}
3360
3361	for (i=0; i < domain_rids.count; i++) {
3362		if (!add_rid_to_array_unique(ctx, domain_rids.ids[i],
3363					     &rids, &num_rids)) {
3364			werr = WERR_NOMEM;
3365			goto done;
3366		}
3367	}
3368
3369	status = rpccli_samr_GetAliasMembership(pipe_cli, talloc_tos(),
3370						&builtin_handle,
3371						&sid_array,
3372						&builtin_rids);
3373	if (!NT_STATUS_IS_OK(status)) {
3374		werr = ntstatus_to_werror(status);
3375		goto done;
3376	}
3377
3378	for (i=0; i < builtin_rids.count; i++) {
3379		if (!add_rid_to_array_unique(ctx, builtin_rids.ids[i],
3380					     &rids, &num_rids)) {
3381			werr = WERR_NOMEM;
3382			goto done;
3383		}
3384	}
3385
3386	status = rpccli_samr_LookupRids(pipe_cli, talloc_tos(),
3387					&builtin_handle,
3388					num_rids,
3389					rids,
3390					&names,
3391					&types);
3392	if (!NT_STATUS_IS_OK(status)) {
3393		werr = ntstatus_to_werror(status);
3394		goto done;
3395	}
3396
3397	for (i=0; i < names.count; i++) {
3398		status = add_LOCALGROUP_USERS_INFO_X_buffer(ctx,
3399							    r->in.level,
3400							    names.names[i].string,
3401							    r->out.buffer,
3402							    &entries_read);
3403		if (!NT_STATUS_IS_OK(status)) {
3404			werr = ntstatus_to_werror(status);
3405			goto done;
3406		}
3407	}
3408
3409	*r->out.entries_read = entries_read;
3410	*r->out.total_entries = entries_read;
3411
3412 done:
3413	if (ctx->disable_policy_handle_cache) {
3414		libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3415		libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3416	}
3417
3418	return werr;
3419}
3420
3421/****************************************************************
3422****************************************************************/
3423
3424WERROR NetUserGetLocalGroups_l(struct libnetapi_ctx *ctx,
3425			       struct NetUserGetLocalGroups *r)
3426{
3427	LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetLocalGroups);
3428}
3429