libnetapi_open_pipe does not need to return cli_state
[Samba/gebeck_regimport.git] / source3 / lib / netapi / user.c
blob9d7f299f59bae03b0ae66b19355dad8b43da8112
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 */
95 info21->last_logon = 0;
96 info21->last_logoff = 0;
97 info21->last_password_change = 0;
98 info21->acct_expiry = 0;
99 info21->allow_password_change = 0;
100 info21->force_password_change = 0;
101 info21->account_name.string = infoX->usriX_name;
102 info21->full_name.string = infoX->usriX_full_name;
103 info21->home_directory.string = infoX->usriX_home_dir;
104 info21->home_drive.string = infoX->usriX_home_dir_drive;
105 info21->logon_script.string = infoX->usriX_script_path;
106 info21->profile_path.string = infoX->usriX_profile;
107 info21->description.string = infoX->usriX_comment;
108 info21->workstations.string = infoX->usriX_workstations;
109 info21->comment.string = infoX->usriX_usr_comment;
110 info21->parameters = zero_parameters;
111 info21->lm_owf_password = zero_parameters;
112 info21->nt_owf_password = zero_parameters;
113 info21->unknown3.string = NULL;
114 info21->buf_count = 0;
115 info21->buffer = NULL;
116 info21->rid = infoX->usriX_user_id;
117 info21->primary_gid = infoX->usriX_primary_group_id;
118 info21->acct_flags = infoX->usriX_flags;
119 info21->fields_present = fields_present;
120 info21->logon_hours = zero_logon_hours;
121 info21->bad_password_count = infoX->usriX_bad_pw_count;
122 info21->logon_count = infoX->usriX_num_logons;
123 info21->country_code = infoX->usriX_country_code;
124 info21->code_page = infoX->usriX_code_page;
125 info21->lm_password_set = 0;
126 info21->nt_password_set = 0;
127 info21->password_expired = infoX->usriX_password_expired;
128 info21->unknown4 = 0;
131 /****************************************************************
132 ****************************************************************/
134 static NTSTATUS construct_USER_INFO_X(uint32_t level,
135 uint8_t *buffer,
136 struct USER_INFO_X *uX)
138 struct USER_INFO_0 *u0 = NULL;
139 struct USER_INFO_1 *u1 = NULL;
140 struct USER_INFO_2 *u2 = NULL;
141 struct USER_INFO_3 *u3 = NULL;
142 struct USER_INFO_1003 *u1003 = NULL;
143 struct USER_INFO_1006 *u1006 = NULL;
144 struct USER_INFO_1007 *u1007 = NULL;
145 struct USER_INFO_1009 *u1009 = NULL;
146 struct USER_INFO_1011 *u1011 = NULL;
147 struct USER_INFO_1012 *u1012 = NULL;
148 struct USER_INFO_1014 *u1014 = NULL;
149 struct USER_INFO_1024 *u1024 = NULL;
150 struct USER_INFO_1051 *u1051 = NULL;
151 struct USER_INFO_1052 *u1052 = NULL;
152 struct USER_INFO_1053 *u1053 = NULL;
154 if (!buffer || !uX) {
155 return NT_STATUS_INVALID_PARAMETER;
158 ZERO_STRUCTP(uX);
160 switch (level) {
161 case 0:
162 u0 = (struct USER_INFO_0 *)buffer;
163 uX->usriX_name = u0->usri0_name;
164 break;
165 case 1:
166 u1 = (struct USER_INFO_1 *)buffer;
167 uX->usriX_name = u1->usri1_name;
168 uX->usriX_password = u1->usri1_password;
169 uX->usriX_password_age = u1->usri1_password_age;
170 uX->usriX_priv = u1->usri1_priv;
171 uX->usriX_home_dir = u1->usri1_home_dir;
172 uX->usriX_comment = u1->usri1_comment;
173 uX->usriX_flags = u1->usri1_flags;
174 uX->usriX_script_path = u1->usri1_script_path;
175 break;
176 case 2:
177 u2 = (struct USER_INFO_2 *)buffer;
178 uX->usriX_name = u2->usri2_name;
179 uX->usriX_password = u2->usri2_password;
180 uX->usriX_password_age = u2->usri2_password_age;
181 uX->usriX_priv = u2->usri2_priv;
182 uX->usriX_home_dir = u2->usri2_home_dir;
183 uX->usriX_comment = u2->usri2_comment;
184 uX->usriX_flags = u2->usri2_flags;
185 uX->usriX_script_path = u2->usri2_script_path;
186 uX->usriX_auth_flags = u2->usri2_auth_flags;
187 uX->usriX_full_name = u2->usri2_full_name;
188 uX->usriX_usr_comment = u2->usri2_usr_comment;
189 uX->usriX_parms = u2->usri2_parms;
190 uX->usriX_workstations = u2->usri2_workstations;
191 uX->usriX_last_logon = u2->usri2_last_logon;
192 uX->usriX_last_logoff = u2->usri2_last_logoff;
193 uX->usriX_acct_expires = u2->usri2_acct_expires;
194 uX->usriX_max_storage = u2->usri2_max_storage;
195 uX->usriX_units_per_week= u2->usri2_units_per_week;
196 uX->usriX_logon_hours = u2->usri2_logon_hours;
197 uX->usriX_bad_pw_count = u2->usri2_bad_pw_count;
198 uX->usriX_num_logons = u2->usri2_num_logons;
199 uX->usriX_logon_server = u2->usri2_logon_server;
200 uX->usriX_country_code = u2->usri2_country_code;
201 uX->usriX_code_page = u2->usri2_code_page;
202 break;
203 case 3:
204 u3 = (struct USER_INFO_3 *)buffer;
205 uX->usriX_name = u3->usri3_name;
206 uX->usriX_password_age = u3->usri3_password_age;
207 uX->usriX_priv = u3->usri3_priv;
208 uX->usriX_home_dir = u3->usri3_home_dir;
209 uX->usriX_comment = u3->usri3_comment;
210 uX->usriX_flags = u3->usri3_flags;
211 uX->usriX_script_path = u3->usri3_script_path;
212 uX->usriX_auth_flags = u3->usri3_auth_flags;
213 uX->usriX_full_name = u3->usri3_full_name;
214 uX->usriX_usr_comment = u3->usri3_usr_comment;
215 uX->usriX_parms = u3->usri3_parms;
216 uX->usriX_workstations = u3->usri3_workstations;
217 uX->usriX_last_logon = u3->usri3_last_logon;
218 uX->usriX_last_logoff = u3->usri3_last_logoff;
219 uX->usriX_acct_expires = u3->usri3_acct_expires;
220 uX->usriX_max_storage = u3->usri3_max_storage;
221 uX->usriX_units_per_week= u3->usri3_units_per_week;
222 uX->usriX_logon_hours = u3->usri3_logon_hours;
223 uX->usriX_bad_pw_count = u3->usri3_bad_pw_count;
224 uX->usriX_num_logons = u3->usri3_num_logons;
225 uX->usriX_logon_server = u3->usri3_logon_server;
226 uX->usriX_country_code = u3->usri3_country_code;
227 uX->usriX_code_page = u3->usri3_code_page;
228 uX->usriX_user_id = u3->usri3_user_id;
229 uX->usriX_primary_group_id = u3->usri3_primary_group_id;
230 uX->usriX_profile = u3->usri3_profile;
231 uX->usriX_home_dir_drive = u3->usri3_home_dir_drive;
232 uX->usriX_password_expired = u3->usri3_password_expired;
233 break;
234 case 1003:
235 u1003 = (struct USER_INFO_1003 *)buffer;
236 uX->usriX_password = u1003->usri1003_password;
237 break;
238 case 1006:
239 u1006 = (struct USER_INFO_1006 *)buffer;
240 uX->usriX_home_dir = u1006->usri1006_home_dir;
241 break;
242 case 1007:
243 u1007 = (struct USER_INFO_1007 *)buffer;
244 uX->usriX_comment = u1007->usri1007_comment;
245 break;
246 case 1009:
247 u1009 = (struct USER_INFO_1009 *)buffer;
248 uX->usriX_script_path = u1009->usri1009_script_path;
249 break;
250 case 1011:
251 u1011 = (struct USER_INFO_1011 *)buffer;
252 uX->usriX_full_name = u1011->usri1011_full_name;
253 break;
254 case 1012:
255 u1012 = (struct USER_INFO_1012 *)buffer;
256 uX->usriX_usr_comment = u1012->usri1012_usr_comment;
257 break;
258 case 1014:
259 u1014 = (struct USER_INFO_1014 *)buffer;
260 uX->usriX_workstations = u1014->usri1014_workstations;
261 break;
262 case 1024:
263 u1024 = (struct USER_INFO_1024 *)buffer;
264 uX->usriX_country_code = u1024->usri1024_country_code;
265 break;
266 case 1051:
267 u1051 = (struct USER_INFO_1051 *)buffer;
268 uX->usriX_primary_group_id = u1051->usri1051_primary_group_id;
269 break;
270 case 1052:
271 u1052 = (struct USER_INFO_1052 *)buffer;
272 uX->usriX_profile = u1052->usri1052_profile;
273 break;
274 case 1053:
275 u1053 = (struct USER_INFO_1053 *)buffer;
276 uX->usriX_home_dir_drive = u1053->usri1053_home_dir_drive;
277 break;
278 case 4:
279 default:
280 return NT_STATUS_INVALID_INFO_CLASS;
283 return NT_STATUS_OK;
286 /****************************************************************
287 ****************************************************************/
289 static NTSTATUS set_user_info_USER_INFO_X(TALLOC_CTX *ctx,
290 struct rpc_pipe_client *pipe_cli,
291 DATA_BLOB *session_key,
292 struct policy_handle *user_handle,
293 struct USER_INFO_X *uX)
295 union samr_UserInfo user_info;
296 struct samr_UserInfo21 info21;
297 NTSTATUS status;
299 if (!uX) {
300 return NT_STATUS_INVALID_PARAMETER;
303 convert_USER_INFO_X_to_samr_user_info21(uX, &info21);
305 ZERO_STRUCT(user_info);
307 if (uX->usriX_password) {
309 user_info.info25.info = info21;
311 init_samr_CryptPasswordEx(uX->usriX_password,
312 session_key,
313 &user_info.info25.password);
315 status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
316 user_handle,
318 &user_info);
320 if (NT_STATUS_EQUAL(status, NT_STATUS(DCERPC_FAULT_INVALID_TAG))) {
322 user_info.info23.info = info21;
324 init_samr_CryptPassword(uX->usriX_password,
325 session_key,
326 &user_info.info23.password);
328 status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
329 user_handle,
331 &user_info);
333 } else {
335 user_info.info21 = info21;
337 status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
338 user_handle,
340 &user_info);
343 return status;
346 /****************************************************************
347 ****************************************************************/
349 WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
350 struct NetUserAdd *r)
352 struct rpc_pipe_client *pipe_cli = NULL;
353 NTSTATUS status;
354 WERROR werr;
355 POLICY_HND connect_handle, domain_handle, user_handle;
356 struct lsa_String lsa_account_name;
357 struct dom_sid2 *domain_sid = NULL;
358 union samr_UserInfo *user_info = NULL;
359 struct samr_PwInfo pw_info;
360 uint32_t access_granted = 0;
361 uint32_t rid = 0;
362 struct USER_INFO_X uX;
364 ZERO_STRUCT(connect_handle);
365 ZERO_STRUCT(domain_handle);
366 ZERO_STRUCT(user_handle);
368 if (!r->in.buffer) {
369 return WERR_INVALID_PARAM;
372 switch (r->in.level) {
373 case 1:
374 break;
375 case 2:
376 case 3:
377 case 4:
378 default:
379 werr = WERR_NOT_SUPPORTED;
380 goto done;
383 werr = libnetapi_open_pipe(ctx, r->in.server_name,
384 &ndr_table_samr.syntax_id,
385 &pipe_cli);
386 if (!W_ERROR_IS_OK(werr)) {
387 goto done;
390 status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
391 if (!NT_STATUS_IS_OK(status)) {
392 werr = ntstatus_to_werror(status);
393 goto done;
396 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
397 SAMR_ACCESS_ENUM_DOMAINS |
398 SAMR_ACCESS_OPEN_DOMAIN,
399 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
400 SAMR_DOMAIN_ACCESS_CREATE_USER |
401 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
402 &connect_handle,
403 &domain_handle,
404 &domain_sid);
405 if (!W_ERROR_IS_OK(werr)) {
406 goto done;
409 init_lsa_String(&lsa_account_name, uX.usriX_name);
411 status = rpccli_samr_CreateUser2(pipe_cli, ctx,
412 &domain_handle,
413 &lsa_account_name,
414 ACB_NORMAL,
415 SEC_STD_WRITE_DAC |
416 SEC_STD_DELETE |
417 SAMR_USER_ACCESS_SET_PASSWORD |
418 SAMR_USER_ACCESS_SET_ATTRIBUTES |
419 SAMR_USER_ACCESS_GET_ATTRIBUTES,
420 &user_handle,
421 &access_granted,
422 &rid);
423 if (!NT_STATUS_IS_OK(status)) {
424 werr = ntstatus_to_werror(status);
425 goto done;
428 status = rpccli_samr_QueryUserInfo(pipe_cli, ctx,
429 &user_handle,
431 &user_info);
432 if (!NT_STATUS_IS_OK(status)) {
433 werr = ntstatus_to_werror(status);
434 goto done;
437 if (!(user_info->info16.acct_flags & ACB_NORMAL)) {
438 werr = WERR_INVALID_PARAM;
439 goto done;
442 status = rpccli_samr_GetUserPwInfo(pipe_cli, ctx,
443 &user_handle,
444 &pw_info);
445 if (!NT_STATUS_IS_OK(status)) {
446 werr = ntstatus_to_werror(status);
447 goto done;
450 uX.usriX_flags |= ACB_NORMAL;
452 status = set_user_info_USER_INFO_X(ctx, pipe_cli,
453 &pipe_cli->auth->user_session_key,
454 &user_handle,
455 &uX);
456 if (!NT_STATUS_IS_OK(status)) {
457 werr = ntstatus_to_werror(status);
458 goto failed;
461 werr = WERR_OK;
462 goto done;
464 failed:
465 rpccli_samr_DeleteUser(pipe_cli, ctx,
466 &user_handle);
468 done:
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 rpc_pipe_client *pipe_cli = NULL;
497 NTSTATUS status;
498 WERROR werr;
499 POLICY_HND connect_handle, builtin_handle, domain_handle, user_handle;
500 struct lsa_String lsa_account_name;
501 struct samr_Ids user_rids, name_types;
502 struct dom_sid2 *domain_sid = NULL;
503 struct dom_sid2 user_sid;
505 ZERO_STRUCT(connect_handle);
506 ZERO_STRUCT(builtin_handle);
507 ZERO_STRUCT(domain_handle);
508 ZERO_STRUCT(user_handle);
510 werr = libnetapi_open_pipe(ctx, r->in.server_name,
511 &ndr_table_samr.syntax_id,
512 &pipe_cli);
514 if (!W_ERROR_IS_OK(werr)) {
515 goto done;
518 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
519 SAMR_ACCESS_ENUM_DOMAINS |
520 SAMR_ACCESS_OPEN_DOMAIN,
521 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
522 &connect_handle,
523 &domain_handle,
524 &domain_sid);
525 if (!W_ERROR_IS_OK(werr)) {
526 goto done;
529 status = rpccli_samr_OpenDomain(pipe_cli, ctx,
530 &connect_handle,
531 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
532 CONST_DISCARD(DOM_SID *, &global_sid_Builtin),
533 &builtin_handle);
534 if (!NT_STATUS_IS_OK(status)) {
535 werr = ntstatus_to_werror(status);
536 goto done;
539 init_lsa_String(&lsa_account_name, r->in.user_name);
541 status = rpccli_samr_LookupNames(pipe_cli, ctx,
542 &domain_handle,
544 &lsa_account_name,
545 &user_rids,
546 &name_types);
547 if (!NT_STATUS_IS_OK(status)) {
548 werr = ntstatus_to_werror(status);
549 goto done;
552 status = rpccli_samr_OpenUser(pipe_cli, ctx,
553 &domain_handle,
554 SEC_STD_DELETE,
555 user_rids.ids[0],
556 &user_handle);
557 if (!NT_STATUS_IS_OK(status)) {
558 werr = ntstatus_to_werror(status);
559 goto done;
562 sid_compose(&user_sid, domain_sid, user_rids.ids[0]);
564 status = rpccli_samr_RemoveMemberFromForeignDomain(pipe_cli, ctx,
565 &builtin_handle,
566 &user_sid);
567 if (!NT_STATUS_IS_OK(status)) {
568 werr = ntstatus_to_werror(status);
569 goto done;
572 status = rpccli_samr_DeleteUser(pipe_cli, ctx,
573 &user_handle);
574 if (!NT_STATUS_IS_OK(status)) {
575 werr = ntstatus_to_werror(status);
576 goto done;
579 werr = WERR_OK;
581 done:
582 if (is_valid_policy_hnd(&user_handle)) {
583 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
586 if (ctx->disable_policy_handle_cache) {
587 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
588 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
589 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
592 return werr;
595 /****************************************************************
596 ****************************************************************/
598 WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
599 struct NetUserDel *r)
601 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserDel);
604 /****************************************************************
605 ****************************************************************/
607 static NTSTATUS libnetapi_samr_lookup_user(TALLOC_CTX *mem_ctx,
608 struct rpc_pipe_client *pipe_cli,
609 struct policy_handle *domain_handle,
610 struct policy_handle *builtin_handle,
611 const char *user_name,
612 const struct dom_sid *domain_sid,
613 uint32_t rid,
614 uint32_t level,
615 struct samr_UserInfo21 **info21,
616 struct sec_desc_buf **sec_desc,
617 uint32_t *auth_flag_p)
619 NTSTATUS status;
621 struct policy_handle user_handle;
622 union samr_UserInfo *user_info = NULL;
623 struct samr_RidWithAttributeArray *rid_array = NULL;
624 uint32_t access_mask = SEC_STD_READ_CONTROL |
625 SAMR_USER_ACCESS_GET_ATTRIBUTES |
626 SAMR_USER_ACCESS_GET_NAME_ETC;
628 ZERO_STRUCT(user_handle);
630 switch (level) {
631 case 0:
632 break;
633 case 1:
634 access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
635 SAMR_USER_ACCESS_GET_GROUPS;
636 break;
637 case 2:
638 case 3:
639 case 4:
640 case 11:
641 access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
642 SAMR_USER_ACCESS_GET_GROUPS |
643 SAMR_USER_ACCESS_GET_LOCALE;
644 break;
645 case 10:
646 case 20:
647 case 23:
648 break;
649 default:
650 return NT_STATUS_INVALID_LEVEL;
653 if (level == 0) {
654 return NT_STATUS_OK;
657 status = rpccli_samr_OpenUser(pipe_cli, mem_ctx,
658 domain_handle,
659 access_mask,
660 rid,
661 &user_handle);
662 if (!NT_STATUS_IS_OK(status)) {
663 goto done;
666 status = rpccli_samr_QueryUserInfo(pipe_cli, mem_ctx,
667 &user_handle,
669 &user_info);
670 if (!NT_STATUS_IS_OK(status)) {
671 goto done;
674 status = rpccli_samr_QuerySecurity(pipe_cli, mem_ctx,
675 &user_handle,
676 SECINFO_DACL,
677 sec_desc);
678 if (!NT_STATUS_IS_OK(status)) {
679 goto done;
682 if (access_mask & SAMR_USER_ACCESS_GET_GROUPS) {
684 struct lsa_SidArray sid_array;
685 struct samr_Ids alias_rids;
686 int i;
687 uint32_t auth_flag = 0;
688 struct dom_sid sid;
690 status = rpccli_samr_GetGroupsForUser(pipe_cli, mem_ctx,
691 &user_handle,
692 &rid_array);
693 if (!NT_STATUS_IS_OK(status)) {
694 goto done;
697 sid_array.num_sids = rid_array->count + 1;
698 sid_array.sids = talloc_array(mem_ctx, struct lsa_SidPtr,
699 sid_array.num_sids);
700 NT_STATUS_HAVE_NO_MEMORY(sid_array.sids);
702 for (i=0; i<rid_array->count; i++) {
703 sid_compose(&sid, domain_sid, rid_array->rids[i].rid);
704 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sid);
705 NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
708 sid_compose(&sid, domain_sid, rid);
709 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sid);
710 NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
712 status = rpccli_samr_GetAliasMembership(pipe_cli, mem_ctx,
713 builtin_handle,
714 &sid_array,
715 &alias_rids);
716 if (!NT_STATUS_IS_OK(status)) {
717 goto done;
720 for (i=0; i<alias_rids.count; i++) {
721 switch (alias_rids.ids[i]) {
722 case 550: /* Print Operators */
723 auth_flag |= AF_OP_PRINT;
724 break;
725 case 549: /* Server Operators */
726 auth_flag |= AF_OP_SERVER;
727 break;
728 case 548: /* Account Operators */
729 auth_flag |= AF_OP_ACCOUNTS;
730 break;
731 default:
732 break;
736 if (auth_flag_p) {
737 *auth_flag_p = auth_flag;
741 *info21 = &user_info->info21;
743 done:
744 if (is_valid_policy_hnd(&user_handle)) {
745 rpccli_samr_Close(pipe_cli, mem_ctx, &user_handle);
748 return status;
751 /****************************************************************
752 ****************************************************************/
754 static uint32_t samr_rid_to_priv_level(uint32_t rid)
756 switch (rid) {
757 case DOMAIN_RID_ADMINISTRATOR:
758 return USER_PRIV_ADMIN;
759 case DOMAIN_RID_GUEST:
760 return USER_PRIV_GUEST;
761 default:
762 return USER_PRIV_USER;
766 /****************************************************************
767 ****************************************************************/
769 static uint32_t samr_acb_flags_to_netapi_flags(uint32_t acb)
771 uint32_t fl = UF_SCRIPT; /* god knows why */
773 fl |= ads_acb2uf(acb);
775 return fl;
778 /****************************************************************
779 ****************************************************************/
781 static NTSTATUS info21_to_USER_INFO_1(TALLOC_CTX *mem_ctx,
782 const struct samr_UserInfo21 *i21,
783 struct USER_INFO_1 *i)
785 ZERO_STRUCTP(i);
786 i->usri1_name = talloc_strdup(mem_ctx, i21->account_name.string);
787 NT_STATUS_HAVE_NO_MEMORY(i->usri1_name);
788 i->usri1_password = NULL;
789 i->usri1_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
790 i->usri1_priv = samr_rid_to_priv_level(i21->rid);
791 i->usri1_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
792 i->usri1_comment = talloc_strdup(mem_ctx, i21->description.string);
793 i->usri1_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
794 i->usri1_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
796 return NT_STATUS_OK;
799 /****************************************************************
800 ****************************************************************/
802 static NTSTATUS info21_to_USER_INFO_2(TALLOC_CTX *mem_ctx,
803 const struct samr_UserInfo21 *i21,
804 uint32_t auth_flag,
805 struct USER_INFO_2 *i)
807 ZERO_STRUCTP(i);
809 i->usri2_name = talloc_strdup(mem_ctx, i21->account_name.string);
810 NT_STATUS_HAVE_NO_MEMORY(i->usri2_name);
811 i->usri2_password = NULL;
812 i->usri2_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
813 i->usri2_priv = samr_rid_to_priv_level(i21->rid);
814 i->usri2_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
815 i->usri2_comment = talloc_strdup(mem_ctx, i21->description.string);
816 i->usri2_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
817 i->usri2_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
818 i->usri2_auth_flags = auth_flag;
819 i->usri2_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
820 i->usri2_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
821 i->usri2_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
822 i->usri2_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
823 i->usri2_last_logon = nt_time_to_unix(i21->last_logon);
824 i->usri2_last_logoff = nt_time_to_unix(i21->last_logoff);
825 i->usri2_acct_expires = nt_time_to_unix(i21->acct_expiry);
826 i->usri2_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
827 i->usri2_units_per_week = i21->logon_hours.units_per_week;
828 i->usri2_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
829 i->usri2_bad_pw_count = i21->bad_password_count;
830 i->usri2_num_logons = i21->logon_count;
831 i->usri2_logon_server = talloc_strdup(mem_ctx, "\\\\*");
832 i->usri2_country_code = i21->country_code;
833 i->usri2_code_page = i21->code_page;
835 return NT_STATUS_OK;
838 /****************************************************************
839 ****************************************************************/
841 static NTSTATUS info21_to_USER_INFO_3(TALLOC_CTX *mem_ctx,
842 const struct samr_UserInfo21 *i21,
843 uint32_t auth_flag,
844 struct USER_INFO_3 *i)
846 ZERO_STRUCTP(i);
848 i->usri3_name = talloc_strdup(mem_ctx, i21->account_name.string);
849 NT_STATUS_HAVE_NO_MEMORY(i->usri3_name);
850 i->usri3_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
851 i->usri3_priv = samr_rid_to_priv_level(i21->rid);
852 i->usri3_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
853 i->usri3_comment = talloc_strdup(mem_ctx, i21->description.string);
854 i->usri3_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
855 i->usri3_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
856 i->usri3_auth_flags = auth_flag;
857 i->usri3_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
858 i->usri3_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
859 i->usri3_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
860 i->usri3_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
861 i->usri3_last_logon = nt_time_to_unix(i21->last_logon);
862 i->usri3_last_logoff = nt_time_to_unix(i21->last_logoff);
863 i->usri3_acct_expires = nt_time_to_unix(i21->acct_expiry);
864 i->usri3_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
865 i->usri3_units_per_week = i21->logon_hours.units_per_week;
866 i->usri3_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
867 i->usri3_bad_pw_count = i21->bad_password_count;
868 i->usri3_num_logons = i21->logon_count;
869 i->usri3_logon_server = talloc_strdup(mem_ctx, "\\\\*");
870 i->usri3_country_code = i21->country_code;
871 i->usri3_code_page = i21->code_page;
872 i->usri3_user_id = i21->rid;
873 i->usri3_primary_group_id = i21->primary_gid;
874 i->usri3_profile = talloc_strdup(mem_ctx, i21->profile_path.string);
875 i->usri3_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
876 i->usri3_password_expired = i21->password_expired;
878 return NT_STATUS_OK;
881 /****************************************************************
882 ****************************************************************/
884 static NTSTATUS info21_to_USER_INFO_4(TALLOC_CTX *mem_ctx,
885 const struct samr_UserInfo21 *i21,
886 uint32_t auth_flag,
887 struct dom_sid *domain_sid,
888 struct USER_INFO_4 *i)
890 struct dom_sid sid;
892 ZERO_STRUCTP(i);
894 i->usri4_name = talloc_strdup(mem_ctx, i21->account_name.string);
895 NT_STATUS_HAVE_NO_MEMORY(i->usri4_name);
896 i->usri4_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
897 i->usri4_password = NULL;
898 i->usri4_priv = samr_rid_to_priv_level(i21->rid);
899 i->usri4_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
900 i->usri4_comment = talloc_strdup(mem_ctx, i21->description.string);
901 i->usri4_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
902 i->usri4_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
903 i->usri4_auth_flags = auth_flag;
904 i->usri4_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
905 i->usri4_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
906 i->usri4_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
907 i->usri4_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
908 i->usri4_last_logon = nt_time_to_unix(i21->last_logon);
909 i->usri4_last_logoff = nt_time_to_unix(i21->last_logoff);
910 i->usri4_acct_expires = nt_time_to_unix(i21->acct_expiry);
911 i->usri4_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
912 i->usri4_units_per_week = i21->logon_hours.units_per_week;
913 i->usri4_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
914 i->usri4_bad_pw_count = i21->bad_password_count;
915 i->usri4_num_logons = i21->logon_count;
916 i->usri4_logon_server = talloc_strdup(mem_ctx, "\\\\*");
917 i->usri4_country_code = i21->country_code;
918 i->usri4_code_page = i21->code_page;
919 if (!sid_compose(&sid, domain_sid, i21->rid)) {
920 return NT_STATUS_NO_MEMORY;
922 i->usri4_user_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
923 i->usri4_primary_group_id = i21->primary_gid;
924 i->usri4_profile = talloc_strdup(mem_ctx, i21->profile_path.string);
925 i->usri4_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
926 i->usri4_password_expired = i21->password_expired;
928 return NT_STATUS_OK;
931 /****************************************************************
932 ****************************************************************/
934 static NTSTATUS info21_to_USER_INFO_10(TALLOC_CTX *mem_ctx,
935 const struct samr_UserInfo21 *i21,
936 struct USER_INFO_10 *i)
938 ZERO_STRUCTP(i);
940 i->usri10_name = talloc_strdup(mem_ctx, i21->account_name.string);
941 NT_STATUS_HAVE_NO_MEMORY(i->usri10_name);
942 i->usri10_comment = talloc_strdup(mem_ctx, i21->description.string);
943 i->usri10_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
944 i->usri10_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
946 return NT_STATUS_OK;
949 /****************************************************************
950 ****************************************************************/
952 static NTSTATUS info21_to_USER_INFO_11(TALLOC_CTX *mem_ctx,
953 const struct samr_UserInfo21 *i21,
954 uint32_t auth_flag,
955 struct USER_INFO_11 *i)
957 ZERO_STRUCTP(i);
959 i->usri11_name = talloc_strdup(mem_ctx, i21->account_name.string);
960 NT_STATUS_HAVE_NO_MEMORY(i->usri11_name);
961 i->usri11_comment = talloc_strdup(mem_ctx, i21->description.string);
962 i->usri11_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
963 i->usri11_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
964 i->usri11_priv = samr_rid_to_priv_level(i21->rid);
965 i->usri11_auth_flags = auth_flag;
966 i->usri11_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
967 i->usri11_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
968 i->usri11_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
969 i->usri11_last_logon = nt_time_to_unix(i21->last_logon);
970 i->usri11_last_logoff = nt_time_to_unix(i21->last_logoff);
971 i->usri11_bad_pw_count = i21->bad_password_count;
972 i->usri11_num_logons = i21->logon_count;
973 i->usri11_logon_server = talloc_strdup(mem_ctx, "\\\\*");
974 i->usri11_country_code = i21->country_code;
975 i->usri11_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
976 i->usri11_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
977 i->usri11_units_per_week = i21->logon_hours.units_per_week;
978 i->usri11_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
979 i->usri11_code_page = i21->code_page;
981 return NT_STATUS_OK;
984 /****************************************************************
985 ****************************************************************/
987 static NTSTATUS info21_to_USER_INFO_20(TALLOC_CTX *mem_ctx,
988 const struct samr_UserInfo21 *i21,
989 struct USER_INFO_20 *i)
991 ZERO_STRUCTP(i);
993 i->usri20_name = talloc_strdup(mem_ctx, i21->account_name.string);
994 NT_STATUS_HAVE_NO_MEMORY(i->usri20_name);
995 i->usri20_comment = talloc_strdup(mem_ctx, i21->description.string);
996 i->usri20_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
997 i->usri20_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
998 i->usri20_user_id = i21->rid;
1000 return NT_STATUS_OK;
1003 /****************************************************************
1004 ****************************************************************/
1006 static NTSTATUS info21_to_USER_INFO_23(TALLOC_CTX *mem_ctx,
1007 const struct samr_UserInfo21 *i21,
1008 struct dom_sid *domain_sid,
1009 struct USER_INFO_23 *i)
1011 struct dom_sid sid;
1013 ZERO_STRUCTP(i);
1015 i->usri23_name = talloc_strdup(mem_ctx, i21->account_name.string);
1016 NT_STATUS_HAVE_NO_MEMORY(i->usri23_name);
1017 i->usri23_comment = talloc_strdup(mem_ctx, i21->description.string);
1018 i->usri23_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
1019 i->usri23_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
1020 if (!sid_compose(&sid, domain_sid, i21->rid)) {
1021 return NT_STATUS_NO_MEMORY;
1023 i->usri23_user_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
1025 return NT_STATUS_OK;
1028 /****************************************************************
1029 ****************************************************************/
1031 static NTSTATUS libnetapi_samr_lookup_user_map_USER_INFO(TALLOC_CTX *mem_ctx,
1032 struct rpc_pipe_client *pipe_cli,
1033 struct dom_sid *domain_sid,
1034 struct policy_handle *domain_handle,
1035 struct policy_handle *builtin_handle,
1036 const char *user_name,
1037 uint32_t rid,
1038 uint32_t level,
1039 uint8_t **buffer,
1040 uint32_t *num_entries)
1042 NTSTATUS status;
1044 struct samr_UserInfo21 *info21 = NULL;
1045 struct sec_desc_buf *sec_desc = NULL;
1046 uint32_t auth_flag = 0;
1048 struct USER_INFO_0 info0;
1049 struct USER_INFO_1 info1;
1050 struct USER_INFO_2 info2;
1051 struct USER_INFO_3 info3;
1052 struct USER_INFO_4 info4;
1053 struct USER_INFO_10 info10;
1054 struct USER_INFO_11 info11;
1055 struct USER_INFO_20 info20;
1056 struct USER_INFO_23 info23;
1058 switch (level) {
1059 case 0:
1060 case 1:
1061 case 2:
1062 case 3:
1063 case 4:
1064 case 10:
1065 case 11:
1066 case 20:
1067 case 23:
1068 break;
1069 default:
1070 return NT_STATUS_INVALID_LEVEL;
1073 if (level == 0) {
1074 info0.usri0_name = talloc_strdup(mem_ctx, user_name);
1075 NT_STATUS_HAVE_NO_MEMORY(info0.usri0_name);
1077 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_0, info0,
1078 (struct USER_INFO_0 **)buffer, num_entries);
1080 return NT_STATUS_OK;
1083 status = libnetapi_samr_lookup_user(mem_ctx, pipe_cli,
1084 domain_handle,
1085 builtin_handle,
1086 user_name,
1087 domain_sid,
1088 rid,
1089 level,
1090 &info21,
1091 &sec_desc,
1092 &auth_flag);
1094 if (!NT_STATUS_IS_OK(status)) {
1095 goto done;
1098 switch (level) {
1099 case 0:
1100 /* already returned above */
1101 break;
1102 case 1:
1103 status = info21_to_USER_INFO_1(mem_ctx, info21, &info1);
1104 NT_STATUS_NOT_OK_RETURN(status);
1106 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_1, info1,
1107 (struct USER_INFO_1 **)buffer, num_entries);
1109 break;
1110 case 2:
1111 status = info21_to_USER_INFO_2(mem_ctx, info21, auth_flag, &info2);
1112 NT_STATUS_NOT_OK_RETURN(status);
1114 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_2, info2,
1115 (struct USER_INFO_2 **)buffer, num_entries);
1117 break;
1118 case 3:
1119 status = info21_to_USER_INFO_3(mem_ctx, info21, auth_flag, &info3);
1120 NT_STATUS_NOT_OK_RETURN(status);
1122 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_3, info3,
1123 (struct USER_INFO_3 **)buffer, num_entries);
1125 break;
1126 case 4:
1127 status = info21_to_USER_INFO_4(mem_ctx, info21, auth_flag, domain_sid, &info4);
1128 NT_STATUS_NOT_OK_RETURN(status);
1130 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_4, info4,
1131 (struct USER_INFO_4 **)buffer, num_entries);
1133 break;
1134 case 10:
1135 status = info21_to_USER_INFO_10(mem_ctx, info21, &info10);
1136 NT_STATUS_NOT_OK_RETURN(status);
1138 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_10, info10,
1139 (struct USER_INFO_10 **)buffer, num_entries);
1141 break;
1142 case 11:
1143 status = info21_to_USER_INFO_11(mem_ctx, info21, auth_flag, &info11);
1144 NT_STATUS_NOT_OK_RETURN(status);
1146 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_11, info11,
1147 (struct USER_INFO_11 **)buffer, num_entries);
1149 break;
1150 case 20:
1151 status = info21_to_USER_INFO_20(mem_ctx, info21, &info20);
1152 NT_STATUS_NOT_OK_RETURN(status);
1154 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_20, info20,
1155 (struct USER_INFO_20 **)buffer, num_entries);
1157 break;
1158 case 23:
1159 status = info21_to_USER_INFO_23(mem_ctx, info21, domain_sid, &info23);
1160 NT_STATUS_NOT_OK_RETURN(status);
1162 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_23, info23,
1163 (struct USER_INFO_23 **)buffer, num_entries);
1164 break;
1165 default:
1166 return NT_STATUS_INVALID_LEVEL;
1169 done:
1170 return status;
1173 /****************************************************************
1174 ****************************************************************/
1176 WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
1177 struct NetUserEnum *r)
1179 struct rpc_pipe_client *pipe_cli = NULL;
1180 struct policy_handle connect_handle;
1181 struct dom_sid2 *domain_sid = NULL;
1182 struct policy_handle domain_handle, builtin_handle;
1183 struct samr_SamArray *sam = NULL;
1184 uint32_t filter = ACB_NORMAL;
1185 int i;
1186 uint32_t entries_read = 0;
1188 NTSTATUS status = NT_STATUS_OK;
1189 WERROR werr;
1191 ZERO_STRUCT(connect_handle);
1192 ZERO_STRUCT(domain_handle);
1193 ZERO_STRUCT(builtin_handle);
1195 if (!r->out.buffer) {
1196 return WERR_INVALID_PARAM;
1199 *r->out.buffer = NULL;
1200 *r->out.entries_read = 0;
1202 switch (r->in.level) {
1203 case 0:
1204 case 1:
1205 case 2:
1206 case 3:
1207 case 4:
1208 case 10:
1209 case 11:
1210 case 20:
1211 case 23:
1212 break;
1213 default:
1214 return WERR_UNKNOWN_LEVEL;
1217 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1218 &ndr_table_samr.syntax_id,
1219 &pipe_cli);
1220 if (!W_ERROR_IS_OK(werr)) {
1221 goto done;
1224 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1225 SAMR_ACCESS_ENUM_DOMAINS |
1226 SAMR_ACCESS_OPEN_DOMAIN,
1227 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1228 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1229 &connect_handle,
1230 &builtin_handle);
1231 if (!W_ERROR_IS_OK(werr)) {
1232 goto done;
1235 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1236 SAMR_ACCESS_ENUM_DOMAINS |
1237 SAMR_ACCESS_OPEN_DOMAIN,
1238 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1239 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1240 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1241 &connect_handle,
1242 &domain_handle,
1243 &domain_sid);
1244 if (!W_ERROR_IS_OK(werr)) {
1245 goto done;
1248 switch (r->in.filter) {
1249 case FILTER_NORMAL_ACCOUNT:
1250 filter = ACB_NORMAL;
1251 break;
1252 case FILTER_TEMP_DUPLICATE_ACCOUNT:
1253 filter = ACB_TEMPDUP;
1254 break;
1255 case FILTER_INTERDOMAIN_TRUST_ACCOUNT:
1256 filter = ACB_DOMTRUST;
1257 break;
1258 case FILTER_WORKSTATION_TRUST_ACCOUNT:
1259 filter = ACB_WSTRUST;
1260 break;
1261 case FILTER_SERVER_TRUST_ACCOUNT:
1262 filter = ACB_SVRTRUST;
1263 break;
1264 default:
1265 break;
1268 status = rpccli_samr_EnumDomainUsers(pipe_cli,
1269 ctx,
1270 &domain_handle,
1271 r->in.resume_handle,
1272 filter,
1273 &sam,
1274 r->in.prefmaxlen,
1275 &entries_read);
1276 werr = ntstatus_to_werror(status);
1277 if (NT_STATUS_IS_ERR(status)) {
1278 goto done;
1281 for (i=0; i < sam->count; i++) {
1283 status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1284 domain_sid,
1285 &domain_handle,
1286 &builtin_handle,
1287 sam->entries[i].name.string,
1288 sam->entries[i].idx,
1289 r->in.level,
1290 r->out.buffer,
1291 r->out.entries_read);
1292 if (!NT_STATUS_IS_OK(status)) {
1293 werr = ntstatus_to_werror(status);
1294 goto done;
1298 done:
1299 /* if last query */
1300 if (NT_STATUS_IS_OK(status) ||
1301 NT_STATUS_IS_ERR(status)) {
1303 if (ctx->disable_policy_handle_cache) {
1304 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1305 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1306 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1310 return werr;
1313 /****************************************************************
1314 ****************************************************************/
1316 WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
1317 struct NetUserEnum *r)
1319 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserEnum);
1322 /****************************************************************
1323 ****************************************************************/
1325 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_USER(TALLOC_CTX *mem_ctx,
1326 struct samr_DispInfoGeneral *info,
1327 uint32_t *entries_read,
1328 void **buffer)
1330 struct NET_DISPLAY_USER *user = NULL;
1331 int i;
1333 user = TALLOC_ZERO_ARRAY(mem_ctx,
1334 struct NET_DISPLAY_USER,
1335 info->count);
1336 W_ERROR_HAVE_NO_MEMORY(user);
1338 for (i = 0; i < info->count; i++) {
1339 user[i].usri1_name = talloc_strdup(mem_ctx,
1340 info->entries[i].account_name.string);
1341 user[i].usri1_comment = talloc_strdup(mem_ctx,
1342 info->entries[i].description.string);
1343 user[i].usri1_flags =
1344 info->entries[i].acct_flags;
1345 user[i].usri1_full_name = talloc_strdup(mem_ctx,
1346 info->entries[i].full_name.string);
1347 user[i].usri1_user_id =
1348 info->entries[i].rid;
1349 user[i].usri1_next_index =
1350 info->entries[i].idx;
1352 if (!user[i].usri1_name) {
1353 return WERR_NOMEM;
1357 *buffer = talloc_memdup(mem_ctx, user,
1358 sizeof(struct NET_DISPLAY_USER) * info->count);
1359 W_ERROR_HAVE_NO_MEMORY(*buffer);
1361 *entries_read = info->count;
1363 return WERR_OK;
1366 /****************************************************************
1367 ****************************************************************/
1369 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(TALLOC_CTX *mem_ctx,
1370 struct samr_DispInfoFull *info,
1371 uint32_t *entries_read,
1372 void **buffer)
1374 struct NET_DISPLAY_MACHINE *machine = NULL;
1375 int i;
1377 machine = TALLOC_ZERO_ARRAY(mem_ctx,
1378 struct NET_DISPLAY_MACHINE,
1379 info->count);
1380 W_ERROR_HAVE_NO_MEMORY(machine);
1382 for (i = 0; i < info->count; i++) {
1383 machine[i].usri2_name = talloc_strdup(mem_ctx,
1384 info->entries[i].account_name.string);
1385 machine[i].usri2_comment = talloc_strdup(mem_ctx,
1386 info->entries[i].description.string);
1387 machine[i].usri2_flags =
1388 info->entries[i].acct_flags;
1389 machine[i].usri2_user_id =
1390 info->entries[i].rid;
1391 machine[i].usri2_next_index =
1392 info->entries[i].idx;
1394 if (!machine[i].usri2_name) {
1395 return WERR_NOMEM;
1399 *buffer = talloc_memdup(mem_ctx, machine,
1400 sizeof(struct NET_DISPLAY_MACHINE) * info->count);
1401 W_ERROR_HAVE_NO_MEMORY(*buffer);
1403 *entries_read = info->count;
1405 return WERR_OK;
1408 /****************************************************************
1409 ****************************************************************/
1411 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_GROUP(TALLOC_CTX *mem_ctx,
1412 struct samr_DispInfoFullGroups *info,
1413 uint32_t *entries_read,
1414 void **buffer)
1416 struct NET_DISPLAY_GROUP *group = NULL;
1417 int i;
1419 group = TALLOC_ZERO_ARRAY(mem_ctx,
1420 struct NET_DISPLAY_GROUP,
1421 info->count);
1422 W_ERROR_HAVE_NO_MEMORY(group);
1424 for (i = 0; i < info->count; i++) {
1425 group[i].grpi3_name = talloc_strdup(mem_ctx,
1426 info->entries[i].account_name.string);
1427 group[i].grpi3_comment = talloc_strdup(mem_ctx,
1428 info->entries[i].description.string);
1429 group[i].grpi3_group_id =
1430 info->entries[i].rid;
1431 group[i].grpi3_attributes =
1432 info->entries[i].acct_flags;
1433 group[i].grpi3_next_index =
1434 info->entries[i].idx;
1436 if (!group[i].grpi3_name) {
1437 return WERR_NOMEM;
1441 *buffer = talloc_memdup(mem_ctx, group,
1442 sizeof(struct NET_DISPLAY_GROUP) * info->count);
1443 W_ERROR_HAVE_NO_MEMORY(*buffer);
1445 *entries_read = info->count;
1447 return WERR_OK;
1451 /****************************************************************
1452 ****************************************************************/
1454 static WERROR convert_samr_dispinfo_to_NET_DISPLAY(TALLOC_CTX *mem_ctx,
1455 union samr_DispInfo *info,
1456 uint32_t level,
1457 uint32_t *entries_read,
1458 void **buffer)
1460 switch (level) {
1461 case 1:
1462 return convert_samr_dispinfo_to_NET_DISPLAY_USER(mem_ctx,
1463 &info->info1,
1464 entries_read,
1465 buffer);
1466 case 2:
1467 return convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(mem_ctx,
1468 &info->info2,
1469 entries_read,
1470 buffer);
1471 case 3:
1472 return convert_samr_dispinfo_to_NET_DISPLAY_GROUP(mem_ctx,
1473 &info->info3,
1474 entries_read,
1475 buffer);
1476 default:
1477 return WERR_UNKNOWN_LEVEL;
1480 return WERR_OK;
1483 /****************************************************************
1484 ****************************************************************/
1486 WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
1487 struct NetQueryDisplayInformation *r)
1489 struct rpc_pipe_client *pipe_cli = NULL;
1490 struct policy_handle connect_handle;
1491 struct dom_sid2 *domain_sid = NULL;
1492 struct policy_handle domain_handle;
1493 union samr_DispInfo info;
1495 uint32_t total_size = 0;
1496 uint32_t returned_size = 0;
1498 NTSTATUS status = NT_STATUS_OK;
1499 WERROR werr;
1501 ZERO_STRUCT(connect_handle);
1502 ZERO_STRUCT(domain_handle);
1504 switch (r->in.level) {
1505 case 1:
1506 case 2:
1507 case 3:
1508 break;
1509 default:
1510 return WERR_UNKNOWN_LEVEL;
1513 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1514 &ndr_table_samr.syntax_id,
1515 &pipe_cli);
1516 if (!W_ERROR_IS_OK(werr)) {
1517 goto done;
1520 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1521 SAMR_ACCESS_ENUM_DOMAINS |
1522 SAMR_ACCESS_OPEN_DOMAIN,
1523 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1524 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1525 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1526 &connect_handle,
1527 &domain_handle,
1528 &domain_sid);
1529 if (!W_ERROR_IS_OK(werr)) {
1530 goto done;
1533 status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
1534 ctx,
1535 &domain_handle,
1536 r->in.level,
1537 r->in.idx,
1538 r->in.entries_requested,
1539 r->in.prefmaxlen,
1540 &total_size,
1541 &returned_size,
1542 &info);
1543 if (!NT_STATUS_IS_OK(status)) {
1544 werr = ntstatus_to_werror(status);
1545 goto done;
1548 werr = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info,
1549 r->in.level,
1550 r->out.entries_read,
1551 r->out.buffer);
1552 done:
1553 /* if last query */
1554 if (NT_STATUS_IS_OK(status) ||
1555 NT_STATUS_IS_ERR(status)) {
1557 if (ctx->disable_policy_handle_cache) {
1558 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1559 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1563 return werr;
1567 /****************************************************************
1568 ****************************************************************/
1571 WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
1572 struct NetQueryDisplayInformation *r)
1574 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetQueryDisplayInformation);
1577 /****************************************************************
1578 ****************************************************************/
1580 WERROR NetUserChangePassword_r(struct libnetapi_ctx *ctx,
1581 struct NetUserChangePassword *r)
1583 return WERR_NOT_SUPPORTED;
1586 /****************************************************************
1587 ****************************************************************/
1589 WERROR NetUserChangePassword_l(struct libnetapi_ctx *ctx,
1590 struct NetUserChangePassword *r)
1592 return WERR_NOT_SUPPORTED;
1595 /****************************************************************
1596 ****************************************************************/
1598 WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx,
1599 struct NetUserGetInfo *r)
1601 struct rpc_pipe_client *pipe_cli = NULL;
1602 NTSTATUS status;
1603 WERROR werr;
1605 struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1606 struct lsa_String lsa_account_name;
1607 struct dom_sid2 *domain_sid = NULL;
1608 struct samr_Ids user_rids, name_types;
1609 uint32_t num_entries = 0;
1611 ZERO_STRUCT(connect_handle);
1612 ZERO_STRUCT(domain_handle);
1613 ZERO_STRUCT(builtin_handle);
1614 ZERO_STRUCT(user_handle);
1616 if (!r->out.buffer) {
1617 return WERR_INVALID_PARAM;
1620 switch (r->in.level) {
1621 case 0:
1622 case 1:
1623 case 2:
1624 case 3:
1625 case 4:
1626 case 10:
1627 case 11:
1628 case 20:
1629 case 23:
1630 break;
1631 default:
1632 werr = WERR_UNKNOWN_LEVEL;
1633 goto done;
1636 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1637 &ndr_table_samr.syntax_id,
1638 &pipe_cli);
1639 if (!W_ERROR_IS_OK(werr)) {
1640 goto done;
1643 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1644 SAMR_ACCESS_ENUM_DOMAINS |
1645 SAMR_ACCESS_OPEN_DOMAIN,
1646 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1647 &connect_handle,
1648 &domain_handle,
1649 &domain_sid);
1650 if (!W_ERROR_IS_OK(werr)) {
1651 goto done;
1654 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1655 SAMR_ACCESS_ENUM_DOMAINS |
1656 SAMR_ACCESS_OPEN_DOMAIN,
1657 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1658 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1659 &connect_handle,
1660 &builtin_handle);
1661 if (!W_ERROR_IS_OK(werr)) {
1662 goto done;
1665 init_lsa_String(&lsa_account_name, r->in.user_name);
1667 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1668 &domain_handle,
1670 &lsa_account_name,
1671 &user_rids,
1672 &name_types);
1673 if (!NT_STATUS_IS_OK(status)) {
1674 werr = ntstatus_to_werror(status);
1675 goto done;
1678 status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1679 domain_sid,
1680 &domain_handle,
1681 &builtin_handle,
1682 r->in.user_name,
1683 user_rids.ids[0],
1684 r->in.level,
1685 r->out.buffer,
1686 &num_entries);
1687 if (!NT_STATUS_IS_OK(status)) {
1688 werr = ntstatus_to_werror(status);
1689 goto done;
1692 done:
1693 if (is_valid_policy_hnd(&user_handle)) {
1694 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
1697 if (ctx->disable_policy_handle_cache) {
1698 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1699 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1702 return werr;
1705 /****************************************************************
1706 ****************************************************************/
1708 WERROR NetUserGetInfo_l(struct libnetapi_ctx *ctx,
1709 struct NetUserGetInfo *r)
1711 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetInfo);
1714 /****************************************************************
1715 ****************************************************************/
1717 WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
1718 struct NetUserSetInfo *r)
1720 struct rpc_pipe_client *pipe_cli = NULL;
1721 NTSTATUS status;
1722 WERROR werr;
1724 struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1725 struct lsa_String lsa_account_name;
1726 struct dom_sid2 *domain_sid = NULL;
1727 struct samr_Ids user_rids, name_types;
1728 uint32_t user_mask = 0;
1730 struct USER_INFO_X uX;
1732 ZERO_STRUCT(connect_handle);
1733 ZERO_STRUCT(domain_handle);
1734 ZERO_STRUCT(builtin_handle);
1735 ZERO_STRUCT(user_handle);
1737 if (!r->in.buffer) {
1738 return WERR_INVALID_PARAM;
1741 switch (r->in.level) {
1742 case 0:
1743 case 1003:
1744 user_mask = SAMR_USER_ACCESS_SET_PASSWORD;
1745 break;
1746 case 1006:
1747 case 1007:
1748 case 1009:
1749 case 1011:
1750 case 1014:
1751 case 1052:
1752 case 1053:
1753 user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
1754 break;
1755 case 1012:
1756 case 1024:
1757 user_mask = SAMR_USER_ACCESS_SET_LOC_COM;
1758 case 1051:
1759 user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES |
1760 SAMR_USER_ACCESS_GET_GROUPS;
1761 break;
1762 case 3:
1763 user_mask = STD_RIGHT_READ_CONTROL_ACCESS |
1764 STD_RIGHT_WRITE_DAC_ACCESS |
1765 SAMR_USER_ACCESS_GET_GROUPS |
1766 SAMR_USER_ACCESS_SET_PASSWORD |
1767 SAMR_USER_ACCESS_SET_ATTRIBUTES |
1768 SAMR_USER_ACCESS_GET_ATTRIBUTES |
1769 SAMR_USER_ACCESS_SET_LOC_COM;
1770 break;
1771 case 1:
1772 case 2:
1773 case 4:
1774 case 21:
1775 case 22:
1776 case 1005:
1777 case 1008:
1778 case 1010:
1779 case 1017:
1780 case 1020:
1781 werr = WERR_NOT_SUPPORTED;
1782 goto done;
1783 default:
1784 werr = WERR_UNKNOWN_LEVEL;
1785 goto done;
1788 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1789 &ndr_table_samr.syntax_id,
1790 &pipe_cli);
1791 if (!W_ERROR_IS_OK(werr)) {
1792 goto done;
1795 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1796 SAMR_ACCESS_ENUM_DOMAINS |
1797 SAMR_ACCESS_OPEN_DOMAIN,
1798 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
1799 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1800 &connect_handle,
1801 &domain_handle,
1802 &domain_sid);
1803 if (!W_ERROR_IS_OK(werr)) {
1804 goto done;
1807 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1808 SAMR_ACCESS_ENUM_DOMAINS |
1809 SAMR_ACCESS_OPEN_DOMAIN,
1810 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1811 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1812 &connect_handle,
1813 &builtin_handle);
1814 if (!W_ERROR_IS_OK(werr)) {
1815 goto done;
1818 init_lsa_String(&lsa_account_name, r->in.user_name);
1820 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1821 &domain_handle,
1823 &lsa_account_name,
1824 &user_rids,
1825 &name_types);
1826 if (!NT_STATUS_IS_OK(status)) {
1827 werr = ntstatus_to_werror(status);
1828 goto done;
1831 status = rpccli_samr_OpenUser(pipe_cli, ctx,
1832 &domain_handle,
1833 user_mask,
1834 user_rids.ids[0],
1835 &user_handle);
1836 if (!NT_STATUS_IS_OK(status)) {
1837 werr = ntstatus_to_werror(status);
1838 goto done;
1841 status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
1842 if (!NT_STATUS_IS_OK(status)) {
1843 werr = ntstatus_to_werror(status);
1844 goto done;
1847 status = set_user_info_USER_INFO_X(ctx, pipe_cli,
1848 &pipe_cli->auth->user_session_key,
1849 &user_handle,
1850 &uX);
1851 if (!NT_STATUS_IS_OK(status)) {
1852 werr = ntstatus_to_werror(status);
1853 goto done;
1856 werr = WERR_OK;
1858 done:
1859 if (is_valid_policy_hnd(&user_handle)) {
1860 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
1863 if (ctx->disable_policy_handle_cache) {
1864 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1865 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1866 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1869 return werr;
1872 /****************************************************************
1873 ****************************************************************/
1875 WERROR NetUserSetInfo_l(struct libnetapi_ctx *ctx,
1876 struct NetUserSetInfo *r)
1878 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetInfo);
1881 /****************************************************************
1882 ****************************************************************/
1884 static NTSTATUS query_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
1885 struct rpc_pipe_client *pipe_cli,
1886 struct policy_handle *domain_handle,
1887 struct samr_DomInfo1 *info1,
1888 struct samr_DomInfo3 *info3,
1889 struct samr_DomInfo5 *info5,
1890 struct samr_DomInfo6 *info6,
1891 struct samr_DomInfo7 *info7,
1892 struct samr_DomInfo12 *info12)
1894 NTSTATUS status;
1895 union samr_DomainInfo *dom_info = NULL;
1897 if (info1) {
1898 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1899 domain_handle,
1901 &dom_info);
1902 NT_STATUS_NOT_OK_RETURN(status);
1904 *info1 = dom_info->info1;
1907 if (info3) {
1908 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1909 domain_handle,
1911 &dom_info);
1912 NT_STATUS_NOT_OK_RETURN(status);
1914 *info3 = dom_info->info3;
1917 if (info5) {
1918 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1919 domain_handle,
1921 &dom_info);
1922 NT_STATUS_NOT_OK_RETURN(status);
1924 *info5 = dom_info->info5;
1927 if (info6) {
1928 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1929 domain_handle,
1931 &dom_info);
1932 NT_STATUS_NOT_OK_RETURN(status);
1934 *info6 = dom_info->info6;
1937 if (info7) {
1938 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1939 domain_handle,
1941 &dom_info);
1942 NT_STATUS_NOT_OK_RETURN(status);
1944 *info7 = dom_info->info7;
1947 if (info12) {
1948 status = rpccli_samr_QueryDomainInfo2(pipe_cli, mem_ctx,
1949 domain_handle,
1951 &dom_info);
1952 NT_STATUS_NOT_OK_RETURN(status);
1954 *info12 = dom_info->info12;
1957 return NT_STATUS_OK;
1960 /****************************************************************
1961 ****************************************************************/
1963 static NTSTATUS query_USER_MODALS_INFO_0(TALLOC_CTX *mem_ctx,
1964 struct rpc_pipe_client *pipe_cli,
1965 struct policy_handle *domain_handle,
1966 struct USER_MODALS_INFO_0 *info0)
1968 NTSTATUS status;
1969 struct samr_DomInfo1 dom_info1;
1970 struct samr_DomInfo3 dom_info3;
1972 ZERO_STRUCTP(info0);
1974 status = query_USER_MODALS_INFO_rpc(mem_ctx,
1975 pipe_cli,
1976 domain_handle,
1977 &dom_info1,
1978 &dom_info3,
1979 NULL,
1980 NULL,
1981 NULL,
1982 NULL);
1983 NT_STATUS_NOT_OK_RETURN(status);
1985 info0->usrmod0_min_passwd_len =
1986 dom_info1.min_password_length;
1987 info0->usrmod0_max_passwd_age =
1988 nt_time_to_unix_abs((NTTIME *)&dom_info1.max_password_age);
1989 info0->usrmod0_min_passwd_age =
1990 nt_time_to_unix_abs((NTTIME *)&dom_info1.min_password_age);
1991 info0->usrmod0_password_hist_len =
1992 dom_info1.password_history_length;
1994 info0->usrmod0_force_logoff =
1995 nt_time_to_unix_abs(&dom_info3.force_logoff_time);
1997 return NT_STATUS_OK;
2000 /****************************************************************
2001 ****************************************************************/
2003 static NTSTATUS query_USER_MODALS_INFO_1(TALLOC_CTX *mem_ctx,
2004 struct rpc_pipe_client *pipe_cli,
2005 struct policy_handle *domain_handle,
2006 struct USER_MODALS_INFO_1 *info1)
2008 NTSTATUS status;
2009 struct samr_DomInfo6 dom_info6;
2010 struct samr_DomInfo7 dom_info7;
2012 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2013 pipe_cli,
2014 domain_handle,
2015 NULL,
2016 NULL,
2017 NULL,
2018 &dom_info6,
2019 &dom_info7,
2020 NULL);
2021 NT_STATUS_NOT_OK_RETURN(status);
2023 info1->usrmod1_primary =
2024 talloc_strdup(mem_ctx, dom_info6.primary.string);
2026 info1->usrmod1_role = dom_info7.role;
2028 return NT_STATUS_OK;
2031 /****************************************************************
2032 ****************************************************************/
2034 static NTSTATUS query_USER_MODALS_INFO_2(TALLOC_CTX *mem_ctx,
2035 struct rpc_pipe_client *pipe_cli,
2036 struct policy_handle *domain_handle,
2037 struct dom_sid *domain_sid,
2038 struct USER_MODALS_INFO_2 *info2)
2040 NTSTATUS status;
2041 struct samr_DomInfo5 dom_info5;
2043 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2044 pipe_cli,
2045 domain_handle,
2046 NULL,
2047 NULL,
2048 &dom_info5,
2049 NULL,
2050 NULL,
2051 NULL);
2052 NT_STATUS_NOT_OK_RETURN(status);
2054 info2->usrmod2_domain_name =
2055 talloc_strdup(mem_ctx, dom_info5.domain_name.string);
2056 info2->usrmod2_domain_id =
2057 (struct domsid *)sid_dup_talloc(mem_ctx, domain_sid);
2059 NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_name);
2060 NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_id);
2062 return NT_STATUS_OK;
2065 /****************************************************************
2066 ****************************************************************/
2068 static NTSTATUS query_USER_MODALS_INFO_3(TALLOC_CTX *mem_ctx,
2069 struct rpc_pipe_client *pipe_cli,
2070 struct policy_handle *domain_handle,
2071 struct USER_MODALS_INFO_3 *info3)
2073 NTSTATUS status;
2074 struct samr_DomInfo12 dom_info12;
2076 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2077 pipe_cli,
2078 domain_handle,
2079 NULL,
2080 NULL,
2081 NULL,
2082 NULL,
2083 NULL,
2084 &dom_info12);
2085 NT_STATUS_NOT_OK_RETURN(status);
2087 info3->usrmod3_lockout_duration =
2088 nt_time_to_unix_abs(&dom_info12.lockout_duration);
2089 info3->usrmod3_lockout_observation_window =
2090 nt_time_to_unix_abs(&dom_info12.lockout_window);
2091 info3->usrmod3_lockout_threshold =
2092 dom_info12.lockout_threshold;
2094 return NT_STATUS_OK;
2097 /****************************************************************
2098 ****************************************************************/
2100 static NTSTATUS query_USER_MODALS_INFO_to_buffer(TALLOC_CTX *mem_ctx,
2101 struct rpc_pipe_client *pipe_cli,
2102 uint32_t level,
2103 struct policy_handle *domain_handle,
2104 struct dom_sid *domain_sid,
2105 uint8_t **buffer)
2107 NTSTATUS status;
2109 struct USER_MODALS_INFO_0 info0;
2110 struct USER_MODALS_INFO_1 info1;
2111 struct USER_MODALS_INFO_2 info2;
2112 struct USER_MODALS_INFO_3 info3;
2114 if (!buffer) {
2115 return ERROR_INSUFFICIENT_BUFFER;
2118 switch (level) {
2119 case 0:
2120 status = query_USER_MODALS_INFO_0(mem_ctx,
2121 pipe_cli,
2122 domain_handle,
2123 &info0);
2124 NT_STATUS_NOT_OK_RETURN(status);
2126 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0,
2127 sizeof(info0));
2128 break;
2130 case 1:
2131 status = query_USER_MODALS_INFO_1(mem_ctx,
2132 pipe_cli,
2133 domain_handle,
2134 &info1);
2135 NT_STATUS_NOT_OK_RETURN(status);
2137 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1,
2138 sizeof(info1));
2139 break;
2140 case 2:
2141 status = query_USER_MODALS_INFO_2(mem_ctx,
2142 pipe_cli,
2143 domain_handle,
2144 domain_sid,
2145 &info2);
2146 NT_STATUS_NOT_OK_RETURN(status);
2148 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2,
2149 sizeof(info2));
2150 break;
2151 case 3:
2152 status = query_USER_MODALS_INFO_3(mem_ctx,
2153 pipe_cli,
2154 domain_handle,
2155 &info3);
2156 NT_STATUS_NOT_OK_RETURN(status);
2158 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3,
2159 sizeof(info3));
2160 break;
2161 default:
2162 break;
2165 NT_STATUS_HAVE_NO_MEMORY(*buffer);
2167 return NT_STATUS_OK;
2170 /****************************************************************
2171 ****************************************************************/
2173 WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx,
2174 struct NetUserModalsGet *r)
2176 struct rpc_pipe_client *pipe_cli = NULL;
2177 NTSTATUS status;
2178 WERROR werr;
2180 struct policy_handle connect_handle, domain_handle;
2181 struct dom_sid2 *domain_sid = NULL;
2182 uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2184 ZERO_STRUCT(connect_handle);
2185 ZERO_STRUCT(domain_handle);
2187 if (!r->out.buffer) {
2188 return WERR_INVALID_PARAM;
2191 switch (r->in.level) {
2192 case 0:
2193 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2194 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2195 break;
2196 case 1:
2197 case 2:
2198 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2199 break;
2200 case 3:
2201 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1;
2202 break;
2203 default:
2204 werr = WERR_UNKNOWN_LEVEL;
2205 goto done;
2208 werr = libnetapi_open_pipe(ctx, r->in.server_name,
2209 &ndr_table_samr.syntax_id,
2210 &pipe_cli);
2211 if (!W_ERROR_IS_OK(werr)) {
2212 goto done;
2215 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2216 SAMR_ACCESS_ENUM_DOMAINS |
2217 SAMR_ACCESS_OPEN_DOMAIN,
2218 access_mask,
2219 &connect_handle,
2220 &domain_handle,
2221 &domain_sid);
2222 if (!W_ERROR_IS_OK(werr)) {
2223 goto done;
2226 /* 0: 1 + 3 */
2227 /* 1: 6 + 7 */
2228 /* 2: 5 */
2229 /* 3: 12 (DomainInfo2) */
2231 status = query_USER_MODALS_INFO_to_buffer(ctx,
2232 pipe_cli,
2233 r->in.level,
2234 &domain_handle,
2235 domain_sid,
2236 r->out.buffer);
2237 if (!NT_STATUS_IS_OK(status)) {
2238 werr = ntstatus_to_werror(status);
2239 goto done;
2242 done:
2243 if (ctx->disable_policy_handle_cache) {
2244 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2245 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2248 return werr;
2251 /****************************************************************
2252 ****************************************************************/
2254 WERROR NetUserModalsGet_l(struct libnetapi_ctx *ctx,
2255 struct NetUserModalsGet *r)
2257 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsGet);
2260 /****************************************************************
2261 ****************************************************************/
2263 static NTSTATUS set_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
2264 struct rpc_pipe_client *pipe_cli,
2265 struct policy_handle *domain_handle,
2266 struct samr_DomInfo1 *info1,
2267 struct samr_DomInfo3 *info3,
2268 struct samr_DomInfo12 *info12)
2270 NTSTATUS status;
2271 union samr_DomainInfo dom_info;
2273 if (info1) {
2275 ZERO_STRUCT(dom_info);
2277 dom_info.info1 = *info1;
2279 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2280 domain_handle,
2282 &dom_info);
2283 NT_STATUS_NOT_OK_RETURN(status);
2286 if (info3) {
2288 ZERO_STRUCT(dom_info);
2290 dom_info.info3 = *info3;
2292 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2293 domain_handle,
2295 &dom_info);
2297 NT_STATUS_NOT_OK_RETURN(status);
2300 if (info12) {
2302 ZERO_STRUCT(dom_info);
2304 dom_info.info12 = *info12;
2306 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2307 domain_handle,
2309 &dom_info);
2311 NT_STATUS_NOT_OK_RETURN(status);
2314 return NT_STATUS_OK;
2317 /****************************************************************
2318 ****************************************************************/
2320 static NTSTATUS set_USER_MODALS_INFO_0_buffer(TALLOC_CTX *mem_ctx,
2321 struct rpc_pipe_client *pipe_cli,
2322 struct policy_handle *domain_handle,
2323 struct USER_MODALS_INFO_0 *info0)
2325 NTSTATUS status;
2326 struct samr_DomInfo1 dom_info_1;
2327 struct samr_DomInfo3 dom_info_3;
2329 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2330 pipe_cli,
2331 domain_handle,
2332 &dom_info_1,
2333 &dom_info_3,
2334 NULL,
2335 NULL,
2336 NULL,
2337 NULL);
2338 NT_STATUS_NOT_OK_RETURN(status);
2340 dom_info_1.min_password_length =
2341 info0->usrmod0_min_passwd_len;
2342 dom_info_1.password_history_length =
2343 info0->usrmod0_password_hist_len;
2345 unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2346 info0->usrmod0_max_passwd_age);
2347 unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2348 info0->usrmod0_min_passwd_age);
2350 unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2351 info0->usrmod0_force_logoff);
2353 return set_USER_MODALS_INFO_rpc(mem_ctx,
2354 pipe_cli,
2355 domain_handle,
2356 &dom_info_1,
2357 &dom_info_3,
2358 NULL);
2361 /****************************************************************
2362 ****************************************************************/
2364 static NTSTATUS set_USER_MODALS_INFO_3_buffer(TALLOC_CTX *mem_ctx,
2365 struct rpc_pipe_client *pipe_cli,
2366 struct policy_handle *domain_handle,
2367 struct USER_MODALS_INFO_3 *info3)
2369 NTSTATUS status;
2370 struct samr_DomInfo12 dom_info_12;
2372 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2373 pipe_cli,
2374 domain_handle,
2375 NULL,
2376 NULL,
2377 NULL,
2378 NULL,
2379 NULL,
2380 &dom_info_12);
2381 NT_STATUS_NOT_OK_RETURN(status);
2383 unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_duration,
2384 info3->usrmod3_lockout_duration);
2385 unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_window,
2386 info3->usrmod3_lockout_observation_window);
2387 dom_info_12.lockout_threshold = info3->usrmod3_lockout_threshold;
2389 return set_USER_MODALS_INFO_rpc(mem_ctx,
2390 pipe_cli,
2391 domain_handle,
2392 NULL,
2393 NULL,
2394 &dom_info_12);
2397 /****************************************************************
2398 ****************************************************************/
2400 static NTSTATUS set_USER_MODALS_INFO_1001_buffer(TALLOC_CTX *mem_ctx,
2401 struct rpc_pipe_client *pipe_cli,
2402 struct policy_handle *domain_handle,
2403 struct USER_MODALS_INFO_1001 *info1001)
2405 NTSTATUS status;
2406 struct samr_DomInfo1 dom_info_1;
2408 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2409 pipe_cli,
2410 domain_handle,
2411 &dom_info_1,
2412 NULL,
2413 NULL,
2414 NULL,
2415 NULL,
2416 NULL);
2417 NT_STATUS_NOT_OK_RETURN(status);
2419 dom_info_1.min_password_length =
2420 info1001->usrmod1001_min_passwd_len;
2422 return set_USER_MODALS_INFO_rpc(mem_ctx,
2423 pipe_cli,
2424 domain_handle,
2425 &dom_info_1,
2426 NULL,
2427 NULL);
2430 /****************************************************************
2431 ****************************************************************/
2433 static NTSTATUS set_USER_MODALS_INFO_1002_buffer(TALLOC_CTX *mem_ctx,
2434 struct rpc_pipe_client *pipe_cli,
2435 struct policy_handle *domain_handle,
2436 struct USER_MODALS_INFO_1002 *info1002)
2438 NTSTATUS status;
2439 struct samr_DomInfo1 dom_info_1;
2441 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2442 pipe_cli,
2443 domain_handle,
2444 &dom_info_1,
2445 NULL,
2446 NULL,
2447 NULL,
2448 NULL,
2449 NULL);
2450 NT_STATUS_NOT_OK_RETURN(status);
2452 unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2453 info1002->usrmod1002_max_passwd_age);
2455 return set_USER_MODALS_INFO_rpc(mem_ctx,
2456 pipe_cli,
2457 domain_handle,
2458 &dom_info_1,
2459 NULL,
2460 NULL);
2463 /****************************************************************
2464 ****************************************************************/
2466 static NTSTATUS set_USER_MODALS_INFO_1003_buffer(TALLOC_CTX *mem_ctx,
2467 struct rpc_pipe_client *pipe_cli,
2468 struct policy_handle *domain_handle,
2469 struct USER_MODALS_INFO_1003 *info1003)
2471 NTSTATUS status;
2472 struct samr_DomInfo1 dom_info_1;
2474 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2475 pipe_cli,
2476 domain_handle,
2477 &dom_info_1,
2478 NULL,
2479 NULL,
2480 NULL,
2481 NULL,
2482 NULL);
2483 NT_STATUS_NOT_OK_RETURN(status);
2485 unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2486 info1003->usrmod1003_min_passwd_age);
2488 return set_USER_MODALS_INFO_rpc(mem_ctx,
2489 pipe_cli,
2490 domain_handle,
2491 &dom_info_1,
2492 NULL,
2493 NULL);
2496 /****************************************************************
2497 ****************************************************************/
2499 static NTSTATUS set_USER_MODALS_INFO_1004_buffer(TALLOC_CTX *mem_ctx,
2500 struct rpc_pipe_client *pipe_cli,
2501 struct policy_handle *domain_handle,
2502 struct USER_MODALS_INFO_1004 *info1004)
2504 NTSTATUS status;
2505 struct samr_DomInfo3 dom_info_3;
2507 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2508 pipe_cli,
2509 domain_handle,
2510 NULL,
2511 &dom_info_3,
2512 NULL,
2513 NULL,
2514 NULL,
2515 NULL);
2516 NT_STATUS_NOT_OK_RETURN(status);
2518 unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2519 info1004->usrmod1004_force_logoff);
2521 return set_USER_MODALS_INFO_rpc(mem_ctx,
2522 pipe_cli,
2523 domain_handle,
2524 NULL,
2525 &dom_info_3,
2526 NULL);
2529 /****************************************************************
2530 ****************************************************************/
2532 static NTSTATUS set_USER_MODALS_INFO_1005_buffer(TALLOC_CTX *mem_ctx,
2533 struct rpc_pipe_client *pipe_cli,
2534 struct policy_handle *domain_handle,
2535 struct USER_MODALS_INFO_1005 *info1005)
2537 NTSTATUS status;
2538 struct samr_DomInfo1 dom_info_1;
2540 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2541 pipe_cli,
2542 domain_handle,
2543 &dom_info_1,
2544 NULL,
2545 NULL,
2546 NULL,
2547 NULL,
2548 NULL);
2549 NT_STATUS_NOT_OK_RETURN(status);
2551 dom_info_1.password_history_length =
2552 info1005->usrmod1005_password_hist_len;
2554 return set_USER_MODALS_INFO_rpc(mem_ctx,
2555 pipe_cli,
2556 domain_handle,
2557 &dom_info_1,
2558 NULL,
2559 NULL);
2562 /****************************************************************
2563 ****************************************************************/
2565 static NTSTATUS set_USER_MODALS_INFO_buffer(TALLOC_CTX *mem_ctx,
2566 struct rpc_pipe_client *pipe_cli,
2567 uint32_t level,
2568 struct policy_handle *domain_handle,
2569 struct dom_sid *domain_sid,
2570 uint8_t *buffer)
2572 struct USER_MODALS_INFO_0 *info0;
2573 struct USER_MODALS_INFO_3 *info3;
2574 struct USER_MODALS_INFO_1001 *info1001;
2575 struct USER_MODALS_INFO_1002 *info1002;
2576 struct USER_MODALS_INFO_1003 *info1003;
2577 struct USER_MODALS_INFO_1004 *info1004;
2578 struct USER_MODALS_INFO_1005 *info1005;
2580 if (!buffer) {
2581 return ERROR_INSUFFICIENT_BUFFER;
2584 switch (level) {
2585 case 0:
2586 info0 = (struct USER_MODALS_INFO_0 *)buffer;
2587 return set_USER_MODALS_INFO_0_buffer(mem_ctx,
2588 pipe_cli,
2589 domain_handle,
2590 info0);
2591 case 3:
2592 info3 = (struct USER_MODALS_INFO_3 *)buffer;
2593 return set_USER_MODALS_INFO_3_buffer(mem_ctx,
2594 pipe_cli,
2595 domain_handle,
2596 info3);
2597 case 1001:
2598 info1001 = (struct USER_MODALS_INFO_1001 *)buffer;
2599 return set_USER_MODALS_INFO_1001_buffer(mem_ctx,
2600 pipe_cli,
2601 domain_handle,
2602 info1001);
2603 case 1002:
2604 info1002 = (struct USER_MODALS_INFO_1002 *)buffer;
2605 return set_USER_MODALS_INFO_1002_buffer(mem_ctx,
2606 pipe_cli,
2607 domain_handle,
2608 info1002);
2609 case 1003:
2610 info1003 = (struct USER_MODALS_INFO_1003 *)buffer;
2611 return set_USER_MODALS_INFO_1003_buffer(mem_ctx,
2612 pipe_cli,
2613 domain_handle,
2614 info1003);
2615 case 1004:
2616 info1004 = (struct USER_MODALS_INFO_1004 *)buffer;
2617 return set_USER_MODALS_INFO_1004_buffer(mem_ctx,
2618 pipe_cli,
2619 domain_handle,
2620 info1004);
2621 case 1005:
2622 info1005 = (struct USER_MODALS_INFO_1005 *)buffer;
2623 return set_USER_MODALS_INFO_1005_buffer(mem_ctx,
2624 pipe_cli,
2625 domain_handle,
2626 info1005);
2628 default:
2629 break;
2632 return NT_STATUS_OK;
2635 /****************************************************************
2636 ****************************************************************/
2638 WERROR NetUserModalsSet_r(struct libnetapi_ctx *ctx,
2639 struct NetUserModalsSet *r)
2641 struct rpc_pipe_client *pipe_cli = NULL;
2642 NTSTATUS status;
2643 WERROR werr;
2645 struct policy_handle connect_handle, domain_handle;
2646 struct dom_sid2 *domain_sid = NULL;
2647 uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2649 ZERO_STRUCT(connect_handle);
2650 ZERO_STRUCT(domain_handle);
2652 if (!r->in.buffer) {
2653 return WERR_INVALID_PARAM;
2656 switch (r->in.level) {
2657 case 0:
2658 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2659 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2660 SAMR_DOMAIN_ACCESS_SET_INFO_1 |
2661 SAMR_DOMAIN_ACCESS_SET_INFO_2;
2662 break;
2663 case 3:
2664 case 1001:
2665 case 1002:
2666 case 1003:
2667 case 1005:
2668 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2669 SAMR_DOMAIN_ACCESS_SET_INFO_1;
2670 break;
2671 case 1004:
2672 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2673 SAMR_DOMAIN_ACCESS_SET_INFO_2;
2674 break;
2675 case 1:
2676 case 2:
2677 case 1006:
2678 case 1007:
2679 werr = WERR_NOT_SUPPORTED;
2680 break;
2681 default:
2682 werr = WERR_UNKNOWN_LEVEL;
2683 goto done;
2686 werr = libnetapi_open_pipe(ctx, r->in.server_name,
2687 &ndr_table_samr.syntax_id,
2688 &pipe_cli);
2689 if (!W_ERROR_IS_OK(werr)) {
2690 goto done;
2693 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2694 SAMR_ACCESS_ENUM_DOMAINS |
2695 SAMR_ACCESS_OPEN_DOMAIN,
2696 access_mask,
2697 &connect_handle,
2698 &domain_handle,
2699 &domain_sid);
2700 if (!W_ERROR_IS_OK(werr)) {
2701 goto done;
2704 status = set_USER_MODALS_INFO_buffer(ctx,
2705 pipe_cli,
2706 r->in.level,
2707 &domain_handle,
2708 domain_sid,
2709 r->in.buffer);
2710 if (!NT_STATUS_IS_OK(status)) {
2711 werr = ntstatus_to_werror(status);
2712 goto done;
2715 done:
2716 if (ctx->disable_policy_handle_cache) {
2717 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2718 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2721 return werr;
2724 /****************************************************************
2725 ****************************************************************/
2727 WERROR NetUserModalsSet_l(struct libnetapi_ctx *ctx,
2728 struct NetUserModalsSet *r)
2730 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsSet);
2733 /****************************************************************
2734 ****************************************************************/
2736 NTSTATUS add_GROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
2737 uint32_t level,
2738 const char *group_name,
2739 uint32_t attributes,
2740 uint8_t **buffer,
2741 uint32_t *num_entries)
2743 struct GROUP_USERS_INFO_0 u0;
2744 struct GROUP_USERS_INFO_1 u1;
2746 switch (level) {
2747 case 0:
2748 if (group_name) {
2749 u0.grui0_name = talloc_strdup(mem_ctx, group_name);
2750 NT_STATUS_HAVE_NO_MEMORY(u0.grui0_name);
2751 } else {
2752 u0.grui0_name = NULL;
2755 ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_0, u0,
2756 (struct GROUP_USERS_INFO_0 **)buffer, num_entries);
2757 break;
2758 case 1:
2759 if (group_name) {
2760 u1.grui1_name = talloc_strdup(mem_ctx, group_name);
2761 NT_STATUS_HAVE_NO_MEMORY(u1.grui1_name);
2762 } else {
2763 u1.grui1_name = NULL;
2766 u1.grui1_attributes = attributes;
2768 ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_1, u1,
2769 (struct GROUP_USERS_INFO_1 **)buffer, num_entries);
2770 break;
2771 default:
2772 return NT_STATUS_INVALID_INFO_CLASS;
2775 return NT_STATUS_OK;
2778 /****************************************************************
2779 ****************************************************************/
2781 WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
2782 struct NetUserGetGroups *r)
2784 struct rpc_pipe_client *pipe_cli = NULL;
2785 struct policy_handle connect_handle, domain_handle, user_handle;
2786 struct lsa_String lsa_account_name;
2787 struct dom_sid2 *domain_sid = NULL;
2788 struct samr_Ids user_rids, name_types;
2789 struct samr_RidWithAttributeArray *rid_array = NULL;
2790 struct lsa_Strings names;
2791 struct samr_Ids types;
2792 uint32_t *rids = NULL;
2794 int i;
2795 uint32_t entries_read = 0;
2797 NTSTATUS status = NT_STATUS_OK;
2798 WERROR werr;
2800 ZERO_STRUCT(connect_handle);
2801 ZERO_STRUCT(domain_handle);
2803 if (!r->out.buffer) {
2804 return WERR_INVALID_PARAM;
2807 *r->out.buffer = NULL;
2808 *r->out.entries_read = 0;
2810 switch (r->in.level) {
2811 case 0:
2812 case 1:
2813 break;
2814 default:
2815 return WERR_UNKNOWN_LEVEL;
2818 werr = libnetapi_open_pipe(ctx, r->in.server_name,
2819 &ndr_table_samr.syntax_id,
2820 &pipe_cli);
2821 if (!W_ERROR_IS_OK(werr)) {
2822 goto done;
2825 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2826 SAMR_ACCESS_ENUM_DOMAINS |
2827 SAMR_ACCESS_OPEN_DOMAIN,
2828 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2829 &connect_handle,
2830 &domain_handle,
2831 &domain_sid);
2832 if (!W_ERROR_IS_OK(werr)) {
2833 goto done;
2836 init_lsa_String(&lsa_account_name, r->in.user_name);
2838 status = rpccli_samr_LookupNames(pipe_cli, ctx,
2839 &domain_handle,
2841 &lsa_account_name,
2842 &user_rids,
2843 &name_types);
2844 if (!NT_STATUS_IS_OK(status)) {
2845 werr = ntstatus_to_werror(status);
2846 goto done;
2849 status = rpccli_samr_OpenUser(pipe_cli, ctx,
2850 &domain_handle,
2851 SAMR_USER_ACCESS_GET_GROUPS,
2852 user_rids.ids[0],
2853 &user_handle);
2854 if (!NT_STATUS_IS_OK(status)) {
2855 werr = ntstatus_to_werror(status);
2856 goto done;
2859 status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
2860 &user_handle,
2861 &rid_array);
2862 if (!NT_STATUS_IS_OK(status)) {
2863 werr = ntstatus_to_werror(status);
2864 goto done;
2867 rids = talloc_array(ctx, uint32_t, rid_array->count);
2868 if (!rids) {
2869 werr = WERR_NOMEM;
2870 goto done;
2873 for (i=0; i < rid_array->count; i++) {
2874 rids[i] = rid_array->rids[i].rid;
2877 status = rpccli_samr_LookupRids(pipe_cli, ctx,
2878 &domain_handle,
2879 rid_array->count,
2880 rids,
2881 &names,
2882 &types);
2883 if (!NT_STATUS_IS_OK(status) &&
2884 !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
2885 werr = ntstatus_to_werror(status);
2886 goto done;
2889 for (i=0; i < names.count; i++) {
2890 status = add_GROUP_USERS_INFO_X_buffer(ctx,
2891 r->in.level,
2892 names.names[i].string,
2893 rid_array->rids[i].attributes,
2894 r->out.buffer,
2895 &entries_read);
2896 if (!NT_STATUS_IS_OK(status)) {
2897 werr = ntstatus_to_werror(status);
2898 goto done;
2902 if (r->out.entries_read) {
2903 *r->out.entries_read = entries_read;
2905 if (r->out.total_entries) {
2906 *r->out.total_entries = entries_read;
2909 done:
2910 if (ctx->disable_policy_handle_cache) {
2911 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2912 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2915 return werr;
2918 /****************************************************************
2919 ****************************************************************/
2921 WERROR NetUserGetGroups_l(struct libnetapi_ctx *ctx,
2922 struct NetUserGetGroups *r)
2924 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetGroups);
2927 /****************************************************************
2928 ****************************************************************/
2930 WERROR NetUserSetGroups_r(struct libnetapi_ctx *ctx,
2931 struct NetUserSetGroups *r)
2933 struct rpc_pipe_client *pipe_cli = NULL;
2934 struct policy_handle connect_handle, domain_handle, user_handle, group_handle;
2935 struct lsa_String lsa_account_name;
2936 struct dom_sid2 *domain_sid = NULL;
2937 struct samr_Ids user_rids, name_types;
2938 struct samr_Ids group_rids;
2939 struct samr_RidWithAttributeArray *rid_array = NULL;
2940 struct lsa_String *lsa_names = NULL;
2942 uint32_t *add_rids = NULL;
2943 uint32_t *del_rids = NULL;
2944 size_t num_add_rids = 0;
2945 size_t num_del_rids = 0;
2947 uint32_t *member_rids = NULL;
2948 size_t num_member_rids = 0;
2950 struct GROUP_USERS_INFO_0 *i0 = NULL;
2951 struct GROUP_USERS_INFO_1 *i1 = NULL;
2953 int i, k;
2955 NTSTATUS status = NT_STATUS_OK;
2956 WERROR werr;
2958 ZERO_STRUCT(connect_handle);
2959 ZERO_STRUCT(domain_handle);
2961 if (!r->in.buffer) {
2962 return WERR_INVALID_PARAM;
2965 switch (r->in.level) {
2966 case 0:
2967 case 1:
2968 break;
2969 default:
2970 return WERR_UNKNOWN_LEVEL;
2973 werr = libnetapi_open_pipe(ctx, r->in.server_name,
2974 &ndr_table_samr.syntax_id,
2975 &pipe_cli);
2976 if (!W_ERROR_IS_OK(werr)) {
2977 goto done;
2980 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2981 SAMR_ACCESS_ENUM_DOMAINS |
2982 SAMR_ACCESS_OPEN_DOMAIN,
2983 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2984 &connect_handle,
2985 &domain_handle,
2986 &domain_sid);
2987 if (!W_ERROR_IS_OK(werr)) {
2988 goto done;
2991 init_lsa_String(&lsa_account_name, r->in.user_name);
2993 status = rpccli_samr_LookupNames(pipe_cli, ctx,
2994 &domain_handle,
2996 &lsa_account_name,
2997 &user_rids,
2998 &name_types);
2999 if (!NT_STATUS_IS_OK(status)) {
3000 werr = ntstatus_to_werror(status);
3001 goto done;
3004 status = rpccli_samr_OpenUser(pipe_cli, ctx,
3005 &domain_handle,
3006 SAMR_USER_ACCESS_GET_GROUPS,
3007 user_rids.ids[0],
3008 &user_handle);
3009 if (!NT_STATUS_IS_OK(status)) {
3010 werr = ntstatus_to_werror(status);
3011 goto done;
3014 switch (r->in.level) {
3015 case 0:
3016 i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
3017 break;
3018 case 1:
3019 i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
3020 break;
3023 lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
3024 if (!lsa_names) {
3025 werr = WERR_NOMEM;
3026 goto done;
3029 for (i=0; i < r->in.num_entries; i++) {
3031 switch (r->in.level) {
3032 case 0:
3033 init_lsa_String(&lsa_names[i], i0->grui0_name);
3034 i0++;
3035 break;
3036 case 1:
3037 init_lsa_String(&lsa_names[i], i1->grui1_name);
3038 i1++;
3039 break;
3043 status = rpccli_samr_LookupNames(pipe_cli, ctx,
3044 &domain_handle,
3045 r->in.num_entries,
3046 lsa_names,
3047 &group_rids,
3048 &name_types);
3049 if (!NT_STATUS_IS_OK(status)) {
3050 werr = ntstatus_to_werror(status);
3051 goto done;
3054 member_rids = group_rids.ids;
3055 num_member_rids = group_rids.count;
3057 status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
3058 &user_handle,
3059 &rid_array);
3060 if (!NT_STATUS_IS_OK(status)) {
3061 werr = ntstatus_to_werror(status);
3062 goto done;
3065 /* add list */
3067 for (i=0; i < r->in.num_entries; i++) {
3068 bool already_member = false;
3069 for (k=0; k < rid_array->count; k++) {
3070 if (member_rids[i] == rid_array->rids[k].rid) {
3071 already_member = true;
3072 break;
3075 if (!already_member) {
3076 if (!add_rid_to_array_unique(ctx,
3077 member_rids[i],
3078 &add_rids, &num_add_rids)) {
3079 werr = WERR_GENERAL_FAILURE;
3080 goto done;
3085 /* del list */
3087 for (k=0; k < rid_array->count; k++) {
3088 bool keep_member = false;
3089 for (i=0; i < r->in.num_entries; i++) {
3090 if (member_rids[i] == rid_array->rids[k].rid) {
3091 keep_member = true;
3092 break;
3095 if (!keep_member) {
3096 if (!add_rid_to_array_unique(ctx,
3097 rid_array->rids[k].rid,
3098 &del_rids, &num_del_rids)) {
3099 werr = WERR_GENERAL_FAILURE;
3100 goto done;
3105 /* add list */
3107 for (i=0; i < num_add_rids; i++) {
3108 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
3109 &domain_handle,
3110 SAMR_GROUP_ACCESS_ADD_MEMBER,
3111 add_rids[i],
3112 &group_handle);
3113 if (!NT_STATUS_IS_OK(status)) {
3114 werr = ntstatus_to_werror(status);
3115 goto done;
3118 status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
3119 &group_handle,
3120 user_rids.ids[0],
3121 7 /* ? */);
3122 if (!NT_STATUS_IS_OK(status)) {
3123 werr = ntstatus_to_werror(status);
3124 goto done;
3127 if (is_valid_policy_hnd(&group_handle)) {
3128 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
3132 /* del list */
3134 for (i=0; i < num_del_rids; i++) {
3135 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
3136 &domain_handle,
3137 SAMR_GROUP_ACCESS_REMOVE_MEMBER,
3138 del_rids[i],
3139 &group_handle);
3140 if (!NT_STATUS_IS_OK(status)) {
3141 werr = ntstatus_to_werror(status);
3142 goto done;
3145 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
3146 &group_handle,
3147 user_rids.ids[0]);
3148 if (!NT_STATUS_IS_OK(status)) {
3149 werr = ntstatus_to_werror(status);
3150 goto done;
3153 if (is_valid_policy_hnd(&group_handle)) {
3154 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
3158 werr = WERR_OK;
3160 done:
3161 if (is_valid_policy_hnd(&group_handle)) {
3162 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
3165 if (ctx->disable_policy_handle_cache) {
3166 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3167 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3170 return werr;
3173 /****************************************************************
3174 ****************************************************************/
3176 WERROR NetUserSetGroups_l(struct libnetapi_ctx *ctx,
3177 struct NetUserSetGroups *r)
3179 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetGroups);
3182 /****************************************************************
3183 ****************************************************************/
3185 static NTSTATUS add_LOCALGROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
3186 uint32_t level,
3187 const char *group_name,
3188 uint8_t **buffer,
3189 uint32_t *num_entries)
3191 struct LOCALGROUP_USERS_INFO_0 u0;
3193 switch (level) {
3194 case 0:
3195 u0.lgrui0_name = talloc_strdup(mem_ctx, group_name);
3196 NT_STATUS_HAVE_NO_MEMORY(u0.lgrui0_name);
3198 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_USERS_INFO_0, u0,
3199 (struct LOCALGROUP_USERS_INFO_0 **)buffer, num_entries);
3200 break;
3201 default:
3202 return NT_STATUS_INVALID_INFO_CLASS;
3205 return NT_STATUS_OK;
3208 /****************************************************************
3209 ****************************************************************/
3211 WERROR NetUserGetLocalGroups_r(struct libnetapi_ctx *ctx,
3212 struct NetUserGetLocalGroups *r)
3214 struct rpc_pipe_client *pipe_cli = NULL;
3215 struct policy_handle connect_handle, domain_handle, user_handle,
3216 builtin_handle;
3217 struct lsa_String lsa_account_name;
3218 struct dom_sid2 *domain_sid = NULL;
3219 struct samr_Ids user_rids, name_types;
3220 struct samr_RidWithAttributeArray *rid_array = NULL;
3221 struct lsa_Strings names;
3222 struct samr_Ids types;
3223 uint32_t *rids = NULL;
3224 size_t num_rids = 0;
3225 struct dom_sid user_sid;
3226 struct lsa_SidArray sid_array;
3227 struct samr_Ids domain_rids;
3228 struct samr_Ids builtin_rids;
3230 int i;
3231 uint32_t entries_read = 0;
3233 NTSTATUS status = NT_STATUS_OK;
3234 WERROR werr;
3236 ZERO_STRUCT(connect_handle);
3237 ZERO_STRUCT(domain_handle);
3239 if (!r->out.buffer) {
3240 return WERR_INVALID_PARAM;
3243 *r->out.buffer = NULL;
3244 *r->out.entries_read = 0;
3246 switch (r->in.level) {
3247 case 0:
3248 case 1:
3249 break;
3250 default:
3251 return WERR_UNKNOWN_LEVEL;
3254 werr = libnetapi_open_pipe(ctx, r->in.server_name,
3255 &ndr_table_samr.syntax_id,
3256 &pipe_cli);
3257 if (!W_ERROR_IS_OK(werr)) {
3258 goto done;
3261 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
3262 SAMR_ACCESS_ENUM_DOMAINS |
3263 SAMR_ACCESS_OPEN_DOMAIN,
3264 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
3265 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
3266 &connect_handle,
3267 &domain_handle,
3268 &domain_sid);
3269 if (!W_ERROR_IS_OK(werr)) {
3270 goto done;
3273 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
3274 SAMR_ACCESS_ENUM_DOMAINS |
3275 SAMR_ACCESS_OPEN_DOMAIN,
3276 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
3277 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
3278 &connect_handle,
3279 &builtin_handle);
3280 if (!W_ERROR_IS_OK(werr)) {
3281 goto done;
3284 init_lsa_String(&lsa_account_name, r->in.user_name);
3286 status = rpccli_samr_LookupNames(pipe_cli, ctx,
3287 &domain_handle,
3289 &lsa_account_name,
3290 &user_rids,
3291 &name_types);
3292 if (!NT_STATUS_IS_OK(status)) {
3293 werr = ntstatus_to_werror(status);
3294 goto done;
3297 status = rpccli_samr_OpenUser(pipe_cli, ctx,
3298 &domain_handle,
3299 SAMR_USER_ACCESS_GET_GROUPS,
3300 user_rids.ids[0],
3301 &user_handle);
3302 if (!NT_STATUS_IS_OK(status)) {
3303 werr = ntstatus_to_werror(status);
3304 goto done;
3307 status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
3308 &user_handle,
3309 &rid_array);
3310 if (!NT_STATUS_IS_OK(status)) {
3311 werr = ntstatus_to_werror(status);
3312 goto done;
3315 if (!sid_compose(&user_sid, domain_sid, user_rids.ids[0])) {
3316 werr = WERR_NOMEM;
3317 goto done;
3320 sid_array.num_sids = rid_array->count + 1;
3321 sid_array.sids = TALLOC_ARRAY(ctx, struct lsa_SidPtr, sid_array.num_sids);
3322 if (!sid_array.sids) {
3323 werr = WERR_NOMEM;
3324 goto done;
3327 sid_array.sids[0].sid = sid_dup_talloc(ctx, &user_sid);
3328 if (!sid_array.sids[0].sid) {
3329 werr = WERR_NOMEM;
3330 goto done;
3333 for (i=0; i < rid_array->count; i++) {
3334 struct dom_sid sid;
3336 if (!sid_compose(&sid, domain_sid, rid_array->rids[i].rid)) {
3337 werr = WERR_NOMEM;
3338 goto done;
3341 sid_array.sids[i+1].sid = sid_dup_talloc(ctx, &sid);
3342 if (!sid_array.sids[i+1].sid) {
3343 werr = WERR_NOMEM;
3344 goto done;
3348 status = rpccli_samr_GetAliasMembership(pipe_cli, ctx,
3349 &domain_handle,
3350 &sid_array,
3351 &domain_rids);
3352 if (!NT_STATUS_IS_OK(status)) {
3353 werr = ntstatus_to_werror(status);
3354 goto done;
3357 for (i=0; i < domain_rids.count; i++) {
3358 if (!add_rid_to_array_unique(ctx, domain_rids.ids[i],
3359 &rids, &num_rids)) {
3360 werr = WERR_NOMEM;
3361 goto done;
3365 status = rpccli_samr_GetAliasMembership(pipe_cli, ctx,
3366 &builtin_handle,
3367 &sid_array,
3368 &builtin_rids);
3369 if (!NT_STATUS_IS_OK(status)) {
3370 werr = ntstatus_to_werror(status);
3371 goto done;
3374 for (i=0; i < builtin_rids.count; i++) {
3375 if (!add_rid_to_array_unique(ctx, builtin_rids.ids[i],
3376 &rids, &num_rids)) {
3377 werr = WERR_NOMEM;
3378 goto done;
3382 status = rpccli_samr_LookupRids(pipe_cli, ctx,
3383 &builtin_handle,
3384 num_rids,
3385 rids,
3386 &names,
3387 &types);
3388 if (!NT_STATUS_IS_OK(status)) {
3389 werr = ntstatus_to_werror(status);
3390 goto done;
3393 for (i=0; i < names.count; i++) {
3394 status = add_LOCALGROUP_USERS_INFO_X_buffer(ctx,
3395 r->in.level,
3396 names.names[i].string,
3397 r->out.buffer,
3398 &entries_read);
3399 if (!NT_STATUS_IS_OK(status)) {
3400 werr = ntstatus_to_werror(status);
3401 goto done;
3405 if (r->out.entries_read) {
3406 *r->out.entries_read = entries_read;
3408 if (r->out.total_entries) {
3409 *r->out.total_entries = entries_read;
3412 done:
3413 if (ctx->disable_policy_handle_cache) {
3414 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3415 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3418 return werr;
3421 /****************************************************************
3422 ****************************************************************/
3424 WERROR NetUserGetLocalGroups_l(struct libnetapi_ctx *ctx,
3425 struct NetUserGetLocalGroups *r)
3427 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetLocalGroups);