s3-netapi: Fix Bug #6451: net/libnetapi user rename using wrong access bits.
[Samba.git] / source / lib / netapi / user.c
blobc989e180e6e3eabf44a0e3db4ac1e3c87f1b530d
1 /*
2 * Unix SMB/CIFS implementation.
3 * NetApi User Support
4 * Copyright (C) Guenther Deschner 2008
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.
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.
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/>.
20 #include "includes.h"
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"
27 /****************************************************************
28 ****************************************************************/
30 static void convert_USER_INFO_X_to_samr_user_info21(struct USER_INFO_X *infoX,
31 struct samr_UserInfo21 *info21)
33 uint32_t fields_present = 0;
34 struct samr_LogonHours zero_logon_hours;
35 struct lsa_BinaryString zero_parameters;
36 NTTIME password_age;
38 ZERO_STRUCTP(info21);
39 ZERO_STRUCT(zero_logon_hours);
40 ZERO_STRUCT(zero_parameters);
42 if (infoX->usriX_flags) {
43 fields_present |= SAMR_FIELD_ACCT_FLAGS;
45 if (infoX->usriX_name) {
46 fields_present |= SAMR_FIELD_ACCOUNT_NAME;
48 if (infoX->usriX_password) {
49 fields_present |= SAMR_FIELD_NT_PASSWORD_PRESENT;
51 if (infoX->usriX_flags) {
52 fields_present |= SAMR_FIELD_ACCT_FLAGS;
54 if (infoX->usriX_name) {
55 fields_present |= SAMR_FIELD_FULL_NAME;
57 if (infoX->usriX_home_dir) {
58 fields_present |= SAMR_FIELD_HOME_DIRECTORY;
60 if (infoX->usriX_script_path) {
61 fields_present |= SAMR_FIELD_LOGON_SCRIPT;
63 if (infoX->usriX_comment) {
64 fields_present |= SAMR_FIELD_DESCRIPTION;
66 if (infoX->usriX_password_age) {
67 fields_present |= SAMR_FIELD_FORCE_PWD_CHANGE;
69 if (infoX->usriX_full_name) {
70 fields_present |= SAMR_FIELD_FULL_NAME;
72 if (infoX->usriX_usr_comment) {
73 fields_present |= SAMR_FIELD_COMMENT;
75 if (infoX->usriX_profile) {
76 fields_present |= SAMR_FIELD_PROFILE_PATH;
78 if (infoX->usriX_home_dir_drive) {
79 fields_present |= SAMR_FIELD_HOME_DRIVE;
81 if (infoX->usriX_primary_group_id) {
82 fields_present |= SAMR_FIELD_PRIMARY_GID;
84 if (infoX->usriX_country_code) {
85 fields_present |= SAMR_FIELD_COUNTRY_CODE;
87 if (infoX->usriX_workstations) {
88 fields_present |= SAMR_FIELD_WORKSTATIONS;
91 unix_to_nt_time_abs(&password_age, infoX->usriX_password_age);
93 /* TODO: infoX->usriX_priv */
94 init_samr_user_info21(info21,
100 password_age,
101 infoX->usriX_name,
102 infoX->usriX_full_name,
103 infoX->usriX_home_dir,
104 infoX->usriX_home_dir_drive,
105 infoX->usriX_script_path,
106 infoX->usriX_profile,
107 infoX->usriX_comment,
108 infoX->usriX_workstations,
109 infoX->usriX_usr_comment,
110 &zero_parameters,
111 infoX->usriX_user_id,
112 infoX->usriX_primary_group_id,
113 infoX->usriX_flags,
114 fields_present,
115 zero_logon_hours,
116 infoX->usriX_bad_pw_count,
117 infoX->usriX_num_logons,
118 infoX->usriX_country_code,
119 infoX->usriX_code_page,
122 infoX->usriX_password_expired);
125 /****************************************************************
126 ****************************************************************/
128 static NTSTATUS construct_USER_INFO_X(uint32_t level,
129 uint8_t *buffer,
130 struct USER_INFO_X *uX)
132 struct USER_INFO_0 *u0 = NULL;
133 struct USER_INFO_1 *u1 = NULL;
134 struct USER_INFO_2 *u2 = NULL;
135 struct USER_INFO_3 *u3 = NULL;
136 struct USER_INFO_1003 *u1003 = NULL;
137 struct USER_INFO_1006 *u1006 = NULL;
138 struct USER_INFO_1007 *u1007 = NULL;
139 struct USER_INFO_1009 *u1009 = NULL;
140 struct USER_INFO_1011 *u1011 = NULL;
141 struct USER_INFO_1012 *u1012 = NULL;
142 struct USER_INFO_1014 *u1014 = NULL;
143 struct USER_INFO_1024 *u1024 = NULL;
144 struct USER_INFO_1051 *u1051 = NULL;
145 struct USER_INFO_1052 *u1052 = NULL;
146 struct USER_INFO_1053 *u1053 = NULL;
148 if (!buffer || !uX) {
149 return NT_STATUS_INVALID_PARAMETER;
152 ZERO_STRUCTP(uX);
154 switch (level) {
155 case 0:
156 u0 = (struct USER_INFO_0 *)buffer;
157 uX->usriX_name = u0->usri0_name;
158 break;
159 case 1:
160 u1 = (struct USER_INFO_1 *)buffer;
161 uX->usriX_name = u1->usri1_name;
162 uX->usriX_password = u1->usri1_password;
163 uX->usriX_password_age = u1->usri1_password_age;
164 uX->usriX_priv = u1->usri1_priv;
165 uX->usriX_home_dir = u1->usri1_home_dir;
166 uX->usriX_comment = u1->usri1_comment;
167 uX->usriX_flags = u1->usri1_flags;
168 uX->usriX_script_path = u1->usri1_script_path;
169 break;
170 case 2:
171 u2 = (struct USER_INFO_2 *)buffer;
172 uX->usriX_name = u2->usri2_name;
173 uX->usriX_password = u2->usri2_password;
174 uX->usriX_password_age = u2->usri2_password_age;
175 uX->usriX_priv = u2->usri2_priv;
176 uX->usriX_home_dir = u2->usri2_home_dir;
177 uX->usriX_comment = u2->usri2_comment;
178 uX->usriX_flags = u2->usri2_flags;
179 uX->usriX_script_path = u2->usri2_script_path;
180 uX->usriX_auth_flags = u2->usri2_auth_flags;
181 uX->usriX_full_name = u2->usri2_full_name;
182 uX->usriX_usr_comment = u2->usri2_usr_comment;
183 uX->usriX_parms = u2->usri2_parms;
184 uX->usriX_workstations = u2->usri2_workstations;
185 uX->usriX_last_logon = u2->usri2_last_logon;
186 uX->usriX_last_logoff = u2->usri2_last_logoff;
187 uX->usriX_acct_expires = u2->usri2_acct_expires;
188 uX->usriX_max_storage = u2->usri2_max_storage;
189 uX->usriX_units_per_week= u2->usri2_units_per_week;
190 uX->usriX_logon_hours = u2->usri2_logon_hours;
191 uX->usriX_bad_pw_count = u2->usri2_bad_pw_count;
192 uX->usriX_num_logons = u2->usri2_num_logons;
193 uX->usriX_logon_server = u2->usri2_logon_server;
194 uX->usriX_country_code = u2->usri2_country_code;
195 uX->usriX_code_page = u2->usri2_code_page;
196 break;
197 case 3:
198 u3 = (struct USER_INFO_3 *)buffer;
199 uX->usriX_name = u3->usri3_name;
200 uX->usriX_password_age = u3->usri3_password_age;
201 uX->usriX_priv = u3->usri3_priv;
202 uX->usriX_home_dir = u3->usri3_home_dir;
203 uX->usriX_comment = u3->usri3_comment;
204 uX->usriX_flags = u3->usri3_flags;
205 uX->usriX_script_path = u3->usri3_script_path;
206 uX->usriX_auth_flags = u3->usri3_auth_flags;
207 uX->usriX_full_name = u3->usri3_full_name;
208 uX->usriX_usr_comment = u3->usri3_usr_comment;
209 uX->usriX_parms = u3->usri3_parms;
210 uX->usriX_workstations = u3->usri3_workstations;
211 uX->usriX_last_logon = u3->usri3_last_logon;
212 uX->usriX_last_logoff = u3->usri3_last_logoff;
213 uX->usriX_acct_expires = u3->usri3_acct_expires;
214 uX->usriX_max_storage = u3->usri3_max_storage;
215 uX->usriX_units_per_week= u3->usri3_units_per_week;
216 uX->usriX_logon_hours = u3->usri3_logon_hours;
217 uX->usriX_bad_pw_count = u3->usri3_bad_pw_count;
218 uX->usriX_num_logons = u3->usri3_num_logons;
219 uX->usriX_logon_server = u3->usri3_logon_server;
220 uX->usriX_country_code = u3->usri3_country_code;
221 uX->usriX_code_page = u3->usri3_code_page;
222 uX->usriX_user_id = u3->usri3_user_id;
223 uX->usriX_primary_group_id = u3->usri3_primary_group_id;
224 uX->usriX_profile = u3->usri3_profile;
225 uX->usriX_home_dir_drive = u3->usri3_home_dir_drive;
226 uX->usriX_password_expired = u3->usri3_password_expired;
227 break;
228 case 1003:
229 u1003 = (struct USER_INFO_1003 *)buffer;
230 uX->usriX_password = u1003->usri1003_password;
231 break;
232 case 1006:
233 u1006 = (struct USER_INFO_1006 *)buffer;
234 uX->usriX_home_dir = u1006->usri1006_home_dir;
235 break;
236 case 1007:
237 u1007 = (struct USER_INFO_1007 *)buffer;
238 uX->usriX_comment = u1007->usri1007_comment;
239 break;
240 case 1009:
241 u1009 = (struct USER_INFO_1009 *)buffer;
242 uX->usriX_script_path = u1009->usri1009_script_path;
243 break;
244 case 1011:
245 u1011 = (struct USER_INFO_1011 *)buffer;
246 uX->usriX_full_name = u1011->usri1011_full_name;
247 break;
248 case 1012:
249 u1012 = (struct USER_INFO_1012 *)buffer;
250 uX->usriX_usr_comment = u1012->usri1012_usr_comment;
251 break;
252 case 1014:
253 u1014 = (struct USER_INFO_1014 *)buffer;
254 uX->usriX_workstations = u1014->usri1014_workstations;
255 break;
256 case 1024:
257 u1024 = (struct USER_INFO_1024 *)buffer;
258 uX->usriX_country_code = u1024->usri1024_country_code;
259 break;
260 case 1051:
261 u1051 = (struct USER_INFO_1051 *)buffer;
262 uX->usriX_primary_group_id = u1051->usri1051_primary_group_id;
263 break;
264 case 1052:
265 u1052 = (struct USER_INFO_1052 *)buffer;
266 uX->usriX_profile = u1052->usri1052_profile;
267 break;
268 case 1053:
269 u1053 = (struct USER_INFO_1053 *)buffer;
270 uX->usriX_home_dir_drive = u1053->usri1053_home_dir_drive;
271 break;
272 case 4:
273 default:
274 return NT_STATUS_INVALID_INFO_CLASS;
277 return NT_STATUS_OK;
280 /****************************************************************
281 ****************************************************************/
283 static NTSTATUS set_user_info_USER_INFO_X(TALLOC_CTX *ctx,
284 struct rpc_pipe_client *pipe_cli,
285 DATA_BLOB *session_key,
286 struct policy_handle *user_handle,
287 struct USER_INFO_X *uX)
289 union samr_UserInfo user_info;
290 struct samr_UserInfo21 info21;
291 NTSTATUS status;
293 if (!uX) {
294 return NT_STATUS_INVALID_PARAMETER;
297 convert_USER_INFO_X_to_samr_user_info21(uX, &info21);
299 ZERO_STRUCT(user_info);
301 if (uX->usriX_password) {
303 user_info.info25.info = info21;
305 init_samr_CryptPasswordEx(uX->usriX_password,
306 session_key,
307 &user_info.info25.password);
309 status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
310 user_handle,
312 &user_info);
314 if (NT_STATUS_EQUAL(status, NT_STATUS(DCERPC_FAULT_INVALID_TAG))) {
316 user_info.info23.info = info21;
318 init_samr_CryptPassword(uX->usriX_password,
319 session_key,
320 &user_info.info23.password);
322 status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
323 user_handle,
325 &user_info);
327 } else {
329 user_info.info21 = info21;
331 status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
332 user_handle,
334 &user_info);
337 return status;
340 /****************************************************************
341 ****************************************************************/
343 WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
344 struct NetUserAdd *r)
346 struct cli_state *cli = NULL;
347 struct rpc_pipe_client *pipe_cli = NULL;
348 NTSTATUS status;
349 WERROR werr;
350 POLICY_HND connect_handle, domain_handle, user_handle;
351 struct lsa_String lsa_account_name;
352 struct dom_sid2 *domain_sid = NULL;
353 union samr_UserInfo *user_info = NULL;
354 struct samr_PwInfo pw_info;
355 uint32_t access_granted = 0;
356 uint32_t rid = 0;
357 struct USER_INFO_X uX;
359 ZERO_STRUCT(connect_handle);
360 ZERO_STRUCT(domain_handle);
361 ZERO_STRUCT(user_handle);
363 if (!r->in.buffer) {
364 return WERR_INVALID_PARAM;
367 switch (r->in.level) {
368 case 1:
369 break;
370 case 2:
371 case 3:
372 case 4:
373 default:
374 werr = WERR_NOT_SUPPORTED;
375 goto done;
378 werr = libnetapi_open_pipe(ctx, r->in.server_name,
379 &ndr_table_samr.syntax_id,
380 &cli,
381 &pipe_cli);
382 if (!W_ERROR_IS_OK(werr)) {
383 goto done;
386 status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
387 if (!NT_STATUS_IS_OK(status)) {
388 werr = ntstatus_to_werror(status);
389 goto done;
392 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
393 SAMR_ACCESS_ENUM_DOMAINS |
394 SAMR_ACCESS_LOOKUP_DOMAIN,
395 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
396 SAMR_DOMAIN_ACCESS_CREATE_USER |
397 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
398 &connect_handle,
399 &domain_handle,
400 &domain_sid);
401 if (!W_ERROR_IS_OK(werr)) {
402 goto done;
405 init_lsa_String(&lsa_account_name, uX.usriX_name);
407 status = rpccli_samr_CreateUser2(pipe_cli, ctx,
408 &domain_handle,
409 &lsa_account_name,
410 ACB_NORMAL,
411 SEC_STD_WRITE_DAC |
412 SEC_STD_DELETE |
413 SAMR_USER_ACCESS_SET_PASSWORD |
414 SAMR_USER_ACCESS_SET_ATTRIBUTES |
415 SAMR_USER_ACCESS_GET_ATTRIBUTES,
416 &user_handle,
417 &access_granted,
418 &rid);
419 if (!NT_STATUS_IS_OK(status)) {
420 werr = ntstatus_to_werror(status);
421 goto done;
424 status = rpccli_samr_QueryUserInfo(pipe_cli, ctx,
425 &user_handle,
427 &user_info);
428 if (!NT_STATUS_IS_OK(status)) {
429 werr = ntstatus_to_werror(status);
430 goto done;
433 if (!(user_info->info16.acct_flags & ACB_NORMAL)) {
434 werr = WERR_INVALID_PARAM;
435 goto done;
438 status = rpccli_samr_GetUserPwInfo(pipe_cli, ctx,
439 &user_handle,
440 &pw_info);
441 if (!NT_STATUS_IS_OK(status)) {
442 werr = ntstatus_to_werror(status);
443 goto done;
446 uX.usriX_flags |= ACB_NORMAL;
448 status = set_user_info_USER_INFO_X(ctx, pipe_cli,
449 &cli->user_session_key,
450 &user_handle,
451 &uX);
452 if (!NT_STATUS_IS_OK(status)) {
453 werr = ntstatus_to_werror(status);
454 goto failed;
457 werr = WERR_OK;
458 goto done;
460 failed:
461 rpccli_samr_DeleteUser(pipe_cli, ctx,
462 &user_handle);
464 done:
465 if (!cli) {
466 return werr;
469 if (is_valid_policy_hnd(&user_handle)) {
470 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
473 if (ctx->disable_policy_handle_cache) {
474 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
475 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
478 return werr;
481 /****************************************************************
482 ****************************************************************/
484 WERROR NetUserAdd_l(struct libnetapi_ctx *ctx,
485 struct NetUserAdd *r)
487 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserAdd);
490 /****************************************************************
491 ****************************************************************/
493 WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
494 struct NetUserDel *r)
496 struct cli_state *cli = NULL;
497 struct rpc_pipe_client *pipe_cli = NULL;
498 NTSTATUS status;
499 WERROR werr;
500 POLICY_HND connect_handle, builtin_handle, domain_handle, user_handle;
501 struct lsa_String lsa_account_name;
502 struct samr_Ids user_rids, name_types;
503 struct dom_sid2 *domain_sid = NULL;
504 struct dom_sid2 user_sid;
506 ZERO_STRUCT(connect_handle);
507 ZERO_STRUCT(builtin_handle);
508 ZERO_STRUCT(domain_handle);
509 ZERO_STRUCT(user_handle);
511 werr = libnetapi_open_pipe(ctx, r->in.server_name,
512 &ndr_table_samr.syntax_id,
513 &cli,
514 &pipe_cli);
516 if (!W_ERROR_IS_OK(werr)) {
517 goto done;
520 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
521 SAMR_ACCESS_ENUM_DOMAINS |
522 SAMR_ACCESS_LOOKUP_DOMAIN,
523 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
524 &connect_handle,
525 &domain_handle,
526 &domain_sid);
527 if (!W_ERROR_IS_OK(werr)) {
528 goto done;
531 status = rpccli_samr_OpenDomain(pipe_cli, ctx,
532 &connect_handle,
533 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
534 CONST_DISCARD(DOM_SID *, &global_sid_Builtin),
535 &builtin_handle);
536 if (!NT_STATUS_IS_OK(status)) {
537 werr = ntstatus_to_werror(status);
538 goto done;
541 init_lsa_String(&lsa_account_name, r->in.user_name);
543 status = rpccli_samr_LookupNames(pipe_cli, ctx,
544 &domain_handle,
546 &lsa_account_name,
547 &user_rids,
548 &name_types);
549 if (!NT_STATUS_IS_OK(status)) {
550 werr = ntstatus_to_werror(status);
551 goto done;
554 status = rpccli_samr_OpenUser(pipe_cli, ctx,
555 &domain_handle,
556 SEC_STD_DELETE,
557 user_rids.ids[0],
558 &user_handle);
559 if (!NT_STATUS_IS_OK(status)) {
560 werr = ntstatus_to_werror(status);
561 goto done;
564 sid_compose(&user_sid, domain_sid, user_rids.ids[0]);
566 status = rpccli_samr_RemoveMemberFromForeignDomain(pipe_cli, ctx,
567 &builtin_handle,
568 &user_sid);
569 if (!NT_STATUS_IS_OK(status)) {
570 werr = ntstatus_to_werror(status);
571 goto done;
574 status = rpccli_samr_DeleteUser(pipe_cli, ctx,
575 &user_handle);
576 if (!NT_STATUS_IS_OK(status)) {
577 werr = ntstatus_to_werror(status);
578 goto done;
581 werr = WERR_OK;
583 done:
584 if (!cli) {
585 return werr;
588 if (is_valid_policy_hnd(&user_handle)) {
589 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
592 if (ctx->disable_policy_handle_cache) {
593 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
594 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
595 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
598 return werr;
601 /****************************************************************
602 ****************************************************************/
604 WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
605 struct NetUserDel *r)
607 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserDel);
610 /****************************************************************
611 ****************************************************************/
613 static NTSTATUS libnetapi_samr_lookup_user(TALLOC_CTX *mem_ctx,
614 struct rpc_pipe_client *pipe_cli,
615 struct policy_handle *domain_handle,
616 struct policy_handle *builtin_handle,
617 const char *user_name,
618 const struct dom_sid *domain_sid,
619 uint32_t rid,
620 uint32_t level,
621 struct samr_UserInfo21 **info21,
622 struct sec_desc_buf **sec_desc,
623 uint32_t *auth_flag_p)
625 NTSTATUS status;
627 struct policy_handle user_handle;
628 union samr_UserInfo *user_info = NULL;
629 struct samr_RidWithAttributeArray *rid_array = NULL;
630 uint32_t access_mask = SEC_STD_READ_CONTROL |
631 SAMR_USER_ACCESS_GET_ATTRIBUTES |
632 SAMR_USER_ACCESS_GET_NAME_ETC;
634 ZERO_STRUCT(user_handle);
636 switch (level) {
637 case 0:
638 break;
639 case 1:
640 access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
641 SAMR_USER_ACCESS_GET_GROUPS;
642 break;
643 case 2:
644 case 3:
645 case 4:
646 case 11:
647 access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
648 SAMR_USER_ACCESS_GET_GROUPS |
649 SAMR_USER_ACCESS_GET_LOCALE;
650 break;
651 case 10:
652 case 20:
653 case 23:
654 break;
655 default:
656 return NT_STATUS_INVALID_LEVEL;
659 if (level == 0) {
660 return NT_STATUS_OK;
663 status = rpccli_samr_OpenUser(pipe_cli, mem_ctx,
664 domain_handle,
665 access_mask,
666 rid,
667 &user_handle);
668 if (!NT_STATUS_IS_OK(status)) {
669 goto done;
672 status = rpccli_samr_QueryUserInfo(pipe_cli, mem_ctx,
673 &user_handle,
675 &user_info);
676 if (!NT_STATUS_IS_OK(status)) {
677 goto done;
680 status = rpccli_samr_QuerySecurity(pipe_cli, mem_ctx,
681 &user_handle,
682 SECINFO_DACL,
683 sec_desc);
684 if (!NT_STATUS_IS_OK(status)) {
685 goto done;
688 if (access_mask & SAMR_USER_ACCESS_GET_GROUPS) {
690 struct lsa_SidArray sid_array;
691 struct samr_Ids alias_rids;
692 int i;
693 uint32_t auth_flag = 0;
694 struct dom_sid sid;
696 status = rpccli_samr_GetGroupsForUser(pipe_cli, mem_ctx,
697 &user_handle,
698 &rid_array);
699 if (!NT_STATUS_IS_OK(status)) {
700 goto done;
703 sid_array.num_sids = rid_array->count + 1;
704 sid_array.sids = talloc_array(mem_ctx, struct lsa_SidPtr,
705 sid_array.num_sids);
706 NT_STATUS_HAVE_NO_MEMORY(sid_array.sids);
708 for (i=0; i<rid_array->count; i++) {
709 sid_compose(&sid, domain_sid, rid_array->rids[i].rid);
710 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sid);
711 NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
714 sid_compose(&sid, domain_sid, rid);
715 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sid);
716 NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
718 status = rpccli_samr_GetAliasMembership(pipe_cli, mem_ctx,
719 builtin_handle,
720 &sid_array,
721 &alias_rids);
722 if (!NT_STATUS_IS_OK(status)) {
723 goto done;
726 for (i=0; i<alias_rids.count; i++) {
727 switch (alias_rids.ids[i]) {
728 case 550: /* Print Operators */
729 auth_flag |= AF_OP_PRINT;
730 break;
731 case 549: /* Server Operators */
732 auth_flag |= AF_OP_SERVER;
733 break;
734 case 548: /* Account Operators */
735 auth_flag |= AF_OP_ACCOUNTS;
736 break;
737 default:
738 break;
742 if (auth_flag_p) {
743 *auth_flag_p = auth_flag;
747 *info21 = &user_info->info21;
749 done:
750 if (is_valid_policy_hnd(&user_handle)) {
751 rpccli_samr_Close(pipe_cli, mem_ctx, &user_handle);
754 return status;
757 /****************************************************************
758 ****************************************************************/
760 static uint32_t samr_rid_to_priv_level(uint32_t rid)
762 switch (rid) {
763 case DOMAIN_RID_ADMINISTRATOR:
764 return USER_PRIV_ADMIN;
765 case DOMAIN_RID_GUEST:
766 return USER_PRIV_GUEST;
767 default:
768 return USER_PRIV_USER;
772 /****************************************************************
773 ****************************************************************/
775 static uint32_t samr_acb_flags_to_netapi_flags(uint32_t acb)
777 uint32_t fl = UF_SCRIPT; /* god knows why */
779 fl |= ads_acb2uf(acb);
781 return fl;
784 /****************************************************************
785 ****************************************************************/
787 static NTSTATUS info21_to_USER_INFO_1(TALLOC_CTX *mem_ctx,
788 const struct samr_UserInfo21 *i21,
789 struct USER_INFO_1 *i)
791 ZERO_STRUCTP(i);
792 i->usri1_name = talloc_strdup(mem_ctx, i21->account_name.string);
793 NT_STATUS_HAVE_NO_MEMORY(i->usri1_name);
794 i->usri1_password = NULL;
795 i->usri1_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
796 i->usri1_priv = samr_rid_to_priv_level(i21->rid);
797 i->usri1_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
798 i->usri1_comment = talloc_strdup(mem_ctx, i21->description.string);
799 i->usri1_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
800 i->usri1_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
802 return NT_STATUS_OK;
805 /****************************************************************
806 ****************************************************************/
808 static NTSTATUS info21_to_USER_INFO_2(TALLOC_CTX *mem_ctx,
809 const struct samr_UserInfo21 *i21,
810 uint32_t auth_flag,
811 struct USER_INFO_2 *i)
813 ZERO_STRUCTP(i);
815 i->usri2_name = talloc_strdup(mem_ctx, i21->account_name.string);
816 NT_STATUS_HAVE_NO_MEMORY(i->usri2_name);
817 i->usri2_password = NULL;
818 i->usri2_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
819 i->usri2_priv = samr_rid_to_priv_level(i21->rid);
820 i->usri2_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
821 i->usri2_comment = talloc_strdup(mem_ctx, i21->description.string);
822 i->usri2_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
823 i->usri2_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
824 i->usri2_auth_flags = auth_flag;
825 i->usri2_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
826 i->usri2_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
827 i->usri2_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
828 i->usri2_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
829 i->usri2_last_logon = nt_time_to_unix(i21->last_logon);
830 i->usri2_last_logoff = nt_time_to_unix(i21->last_logoff);
831 i->usri2_acct_expires = nt_time_to_unix(i21->acct_expiry);
832 i->usri2_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
833 i->usri2_units_per_week = i21->logon_hours.units_per_week;
834 i->usri2_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
835 i->usri2_bad_pw_count = i21->bad_password_count;
836 i->usri2_num_logons = i21->logon_count;
837 i->usri2_logon_server = talloc_strdup(mem_ctx, "\\\\*");
838 i->usri2_country_code = i21->country_code;
839 i->usri2_code_page = i21->code_page;
841 return NT_STATUS_OK;
844 /****************************************************************
845 ****************************************************************/
847 static NTSTATUS info21_to_USER_INFO_3(TALLOC_CTX *mem_ctx,
848 const struct samr_UserInfo21 *i21,
849 uint32_t auth_flag,
850 struct USER_INFO_3 *i)
852 ZERO_STRUCTP(i);
854 i->usri3_name = talloc_strdup(mem_ctx, i21->account_name.string);
855 NT_STATUS_HAVE_NO_MEMORY(i->usri3_name);
856 i->usri3_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
857 i->usri3_priv = samr_rid_to_priv_level(i21->rid);
858 i->usri3_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
859 i->usri3_comment = talloc_strdup(mem_ctx, i21->description.string);
860 i->usri3_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
861 i->usri3_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
862 i->usri3_auth_flags = auth_flag;
863 i->usri3_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
864 i->usri3_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
865 i->usri3_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
866 i->usri3_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
867 i->usri3_last_logon = nt_time_to_unix(i21->last_logon);
868 i->usri3_last_logoff = nt_time_to_unix(i21->last_logoff);
869 i->usri3_acct_expires = nt_time_to_unix(i21->acct_expiry);
870 i->usri3_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
871 i->usri3_units_per_week = i21->logon_hours.units_per_week;
872 i->usri3_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
873 i->usri3_bad_pw_count = i21->bad_password_count;
874 i->usri3_num_logons = i21->logon_count;
875 i->usri3_logon_server = talloc_strdup(mem_ctx, "\\\\*");
876 i->usri3_country_code = i21->country_code;
877 i->usri3_code_page = i21->code_page;
878 i->usri3_user_id = i21->rid;
879 i->usri3_primary_group_id = i21->primary_gid;
880 i->usri3_profile = talloc_strdup(mem_ctx, i21->profile_path.string);
881 i->usri3_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
882 i->usri3_password_expired = i21->password_expired;
884 return NT_STATUS_OK;
887 /****************************************************************
888 ****************************************************************/
890 static NTSTATUS info21_to_USER_INFO_4(TALLOC_CTX *mem_ctx,
891 const struct samr_UserInfo21 *i21,
892 uint32_t auth_flag,
893 struct dom_sid *domain_sid,
894 struct USER_INFO_4 *i)
896 struct dom_sid sid;
898 ZERO_STRUCTP(i);
900 i->usri4_name = talloc_strdup(mem_ctx, i21->account_name.string);
901 NT_STATUS_HAVE_NO_MEMORY(i->usri4_name);
902 i->usri4_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
903 i->usri4_password = NULL;
904 i->usri4_priv = samr_rid_to_priv_level(i21->rid);
905 i->usri4_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
906 i->usri4_comment = talloc_strdup(mem_ctx, i21->description.string);
907 i->usri4_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
908 i->usri4_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
909 i->usri4_auth_flags = auth_flag;
910 i->usri4_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
911 i->usri4_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
912 i->usri4_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
913 i->usri4_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
914 i->usri4_last_logon = nt_time_to_unix(i21->last_logon);
915 i->usri4_last_logoff = nt_time_to_unix(i21->last_logoff);
916 i->usri4_acct_expires = nt_time_to_unix(i21->acct_expiry);
917 i->usri4_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
918 i->usri4_units_per_week = i21->logon_hours.units_per_week;
919 i->usri4_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
920 i->usri4_bad_pw_count = i21->bad_password_count;
921 i->usri4_num_logons = i21->logon_count;
922 i->usri4_logon_server = talloc_strdup(mem_ctx, "\\\\*");
923 i->usri4_country_code = i21->country_code;
924 i->usri4_code_page = i21->code_page;
925 if (!sid_compose(&sid, domain_sid, i21->rid)) {
926 return NT_STATUS_NO_MEMORY;
928 i->usri4_user_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
929 i->usri4_primary_group_id = i21->primary_gid;
930 i->usri4_profile = talloc_strdup(mem_ctx, i21->profile_path.string);
931 i->usri4_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
932 i->usri4_password_expired = i21->password_expired;
934 return NT_STATUS_OK;
937 /****************************************************************
938 ****************************************************************/
940 static NTSTATUS info21_to_USER_INFO_10(TALLOC_CTX *mem_ctx,
941 const struct samr_UserInfo21 *i21,
942 struct USER_INFO_10 *i)
944 ZERO_STRUCTP(i);
946 i->usri10_name = talloc_strdup(mem_ctx, i21->account_name.string);
947 NT_STATUS_HAVE_NO_MEMORY(i->usri10_name);
948 i->usri10_comment = talloc_strdup(mem_ctx, i21->description.string);
949 i->usri10_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
950 i->usri10_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
952 return NT_STATUS_OK;
955 /****************************************************************
956 ****************************************************************/
958 static NTSTATUS info21_to_USER_INFO_11(TALLOC_CTX *mem_ctx,
959 const struct samr_UserInfo21 *i21,
960 uint32_t auth_flag,
961 struct USER_INFO_11 *i)
963 ZERO_STRUCTP(i);
965 i->usri11_name = talloc_strdup(mem_ctx, i21->account_name.string);
966 NT_STATUS_HAVE_NO_MEMORY(i->usri11_name);
967 i->usri11_comment = talloc_strdup(mem_ctx, i21->description.string);
968 i->usri11_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
969 i->usri11_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
970 i->usri11_priv = samr_rid_to_priv_level(i21->rid);
971 i->usri11_auth_flags = auth_flag;
972 i->usri11_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
973 i->usri11_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
974 i->usri11_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
975 i->usri11_last_logon = nt_time_to_unix(i21->last_logon);
976 i->usri11_last_logoff = nt_time_to_unix(i21->last_logoff);
977 i->usri11_bad_pw_count = i21->bad_password_count;
978 i->usri11_num_logons = i21->logon_count;
979 i->usri11_logon_server = talloc_strdup(mem_ctx, "\\\\*");
980 i->usri11_country_code = i21->country_code;
981 i->usri11_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
982 i->usri11_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
983 i->usri11_units_per_week = i21->logon_hours.units_per_week;
984 i->usri11_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
985 i->usri11_code_page = i21->code_page;
987 return NT_STATUS_OK;
990 /****************************************************************
991 ****************************************************************/
993 static NTSTATUS info21_to_USER_INFO_20(TALLOC_CTX *mem_ctx,
994 const struct samr_UserInfo21 *i21,
995 struct USER_INFO_20 *i)
997 ZERO_STRUCTP(i);
999 i->usri20_name = talloc_strdup(mem_ctx, i21->account_name.string);
1000 NT_STATUS_HAVE_NO_MEMORY(i->usri20_name);
1001 i->usri20_comment = talloc_strdup(mem_ctx, i21->description.string);
1002 i->usri20_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
1003 i->usri20_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
1004 i->usri20_user_id = i21->rid;
1006 return NT_STATUS_OK;
1009 /****************************************************************
1010 ****************************************************************/
1012 static NTSTATUS info21_to_USER_INFO_23(TALLOC_CTX *mem_ctx,
1013 const struct samr_UserInfo21 *i21,
1014 struct dom_sid *domain_sid,
1015 struct USER_INFO_23 *i)
1017 struct dom_sid sid;
1019 ZERO_STRUCTP(i);
1021 i->usri23_name = talloc_strdup(mem_ctx, i21->account_name.string);
1022 NT_STATUS_HAVE_NO_MEMORY(i->usri23_name);
1023 i->usri23_comment = talloc_strdup(mem_ctx, i21->description.string);
1024 i->usri23_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
1025 i->usri23_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
1026 if (!sid_compose(&sid, domain_sid, i21->rid)) {
1027 return NT_STATUS_NO_MEMORY;
1029 i->usri23_user_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
1031 return NT_STATUS_OK;
1034 /****************************************************************
1035 ****************************************************************/
1037 static NTSTATUS libnetapi_samr_lookup_user_map_USER_INFO(TALLOC_CTX *mem_ctx,
1038 struct rpc_pipe_client *pipe_cli,
1039 struct dom_sid *domain_sid,
1040 struct policy_handle *domain_handle,
1041 struct policy_handle *builtin_handle,
1042 const char *user_name,
1043 uint32_t rid,
1044 uint32_t level,
1045 uint8_t **buffer,
1046 uint32_t *num_entries)
1048 NTSTATUS status;
1050 struct samr_UserInfo21 *info21 = NULL;
1051 struct sec_desc_buf *sec_desc = NULL;
1052 uint32_t auth_flag = 0;
1054 struct USER_INFO_0 info0;
1055 struct USER_INFO_1 info1;
1056 struct USER_INFO_2 info2;
1057 struct USER_INFO_3 info3;
1058 struct USER_INFO_4 info4;
1059 struct USER_INFO_10 info10;
1060 struct USER_INFO_11 info11;
1061 struct USER_INFO_20 info20;
1062 struct USER_INFO_23 info23;
1064 switch (level) {
1065 case 0:
1066 case 1:
1067 case 2:
1068 case 3:
1069 case 4:
1070 case 10:
1071 case 11:
1072 case 20:
1073 case 23:
1074 break;
1075 default:
1076 return NT_STATUS_INVALID_LEVEL;
1079 if (level == 0) {
1080 info0.usri0_name = talloc_strdup(mem_ctx, user_name);
1081 NT_STATUS_HAVE_NO_MEMORY(info0.usri0_name);
1083 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_0, info0,
1084 (struct USER_INFO_0 **)buffer, num_entries);
1086 return NT_STATUS_OK;
1089 status = libnetapi_samr_lookup_user(mem_ctx, pipe_cli,
1090 domain_handle,
1091 builtin_handle,
1092 user_name,
1093 domain_sid,
1094 rid,
1095 level,
1096 &info21,
1097 &sec_desc,
1098 &auth_flag);
1100 if (!NT_STATUS_IS_OK(status)) {
1101 goto done;
1104 switch (level) {
1105 case 0:
1106 /* already returned above */
1107 break;
1108 case 1:
1109 status = info21_to_USER_INFO_1(mem_ctx, info21, &info1);
1110 NT_STATUS_NOT_OK_RETURN(status);
1112 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_1, info1,
1113 (struct USER_INFO_1 **)buffer, num_entries);
1115 break;
1116 case 2:
1117 status = info21_to_USER_INFO_2(mem_ctx, info21, auth_flag, &info2);
1118 NT_STATUS_NOT_OK_RETURN(status);
1120 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_2, info2,
1121 (struct USER_INFO_2 **)buffer, num_entries);
1123 break;
1124 case 3:
1125 status = info21_to_USER_INFO_3(mem_ctx, info21, auth_flag, &info3);
1126 NT_STATUS_NOT_OK_RETURN(status);
1128 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_3, info3,
1129 (struct USER_INFO_3 **)buffer, num_entries);
1131 break;
1132 case 4:
1133 status = info21_to_USER_INFO_4(mem_ctx, info21, auth_flag, domain_sid, &info4);
1134 NT_STATUS_NOT_OK_RETURN(status);
1136 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_4, info4,
1137 (struct USER_INFO_4 **)buffer, num_entries);
1139 break;
1140 case 10:
1141 status = info21_to_USER_INFO_10(mem_ctx, info21, &info10);
1142 NT_STATUS_NOT_OK_RETURN(status);
1144 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_10, info10,
1145 (struct USER_INFO_10 **)buffer, num_entries);
1147 break;
1148 case 11:
1149 status = info21_to_USER_INFO_11(mem_ctx, info21, auth_flag, &info11);
1150 NT_STATUS_NOT_OK_RETURN(status);
1152 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_11, info11,
1153 (struct USER_INFO_11 **)buffer, num_entries);
1155 break;
1156 case 20:
1157 status = info21_to_USER_INFO_20(mem_ctx, info21, &info20);
1158 NT_STATUS_NOT_OK_RETURN(status);
1160 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_20, info20,
1161 (struct USER_INFO_20 **)buffer, num_entries);
1163 break;
1164 case 23:
1165 status = info21_to_USER_INFO_23(mem_ctx, info21, domain_sid, &info23);
1166 NT_STATUS_NOT_OK_RETURN(status);
1168 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_23, info23,
1169 (struct USER_INFO_23 **)buffer, num_entries);
1170 break;
1171 default:
1172 return NT_STATUS_INVALID_LEVEL;
1175 done:
1176 return status;
1179 /****************************************************************
1180 ****************************************************************/
1182 WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
1183 struct NetUserEnum *r)
1185 struct cli_state *cli = NULL;
1186 struct rpc_pipe_client *pipe_cli = NULL;
1187 struct policy_handle connect_handle;
1188 struct dom_sid2 *domain_sid = NULL;
1189 struct policy_handle domain_handle, builtin_handle;
1190 struct samr_SamArray *sam = NULL;
1191 uint32_t filter = ACB_NORMAL;
1192 int i;
1193 uint32_t entries_read = 0;
1195 NTSTATUS status = NT_STATUS_OK;
1196 WERROR werr;
1198 ZERO_STRUCT(connect_handle);
1199 ZERO_STRUCT(domain_handle);
1200 ZERO_STRUCT(builtin_handle);
1202 if (!r->out.buffer) {
1203 return WERR_INVALID_PARAM;
1206 *r->out.buffer = NULL;
1207 *r->out.entries_read = 0;
1209 switch (r->in.level) {
1210 case 0:
1211 case 1:
1212 case 2:
1213 case 3:
1214 case 4:
1215 case 10:
1216 case 11:
1217 case 20:
1218 case 23:
1219 break;
1220 default:
1221 return WERR_UNKNOWN_LEVEL;
1224 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1225 &ndr_table_samr.syntax_id,
1226 &cli,
1227 &pipe_cli);
1228 if (!W_ERROR_IS_OK(werr)) {
1229 goto done;
1232 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1233 SAMR_ACCESS_ENUM_DOMAINS |
1234 SAMR_ACCESS_LOOKUP_DOMAIN,
1235 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1236 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1237 &connect_handle,
1238 &builtin_handle);
1239 if (!W_ERROR_IS_OK(werr)) {
1240 goto done;
1243 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1244 SAMR_ACCESS_ENUM_DOMAINS |
1245 SAMR_ACCESS_LOOKUP_DOMAIN,
1246 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1247 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1248 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1249 &connect_handle,
1250 &domain_handle,
1251 &domain_sid);
1252 if (!W_ERROR_IS_OK(werr)) {
1253 goto done;
1256 switch (r->in.filter) {
1257 case FILTER_NORMAL_ACCOUNT:
1258 filter = ACB_NORMAL;
1259 break;
1260 case FILTER_TEMP_DUPLICATE_ACCOUNT:
1261 filter = ACB_TEMPDUP;
1262 break;
1263 case FILTER_INTERDOMAIN_TRUST_ACCOUNT:
1264 filter = ACB_DOMTRUST;
1265 break;
1266 case FILTER_WORKSTATION_TRUST_ACCOUNT:
1267 filter = ACB_WSTRUST;
1268 break;
1269 case FILTER_SERVER_TRUST_ACCOUNT:
1270 filter = ACB_SVRTRUST;
1271 break;
1272 default:
1273 break;
1276 status = rpccli_samr_EnumDomainUsers(pipe_cli,
1277 ctx,
1278 &domain_handle,
1279 r->in.resume_handle,
1280 filter,
1281 &sam,
1282 r->in.prefmaxlen,
1283 &entries_read);
1284 werr = ntstatus_to_werror(status);
1285 if (NT_STATUS_IS_ERR(status)) {
1286 goto done;
1289 for (i=0; i < sam->count; i++) {
1291 status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1292 domain_sid,
1293 &domain_handle,
1294 &builtin_handle,
1295 sam->entries[i].name.string,
1296 sam->entries[i].idx,
1297 r->in.level,
1298 r->out.buffer,
1299 r->out.entries_read);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 werr = ntstatus_to_werror(status);
1302 goto done;
1306 done:
1307 if (!cli) {
1308 return werr;
1311 /* if last query */
1312 if (NT_STATUS_IS_OK(status) ||
1313 NT_STATUS_IS_ERR(status)) {
1315 if (ctx->disable_policy_handle_cache) {
1316 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1317 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1318 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1322 return werr;
1325 /****************************************************************
1326 ****************************************************************/
1328 WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
1329 struct NetUserEnum *r)
1331 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserEnum);
1334 /****************************************************************
1335 ****************************************************************/
1337 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_USER(TALLOC_CTX *mem_ctx,
1338 struct samr_DispInfoGeneral *info,
1339 uint32_t *entries_read,
1340 void **buffer)
1342 struct NET_DISPLAY_USER *user = NULL;
1343 int i;
1345 user = TALLOC_ZERO_ARRAY(mem_ctx,
1346 struct NET_DISPLAY_USER,
1347 info->count);
1348 W_ERROR_HAVE_NO_MEMORY(user);
1350 for (i = 0; i < info->count; i++) {
1351 user[i].usri1_name = talloc_strdup(mem_ctx,
1352 info->entries[i].account_name.string);
1353 user[i].usri1_comment = talloc_strdup(mem_ctx,
1354 info->entries[i].description.string);
1355 user[i].usri1_flags =
1356 info->entries[i].acct_flags;
1357 user[i].usri1_full_name = talloc_strdup(mem_ctx,
1358 info->entries[i].full_name.string);
1359 user[i].usri1_user_id =
1360 info->entries[i].rid;
1361 user[i].usri1_next_index =
1362 info->entries[i].idx;
1364 if (!user[i].usri1_name) {
1365 return WERR_NOMEM;
1369 *buffer = talloc_memdup(mem_ctx, user,
1370 sizeof(struct NET_DISPLAY_USER) * info->count);
1371 W_ERROR_HAVE_NO_MEMORY(*buffer);
1373 *entries_read = info->count;
1375 return WERR_OK;
1378 /****************************************************************
1379 ****************************************************************/
1381 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(TALLOC_CTX *mem_ctx,
1382 struct samr_DispInfoFull *info,
1383 uint32_t *entries_read,
1384 void **buffer)
1386 struct NET_DISPLAY_MACHINE *machine = NULL;
1387 int i;
1389 machine = TALLOC_ZERO_ARRAY(mem_ctx,
1390 struct NET_DISPLAY_MACHINE,
1391 info->count);
1392 W_ERROR_HAVE_NO_MEMORY(machine);
1394 for (i = 0; i < info->count; i++) {
1395 machine[i].usri2_name = talloc_strdup(mem_ctx,
1396 info->entries[i].account_name.string);
1397 machine[i].usri2_comment = talloc_strdup(mem_ctx,
1398 info->entries[i].description.string);
1399 machine[i].usri2_flags =
1400 info->entries[i].acct_flags;
1401 machine[i].usri2_user_id =
1402 info->entries[i].rid;
1403 machine[i].usri2_next_index =
1404 info->entries[i].idx;
1406 if (!machine[i].usri2_name) {
1407 return WERR_NOMEM;
1411 *buffer = talloc_memdup(mem_ctx, machine,
1412 sizeof(struct NET_DISPLAY_MACHINE) * info->count);
1413 W_ERROR_HAVE_NO_MEMORY(*buffer);
1415 *entries_read = info->count;
1417 return WERR_OK;
1420 /****************************************************************
1421 ****************************************************************/
1423 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_GROUP(TALLOC_CTX *mem_ctx,
1424 struct samr_DispInfoFullGroups *info,
1425 uint32_t *entries_read,
1426 void **buffer)
1428 struct NET_DISPLAY_GROUP *group = NULL;
1429 int i;
1431 group = TALLOC_ZERO_ARRAY(mem_ctx,
1432 struct NET_DISPLAY_GROUP,
1433 info->count);
1434 W_ERROR_HAVE_NO_MEMORY(group);
1436 for (i = 0; i < info->count; i++) {
1437 group[i].grpi3_name = talloc_strdup(mem_ctx,
1438 info->entries[i].account_name.string);
1439 group[i].grpi3_comment = talloc_strdup(mem_ctx,
1440 info->entries[i].description.string);
1441 group[i].grpi3_group_id =
1442 info->entries[i].rid;
1443 group[i].grpi3_attributes =
1444 info->entries[i].acct_flags;
1445 group[i].grpi3_next_index =
1446 info->entries[i].idx;
1448 if (!group[i].grpi3_name) {
1449 return WERR_NOMEM;
1453 *buffer = talloc_memdup(mem_ctx, group,
1454 sizeof(struct NET_DISPLAY_GROUP) * info->count);
1455 W_ERROR_HAVE_NO_MEMORY(*buffer);
1457 *entries_read = info->count;
1459 return WERR_OK;
1463 /****************************************************************
1464 ****************************************************************/
1466 static WERROR convert_samr_dispinfo_to_NET_DISPLAY(TALLOC_CTX *mem_ctx,
1467 union samr_DispInfo *info,
1468 uint32_t level,
1469 uint32_t *entries_read,
1470 void **buffer)
1472 switch (level) {
1473 case 1:
1474 return convert_samr_dispinfo_to_NET_DISPLAY_USER(mem_ctx,
1475 &info->info1,
1476 entries_read,
1477 buffer);
1478 case 2:
1479 return convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(mem_ctx,
1480 &info->info2,
1481 entries_read,
1482 buffer);
1483 case 3:
1484 return convert_samr_dispinfo_to_NET_DISPLAY_GROUP(mem_ctx,
1485 &info->info3,
1486 entries_read,
1487 buffer);
1488 default:
1489 return WERR_UNKNOWN_LEVEL;
1492 return WERR_OK;
1495 /****************************************************************
1496 ****************************************************************/
1498 WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
1499 struct NetQueryDisplayInformation *r)
1501 struct cli_state *cli = NULL;
1502 struct rpc_pipe_client *pipe_cli = NULL;
1503 struct policy_handle connect_handle;
1504 struct dom_sid2 *domain_sid = NULL;
1505 struct policy_handle domain_handle;
1506 union samr_DispInfo info;
1508 uint32_t total_size = 0;
1509 uint32_t returned_size = 0;
1511 NTSTATUS status = NT_STATUS_OK;
1512 WERROR werr;
1513 WERROR werr_tmp;
1515 *r->out.entries_read = 0;
1517 ZERO_STRUCT(connect_handle);
1518 ZERO_STRUCT(domain_handle);
1520 switch (r->in.level) {
1521 case 1:
1522 case 2:
1523 case 3:
1524 break;
1525 default:
1526 return WERR_UNKNOWN_LEVEL;
1529 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1530 &ndr_table_samr.syntax_id,
1531 &cli,
1532 &pipe_cli);
1533 if (!W_ERROR_IS_OK(werr)) {
1534 goto done;
1537 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1538 SAMR_ACCESS_ENUM_DOMAINS |
1539 SAMR_ACCESS_LOOKUP_DOMAIN,
1540 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1541 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1542 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1543 &connect_handle,
1544 &domain_handle,
1545 &domain_sid);
1546 if (!W_ERROR_IS_OK(werr)) {
1547 goto done;
1550 status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
1551 ctx,
1552 &domain_handle,
1553 r->in.level,
1554 r->in.idx,
1555 r->in.entries_requested,
1556 r->in.prefmaxlen,
1557 &total_size,
1558 &returned_size,
1559 &info);
1560 werr = ntstatus_to_werror(status);
1561 if (NT_STATUS_IS_ERR(status)) {
1562 goto done;
1565 werr_tmp = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info,
1566 r->in.level,
1567 r->out.entries_read,
1568 r->out.buffer);
1569 if (!W_ERROR_IS_OK(werr_tmp)) {
1570 werr = werr_tmp;
1572 done:
1573 if (!cli) {
1574 return werr;
1577 /* if last query */
1578 if (NT_STATUS_IS_OK(status) ||
1579 NT_STATUS_IS_ERR(status)) {
1581 if (ctx->disable_policy_handle_cache) {
1582 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1583 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1587 return werr;
1591 /****************************************************************
1592 ****************************************************************/
1595 WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
1596 struct NetQueryDisplayInformation *r)
1598 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetQueryDisplayInformation);
1601 /****************************************************************
1602 ****************************************************************/
1604 WERROR NetUserChangePassword_r(struct libnetapi_ctx *ctx,
1605 struct NetUserChangePassword *r)
1607 return WERR_NOT_SUPPORTED;
1610 /****************************************************************
1611 ****************************************************************/
1613 WERROR NetUserChangePassword_l(struct libnetapi_ctx *ctx,
1614 struct NetUserChangePassword *r)
1616 return WERR_NOT_SUPPORTED;
1619 /****************************************************************
1620 ****************************************************************/
1622 WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx,
1623 struct NetUserGetInfo *r)
1625 struct cli_state *cli = NULL;
1626 struct rpc_pipe_client *pipe_cli = NULL;
1627 NTSTATUS status;
1628 WERROR werr;
1630 struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1631 struct lsa_String lsa_account_name;
1632 struct dom_sid2 *domain_sid = NULL;
1633 struct samr_Ids user_rids, name_types;
1634 uint32_t num_entries = 0;
1636 ZERO_STRUCT(connect_handle);
1637 ZERO_STRUCT(domain_handle);
1638 ZERO_STRUCT(builtin_handle);
1639 ZERO_STRUCT(user_handle);
1641 if (!r->out.buffer) {
1642 return WERR_INVALID_PARAM;
1645 switch (r->in.level) {
1646 case 0:
1647 case 1:
1648 case 2:
1649 case 3:
1650 case 4:
1651 case 10:
1652 case 11:
1653 case 20:
1654 case 23:
1655 break;
1656 default:
1657 werr = WERR_UNKNOWN_LEVEL;
1658 goto done;
1661 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1662 &ndr_table_samr.syntax_id,
1663 &cli,
1664 &pipe_cli);
1665 if (!W_ERROR_IS_OK(werr)) {
1666 goto done;
1669 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1670 SAMR_ACCESS_ENUM_DOMAINS |
1671 SAMR_ACCESS_LOOKUP_DOMAIN,
1672 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1673 &connect_handle,
1674 &domain_handle,
1675 &domain_sid);
1676 if (!W_ERROR_IS_OK(werr)) {
1677 goto done;
1680 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1681 SAMR_ACCESS_ENUM_DOMAINS |
1682 SAMR_ACCESS_LOOKUP_DOMAIN,
1683 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1684 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1685 &connect_handle,
1686 &builtin_handle);
1687 if (!W_ERROR_IS_OK(werr)) {
1688 goto done;
1691 init_lsa_String(&lsa_account_name, r->in.user_name);
1693 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1694 &domain_handle,
1696 &lsa_account_name,
1697 &user_rids,
1698 &name_types);
1699 if (!NT_STATUS_IS_OK(status)) {
1700 werr = ntstatus_to_werror(status);
1701 goto done;
1704 status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1705 domain_sid,
1706 &domain_handle,
1707 &builtin_handle,
1708 r->in.user_name,
1709 user_rids.ids[0],
1710 r->in.level,
1711 r->out.buffer,
1712 &num_entries);
1713 if (!NT_STATUS_IS_OK(status)) {
1714 werr = ntstatus_to_werror(status);
1715 goto done;
1718 done:
1719 if (!cli) {
1720 return werr;
1723 if (is_valid_policy_hnd(&user_handle)) {
1724 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
1727 if (ctx->disable_policy_handle_cache) {
1728 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1729 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1732 return werr;
1735 /****************************************************************
1736 ****************************************************************/
1738 WERROR NetUserGetInfo_l(struct libnetapi_ctx *ctx,
1739 struct NetUserGetInfo *r)
1741 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetInfo);
1744 /****************************************************************
1745 ****************************************************************/
1747 WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
1748 struct NetUserSetInfo *r)
1750 struct cli_state *cli = NULL;
1751 struct rpc_pipe_client *pipe_cli = NULL;
1752 NTSTATUS status;
1753 WERROR werr;
1755 struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1756 struct lsa_String lsa_account_name;
1757 struct dom_sid2 *domain_sid = NULL;
1758 struct samr_Ids user_rids, name_types;
1759 uint32_t user_mask = 0;
1761 struct USER_INFO_X uX;
1763 ZERO_STRUCT(connect_handle);
1764 ZERO_STRUCT(domain_handle);
1765 ZERO_STRUCT(builtin_handle);
1766 ZERO_STRUCT(user_handle);
1768 if (!r->in.buffer) {
1769 return WERR_INVALID_PARAM;
1772 switch (r->in.level) {
1773 case 0:
1774 user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
1775 break;
1776 case 1003:
1777 user_mask = SAMR_USER_ACCESS_SET_PASSWORD;
1778 break;
1779 case 1006:
1780 case 1007:
1781 case 1009:
1782 case 1011:
1783 case 1014:
1784 case 1052:
1785 case 1053:
1786 user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
1787 break;
1788 case 1012:
1789 case 1024:
1790 user_mask = SAMR_USER_ACCESS_SET_LOC_COM;
1791 case 1051:
1792 user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES |
1793 SAMR_USER_ACCESS_GET_GROUPS;
1794 break;
1795 case 3:
1796 user_mask = STD_RIGHT_READ_CONTROL_ACCESS |
1797 STD_RIGHT_WRITE_DAC_ACCESS |
1798 SAMR_USER_ACCESS_GET_GROUPS |
1799 SAMR_USER_ACCESS_SET_PASSWORD |
1800 SAMR_USER_ACCESS_SET_ATTRIBUTES |
1801 SAMR_USER_ACCESS_GET_ATTRIBUTES |
1802 SAMR_USER_ACCESS_SET_LOC_COM;
1803 break;
1804 case 1:
1805 case 2:
1806 case 4:
1807 case 21:
1808 case 22:
1809 case 1005:
1810 case 1008:
1811 case 1010:
1812 case 1017:
1813 case 1020:
1814 werr = WERR_NOT_SUPPORTED;
1815 goto done;
1816 default:
1817 werr = WERR_UNKNOWN_LEVEL;
1818 goto done;
1821 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1822 &ndr_table_samr.syntax_id,
1823 &cli,
1824 &pipe_cli);
1825 if (!W_ERROR_IS_OK(werr)) {
1826 goto done;
1829 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1830 SAMR_ACCESS_ENUM_DOMAINS |
1831 SAMR_ACCESS_LOOKUP_DOMAIN,
1832 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
1833 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1834 &connect_handle,
1835 &domain_handle,
1836 &domain_sid);
1837 if (!W_ERROR_IS_OK(werr)) {
1838 goto done;
1841 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1842 SAMR_ACCESS_ENUM_DOMAINS |
1843 SAMR_ACCESS_LOOKUP_DOMAIN,
1844 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1845 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1846 &connect_handle,
1847 &builtin_handle);
1848 if (!W_ERROR_IS_OK(werr)) {
1849 goto done;
1852 init_lsa_String(&lsa_account_name, r->in.user_name);
1854 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1855 &domain_handle,
1857 &lsa_account_name,
1858 &user_rids,
1859 &name_types);
1860 if (!NT_STATUS_IS_OK(status)) {
1861 werr = ntstatus_to_werror(status);
1862 goto done;
1865 status = rpccli_samr_OpenUser(pipe_cli, ctx,
1866 &domain_handle,
1867 user_mask,
1868 user_rids.ids[0],
1869 &user_handle);
1870 if (!NT_STATUS_IS_OK(status)) {
1871 werr = ntstatus_to_werror(status);
1872 goto done;
1875 status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
1876 if (!NT_STATUS_IS_OK(status)) {
1877 werr = ntstatus_to_werror(status);
1878 goto done;
1881 status = set_user_info_USER_INFO_X(ctx, pipe_cli,
1882 &cli->user_session_key,
1883 &user_handle,
1884 &uX);
1885 if (!NT_STATUS_IS_OK(status)) {
1886 werr = ntstatus_to_werror(status);
1887 goto done;
1890 werr = WERR_OK;
1892 done:
1893 if (!cli) {
1894 return werr;
1897 if (is_valid_policy_hnd(&user_handle)) {
1898 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
1901 if (ctx->disable_policy_handle_cache) {
1902 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1903 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1904 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1907 return werr;
1910 /****************************************************************
1911 ****************************************************************/
1913 WERROR NetUserSetInfo_l(struct libnetapi_ctx *ctx,
1914 struct NetUserSetInfo *r)
1916 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetInfo);
1919 /****************************************************************
1920 ****************************************************************/
1922 static NTSTATUS query_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
1923 struct rpc_pipe_client *pipe_cli,
1924 struct policy_handle *domain_handle,
1925 struct samr_DomInfo1 *info1,
1926 struct samr_DomInfo3 *info3,
1927 struct samr_DomInfo5 *info5,
1928 struct samr_DomInfo6 *info6,
1929 struct samr_DomInfo7 *info7,
1930 struct samr_DomInfo12 *info12)
1932 NTSTATUS status;
1933 union samr_DomainInfo *dom_info = NULL;
1935 if (info1) {
1936 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1937 domain_handle,
1939 &dom_info);
1940 NT_STATUS_NOT_OK_RETURN(status);
1942 *info1 = dom_info->info1;
1945 if (info3) {
1946 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1947 domain_handle,
1949 &dom_info);
1950 NT_STATUS_NOT_OK_RETURN(status);
1952 *info3 = dom_info->info3;
1955 if (info5) {
1956 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1957 domain_handle,
1959 &dom_info);
1960 NT_STATUS_NOT_OK_RETURN(status);
1962 *info5 = dom_info->info5;
1965 if (info6) {
1966 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1967 domain_handle,
1969 &dom_info);
1970 NT_STATUS_NOT_OK_RETURN(status);
1972 *info6 = dom_info->info6;
1975 if (info7) {
1976 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1977 domain_handle,
1979 &dom_info);
1980 NT_STATUS_NOT_OK_RETURN(status);
1982 *info7 = dom_info->info7;
1985 if (info12) {
1986 status = rpccli_samr_QueryDomainInfo2(pipe_cli, mem_ctx,
1987 domain_handle,
1989 &dom_info);
1990 NT_STATUS_NOT_OK_RETURN(status);
1992 *info12 = dom_info->info12;
1995 return NT_STATUS_OK;
1998 /****************************************************************
1999 ****************************************************************/
2001 static NTSTATUS query_USER_MODALS_INFO_0(TALLOC_CTX *mem_ctx,
2002 struct rpc_pipe_client *pipe_cli,
2003 struct policy_handle *domain_handle,
2004 struct USER_MODALS_INFO_0 *info0)
2006 NTSTATUS status;
2007 struct samr_DomInfo1 dom_info1;
2008 struct samr_DomInfo3 dom_info3;
2010 ZERO_STRUCTP(info0);
2012 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2013 pipe_cli,
2014 domain_handle,
2015 &dom_info1,
2016 &dom_info3,
2017 NULL,
2018 NULL,
2019 NULL,
2020 NULL);
2021 NT_STATUS_NOT_OK_RETURN(status);
2023 info0->usrmod0_min_passwd_len =
2024 dom_info1.min_password_length;
2025 info0->usrmod0_max_passwd_age =
2026 nt_time_to_unix_abs((NTTIME *)&dom_info1.max_password_age);
2027 info0->usrmod0_min_passwd_age =
2028 nt_time_to_unix_abs((NTTIME *)&dom_info1.min_password_age);
2029 info0->usrmod0_password_hist_len =
2030 dom_info1.password_history_length;
2032 info0->usrmod0_force_logoff =
2033 nt_time_to_unix_abs(&dom_info3.force_logoff_time);
2035 return NT_STATUS_OK;
2038 /****************************************************************
2039 ****************************************************************/
2041 static NTSTATUS query_USER_MODALS_INFO_1(TALLOC_CTX *mem_ctx,
2042 struct rpc_pipe_client *pipe_cli,
2043 struct policy_handle *domain_handle,
2044 struct USER_MODALS_INFO_1 *info1)
2046 NTSTATUS status;
2047 struct samr_DomInfo6 dom_info6;
2048 struct samr_DomInfo7 dom_info7;
2050 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2051 pipe_cli,
2052 domain_handle,
2053 NULL,
2054 NULL,
2055 NULL,
2056 &dom_info6,
2057 &dom_info7,
2058 NULL);
2059 NT_STATUS_NOT_OK_RETURN(status);
2061 info1->usrmod1_primary =
2062 talloc_strdup(mem_ctx, dom_info6.primary.string);
2064 info1->usrmod1_role = dom_info7.role;
2066 return NT_STATUS_OK;
2069 /****************************************************************
2070 ****************************************************************/
2072 static NTSTATUS query_USER_MODALS_INFO_2(TALLOC_CTX *mem_ctx,
2073 struct rpc_pipe_client *pipe_cli,
2074 struct policy_handle *domain_handle,
2075 struct dom_sid *domain_sid,
2076 struct USER_MODALS_INFO_2 *info2)
2078 NTSTATUS status;
2079 struct samr_DomInfo5 dom_info5;
2081 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2082 pipe_cli,
2083 domain_handle,
2084 NULL,
2085 NULL,
2086 &dom_info5,
2087 NULL,
2088 NULL,
2089 NULL);
2090 NT_STATUS_NOT_OK_RETURN(status);
2092 info2->usrmod2_domain_name =
2093 talloc_strdup(mem_ctx, dom_info5.domain_name.string);
2094 info2->usrmod2_domain_id =
2095 (struct domsid *)sid_dup_talloc(mem_ctx, domain_sid);
2097 NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_name);
2098 NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_id);
2100 return NT_STATUS_OK;
2103 /****************************************************************
2104 ****************************************************************/
2106 static NTSTATUS query_USER_MODALS_INFO_3(TALLOC_CTX *mem_ctx,
2107 struct rpc_pipe_client *pipe_cli,
2108 struct policy_handle *domain_handle,
2109 struct USER_MODALS_INFO_3 *info3)
2111 NTSTATUS status;
2112 struct samr_DomInfo12 dom_info12;
2114 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2115 pipe_cli,
2116 domain_handle,
2117 NULL,
2118 NULL,
2119 NULL,
2120 NULL,
2121 NULL,
2122 &dom_info12);
2123 NT_STATUS_NOT_OK_RETURN(status);
2125 info3->usrmod3_lockout_duration =
2126 nt_time_to_unix_abs(&dom_info12.lockout_duration);
2127 info3->usrmod3_lockout_observation_window =
2128 nt_time_to_unix_abs(&dom_info12.lockout_window);
2129 info3->usrmod3_lockout_threshold =
2130 dom_info12.lockout_threshold;
2132 return NT_STATUS_OK;
2135 /****************************************************************
2136 ****************************************************************/
2138 static NTSTATUS query_USER_MODALS_INFO_to_buffer(TALLOC_CTX *mem_ctx,
2139 struct rpc_pipe_client *pipe_cli,
2140 uint32_t level,
2141 struct policy_handle *domain_handle,
2142 struct dom_sid *domain_sid,
2143 uint8_t **buffer)
2145 NTSTATUS status;
2147 struct USER_MODALS_INFO_0 info0;
2148 struct USER_MODALS_INFO_1 info1;
2149 struct USER_MODALS_INFO_2 info2;
2150 struct USER_MODALS_INFO_3 info3;
2152 if (!buffer) {
2153 return ERROR_INSUFFICIENT_BUFFER;
2156 switch (level) {
2157 case 0:
2158 status = query_USER_MODALS_INFO_0(mem_ctx,
2159 pipe_cli,
2160 domain_handle,
2161 &info0);
2162 NT_STATUS_NOT_OK_RETURN(status);
2164 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0,
2165 sizeof(info0));
2166 break;
2168 case 1:
2169 status = query_USER_MODALS_INFO_1(mem_ctx,
2170 pipe_cli,
2171 domain_handle,
2172 &info1);
2173 NT_STATUS_NOT_OK_RETURN(status);
2175 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1,
2176 sizeof(info1));
2177 break;
2178 case 2:
2179 status = query_USER_MODALS_INFO_2(mem_ctx,
2180 pipe_cli,
2181 domain_handle,
2182 domain_sid,
2183 &info2);
2184 NT_STATUS_NOT_OK_RETURN(status);
2186 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2,
2187 sizeof(info2));
2188 break;
2189 case 3:
2190 status = query_USER_MODALS_INFO_3(mem_ctx,
2191 pipe_cli,
2192 domain_handle,
2193 &info3);
2194 NT_STATUS_NOT_OK_RETURN(status);
2196 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3,
2197 sizeof(info3));
2198 break;
2199 default:
2200 break;
2203 NT_STATUS_HAVE_NO_MEMORY(*buffer);
2205 return NT_STATUS_OK;
2208 /****************************************************************
2209 ****************************************************************/
2211 WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx,
2212 struct NetUserModalsGet *r)
2214 struct cli_state *cli = NULL;
2215 struct rpc_pipe_client *pipe_cli = NULL;
2216 NTSTATUS status;
2217 WERROR werr;
2219 struct policy_handle connect_handle, domain_handle;
2220 struct dom_sid2 *domain_sid = NULL;
2221 uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2223 ZERO_STRUCT(connect_handle);
2224 ZERO_STRUCT(domain_handle);
2226 if (!r->out.buffer) {
2227 return WERR_INVALID_PARAM;
2230 switch (r->in.level) {
2231 case 0:
2232 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2233 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2234 break;
2235 case 1:
2236 case 2:
2237 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2238 break;
2239 case 3:
2240 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1;
2241 break;
2242 default:
2243 werr = WERR_UNKNOWN_LEVEL;
2244 goto done;
2247 werr = libnetapi_open_pipe(ctx, r->in.server_name,
2248 &ndr_table_samr.syntax_id,
2249 &cli,
2250 &pipe_cli);
2251 if (!W_ERROR_IS_OK(werr)) {
2252 goto done;
2255 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2256 SAMR_ACCESS_ENUM_DOMAINS |
2257 SAMR_ACCESS_LOOKUP_DOMAIN,
2258 access_mask,
2259 &connect_handle,
2260 &domain_handle,
2261 &domain_sid);
2262 if (!W_ERROR_IS_OK(werr)) {
2263 goto done;
2266 /* 0: 1 + 3 */
2267 /* 1: 6 + 7 */
2268 /* 2: 5 */
2269 /* 3: 12 (DomainInfo2) */
2271 status = query_USER_MODALS_INFO_to_buffer(ctx,
2272 pipe_cli,
2273 r->in.level,
2274 &domain_handle,
2275 domain_sid,
2276 r->out.buffer);
2277 if (!NT_STATUS_IS_OK(status)) {
2278 werr = ntstatus_to_werror(status);
2279 goto done;
2282 done:
2283 if (!cli) {
2284 return werr;
2287 if (ctx->disable_policy_handle_cache) {
2288 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2289 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2292 return werr;
2295 /****************************************************************
2296 ****************************************************************/
2298 WERROR NetUserModalsGet_l(struct libnetapi_ctx *ctx,
2299 struct NetUserModalsGet *r)
2301 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsGet);
2304 /****************************************************************
2305 ****************************************************************/
2307 static NTSTATUS set_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
2308 struct rpc_pipe_client *pipe_cli,
2309 struct policy_handle *domain_handle,
2310 struct samr_DomInfo1 *info1,
2311 struct samr_DomInfo3 *info3,
2312 struct samr_DomInfo12 *info12)
2314 NTSTATUS status;
2315 union samr_DomainInfo dom_info;
2317 if (info1) {
2319 ZERO_STRUCT(dom_info);
2321 dom_info.info1 = *info1;
2323 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2324 domain_handle,
2326 &dom_info);
2327 NT_STATUS_NOT_OK_RETURN(status);
2330 if (info3) {
2332 ZERO_STRUCT(dom_info);
2334 dom_info.info3 = *info3;
2336 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2337 domain_handle,
2339 &dom_info);
2341 NT_STATUS_NOT_OK_RETURN(status);
2344 if (info12) {
2346 ZERO_STRUCT(dom_info);
2348 dom_info.info12 = *info12;
2350 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2351 domain_handle,
2353 &dom_info);
2355 NT_STATUS_NOT_OK_RETURN(status);
2358 return NT_STATUS_OK;
2361 /****************************************************************
2362 ****************************************************************/
2364 static NTSTATUS set_USER_MODALS_INFO_0_buffer(TALLOC_CTX *mem_ctx,
2365 struct rpc_pipe_client *pipe_cli,
2366 struct policy_handle *domain_handle,
2367 struct USER_MODALS_INFO_0 *info0)
2369 NTSTATUS status;
2370 struct samr_DomInfo1 dom_info_1;
2371 struct samr_DomInfo3 dom_info_3;
2373 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2374 pipe_cli,
2375 domain_handle,
2376 &dom_info_1,
2377 &dom_info_3,
2378 NULL,
2379 NULL,
2380 NULL,
2381 NULL);
2382 NT_STATUS_NOT_OK_RETURN(status);
2384 dom_info_1.min_password_length =
2385 info0->usrmod0_min_passwd_len;
2386 dom_info_1.password_history_length =
2387 info0->usrmod0_password_hist_len;
2389 unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2390 info0->usrmod0_max_passwd_age);
2391 unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2392 info0->usrmod0_min_passwd_age);
2394 unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2395 info0->usrmod0_force_logoff);
2397 return set_USER_MODALS_INFO_rpc(mem_ctx,
2398 pipe_cli,
2399 domain_handle,
2400 &dom_info_1,
2401 &dom_info_3,
2402 NULL);
2405 /****************************************************************
2406 ****************************************************************/
2408 static NTSTATUS set_USER_MODALS_INFO_3_buffer(TALLOC_CTX *mem_ctx,
2409 struct rpc_pipe_client *pipe_cli,
2410 struct policy_handle *domain_handle,
2411 struct USER_MODALS_INFO_3 *info3)
2413 NTSTATUS status;
2414 struct samr_DomInfo12 dom_info_12;
2416 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2417 pipe_cli,
2418 domain_handle,
2419 NULL,
2420 NULL,
2421 NULL,
2422 NULL,
2423 NULL,
2424 &dom_info_12);
2425 NT_STATUS_NOT_OK_RETURN(status);
2427 unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_duration,
2428 info3->usrmod3_lockout_duration);
2429 unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_window,
2430 info3->usrmod3_lockout_observation_window);
2431 dom_info_12.lockout_threshold = info3->usrmod3_lockout_threshold;
2433 return set_USER_MODALS_INFO_rpc(mem_ctx,
2434 pipe_cli,
2435 domain_handle,
2436 NULL,
2437 NULL,
2438 &dom_info_12);
2441 /****************************************************************
2442 ****************************************************************/
2444 static NTSTATUS set_USER_MODALS_INFO_1001_buffer(TALLOC_CTX *mem_ctx,
2445 struct rpc_pipe_client *pipe_cli,
2446 struct policy_handle *domain_handle,
2447 struct USER_MODALS_INFO_1001 *info1001)
2449 NTSTATUS status;
2450 struct samr_DomInfo1 dom_info_1;
2452 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2453 pipe_cli,
2454 domain_handle,
2455 &dom_info_1,
2456 NULL,
2457 NULL,
2458 NULL,
2459 NULL,
2460 NULL);
2461 NT_STATUS_NOT_OK_RETURN(status);
2463 dom_info_1.min_password_length =
2464 info1001->usrmod1001_min_passwd_len;
2466 return set_USER_MODALS_INFO_rpc(mem_ctx,
2467 pipe_cli,
2468 domain_handle,
2469 &dom_info_1,
2470 NULL,
2471 NULL);
2474 /****************************************************************
2475 ****************************************************************/
2477 static NTSTATUS set_USER_MODALS_INFO_1002_buffer(TALLOC_CTX *mem_ctx,
2478 struct rpc_pipe_client *pipe_cli,
2479 struct policy_handle *domain_handle,
2480 struct USER_MODALS_INFO_1002 *info1002)
2482 NTSTATUS status;
2483 struct samr_DomInfo1 dom_info_1;
2485 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2486 pipe_cli,
2487 domain_handle,
2488 &dom_info_1,
2489 NULL,
2490 NULL,
2491 NULL,
2492 NULL,
2493 NULL);
2494 NT_STATUS_NOT_OK_RETURN(status);
2496 unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2497 info1002->usrmod1002_max_passwd_age);
2499 return set_USER_MODALS_INFO_rpc(mem_ctx,
2500 pipe_cli,
2501 domain_handle,
2502 &dom_info_1,
2503 NULL,
2504 NULL);
2507 /****************************************************************
2508 ****************************************************************/
2510 static NTSTATUS set_USER_MODALS_INFO_1003_buffer(TALLOC_CTX *mem_ctx,
2511 struct rpc_pipe_client *pipe_cli,
2512 struct policy_handle *domain_handle,
2513 struct USER_MODALS_INFO_1003 *info1003)
2515 NTSTATUS status;
2516 struct samr_DomInfo1 dom_info_1;
2518 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2519 pipe_cli,
2520 domain_handle,
2521 &dom_info_1,
2522 NULL,
2523 NULL,
2524 NULL,
2525 NULL,
2526 NULL);
2527 NT_STATUS_NOT_OK_RETURN(status);
2529 unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2530 info1003->usrmod1003_min_passwd_age);
2532 return set_USER_MODALS_INFO_rpc(mem_ctx,
2533 pipe_cli,
2534 domain_handle,
2535 &dom_info_1,
2536 NULL,
2537 NULL);
2540 /****************************************************************
2541 ****************************************************************/
2543 static NTSTATUS set_USER_MODALS_INFO_1004_buffer(TALLOC_CTX *mem_ctx,
2544 struct rpc_pipe_client *pipe_cli,
2545 struct policy_handle *domain_handle,
2546 struct USER_MODALS_INFO_1004 *info1004)
2548 NTSTATUS status;
2549 struct samr_DomInfo3 dom_info_3;
2551 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2552 pipe_cli,
2553 domain_handle,
2554 NULL,
2555 &dom_info_3,
2556 NULL,
2557 NULL,
2558 NULL,
2559 NULL);
2560 NT_STATUS_NOT_OK_RETURN(status);
2562 unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2563 info1004->usrmod1004_force_logoff);
2565 return set_USER_MODALS_INFO_rpc(mem_ctx,
2566 pipe_cli,
2567 domain_handle,
2568 NULL,
2569 &dom_info_3,
2570 NULL);
2573 /****************************************************************
2574 ****************************************************************/
2576 static NTSTATUS set_USER_MODALS_INFO_1005_buffer(TALLOC_CTX *mem_ctx,
2577 struct rpc_pipe_client *pipe_cli,
2578 struct policy_handle *domain_handle,
2579 struct USER_MODALS_INFO_1005 *info1005)
2581 NTSTATUS status;
2582 struct samr_DomInfo1 dom_info_1;
2584 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2585 pipe_cli,
2586 domain_handle,
2587 &dom_info_1,
2588 NULL,
2589 NULL,
2590 NULL,
2591 NULL,
2592 NULL);
2593 NT_STATUS_NOT_OK_RETURN(status);
2595 dom_info_1.password_history_length =
2596 info1005->usrmod1005_password_hist_len;
2598 return set_USER_MODALS_INFO_rpc(mem_ctx,
2599 pipe_cli,
2600 domain_handle,
2601 &dom_info_1,
2602 NULL,
2603 NULL);
2606 /****************************************************************
2607 ****************************************************************/
2609 static NTSTATUS set_USER_MODALS_INFO_buffer(TALLOC_CTX *mem_ctx,
2610 struct rpc_pipe_client *pipe_cli,
2611 uint32_t level,
2612 struct policy_handle *domain_handle,
2613 struct dom_sid *domain_sid,
2614 uint8_t *buffer)
2616 struct USER_MODALS_INFO_0 *info0;
2617 struct USER_MODALS_INFO_3 *info3;
2618 struct USER_MODALS_INFO_1001 *info1001;
2619 struct USER_MODALS_INFO_1002 *info1002;
2620 struct USER_MODALS_INFO_1003 *info1003;
2621 struct USER_MODALS_INFO_1004 *info1004;
2622 struct USER_MODALS_INFO_1005 *info1005;
2624 if (!buffer) {
2625 return ERROR_INSUFFICIENT_BUFFER;
2628 switch (level) {
2629 case 0:
2630 info0 = (struct USER_MODALS_INFO_0 *)buffer;
2631 return set_USER_MODALS_INFO_0_buffer(mem_ctx,
2632 pipe_cli,
2633 domain_handle,
2634 info0);
2635 case 3:
2636 info3 = (struct USER_MODALS_INFO_3 *)buffer;
2637 return set_USER_MODALS_INFO_3_buffer(mem_ctx,
2638 pipe_cli,
2639 domain_handle,
2640 info3);
2641 case 1001:
2642 info1001 = (struct USER_MODALS_INFO_1001 *)buffer;
2643 return set_USER_MODALS_INFO_1001_buffer(mem_ctx,
2644 pipe_cli,
2645 domain_handle,
2646 info1001);
2647 case 1002:
2648 info1002 = (struct USER_MODALS_INFO_1002 *)buffer;
2649 return set_USER_MODALS_INFO_1002_buffer(mem_ctx,
2650 pipe_cli,
2651 domain_handle,
2652 info1002);
2653 case 1003:
2654 info1003 = (struct USER_MODALS_INFO_1003 *)buffer;
2655 return set_USER_MODALS_INFO_1003_buffer(mem_ctx,
2656 pipe_cli,
2657 domain_handle,
2658 info1003);
2659 case 1004:
2660 info1004 = (struct USER_MODALS_INFO_1004 *)buffer;
2661 return set_USER_MODALS_INFO_1004_buffer(mem_ctx,
2662 pipe_cli,
2663 domain_handle,
2664 info1004);
2665 case 1005:
2666 info1005 = (struct USER_MODALS_INFO_1005 *)buffer;
2667 return set_USER_MODALS_INFO_1005_buffer(mem_ctx,
2668 pipe_cli,
2669 domain_handle,
2670 info1005);
2672 default:
2673 break;
2676 return NT_STATUS_OK;
2679 /****************************************************************
2680 ****************************************************************/
2682 WERROR NetUserModalsSet_r(struct libnetapi_ctx *ctx,
2683 struct NetUserModalsSet *r)
2685 struct cli_state *cli = NULL;
2686 struct rpc_pipe_client *pipe_cli = NULL;
2687 NTSTATUS status;
2688 WERROR werr;
2690 struct policy_handle connect_handle, domain_handle;
2691 struct dom_sid2 *domain_sid = NULL;
2692 uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2694 ZERO_STRUCT(connect_handle);
2695 ZERO_STRUCT(domain_handle);
2697 if (!r->in.buffer) {
2698 return WERR_INVALID_PARAM;
2701 switch (r->in.level) {
2702 case 0:
2703 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2704 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2705 SAMR_DOMAIN_ACCESS_SET_INFO_1 |
2706 SAMR_DOMAIN_ACCESS_SET_INFO_2;
2707 break;
2708 case 3:
2709 case 1001:
2710 case 1002:
2711 case 1003:
2712 case 1005:
2713 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2714 SAMR_DOMAIN_ACCESS_SET_INFO_1;
2715 break;
2716 case 1004:
2717 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2718 SAMR_DOMAIN_ACCESS_SET_INFO_2;
2719 break;
2720 case 1:
2721 case 2:
2722 case 1006:
2723 case 1007:
2724 werr = WERR_NOT_SUPPORTED;
2725 break;
2726 default:
2727 werr = WERR_UNKNOWN_LEVEL;
2728 goto done;
2731 werr = libnetapi_open_pipe(ctx, r->in.server_name,
2732 &ndr_table_samr.syntax_id,
2733 &cli,
2734 &pipe_cli);
2735 if (!W_ERROR_IS_OK(werr)) {
2736 goto done;
2739 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2740 SAMR_ACCESS_ENUM_DOMAINS |
2741 SAMR_ACCESS_LOOKUP_DOMAIN,
2742 access_mask,
2743 &connect_handle,
2744 &domain_handle,
2745 &domain_sid);
2746 if (!W_ERROR_IS_OK(werr)) {
2747 goto done;
2750 status = set_USER_MODALS_INFO_buffer(ctx,
2751 pipe_cli,
2752 r->in.level,
2753 &domain_handle,
2754 domain_sid,
2755 r->in.buffer);
2756 if (!NT_STATUS_IS_OK(status)) {
2757 werr = ntstatus_to_werror(status);
2758 goto done;
2761 done:
2762 if (!cli) {
2763 return werr;
2766 if (ctx->disable_policy_handle_cache) {
2767 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2768 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2771 return werr;
2774 /****************************************************************
2775 ****************************************************************/
2777 WERROR NetUserModalsSet_l(struct libnetapi_ctx *ctx,
2778 struct NetUserModalsSet *r)
2780 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsSet);
2783 /****************************************************************
2784 ****************************************************************/
2786 NTSTATUS add_GROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
2787 uint32_t level,
2788 const char *group_name,
2789 uint32_t attributes,
2790 uint8_t **buffer,
2791 uint32_t *num_entries)
2793 struct GROUP_USERS_INFO_0 u0;
2794 struct GROUP_USERS_INFO_1 u1;
2796 switch (level) {
2797 case 0:
2798 if (group_name) {
2799 u0.grui0_name = talloc_strdup(mem_ctx, group_name);
2800 NT_STATUS_HAVE_NO_MEMORY(u0.grui0_name);
2801 } else {
2802 u0.grui0_name = NULL;
2805 ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_0, u0,
2806 (struct GROUP_USERS_INFO_0 **)buffer, num_entries);
2807 break;
2808 case 1:
2809 if (group_name) {
2810 u1.grui1_name = talloc_strdup(mem_ctx, group_name);
2811 NT_STATUS_HAVE_NO_MEMORY(u1.grui1_name);
2812 } else {
2813 u1.grui1_name = NULL;
2816 u1.grui1_attributes = attributes;
2818 ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_1, u1,
2819 (struct GROUP_USERS_INFO_1 **)buffer, num_entries);
2820 break;
2821 default:
2822 return NT_STATUS_INVALID_INFO_CLASS;
2825 return NT_STATUS_OK;
2828 /****************************************************************
2829 ****************************************************************/
2831 WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
2832 struct NetUserGetGroups *r)
2834 struct cli_state *cli = NULL;
2835 struct rpc_pipe_client *pipe_cli = NULL;
2836 struct policy_handle connect_handle, domain_handle, user_handle;
2837 struct lsa_String lsa_account_name;
2838 struct dom_sid2 *domain_sid = NULL;
2839 struct samr_Ids user_rids, name_types;
2840 struct samr_RidWithAttributeArray *rid_array = NULL;
2841 struct lsa_Strings names;
2842 struct samr_Ids types;
2843 uint32_t *rids = NULL;
2845 int i;
2846 uint32_t entries_read = 0;
2848 NTSTATUS status = NT_STATUS_OK;
2849 WERROR werr;
2851 ZERO_STRUCT(connect_handle);
2852 ZERO_STRUCT(domain_handle);
2854 if (!r->out.buffer) {
2855 return WERR_INVALID_PARAM;
2858 *r->out.buffer = NULL;
2859 *r->out.entries_read = 0;
2860 *r->out.total_entries = 0;
2862 switch (r->in.level) {
2863 case 0:
2864 case 1:
2865 break;
2866 default:
2867 return WERR_UNKNOWN_LEVEL;
2870 werr = libnetapi_open_pipe(ctx, r->in.server_name,
2871 &ndr_table_samr.syntax_id,
2872 &cli,
2873 &pipe_cli);
2874 if (!W_ERROR_IS_OK(werr)) {
2875 goto done;
2878 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2879 SAMR_ACCESS_ENUM_DOMAINS |
2880 SAMR_ACCESS_LOOKUP_DOMAIN,
2881 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2882 &connect_handle,
2883 &domain_handle,
2884 &domain_sid);
2885 if (!W_ERROR_IS_OK(werr)) {
2886 goto done;
2889 init_lsa_String(&lsa_account_name, r->in.user_name);
2891 status = rpccli_samr_LookupNames(pipe_cli, ctx,
2892 &domain_handle,
2894 &lsa_account_name,
2895 &user_rids,
2896 &name_types);
2897 if (!NT_STATUS_IS_OK(status)) {
2898 werr = ntstatus_to_werror(status);
2899 goto done;
2902 status = rpccli_samr_OpenUser(pipe_cli, ctx,
2903 &domain_handle,
2904 SAMR_USER_ACCESS_GET_GROUPS,
2905 user_rids.ids[0],
2906 &user_handle);
2907 if (!NT_STATUS_IS_OK(status)) {
2908 werr = ntstatus_to_werror(status);
2909 goto done;
2912 status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
2913 &user_handle,
2914 &rid_array);
2915 if (!NT_STATUS_IS_OK(status)) {
2916 werr = ntstatus_to_werror(status);
2917 goto done;
2920 rids = talloc_array(ctx, uint32_t, rid_array->count);
2921 if (!rids) {
2922 werr = WERR_NOMEM;
2923 goto done;
2926 for (i=0; i < rid_array->count; i++) {
2927 rids[i] = rid_array->rids[i].rid;
2930 status = rpccli_samr_LookupRids(pipe_cli, ctx,
2931 &domain_handle,
2932 rid_array->count,
2933 rids,
2934 &names,
2935 &types);
2936 if (!NT_STATUS_IS_OK(status) &&
2937 !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
2938 werr = ntstatus_to_werror(status);
2939 goto done;
2942 for (i=0; i < names.count; i++) {
2943 status = add_GROUP_USERS_INFO_X_buffer(ctx,
2944 r->in.level,
2945 names.names[i].string,
2946 rid_array->rids[i].attributes,
2947 r->out.buffer,
2948 &entries_read);
2949 if (!NT_STATUS_IS_OK(status)) {
2950 werr = ntstatus_to_werror(status);
2951 goto done;
2955 *r->out.entries_read = entries_read;
2956 *r->out.total_entries = entries_read;
2958 done:
2959 if (!cli) {
2960 return werr;
2963 if (ctx->disable_policy_handle_cache) {
2964 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2965 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2968 return werr;
2971 /****************************************************************
2972 ****************************************************************/
2974 WERROR NetUserGetGroups_l(struct libnetapi_ctx *ctx,
2975 struct NetUserGetGroups *r)
2977 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetGroups);
2980 /****************************************************************
2981 ****************************************************************/
2983 WERROR NetUserSetGroups_r(struct libnetapi_ctx *ctx,
2984 struct NetUserSetGroups *r)
2986 struct cli_state *cli = NULL;
2987 struct rpc_pipe_client *pipe_cli = NULL;
2988 struct policy_handle connect_handle, domain_handle, user_handle, group_handle;
2989 struct lsa_String lsa_account_name;
2990 struct dom_sid2 *domain_sid = NULL;
2991 struct samr_Ids user_rids, name_types;
2992 struct samr_Ids group_rids;
2993 struct samr_RidWithAttributeArray *rid_array = NULL;
2994 struct lsa_String *lsa_names = NULL;
2996 uint32_t *add_rids = NULL;
2997 uint32_t *del_rids = NULL;
2998 size_t num_add_rids = 0;
2999 size_t num_del_rids = 0;
3001 uint32_t *member_rids = NULL;
3002 size_t num_member_rids = 0;
3004 struct GROUP_USERS_INFO_0 *i0 = NULL;
3005 struct GROUP_USERS_INFO_1 *i1 = NULL;
3007 int i, k;
3009 NTSTATUS status = NT_STATUS_OK;
3010 WERROR werr;
3012 ZERO_STRUCT(connect_handle);
3013 ZERO_STRUCT(domain_handle);
3015 if (!r->in.buffer) {
3016 return WERR_INVALID_PARAM;
3019 switch (r->in.level) {
3020 case 0:
3021 case 1:
3022 break;
3023 default:
3024 return WERR_UNKNOWN_LEVEL;
3027 werr = libnetapi_open_pipe(ctx, r->in.server_name,
3028 &ndr_table_samr.syntax_id,
3029 &cli,
3030 &pipe_cli);
3031 if (!W_ERROR_IS_OK(werr)) {
3032 goto done;
3035 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
3036 SAMR_ACCESS_ENUM_DOMAINS |
3037 SAMR_ACCESS_LOOKUP_DOMAIN,
3038 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
3039 &connect_handle,
3040 &domain_handle,
3041 &domain_sid);
3042 if (!W_ERROR_IS_OK(werr)) {
3043 goto done;
3046 init_lsa_String(&lsa_account_name, r->in.user_name);
3048 status = rpccli_samr_LookupNames(pipe_cli, ctx,
3049 &domain_handle,
3051 &lsa_account_name,
3052 &user_rids,
3053 &name_types);
3054 if (!NT_STATUS_IS_OK(status)) {
3055 werr = ntstatus_to_werror(status);
3056 goto done;
3059 status = rpccli_samr_OpenUser(pipe_cli, ctx,
3060 &domain_handle,
3061 SAMR_USER_ACCESS_GET_GROUPS,
3062 user_rids.ids[0],
3063 &user_handle);
3064 if (!NT_STATUS_IS_OK(status)) {
3065 werr = ntstatus_to_werror(status);
3066 goto done;
3069 switch (r->in.level) {
3070 case 0:
3071 i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
3072 break;
3073 case 1:
3074 i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
3075 break;
3078 lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
3079 if (!lsa_names) {
3080 werr = WERR_NOMEM;
3081 goto done;
3084 for (i=0; i < r->in.num_entries; i++) {
3086 switch (r->in.level) {
3087 case 0:
3088 init_lsa_String(&lsa_names[i], i0->grui0_name);
3089 i0++;
3090 break;
3091 case 1:
3092 init_lsa_String(&lsa_names[i], i1->grui1_name);
3093 i1++;
3094 break;
3098 status = rpccli_samr_LookupNames(pipe_cli, ctx,
3099 &domain_handle,
3100 r->in.num_entries,
3101 lsa_names,
3102 &group_rids,
3103 &name_types);
3104 if (!NT_STATUS_IS_OK(status)) {
3105 werr = ntstatus_to_werror(status);
3106 goto done;
3109 member_rids = group_rids.ids;
3110 num_member_rids = group_rids.count;
3112 status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
3113 &user_handle,
3114 &rid_array);
3115 if (!NT_STATUS_IS_OK(status)) {
3116 werr = ntstatus_to_werror(status);
3117 goto done;
3120 /* add list */
3122 for (i=0; i < r->in.num_entries; i++) {
3123 bool already_member = false;
3124 for (k=0; k < rid_array->count; k++) {
3125 if (member_rids[i] == rid_array->rids[k].rid) {
3126 already_member = true;
3127 break;
3130 if (!already_member) {
3131 if (!add_rid_to_array_unique(ctx,
3132 member_rids[i],
3133 &add_rids, &num_add_rids)) {
3134 werr = WERR_GENERAL_FAILURE;
3135 goto done;
3140 /* del list */
3142 for (k=0; k < rid_array->count; k++) {
3143 bool keep_member = false;
3144 for (i=0; i < r->in.num_entries; i++) {
3145 if (member_rids[i] == rid_array->rids[k].rid) {
3146 keep_member = true;
3147 break;
3150 if (!keep_member) {
3151 if (!add_rid_to_array_unique(ctx,
3152 rid_array->rids[k].rid,
3153 &del_rids, &num_del_rids)) {
3154 werr = WERR_GENERAL_FAILURE;
3155 goto done;
3160 /* add list */
3162 for (i=0; i < num_add_rids; i++) {
3163 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
3164 &domain_handle,
3165 SAMR_GROUP_ACCESS_ADD_MEMBER,
3166 add_rids[i],
3167 &group_handle);
3168 if (!NT_STATUS_IS_OK(status)) {
3169 werr = ntstatus_to_werror(status);
3170 goto done;
3173 status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
3174 &group_handle,
3175 user_rids.ids[0],
3176 7 /* ? */);
3177 if (!NT_STATUS_IS_OK(status)) {
3178 werr = ntstatus_to_werror(status);
3179 goto done;
3182 if (is_valid_policy_hnd(&group_handle)) {
3183 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
3187 /* del list */
3189 for (i=0; i < num_del_rids; i++) {
3190 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
3191 &domain_handle,
3192 SAMR_GROUP_ACCESS_REMOVE_MEMBER,
3193 del_rids[i],
3194 &group_handle);
3195 if (!NT_STATUS_IS_OK(status)) {
3196 werr = ntstatus_to_werror(status);
3197 goto done;
3200 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
3201 &group_handle,
3202 user_rids.ids[0]);
3203 if (!NT_STATUS_IS_OK(status)) {
3204 werr = ntstatus_to_werror(status);
3205 goto done;
3208 if (is_valid_policy_hnd(&group_handle)) {
3209 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
3213 werr = WERR_OK;
3215 done:
3216 if (!cli) {
3217 return werr;
3220 if (is_valid_policy_hnd(&group_handle)) {
3221 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
3224 if (ctx->disable_policy_handle_cache) {
3225 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3226 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3229 return werr;
3232 /****************************************************************
3233 ****************************************************************/
3235 WERROR NetUserSetGroups_l(struct libnetapi_ctx *ctx,
3236 struct NetUserSetGroups *r)
3238 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetGroups);
3241 /****************************************************************
3242 ****************************************************************/
3244 static NTSTATUS add_LOCALGROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
3245 uint32_t level,
3246 const char *group_name,
3247 uint8_t **buffer,
3248 uint32_t *num_entries)
3250 struct LOCALGROUP_USERS_INFO_0 u0;
3252 switch (level) {
3253 case 0:
3254 u0.lgrui0_name = talloc_strdup(mem_ctx, group_name);
3255 NT_STATUS_HAVE_NO_MEMORY(u0.lgrui0_name);
3257 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_USERS_INFO_0, u0,
3258 (struct LOCALGROUP_USERS_INFO_0 **)buffer, num_entries);
3259 break;
3260 default:
3261 return NT_STATUS_INVALID_INFO_CLASS;
3264 return NT_STATUS_OK;
3267 /****************************************************************
3268 ****************************************************************/
3270 WERROR NetUserGetLocalGroups_r(struct libnetapi_ctx *ctx,
3271 struct NetUserGetLocalGroups *r)
3273 struct cli_state *cli = NULL;
3274 struct rpc_pipe_client *pipe_cli = NULL;
3275 struct policy_handle connect_handle, domain_handle, user_handle,
3276 builtin_handle;
3277 struct lsa_String lsa_account_name;
3278 struct dom_sid2 *domain_sid = NULL;
3279 struct samr_Ids user_rids, name_types;
3280 struct samr_RidWithAttributeArray *rid_array = NULL;
3281 struct lsa_Strings names;
3282 struct samr_Ids types;
3283 uint32_t *rids = NULL;
3284 size_t num_rids = 0;
3285 struct dom_sid user_sid;
3286 struct lsa_SidArray sid_array;
3287 struct samr_Ids domain_rids;
3288 struct samr_Ids builtin_rids;
3290 int i;
3291 uint32_t entries_read = 0;
3293 NTSTATUS status = NT_STATUS_OK;
3294 WERROR werr;
3296 ZERO_STRUCT(connect_handle);
3297 ZERO_STRUCT(domain_handle);
3299 if (!r->out.buffer) {
3300 return WERR_INVALID_PARAM;
3303 *r->out.buffer = NULL;
3304 *r->out.entries_read = 0;
3305 *r->out.total_entries = 0;
3307 switch (r->in.level) {
3308 case 0:
3309 case 1:
3310 break;
3311 default:
3312 return WERR_UNKNOWN_LEVEL;
3315 werr = libnetapi_open_pipe(ctx, r->in.server_name,
3316 &ndr_table_samr.syntax_id,
3317 &cli,
3318 &pipe_cli);
3319 if (!W_ERROR_IS_OK(werr)) {
3320 goto done;
3323 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
3324 SAMR_ACCESS_ENUM_DOMAINS |
3325 SAMR_ACCESS_LOOKUP_DOMAIN,
3326 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
3327 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
3328 &connect_handle,
3329 &domain_handle,
3330 &domain_sid);
3331 if (!W_ERROR_IS_OK(werr)) {
3332 goto done;
3335 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
3336 SAMR_ACCESS_ENUM_DOMAINS |
3337 SAMR_ACCESS_LOOKUP_DOMAIN,
3338 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
3339 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
3340 &connect_handle,
3341 &builtin_handle);
3342 if (!W_ERROR_IS_OK(werr)) {
3343 goto done;
3346 init_lsa_String(&lsa_account_name, r->in.user_name);
3348 status = rpccli_samr_LookupNames(pipe_cli, ctx,
3349 &domain_handle,
3351 &lsa_account_name,
3352 &user_rids,
3353 &name_types);
3354 if (!NT_STATUS_IS_OK(status)) {
3355 werr = ntstatus_to_werror(status);
3356 goto done;
3359 status = rpccli_samr_OpenUser(pipe_cli, ctx,
3360 &domain_handle,
3361 SAMR_USER_ACCESS_GET_GROUPS,
3362 user_rids.ids[0],
3363 &user_handle);
3364 if (!NT_STATUS_IS_OK(status)) {
3365 werr = ntstatus_to_werror(status);
3366 goto done;
3369 status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
3370 &user_handle,
3371 &rid_array);
3372 if (!NT_STATUS_IS_OK(status)) {
3373 werr = ntstatus_to_werror(status);
3374 goto done;
3377 if (!sid_compose(&user_sid, domain_sid, user_rids.ids[0])) {
3378 werr = WERR_NOMEM;
3379 goto done;
3382 sid_array.num_sids = rid_array->count + 1;
3383 sid_array.sids = TALLOC_ARRAY(ctx, struct lsa_SidPtr, sid_array.num_sids);
3384 if (!sid_array.sids) {
3385 werr = WERR_NOMEM;
3386 goto done;
3389 sid_array.sids[0].sid = sid_dup_talloc(ctx, &user_sid);
3390 if (!sid_array.sids[0].sid) {
3391 werr = WERR_NOMEM;
3392 goto done;
3395 for (i=0; i < rid_array->count; i++) {
3396 struct dom_sid sid;
3398 if (!sid_compose(&sid, domain_sid, rid_array->rids[i].rid)) {
3399 werr = WERR_NOMEM;
3400 goto done;
3403 sid_array.sids[i+1].sid = sid_dup_talloc(ctx, &sid);
3404 if (!sid_array.sids[i+1].sid) {
3405 werr = WERR_NOMEM;
3406 goto done;
3410 status = rpccli_samr_GetAliasMembership(pipe_cli, ctx,
3411 &domain_handle,
3412 &sid_array,
3413 &domain_rids);
3414 if (!NT_STATUS_IS_OK(status)) {
3415 werr = ntstatus_to_werror(status);
3416 goto done;
3419 for (i=0; i < domain_rids.count; i++) {
3420 if (!add_rid_to_array_unique(ctx, domain_rids.ids[i],
3421 &rids, &num_rids)) {
3422 werr = WERR_NOMEM;
3423 goto done;
3427 status = rpccli_samr_GetAliasMembership(pipe_cli, ctx,
3428 &builtin_handle,
3429 &sid_array,
3430 &builtin_rids);
3431 if (!NT_STATUS_IS_OK(status)) {
3432 werr = ntstatus_to_werror(status);
3433 goto done;
3436 for (i=0; i < builtin_rids.count; i++) {
3437 if (!add_rid_to_array_unique(ctx, builtin_rids.ids[i],
3438 &rids, &num_rids)) {
3439 werr = WERR_NOMEM;
3440 goto done;
3444 status = rpccli_samr_LookupRids(pipe_cli, ctx,
3445 &builtin_handle,
3446 num_rids,
3447 rids,
3448 &names,
3449 &types);
3450 if (!NT_STATUS_IS_OK(status)) {
3451 werr = ntstatus_to_werror(status);
3452 goto done;
3455 for (i=0; i < names.count; i++) {
3456 status = add_LOCALGROUP_USERS_INFO_X_buffer(ctx,
3457 r->in.level,
3458 names.names[i].string,
3459 r->out.buffer,
3460 &entries_read);
3461 if (!NT_STATUS_IS_OK(status)) {
3462 werr = ntstatus_to_werror(status);
3463 goto done;
3467 *r->out.entries_read = entries_read;
3468 *r->out.total_entries = entries_read;
3470 done:
3471 if (!cli) {
3472 return werr;
3475 if (ctx->disable_policy_handle_cache) {
3476 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3477 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3480 return werr;
3483 /****************************************************************
3484 ****************************************************************/
3486 WERROR NetUserGetLocalGroups_l(struct libnetapi_ctx *ctx,
3487 struct NetUserGetLocalGroups *r)
3489 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetLocalGroups);