WHATSNEW: Update changed parameters.
[Samba/gbeck.git] / source3 / lib / netapi / user.c
blob152b72733db68bc5d3947209ee0cf445beb64bc7
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"
26 #include "../librpc/gen_ndr/cli_samr.h"
27 #include "rpc_client/init_samr.h"
28 #include "../libds/common/flags.h"
29 #include "rpc_client/init_lsa.h"
30 #include "../libcli/security/security.h"
32 /****************************************************************
33 ****************************************************************/
35 static void convert_USER_INFO_X_to_samr_user_info21(struct USER_INFO_X *infoX,
36 struct samr_UserInfo21 *info21)
38 uint32_t fields_present = 0;
39 struct samr_LogonHours zero_logon_hours;
40 struct lsa_BinaryString zero_parameters;
41 NTTIME password_age;
43 ZERO_STRUCTP(info21);
44 ZERO_STRUCT(zero_logon_hours);
45 ZERO_STRUCT(zero_parameters);
47 if (infoX->usriX_flags) {
48 fields_present |= SAMR_FIELD_ACCT_FLAGS;
50 if (infoX->usriX_name) {
51 fields_present |= SAMR_FIELD_ACCOUNT_NAME;
53 if (infoX->usriX_password) {
54 fields_present |= SAMR_FIELD_NT_PASSWORD_PRESENT;
56 if (infoX->usriX_flags) {
57 fields_present |= SAMR_FIELD_ACCT_FLAGS;
59 if (infoX->usriX_name) {
60 fields_present |= SAMR_FIELD_FULL_NAME;
62 if (infoX->usriX_home_dir) {
63 fields_present |= SAMR_FIELD_HOME_DIRECTORY;
65 if (infoX->usriX_script_path) {
66 fields_present |= SAMR_FIELD_LOGON_SCRIPT;
68 if (infoX->usriX_comment) {
69 fields_present |= SAMR_FIELD_DESCRIPTION;
71 if (infoX->usriX_password_age) {
72 fields_present |= SAMR_FIELD_FORCE_PWD_CHANGE;
74 if (infoX->usriX_full_name) {
75 fields_present |= SAMR_FIELD_FULL_NAME;
77 if (infoX->usriX_usr_comment) {
78 fields_present |= SAMR_FIELD_COMMENT;
80 if (infoX->usriX_profile) {
81 fields_present |= SAMR_FIELD_PROFILE_PATH;
83 if (infoX->usriX_home_dir_drive) {
84 fields_present |= SAMR_FIELD_HOME_DRIVE;
86 if (infoX->usriX_primary_group_id) {
87 fields_present |= SAMR_FIELD_PRIMARY_GID;
89 if (infoX->usriX_country_code) {
90 fields_present |= SAMR_FIELD_COUNTRY_CODE;
92 if (infoX->usriX_workstations) {
93 fields_present |= SAMR_FIELD_WORKSTATIONS;
96 unix_to_nt_time_abs(&password_age, infoX->usriX_password_age);
98 /* TODO: infoX->usriX_priv */
100 info21->last_logon = 0;
101 info21->last_logoff = 0;
102 info21->last_password_change = 0;
103 info21->acct_expiry = 0;
104 info21->allow_password_change = 0;
105 info21->force_password_change = 0;
106 info21->account_name.string = infoX->usriX_name;
107 info21->full_name.string = infoX->usriX_full_name;
108 info21->home_directory.string = infoX->usriX_home_dir;
109 info21->home_drive.string = infoX->usriX_home_dir_drive;
110 info21->logon_script.string = infoX->usriX_script_path;
111 info21->profile_path.string = infoX->usriX_profile;
112 info21->description.string = infoX->usriX_comment;
113 info21->workstations.string = infoX->usriX_workstations;
114 info21->comment.string = infoX->usriX_usr_comment;
115 info21->parameters = zero_parameters;
116 info21->lm_owf_password = zero_parameters;
117 info21->nt_owf_password = zero_parameters;
118 info21->private_data.string = NULL;
119 info21->buf_count = 0;
120 info21->buffer = NULL;
121 info21->rid = infoX->usriX_user_id;
122 info21->primary_gid = infoX->usriX_primary_group_id;
123 info21->acct_flags = infoX->usriX_flags;
124 info21->fields_present = fields_present;
125 info21->logon_hours = zero_logon_hours;
126 info21->bad_password_count = infoX->usriX_bad_pw_count;
127 info21->logon_count = infoX->usriX_num_logons;
128 info21->country_code = infoX->usriX_country_code;
129 info21->code_page = infoX->usriX_code_page;
130 info21->lm_password_set = 0;
131 info21->nt_password_set = 0;
132 info21->password_expired = infoX->usriX_password_expired;
133 info21->private_data_sensitive = 0;
136 /****************************************************************
137 ****************************************************************/
139 static NTSTATUS construct_USER_INFO_X(uint32_t level,
140 uint8_t *buffer,
141 struct USER_INFO_X *uX)
143 struct USER_INFO_0 *u0 = NULL;
144 struct USER_INFO_1 *u1 = NULL;
145 struct USER_INFO_2 *u2 = NULL;
146 struct USER_INFO_3 *u3 = NULL;
147 struct USER_INFO_1003 *u1003 = NULL;
148 struct USER_INFO_1006 *u1006 = NULL;
149 struct USER_INFO_1007 *u1007 = NULL;
150 struct USER_INFO_1009 *u1009 = NULL;
151 struct USER_INFO_1011 *u1011 = NULL;
152 struct USER_INFO_1012 *u1012 = NULL;
153 struct USER_INFO_1014 *u1014 = NULL;
154 struct USER_INFO_1024 *u1024 = NULL;
155 struct USER_INFO_1051 *u1051 = NULL;
156 struct USER_INFO_1052 *u1052 = NULL;
157 struct USER_INFO_1053 *u1053 = NULL;
159 if (!buffer || !uX) {
160 return NT_STATUS_INVALID_PARAMETER;
163 ZERO_STRUCTP(uX);
165 switch (level) {
166 case 0:
167 u0 = (struct USER_INFO_0 *)buffer;
168 uX->usriX_name = u0->usri0_name;
169 break;
170 case 1:
171 u1 = (struct USER_INFO_1 *)buffer;
172 uX->usriX_name = u1->usri1_name;
173 uX->usriX_password = u1->usri1_password;
174 uX->usriX_password_age = u1->usri1_password_age;
175 uX->usriX_priv = u1->usri1_priv;
176 uX->usriX_home_dir = u1->usri1_home_dir;
177 uX->usriX_comment = u1->usri1_comment;
178 uX->usriX_flags = u1->usri1_flags;
179 uX->usriX_script_path = u1->usri1_script_path;
180 break;
181 case 2:
182 u2 = (struct USER_INFO_2 *)buffer;
183 uX->usriX_name = u2->usri2_name;
184 uX->usriX_password = u2->usri2_password;
185 uX->usriX_password_age = u2->usri2_password_age;
186 uX->usriX_priv = u2->usri2_priv;
187 uX->usriX_home_dir = u2->usri2_home_dir;
188 uX->usriX_comment = u2->usri2_comment;
189 uX->usriX_flags = u2->usri2_flags;
190 uX->usriX_script_path = u2->usri2_script_path;
191 uX->usriX_auth_flags = u2->usri2_auth_flags;
192 uX->usriX_full_name = u2->usri2_full_name;
193 uX->usriX_usr_comment = u2->usri2_usr_comment;
194 uX->usriX_parms = u2->usri2_parms;
195 uX->usriX_workstations = u2->usri2_workstations;
196 uX->usriX_last_logon = u2->usri2_last_logon;
197 uX->usriX_last_logoff = u2->usri2_last_logoff;
198 uX->usriX_acct_expires = u2->usri2_acct_expires;
199 uX->usriX_max_storage = u2->usri2_max_storage;
200 uX->usriX_units_per_week= u2->usri2_units_per_week;
201 uX->usriX_logon_hours = u2->usri2_logon_hours;
202 uX->usriX_bad_pw_count = u2->usri2_bad_pw_count;
203 uX->usriX_num_logons = u2->usri2_num_logons;
204 uX->usriX_logon_server = u2->usri2_logon_server;
205 uX->usriX_country_code = u2->usri2_country_code;
206 uX->usriX_code_page = u2->usri2_code_page;
207 break;
208 case 3:
209 u3 = (struct USER_INFO_3 *)buffer;
210 uX->usriX_name = u3->usri3_name;
211 uX->usriX_password_age = u3->usri3_password_age;
212 uX->usriX_priv = u3->usri3_priv;
213 uX->usriX_home_dir = u3->usri3_home_dir;
214 uX->usriX_comment = u3->usri3_comment;
215 uX->usriX_flags = u3->usri3_flags;
216 uX->usriX_script_path = u3->usri3_script_path;
217 uX->usriX_auth_flags = u3->usri3_auth_flags;
218 uX->usriX_full_name = u3->usri3_full_name;
219 uX->usriX_usr_comment = u3->usri3_usr_comment;
220 uX->usriX_parms = u3->usri3_parms;
221 uX->usriX_workstations = u3->usri3_workstations;
222 uX->usriX_last_logon = u3->usri3_last_logon;
223 uX->usriX_last_logoff = u3->usri3_last_logoff;
224 uX->usriX_acct_expires = u3->usri3_acct_expires;
225 uX->usriX_max_storage = u3->usri3_max_storage;
226 uX->usriX_units_per_week= u3->usri3_units_per_week;
227 uX->usriX_logon_hours = u3->usri3_logon_hours;
228 uX->usriX_bad_pw_count = u3->usri3_bad_pw_count;
229 uX->usriX_num_logons = u3->usri3_num_logons;
230 uX->usriX_logon_server = u3->usri3_logon_server;
231 uX->usriX_country_code = u3->usri3_country_code;
232 uX->usriX_code_page = u3->usri3_code_page;
233 uX->usriX_user_id = u3->usri3_user_id;
234 uX->usriX_primary_group_id = u3->usri3_primary_group_id;
235 uX->usriX_profile = u3->usri3_profile;
236 uX->usriX_home_dir_drive = u3->usri3_home_dir_drive;
237 uX->usriX_password_expired = u3->usri3_password_expired;
238 break;
239 case 1003:
240 u1003 = (struct USER_INFO_1003 *)buffer;
241 uX->usriX_password = u1003->usri1003_password;
242 break;
243 case 1006:
244 u1006 = (struct USER_INFO_1006 *)buffer;
245 uX->usriX_home_dir = u1006->usri1006_home_dir;
246 break;
247 case 1007:
248 u1007 = (struct USER_INFO_1007 *)buffer;
249 uX->usriX_comment = u1007->usri1007_comment;
250 break;
251 case 1009:
252 u1009 = (struct USER_INFO_1009 *)buffer;
253 uX->usriX_script_path = u1009->usri1009_script_path;
254 break;
255 case 1011:
256 u1011 = (struct USER_INFO_1011 *)buffer;
257 uX->usriX_full_name = u1011->usri1011_full_name;
258 break;
259 case 1012:
260 u1012 = (struct USER_INFO_1012 *)buffer;
261 uX->usriX_usr_comment = u1012->usri1012_usr_comment;
262 break;
263 case 1014:
264 u1014 = (struct USER_INFO_1014 *)buffer;
265 uX->usriX_workstations = u1014->usri1014_workstations;
266 break;
267 case 1024:
268 u1024 = (struct USER_INFO_1024 *)buffer;
269 uX->usriX_country_code = u1024->usri1024_country_code;
270 break;
271 case 1051:
272 u1051 = (struct USER_INFO_1051 *)buffer;
273 uX->usriX_primary_group_id = u1051->usri1051_primary_group_id;
274 break;
275 case 1052:
276 u1052 = (struct USER_INFO_1052 *)buffer;
277 uX->usriX_profile = u1052->usri1052_profile;
278 break;
279 case 1053:
280 u1053 = (struct USER_INFO_1053 *)buffer;
281 uX->usriX_home_dir_drive = u1053->usri1053_home_dir_drive;
282 break;
283 case 4:
284 default:
285 return NT_STATUS_INVALID_INFO_CLASS;
288 return NT_STATUS_OK;
291 /****************************************************************
292 ****************************************************************/
294 static NTSTATUS set_user_info_USER_INFO_X(TALLOC_CTX *ctx,
295 struct rpc_pipe_client *pipe_cli,
296 DATA_BLOB *session_key,
297 struct policy_handle *user_handle,
298 struct USER_INFO_X *uX)
300 union samr_UserInfo user_info;
301 struct samr_UserInfo21 info21;
302 NTSTATUS status;
304 if (!uX) {
305 return NT_STATUS_INVALID_PARAMETER;
308 convert_USER_INFO_X_to_samr_user_info21(uX, &info21);
310 ZERO_STRUCT(user_info);
312 if (uX->usriX_password) {
314 user_info.info25.info = info21;
316 init_samr_CryptPasswordEx(uX->usriX_password,
317 session_key,
318 &user_info.info25.password);
320 status = rpccli_samr_SetUserInfo2(pipe_cli, talloc_tos(),
321 user_handle,
323 &user_info);
325 if (NT_STATUS_EQUAL(status, NT_STATUS(DCERPC_FAULT_INVALID_TAG))) {
327 user_info.info23.info = info21;
329 init_samr_CryptPassword(uX->usriX_password,
330 session_key,
331 &user_info.info23.password);
333 status = rpccli_samr_SetUserInfo2(pipe_cli, talloc_tos(),
334 user_handle,
336 &user_info);
338 } else {
340 user_info.info21 = info21;
342 status = rpccli_samr_SetUserInfo(pipe_cli, talloc_tos(),
343 user_handle,
345 &user_info);
348 return status;
351 /****************************************************************
352 ****************************************************************/
354 WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
355 struct NetUserAdd *r)
357 struct rpc_pipe_client *pipe_cli = NULL;
358 NTSTATUS status;
359 WERROR werr;
360 struct policy_handle connect_handle, domain_handle, user_handle;
361 struct lsa_String lsa_account_name;
362 struct dom_sid2 *domain_sid = NULL;
363 union samr_UserInfo *user_info = NULL;
364 struct samr_PwInfo pw_info;
365 uint32_t access_granted = 0;
366 uint32_t rid = 0;
367 struct USER_INFO_X uX;
369 ZERO_STRUCT(connect_handle);
370 ZERO_STRUCT(domain_handle);
371 ZERO_STRUCT(user_handle);
373 if (!r->in.buffer) {
374 return WERR_INVALID_PARAM;
377 switch (r->in.level) {
378 case 1:
379 break;
380 case 2:
381 case 3:
382 case 4:
383 default:
384 werr = WERR_NOT_SUPPORTED;
385 goto done;
388 werr = libnetapi_open_pipe(ctx, r->in.server_name,
389 &ndr_table_samr.syntax_id,
390 &pipe_cli);
391 if (!W_ERROR_IS_OK(werr)) {
392 goto done;
395 status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
396 if (!NT_STATUS_IS_OK(status)) {
397 werr = ntstatus_to_werror(status);
398 goto done;
401 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
402 SAMR_ACCESS_ENUM_DOMAINS |
403 SAMR_ACCESS_LOOKUP_DOMAIN,
404 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
405 SAMR_DOMAIN_ACCESS_CREATE_USER |
406 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
407 &connect_handle,
408 &domain_handle,
409 &domain_sid);
410 if (!W_ERROR_IS_OK(werr)) {
411 goto done;
414 init_lsa_String(&lsa_account_name, uX.usriX_name);
416 status = rpccli_samr_CreateUser2(pipe_cli, talloc_tos(),
417 &domain_handle,
418 &lsa_account_name,
419 ACB_NORMAL,
420 SEC_STD_WRITE_DAC |
421 SEC_STD_DELETE |
422 SAMR_USER_ACCESS_SET_PASSWORD |
423 SAMR_USER_ACCESS_SET_ATTRIBUTES |
424 SAMR_USER_ACCESS_GET_ATTRIBUTES,
425 &user_handle,
426 &access_granted,
427 &rid);
428 if (!NT_STATUS_IS_OK(status)) {
429 werr = ntstatus_to_werror(status);
430 goto done;
433 status = rpccli_samr_QueryUserInfo(pipe_cli, talloc_tos(),
434 &user_handle,
436 &user_info);
437 if (!NT_STATUS_IS_OK(status)) {
438 werr = ntstatus_to_werror(status);
439 goto done;
442 if (!(user_info->info16.acct_flags & ACB_NORMAL)) {
443 werr = WERR_INVALID_PARAM;
444 goto done;
447 status = rpccli_samr_GetUserPwInfo(pipe_cli, talloc_tos(),
448 &user_handle,
449 &pw_info);
450 if (!NT_STATUS_IS_OK(status)) {
451 werr = ntstatus_to_werror(status);
452 goto done;
455 uX.usriX_flags |= ACB_NORMAL;
457 status = set_user_info_USER_INFO_X(ctx, pipe_cli,
458 &pipe_cli->auth->user_session_key,
459 &user_handle,
460 &uX);
461 if (!NT_STATUS_IS_OK(status)) {
462 werr = ntstatus_to_werror(status);
463 goto failed;
466 werr = WERR_OK;
467 goto done;
469 failed:
470 rpccli_samr_DeleteUser(pipe_cli, talloc_tos(),
471 &user_handle);
473 done:
474 if (is_valid_policy_hnd(&user_handle) && pipe_cli) {
475 rpccli_samr_Close(pipe_cli, talloc_tos(), &user_handle);
478 if (ctx->disable_policy_handle_cache) {
479 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
480 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
483 return werr;
486 /****************************************************************
487 ****************************************************************/
489 WERROR NetUserAdd_l(struct libnetapi_ctx *ctx,
490 struct NetUserAdd *r)
492 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserAdd);
495 /****************************************************************
496 ****************************************************************/
498 WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
499 struct NetUserDel *r)
501 struct rpc_pipe_client *pipe_cli = NULL;
502 NTSTATUS status;
503 WERROR werr;
504 struct policy_handle connect_handle, builtin_handle, domain_handle, user_handle;
505 struct lsa_String lsa_account_name;
506 struct samr_Ids user_rids, name_types;
507 struct dom_sid2 *domain_sid = NULL;
508 struct dom_sid2 user_sid;
510 ZERO_STRUCT(connect_handle);
511 ZERO_STRUCT(builtin_handle);
512 ZERO_STRUCT(domain_handle);
513 ZERO_STRUCT(user_handle);
515 werr = libnetapi_open_pipe(ctx, r->in.server_name,
516 &ndr_table_samr.syntax_id,
517 &pipe_cli);
519 if (!W_ERROR_IS_OK(werr)) {
520 goto done;
523 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
524 SAMR_ACCESS_ENUM_DOMAINS |
525 SAMR_ACCESS_LOOKUP_DOMAIN,
526 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
527 &connect_handle,
528 &domain_handle,
529 &domain_sid);
530 if (!W_ERROR_IS_OK(werr)) {
531 goto done;
534 status = rpccli_samr_OpenDomain(pipe_cli, talloc_tos(),
535 &connect_handle,
536 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
537 CONST_DISCARD(struct dom_sid *, &global_sid_Builtin),
538 &builtin_handle);
539 if (!NT_STATUS_IS_OK(status)) {
540 werr = ntstatus_to_werror(status);
541 goto done;
544 init_lsa_String(&lsa_account_name, r->in.user_name);
546 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
547 &domain_handle,
549 &lsa_account_name,
550 &user_rids,
551 &name_types);
552 if (!NT_STATUS_IS_OK(status)) {
553 werr = ntstatus_to_werror(status);
554 goto done;
557 status = rpccli_samr_OpenUser(pipe_cli, talloc_tos(),
558 &domain_handle,
559 SEC_STD_DELETE,
560 user_rids.ids[0],
561 &user_handle);
562 if (!NT_STATUS_IS_OK(status)) {
563 werr = ntstatus_to_werror(status);
564 goto done;
567 sid_compose(&user_sid, domain_sid, user_rids.ids[0]);
569 status = rpccli_samr_RemoveMemberFromForeignDomain(pipe_cli, talloc_tos(),
570 &builtin_handle,
571 &user_sid);
572 if (!NT_STATUS_IS_OK(status)) {
573 werr = ntstatus_to_werror(status);
574 goto done;
577 status = rpccli_samr_DeleteUser(pipe_cli, talloc_tos(),
578 &user_handle);
579 if (!NT_STATUS_IS_OK(status)) {
580 werr = ntstatus_to_werror(status);
581 goto done;
584 werr = WERR_OK;
586 done:
587 if (is_valid_policy_hnd(&user_handle)) {
588 rpccli_samr_Close(pipe_cli, talloc_tos(), &user_handle);
591 if (ctx->disable_policy_handle_cache) {
592 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
593 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
594 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
597 return werr;
600 /****************************************************************
601 ****************************************************************/
603 WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
604 struct NetUserDel *r)
606 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserDel);
609 /****************************************************************
610 ****************************************************************/
612 static NTSTATUS libnetapi_samr_lookup_user(TALLOC_CTX *mem_ctx,
613 struct rpc_pipe_client *pipe_cli,
614 struct policy_handle *domain_handle,
615 struct policy_handle *builtin_handle,
616 const char *user_name,
617 const struct dom_sid *domain_sid,
618 uint32_t rid,
619 uint32_t level,
620 struct samr_UserInfo21 **info21,
621 struct sec_desc_buf **sec_desc,
622 uint32_t *auth_flag_p)
624 NTSTATUS status;
626 struct policy_handle user_handle;
627 union samr_UserInfo *user_info = NULL;
628 struct samr_RidWithAttributeArray *rid_array = NULL;
629 uint32_t access_mask = SEC_STD_READ_CONTROL |
630 SAMR_USER_ACCESS_GET_ATTRIBUTES |
631 SAMR_USER_ACCESS_GET_NAME_ETC;
633 ZERO_STRUCT(user_handle);
635 switch (level) {
636 case 0:
637 break;
638 case 1:
639 access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
640 SAMR_USER_ACCESS_GET_GROUPS;
641 break;
642 case 2:
643 case 3:
644 case 4:
645 case 11:
646 access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
647 SAMR_USER_ACCESS_GET_GROUPS |
648 SAMR_USER_ACCESS_GET_LOCALE;
649 break;
650 case 10:
651 case 20:
652 case 23:
653 break;
654 default:
655 return NT_STATUS_INVALID_LEVEL;
658 if (level == 0) {
659 return NT_STATUS_OK;
662 status = rpccli_samr_OpenUser(pipe_cli, mem_ctx,
663 domain_handle,
664 access_mask,
665 rid,
666 &user_handle);
667 if (!NT_STATUS_IS_OK(status)) {
668 goto done;
671 status = rpccli_samr_QueryUserInfo(pipe_cli, mem_ctx,
672 &user_handle,
674 &user_info);
675 if (!NT_STATUS_IS_OK(status)) {
676 goto done;
679 status = rpccli_samr_QuerySecurity(pipe_cli, mem_ctx,
680 &user_handle,
681 SECINFO_DACL,
682 sec_desc);
683 if (!NT_STATUS_IS_OK(status)) {
684 goto done;
687 if (access_mask & SAMR_USER_ACCESS_GET_GROUPS) {
689 struct lsa_SidArray sid_array;
690 struct samr_Ids alias_rids;
691 int i;
692 uint32_t auth_flag = 0;
693 struct dom_sid sid;
695 status = rpccli_samr_GetGroupsForUser(pipe_cli, mem_ctx,
696 &user_handle,
697 &rid_array);
698 if (!NT_STATUS_IS_OK(status)) {
699 goto done;
702 sid_array.num_sids = rid_array->count + 1;
703 sid_array.sids = talloc_array(mem_ctx, struct lsa_SidPtr,
704 sid_array.num_sids);
705 NT_STATUS_HAVE_NO_MEMORY(sid_array.sids);
707 for (i=0; i<rid_array->count; i++) {
708 sid_compose(&sid, domain_sid, rid_array->rids[i].rid);
709 sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sid);
710 NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
713 sid_compose(&sid, domain_sid, rid);
714 sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sid);
715 NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
717 status = rpccli_samr_GetAliasMembership(pipe_cli, mem_ctx,
718 builtin_handle,
719 &sid_array,
720 &alias_rids);
721 if (!NT_STATUS_IS_OK(status)) {
722 goto done;
725 for (i=0; i<alias_rids.count; i++) {
726 switch (alias_rids.ids[i]) {
727 case 550: /* Print Operators */
728 auth_flag |= AF_OP_PRINT;
729 break;
730 case 549: /* Server Operators */
731 auth_flag |= AF_OP_SERVER;
732 break;
733 case 548: /* Account Operators */
734 auth_flag |= AF_OP_ACCOUNTS;
735 break;
736 default:
737 break;
741 if (auth_flag_p) {
742 *auth_flag_p = auth_flag;
746 *info21 = &user_info->info21;
748 done:
749 if (is_valid_policy_hnd(&user_handle)) {
750 rpccli_samr_Close(pipe_cli, mem_ctx, &user_handle);
753 return status;
756 /****************************************************************
757 ****************************************************************/
759 static uint32_t samr_rid_to_priv_level(uint32_t rid)
761 switch (rid) {
762 case DOMAIN_RID_ADMINISTRATOR:
763 return USER_PRIV_ADMIN;
764 case DOMAIN_RID_GUEST:
765 return USER_PRIV_GUEST;
766 default:
767 return USER_PRIV_USER;
771 /****************************************************************
772 ****************************************************************/
774 static uint32_t samr_acb_flags_to_netapi_flags(uint32_t acb)
776 uint32_t fl = UF_SCRIPT; /* god knows why */
778 fl |= ds_acb2uf(acb);
780 return fl;
783 /****************************************************************
784 ****************************************************************/
786 static NTSTATUS info21_to_USER_INFO_1(TALLOC_CTX *mem_ctx,
787 const struct samr_UserInfo21 *i21,
788 struct USER_INFO_1 *i)
790 ZERO_STRUCTP(i);
791 i->usri1_name = talloc_strdup(mem_ctx, i21->account_name.string);
792 NT_STATUS_HAVE_NO_MEMORY(i->usri1_name);
793 i->usri1_password = NULL;
794 i->usri1_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
795 i->usri1_priv = samr_rid_to_priv_level(i21->rid);
796 i->usri1_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
797 i->usri1_comment = talloc_strdup(mem_ctx, i21->description.string);
798 i->usri1_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
799 i->usri1_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
801 return NT_STATUS_OK;
804 /****************************************************************
805 ****************************************************************/
807 static NTSTATUS info21_to_USER_INFO_2(TALLOC_CTX *mem_ctx,
808 const struct samr_UserInfo21 *i21,
809 uint32_t auth_flag,
810 struct USER_INFO_2 *i)
812 ZERO_STRUCTP(i);
814 i->usri2_name = talloc_strdup(mem_ctx, i21->account_name.string);
815 NT_STATUS_HAVE_NO_MEMORY(i->usri2_name);
816 i->usri2_password = NULL;
817 i->usri2_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
818 i->usri2_priv = samr_rid_to_priv_level(i21->rid);
819 i->usri2_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
820 i->usri2_comment = talloc_strdup(mem_ctx, i21->description.string);
821 i->usri2_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
822 i->usri2_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
823 i->usri2_auth_flags = auth_flag;
824 i->usri2_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
825 i->usri2_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
826 i->usri2_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
827 i->usri2_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
828 i->usri2_last_logon = nt_time_to_unix(i21->last_logon);
829 i->usri2_last_logoff = nt_time_to_unix(i21->last_logoff);
830 i->usri2_acct_expires = nt_time_to_unix(i21->acct_expiry);
831 i->usri2_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
832 i->usri2_units_per_week = i21->logon_hours.units_per_week;
833 i->usri2_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
834 i->usri2_bad_pw_count = i21->bad_password_count;
835 i->usri2_num_logons = i21->logon_count;
836 i->usri2_logon_server = talloc_strdup(mem_ctx, "\\\\*");
837 i->usri2_country_code = i21->country_code;
838 i->usri2_code_page = i21->code_page;
840 return NT_STATUS_OK;
843 /****************************************************************
844 ****************************************************************/
846 static NTSTATUS info21_to_USER_INFO_3(TALLOC_CTX *mem_ctx,
847 const struct samr_UserInfo21 *i21,
848 uint32_t auth_flag,
849 struct USER_INFO_3 *i)
851 ZERO_STRUCTP(i);
853 i->usri3_name = talloc_strdup(mem_ctx, i21->account_name.string);
854 NT_STATUS_HAVE_NO_MEMORY(i->usri3_name);
855 i->usri3_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
856 i->usri3_priv = samr_rid_to_priv_level(i21->rid);
857 i->usri3_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
858 i->usri3_comment = talloc_strdup(mem_ctx, i21->description.string);
859 i->usri3_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
860 i->usri3_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
861 i->usri3_auth_flags = auth_flag;
862 i->usri3_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
863 i->usri3_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
864 i->usri3_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
865 i->usri3_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
866 i->usri3_last_logon = nt_time_to_unix(i21->last_logon);
867 i->usri3_last_logoff = nt_time_to_unix(i21->last_logoff);
868 i->usri3_acct_expires = nt_time_to_unix(i21->acct_expiry);
869 i->usri3_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
870 i->usri3_units_per_week = i21->logon_hours.units_per_week;
871 i->usri3_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
872 i->usri3_bad_pw_count = i21->bad_password_count;
873 i->usri3_num_logons = i21->logon_count;
874 i->usri3_logon_server = talloc_strdup(mem_ctx, "\\\\*");
875 i->usri3_country_code = i21->country_code;
876 i->usri3_code_page = i21->code_page;
877 i->usri3_user_id = i21->rid;
878 i->usri3_primary_group_id = i21->primary_gid;
879 i->usri3_profile = talloc_strdup(mem_ctx, i21->profile_path.string);
880 i->usri3_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
881 i->usri3_password_expired = i21->password_expired;
883 return NT_STATUS_OK;
886 /****************************************************************
887 ****************************************************************/
889 static NTSTATUS info21_to_USER_INFO_4(TALLOC_CTX *mem_ctx,
890 const struct samr_UserInfo21 *i21,
891 uint32_t auth_flag,
892 struct dom_sid *domain_sid,
893 struct USER_INFO_4 *i)
895 struct dom_sid sid;
897 ZERO_STRUCTP(i);
899 i->usri4_name = talloc_strdup(mem_ctx, i21->account_name.string);
900 NT_STATUS_HAVE_NO_MEMORY(i->usri4_name);
901 i->usri4_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
902 i->usri4_password = NULL;
903 i->usri4_priv = samr_rid_to_priv_level(i21->rid);
904 i->usri4_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
905 i->usri4_comment = talloc_strdup(mem_ctx, i21->description.string);
906 i->usri4_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
907 i->usri4_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
908 i->usri4_auth_flags = auth_flag;
909 i->usri4_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
910 i->usri4_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
911 i->usri4_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
912 i->usri4_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
913 i->usri4_last_logon = nt_time_to_unix(i21->last_logon);
914 i->usri4_last_logoff = nt_time_to_unix(i21->last_logoff);
915 i->usri4_acct_expires = nt_time_to_unix(i21->acct_expiry);
916 i->usri4_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
917 i->usri4_units_per_week = i21->logon_hours.units_per_week;
918 i->usri4_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
919 i->usri4_bad_pw_count = i21->bad_password_count;
920 i->usri4_num_logons = i21->logon_count;
921 i->usri4_logon_server = talloc_strdup(mem_ctx, "\\\\*");
922 i->usri4_country_code = i21->country_code;
923 i->usri4_code_page = i21->code_page;
924 if (!sid_compose(&sid, domain_sid, i21->rid)) {
925 return NT_STATUS_NO_MEMORY;
927 i->usri4_user_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
928 i->usri4_primary_group_id = i21->primary_gid;
929 i->usri4_profile = talloc_strdup(mem_ctx, i21->profile_path.string);
930 i->usri4_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
931 i->usri4_password_expired = i21->password_expired;
933 return NT_STATUS_OK;
936 /****************************************************************
937 ****************************************************************/
939 static NTSTATUS info21_to_USER_INFO_10(TALLOC_CTX *mem_ctx,
940 const struct samr_UserInfo21 *i21,
941 struct USER_INFO_10 *i)
943 ZERO_STRUCTP(i);
945 i->usri10_name = talloc_strdup(mem_ctx, i21->account_name.string);
946 NT_STATUS_HAVE_NO_MEMORY(i->usri10_name);
947 i->usri10_comment = talloc_strdup(mem_ctx, i21->description.string);
948 i->usri10_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
949 i->usri10_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
951 return NT_STATUS_OK;
954 /****************************************************************
955 ****************************************************************/
957 static NTSTATUS info21_to_USER_INFO_11(TALLOC_CTX *mem_ctx,
958 const struct samr_UserInfo21 *i21,
959 uint32_t auth_flag,
960 struct USER_INFO_11 *i)
962 ZERO_STRUCTP(i);
964 i->usri11_name = talloc_strdup(mem_ctx, i21->account_name.string);
965 NT_STATUS_HAVE_NO_MEMORY(i->usri11_name);
966 i->usri11_comment = talloc_strdup(mem_ctx, i21->description.string);
967 i->usri11_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
968 i->usri11_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
969 i->usri11_priv = samr_rid_to_priv_level(i21->rid);
970 i->usri11_auth_flags = auth_flag;
971 i->usri11_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
972 i->usri11_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
973 i->usri11_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
974 i->usri11_last_logon = nt_time_to_unix(i21->last_logon);
975 i->usri11_last_logoff = nt_time_to_unix(i21->last_logoff);
976 i->usri11_bad_pw_count = i21->bad_password_count;
977 i->usri11_num_logons = i21->logon_count;
978 i->usri11_logon_server = talloc_strdup(mem_ctx, "\\\\*");
979 i->usri11_country_code = i21->country_code;
980 i->usri11_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
981 i->usri11_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
982 i->usri11_units_per_week = i21->logon_hours.units_per_week;
983 i->usri11_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
984 i->usri11_code_page = i21->code_page;
986 return NT_STATUS_OK;
989 /****************************************************************
990 ****************************************************************/
992 static NTSTATUS info21_to_USER_INFO_20(TALLOC_CTX *mem_ctx,
993 const struct samr_UserInfo21 *i21,
994 struct USER_INFO_20 *i)
996 ZERO_STRUCTP(i);
998 i->usri20_name = talloc_strdup(mem_ctx, i21->account_name.string);
999 NT_STATUS_HAVE_NO_MEMORY(i->usri20_name);
1000 i->usri20_comment = talloc_strdup(mem_ctx, i21->description.string);
1001 i->usri20_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
1002 i->usri20_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
1003 i->usri20_user_id = i21->rid;
1005 return NT_STATUS_OK;
1008 /****************************************************************
1009 ****************************************************************/
1011 static NTSTATUS info21_to_USER_INFO_23(TALLOC_CTX *mem_ctx,
1012 const struct samr_UserInfo21 *i21,
1013 struct dom_sid *domain_sid,
1014 struct USER_INFO_23 *i)
1016 struct dom_sid sid;
1018 ZERO_STRUCTP(i);
1020 i->usri23_name = talloc_strdup(mem_ctx, i21->account_name.string);
1021 NT_STATUS_HAVE_NO_MEMORY(i->usri23_name);
1022 i->usri23_comment = talloc_strdup(mem_ctx, i21->description.string);
1023 i->usri23_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
1024 i->usri23_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
1025 if (!sid_compose(&sid, domain_sid, i21->rid)) {
1026 return NT_STATUS_NO_MEMORY;
1028 i->usri23_user_sid = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
1030 return NT_STATUS_OK;
1033 /****************************************************************
1034 ****************************************************************/
1036 static NTSTATUS libnetapi_samr_lookup_user_map_USER_INFO(TALLOC_CTX *mem_ctx,
1037 struct rpc_pipe_client *pipe_cli,
1038 struct dom_sid *domain_sid,
1039 struct policy_handle *domain_handle,
1040 struct policy_handle *builtin_handle,
1041 const char *user_name,
1042 uint32_t rid,
1043 uint32_t level,
1044 uint8_t **buffer,
1045 uint32_t *num_entries)
1047 NTSTATUS status;
1049 struct samr_UserInfo21 *info21 = NULL;
1050 struct sec_desc_buf *sec_desc = NULL;
1051 uint32_t auth_flag = 0;
1053 struct USER_INFO_0 info0;
1054 struct USER_INFO_1 info1;
1055 struct USER_INFO_2 info2;
1056 struct USER_INFO_3 info3;
1057 struct USER_INFO_4 info4;
1058 struct USER_INFO_10 info10;
1059 struct USER_INFO_11 info11;
1060 struct USER_INFO_20 info20;
1061 struct USER_INFO_23 info23;
1063 switch (level) {
1064 case 0:
1065 case 1:
1066 case 2:
1067 case 3:
1068 case 4:
1069 case 10:
1070 case 11:
1071 case 20:
1072 case 23:
1073 break;
1074 default:
1075 return NT_STATUS_INVALID_LEVEL;
1078 if (level == 0) {
1079 info0.usri0_name = talloc_strdup(mem_ctx, user_name);
1080 NT_STATUS_HAVE_NO_MEMORY(info0.usri0_name);
1082 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_0, info0,
1083 (struct USER_INFO_0 **)buffer, num_entries);
1085 return NT_STATUS_OK;
1088 status = libnetapi_samr_lookup_user(mem_ctx, pipe_cli,
1089 domain_handle,
1090 builtin_handle,
1091 user_name,
1092 domain_sid,
1093 rid,
1094 level,
1095 &info21,
1096 &sec_desc,
1097 &auth_flag);
1099 if (!NT_STATUS_IS_OK(status)) {
1100 goto done;
1103 switch (level) {
1104 case 0:
1105 /* already returned above */
1106 break;
1107 case 1:
1108 status = info21_to_USER_INFO_1(mem_ctx, info21, &info1);
1109 NT_STATUS_NOT_OK_RETURN(status);
1111 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_1, info1,
1112 (struct USER_INFO_1 **)buffer, num_entries);
1114 break;
1115 case 2:
1116 status = info21_to_USER_INFO_2(mem_ctx, info21, auth_flag, &info2);
1117 NT_STATUS_NOT_OK_RETURN(status);
1119 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_2, info2,
1120 (struct USER_INFO_2 **)buffer, num_entries);
1122 break;
1123 case 3:
1124 status = info21_to_USER_INFO_3(mem_ctx, info21, auth_flag, &info3);
1125 NT_STATUS_NOT_OK_RETURN(status);
1127 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_3, info3,
1128 (struct USER_INFO_3 **)buffer, num_entries);
1130 break;
1131 case 4:
1132 status = info21_to_USER_INFO_4(mem_ctx, info21, auth_flag, domain_sid, &info4);
1133 NT_STATUS_NOT_OK_RETURN(status);
1135 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_4, info4,
1136 (struct USER_INFO_4 **)buffer, num_entries);
1138 break;
1139 case 10:
1140 status = info21_to_USER_INFO_10(mem_ctx, info21, &info10);
1141 NT_STATUS_NOT_OK_RETURN(status);
1143 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_10, info10,
1144 (struct USER_INFO_10 **)buffer, num_entries);
1146 break;
1147 case 11:
1148 status = info21_to_USER_INFO_11(mem_ctx, info21, auth_flag, &info11);
1149 NT_STATUS_NOT_OK_RETURN(status);
1151 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_11, info11,
1152 (struct USER_INFO_11 **)buffer, num_entries);
1154 break;
1155 case 20:
1156 status = info21_to_USER_INFO_20(mem_ctx, info21, &info20);
1157 NT_STATUS_NOT_OK_RETURN(status);
1159 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_20, info20,
1160 (struct USER_INFO_20 **)buffer, num_entries);
1162 break;
1163 case 23:
1164 status = info21_to_USER_INFO_23(mem_ctx, info21, domain_sid, &info23);
1165 NT_STATUS_NOT_OK_RETURN(status);
1167 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_23, info23,
1168 (struct USER_INFO_23 **)buffer, num_entries);
1169 break;
1170 default:
1171 return NT_STATUS_INVALID_LEVEL;
1174 done:
1175 return status;
1178 /****************************************************************
1179 ****************************************************************/
1181 WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
1182 struct NetUserEnum *r)
1184 struct rpc_pipe_client *pipe_cli = NULL;
1185 struct policy_handle connect_handle;
1186 struct dom_sid2 *domain_sid = NULL;
1187 struct policy_handle domain_handle, builtin_handle;
1188 struct samr_SamArray *sam = NULL;
1189 uint32_t filter = ACB_NORMAL;
1190 int i;
1191 uint32_t entries_read = 0;
1193 NTSTATUS status = NT_STATUS_OK;
1194 WERROR werr;
1196 ZERO_STRUCT(connect_handle);
1197 ZERO_STRUCT(domain_handle);
1198 ZERO_STRUCT(builtin_handle);
1200 if (!r->out.buffer) {
1201 return WERR_INVALID_PARAM;
1204 *r->out.buffer = NULL;
1205 *r->out.entries_read = 0;
1207 switch (r->in.level) {
1208 case 0:
1209 case 1:
1210 case 2:
1211 case 3:
1212 case 4:
1213 case 10:
1214 case 11:
1215 case 20:
1216 case 23:
1217 break;
1218 default:
1219 return WERR_UNKNOWN_LEVEL;
1222 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1223 &ndr_table_samr.syntax_id,
1224 &pipe_cli);
1225 if (!W_ERROR_IS_OK(werr)) {
1226 goto done;
1229 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1230 SAMR_ACCESS_ENUM_DOMAINS |
1231 SAMR_ACCESS_LOOKUP_DOMAIN,
1232 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1233 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1234 &connect_handle,
1235 &builtin_handle);
1236 if (!W_ERROR_IS_OK(werr)) {
1237 goto done;
1240 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1241 SAMR_ACCESS_ENUM_DOMAINS |
1242 SAMR_ACCESS_LOOKUP_DOMAIN,
1243 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1244 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1245 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1246 &connect_handle,
1247 &domain_handle,
1248 &domain_sid);
1249 if (!W_ERROR_IS_OK(werr)) {
1250 goto done;
1253 switch (r->in.filter) {
1254 case FILTER_NORMAL_ACCOUNT:
1255 filter = ACB_NORMAL;
1256 break;
1257 case FILTER_TEMP_DUPLICATE_ACCOUNT:
1258 filter = ACB_TEMPDUP;
1259 break;
1260 case FILTER_INTERDOMAIN_TRUST_ACCOUNT:
1261 filter = ACB_DOMTRUST;
1262 break;
1263 case FILTER_WORKSTATION_TRUST_ACCOUNT:
1264 filter = ACB_WSTRUST;
1265 break;
1266 case FILTER_SERVER_TRUST_ACCOUNT:
1267 filter = ACB_SVRTRUST;
1268 break;
1269 default:
1270 break;
1273 status = rpccli_samr_EnumDomainUsers(pipe_cli,
1274 ctx,
1275 &domain_handle,
1276 r->in.resume_handle,
1277 filter,
1278 &sam,
1279 r->in.prefmaxlen,
1280 &entries_read);
1281 werr = ntstatus_to_werror(status);
1282 if (NT_STATUS_IS_ERR(status)) {
1283 goto done;
1286 for (i=0; i < sam->count; i++) {
1288 status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1289 domain_sid,
1290 &domain_handle,
1291 &builtin_handle,
1292 sam->entries[i].name.string,
1293 sam->entries[i].idx,
1294 r->in.level,
1295 r->out.buffer,
1296 r->out.entries_read);
1297 if (!NT_STATUS_IS_OK(status)) {
1298 werr = ntstatus_to_werror(status);
1299 goto done;
1303 done:
1304 /* if last query */
1305 if (NT_STATUS_IS_OK(status) ||
1306 NT_STATUS_IS_ERR(status)) {
1308 if (ctx->disable_policy_handle_cache) {
1309 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1310 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1311 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1315 return werr;
1318 /****************************************************************
1319 ****************************************************************/
1321 WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
1322 struct NetUserEnum *r)
1324 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserEnum);
1327 /****************************************************************
1328 ****************************************************************/
1330 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_USER(TALLOC_CTX *mem_ctx,
1331 struct samr_DispInfoGeneral *info,
1332 uint32_t *entries_read,
1333 void **buffer)
1335 struct NET_DISPLAY_USER *user = NULL;
1336 int i;
1338 user = TALLOC_ZERO_ARRAY(mem_ctx,
1339 struct NET_DISPLAY_USER,
1340 info->count);
1341 W_ERROR_HAVE_NO_MEMORY(user);
1343 for (i = 0; i < info->count; i++) {
1344 user[i].usri1_name = talloc_strdup(mem_ctx,
1345 info->entries[i].account_name.string);
1346 user[i].usri1_comment = talloc_strdup(mem_ctx,
1347 info->entries[i].description.string);
1348 user[i].usri1_flags =
1349 info->entries[i].acct_flags;
1350 user[i].usri1_full_name = talloc_strdup(mem_ctx,
1351 info->entries[i].full_name.string);
1352 user[i].usri1_user_id =
1353 info->entries[i].rid;
1354 user[i].usri1_next_index =
1355 info->entries[i].idx;
1357 if (!user[i].usri1_name) {
1358 return WERR_NOMEM;
1362 *buffer = talloc_memdup(mem_ctx, user,
1363 sizeof(struct NET_DISPLAY_USER) * info->count);
1364 W_ERROR_HAVE_NO_MEMORY(*buffer);
1366 *entries_read = info->count;
1368 return WERR_OK;
1371 /****************************************************************
1372 ****************************************************************/
1374 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(TALLOC_CTX *mem_ctx,
1375 struct samr_DispInfoFull *info,
1376 uint32_t *entries_read,
1377 void **buffer)
1379 struct NET_DISPLAY_MACHINE *machine = NULL;
1380 int i;
1382 machine = TALLOC_ZERO_ARRAY(mem_ctx,
1383 struct NET_DISPLAY_MACHINE,
1384 info->count);
1385 W_ERROR_HAVE_NO_MEMORY(machine);
1387 for (i = 0; i < info->count; i++) {
1388 machine[i].usri2_name = talloc_strdup(mem_ctx,
1389 info->entries[i].account_name.string);
1390 machine[i].usri2_comment = talloc_strdup(mem_ctx,
1391 info->entries[i].description.string);
1392 machine[i].usri2_flags =
1393 info->entries[i].acct_flags;
1394 machine[i].usri2_user_id =
1395 info->entries[i].rid;
1396 machine[i].usri2_next_index =
1397 info->entries[i].idx;
1399 if (!machine[i].usri2_name) {
1400 return WERR_NOMEM;
1404 *buffer = talloc_memdup(mem_ctx, machine,
1405 sizeof(struct NET_DISPLAY_MACHINE) * info->count);
1406 W_ERROR_HAVE_NO_MEMORY(*buffer);
1408 *entries_read = info->count;
1410 return WERR_OK;
1413 /****************************************************************
1414 ****************************************************************/
1416 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_GROUP(TALLOC_CTX *mem_ctx,
1417 struct samr_DispInfoFullGroups *info,
1418 uint32_t *entries_read,
1419 void **buffer)
1421 struct NET_DISPLAY_GROUP *group = NULL;
1422 int i;
1424 group = TALLOC_ZERO_ARRAY(mem_ctx,
1425 struct NET_DISPLAY_GROUP,
1426 info->count);
1427 W_ERROR_HAVE_NO_MEMORY(group);
1429 for (i = 0; i < info->count; i++) {
1430 group[i].grpi3_name = talloc_strdup(mem_ctx,
1431 info->entries[i].account_name.string);
1432 group[i].grpi3_comment = talloc_strdup(mem_ctx,
1433 info->entries[i].description.string);
1434 group[i].grpi3_group_id =
1435 info->entries[i].rid;
1436 group[i].grpi3_attributes =
1437 info->entries[i].acct_flags;
1438 group[i].grpi3_next_index =
1439 info->entries[i].idx;
1441 if (!group[i].grpi3_name) {
1442 return WERR_NOMEM;
1446 *buffer = talloc_memdup(mem_ctx, group,
1447 sizeof(struct NET_DISPLAY_GROUP) * info->count);
1448 W_ERROR_HAVE_NO_MEMORY(*buffer);
1450 *entries_read = info->count;
1452 return WERR_OK;
1456 /****************************************************************
1457 ****************************************************************/
1459 static WERROR convert_samr_dispinfo_to_NET_DISPLAY(TALLOC_CTX *mem_ctx,
1460 union samr_DispInfo *info,
1461 uint32_t level,
1462 uint32_t *entries_read,
1463 void **buffer)
1465 switch (level) {
1466 case 1:
1467 return convert_samr_dispinfo_to_NET_DISPLAY_USER(mem_ctx,
1468 &info->info1,
1469 entries_read,
1470 buffer);
1471 case 2:
1472 return convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(mem_ctx,
1473 &info->info2,
1474 entries_read,
1475 buffer);
1476 case 3:
1477 return convert_samr_dispinfo_to_NET_DISPLAY_GROUP(mem_ctx,
1478 &info->info3,
1479 entries_read,
1480 buffer);
1481 default:
1482 break;
1485 return WERR_UNKNOWN_LEVEL;
1488 /****************************************************************
1489 ****************************************************************/
1491 WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
1492 struct NetQueryDisplayInformation *r)
1494 struct rpc_pipe_client *pipe_cli = NULL;
1495 struct policy_handle connect_handle;
1496 struct dom_sid2 *domain_sid = NULL;
1497 struct policy_handle domain_handle;
1498 union samr_DispInfo info;
1500 uint32_t total_size = 0;
1501 uint32_t returned_size = 0;
1503 NTSTATUS status = NT_STATUS_OK;
1504 WERROR werr;
1505 WERROR werr_tmp;
1507 *r->out.entries_read = 0;
1509 ZERO_STRUCT(connect_handle);
1510 ZERO_STRUCT(domain_handle);
1512 switch (r->in.level) {
1513 case 1:
1514 case 2:
1515 case 3:
1516 break;
1517 default:
1518 return WERR_UNKNOWN_LEVEL;
1521 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1522 &ndr_table_samr.syntax_id,
1523 &pipe_cli);
1524 if (!W_ERROR_IS_OK(werr)) {
1525 goto done;
1528 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1529 SAMR_ACCESS_ENUM_DOMAINS |
1530 SAMR_ACCESS_LOOKUP_DOMAIN,
1531 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1532 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1533 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1534 &connect_handle,
1535 &domain_handle,
1536 &domain_sid);
1537 if (!W_ERROR_IS_OK(werr)) {
1538 goto done;
1541 status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
1542 ctx,
1543 &domain_handle,
1544 r->in.level,
1545 r->in.idx,
1546 r->in.entries_requested,
1547 r->in.prefmaxlen,
1548 &total_size,
1549 &returned_size,
1550 &info);
1551 werr = ntstatus_to_werror(status);
1552 if (NT_STATUS_IS_ERR(status)) {
1553 goto done;
1556 werr_tmp = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info,
1557 r->in.level,
1558 r->out.entries_read,
1559 r->out.buffer);
1560 if (!W_ERROR_IS_OK(werr_tmp)) {
1561 werr = werr_tmp;
1563 done:
1564 /* if last query */
1565 if (NT_STATUS_IS_OK(status) ||
1566 NT_STATUS_IS_ERR(status)) {
1568 if (ctx->disable_policy_handle_cache) {
1569 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1570 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1574 return werr;
1578 /****************************************************************
1579 ****************************************************************/
1582 WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
1583 struct NetQueryDisplayInformation *r)
1585 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetQueryDisplayInformation);
1588 /****************************************************************
1589 ****************************************************************/
1591 WERROR NetUserChangePassword_r(struct libnetapi_ctx *ctx,
1592 struct NetUserChangePassword *r)
1594 return WERR_NOT_SUPPORTED;
1597 /****************************************************************
1598 ****************************************************************/
1600 WERROR NetUserChangePassword_l(struct libnetapi_ctx *ctx,
1601 struct NetUserChangePassword *r)
1603 return WERR_NOT_SUPPORTED;
1606 /****************************************************************
1607 ****************************************************************/
1609 WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx,
1610 struct NetUserGetInfo *r)
1612 struct rpc_pipe_client *pipe_cli = NULL;
1613 NTSTATUS status;
1614 WERROR werr;
1616 struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1617 struct lsa_String lsa_account_name;
1618 struct dom_sid2 *domain_sid = NULL;
1619 struct samr_Ids user_rids, name_types;
1620 uint32_t num_entries = 0;
1622 ZERO_STRUCT(connect_handle);
1623 ZERO_STRUCT(domain_handle);
1624 ZERO_STRUCT(builtin_handle);
1625 ZERO_STRUCT(user_handle);
1627 if (!r->out.buffer) {
1628 return WERR_INVALID_PARAM;
1631 switch (r->in.level) {
1632 case 0:
1633 case 1:
1634 case 2:
1635 case 3:
1636 case 4:
1637 case 10:
1638 case 11:
1639 case 20:
1640 case 23:
1641 break;
1642 default:
1643 werr = WERR_UNKNOWN_LEVEL;
1644 goto done;
1647 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1648 &ndr_table_samr.syntax_id,
1649 &pipe_cli);
1650 if (!W_ERROR_IS_OK(werr)) {
1651 goto done;
1654 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1655 SAMR_ACCESS_ENUM_DOMAINS |
1656 SAMR_ACCESS_LOOKUP_DOMAIN,
1657 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1658 &connect_handle,
1659 &domain_handle,
1660 &domain_sid);
1661 if (!W_ERROR_IS_OK(werr)) {
1662 goto done;
1665 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1666 SAMR_ACCESS_ENUM_DOMAINS |
1667 SAMR_ACCESS_LOOKUP_DOMAIN,
1668 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1669 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1670 &connect_handle,
1671 &builtin_handle);
1672 if (!W_ERROR_IS_OK(werr)) {
1673 goto done;
1676 init_lsa_String(&lsa_account_name, r->in.user_name);
1678 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
1679 &domain_handle,
1681 &lsa_account_name,
1682 &user_rids,
1683 &name_types);
1684 if (!NT_STATUS_IS_OK(status)) {
1685 werr = ntstatus_to_werror(status);
1686 goto done;
1689 status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1690 domain_sid,
1691 &domain_handle,
1692 &builtin_handle,
1693 r->in.user_name,
1694 user_rids.ids[0],
1695 r->in.level,
1696 r->out.buffer,
1697 &num_entries);
1698 if (!NT_STATUS_IS_OK(status)) {
1699 werr = ntstatus_to_werror(status);
1700 goto done;
1703 done:
1704 if (is_valid_policy_hnd(&user_handle) && pipe_cli) {
1705 rpccli_samr_Close(pipe_cli, talloc_tos(), &user_handle);
1708 if (ctx->disable_policy_handle_cache) {
1709 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1710 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1713 return werr;
1716 /****************************************************************
1717 ****************************************************************/
1719 WERROR NetUserGetInfo_l(struct libnetapi_ctx *ctx,
1720 struct NetUserGetInfo *r)
1722 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetInfo);
1725 /****************************************************************
1726 ****************************************************************/
1728 WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
1729 struct NetUserSetInfo *r)
1731 struct rpc_pipe_client *pipe_cli = NULL;
1732 NTSTATUS status;
1733 WERROR werr;
1735 struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1736 struct lsa_String lsa_account_name;
1737 struct dom_sid2 *domain_sid = NULL;
1738 struct samr_Ids user_rids, name_types;
1739 uint32_t user_mask = 0;
1741 struct USER_INFO_X uX;
1743 ZERO_STRUCT(connect_handle);
1744 ZERO_STRUCT(domain_handle);
1745 ZERO_STRUCT(builtin_handle);
1746 ZERO_STRUCT(user_handle);
1748 if (!r->in.buffer) {
1749 return WERR_INVALID_PARAM;
1752 switch (r->in.level) {
1753 case 0:
1754 user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
1755 break;
1756 case 1003:
1757 user_mask = SAMR_USER_ACCESS_SET_PASSWORD;
1758 break;
1759 case 1006:
1760 case 1007:
1761 case 1009:
1762 case 1011:
1763 case 1014:
1764 case 1052:
1765 case 1053:
1766 user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
1767 break;
1768 case 1012:
1769 case 1024:
1770 user_mask = SAMR_USER_ACCESS_SET_LOC_COM;
1771 case 1051:
1772 user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES |
1773 SAMR_USER_ACCESS_GET_GROUPS;
1774 break;
1775 case 3:
1776 user_mask = SEC_STD_READ_CONTROL |
1777 SEC_STD_WRITE_DAC |
1778 SAMR_USER_ACCESS_GET_GROUPS |
1779 SAMR_USER_ACCESS_SET_PASSWORD |
1780 SAMR_USER_ACCESS_SET_ATTRIBUTES |
1781 SAMR_USER_ACCESS_GET_ATTRIBUTES |
1782 SAMR_USER_ACCESS_SET_LOC_COM;
1783 break;
1784 case 1:
1785 case 2:
1786 case 4:
1787 case 21:
1788 case 22:
1789 case 1005:
1790 case 1008:
1791 case 1010:
1792 case 1017:
1793 case 1020:
1794 werr = WERR_NOT_SUPPORTED;
1795 goto done;
1796 default:
1797 werr = WERR_UNKNOWN_LEVEL;
1798 goto done;
1801 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1802 &ndr_table_samr.syntax_id,
1803 &pipe_cli);
1804 if (!W_ERROR_IS_OK(werr)) {
1805 goto done;
1808 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1809 SAMR_ACCESS_ENUM_DOMAINS |
1810 SAMR_ACCESS_LOOKUP_DOMAIN,
1811 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
1812 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1813 &connect_handle,
1814 &domain_handle,
1815 &domain_sid);
1816 if (!W_ERROR_IS_OK(werr)) {
1817 goto done;
1820 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1821 SAMR_ACCESS_ENUM_DOMAINS |
1822 SAMR_ACCESS_LOOKUP_DOMAIN,
1823 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1824 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1825 &connect_handle,
1826 &builtin_handle);
1827 if (!W_ERROR_IS_OK(werr)) {
1828 goto done;
1831 init_lsa_String(&lsa_account_name, r->in.user_name);
1833 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
1834 &domain_handle,
1836 &lsa_account_name,
1837 &user_rids,
1838 &name_types);
1839 if (!NT_STATUS_IS_OK(status)) {
1840 werr = ntstatus_to_werror(status);
1841 goto done;
1844 status = rpccli_samr_OpenUser(pipe_cli, talloc_tos(),
1845 &domain_handle,
1846 user_mask,
1847 user_rids.ids[0],
1848 &user_handle);
1849 if (!NT_STATUS_IS_OK(status)) {
1850 werr = ntstatus_to_werror(status);
1851 goto done;
1854 status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
1855 if (!NT_STATUS_IS_OK(status)) {
1856 werr = ntstatus_to_werror(status);
1857 goto done;
1860 status = set_user_info_USER_INFO_X(ctx, pipe_cli,
1861 &pipe_cli->auth->user_session_key,
1862 &user_handle,
1863 &uX);
1864 if (!NT_STATUS_IS_OK(status)) {
1865 werr = ntstatus_to_werror(status);
1866 goto done;
1869 werr = WERR_OK;
1871 done:
1872 if (is_valid_policy_hnd(&user_handle) && pipe_cli) {
1873 rpccli_samr_Close(pipe_cli, talloc_tos(), &user_handle);
1876 if (ctx->disable_policy_handle_cache) {
1877 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1878 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1879 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1882 return werr;
1885 /****************************************************************
1886 ****************************************************************/
1888 WERROR NetUserSetInfo_l(struct libnetapi_ctx *ctx,
1889 struct NetUserSetInfo *r)
1891 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetInfo);
1894 /****************************************************************
1895 ****************************************************************/
1897 static NTSTATUS query_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
1898 struct rpc_pipe_client *pipe_cli,
1899 struct policy_handle *domain_handle,
1900 struct samr_DomInfo1 *info1,
1901 struct samr_DomInfo3 *info3,
1902 struct samr_DomInfo5 *info5,
1903 struct samr_DomInfo6 *info6,
1904 struct samr_DomInfo7 *info7,
1905 struct samr_DomInfo12 *info12)
1907 NTSTATUS status;
1908 union samr_DomainInfo *dom_info = NULL;
1910 if (info1) {
1911 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1912 domain_handle,
1914 &dom_info);
1915 NT_STATUS_NOT_OK_RETURN(status);
1917 *info1 = dom_info->info1;
1920 if (info3) {
1921 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1922 domain_handle,
1924 &dom_info);
1925 NT_STATUS_NOT_OK_RETURN(status);
1927 *info3 = dom_info->info3;
1930 if (info5) {
1931 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1932 domain_handle,
1934 &dom_info);
1935 NT_STATUS_NOT_OK_RETURN(status);
1937 *info5 = dom_info->info5;
1940 if (info6) {
1941 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1942 domain_handle,
1944 &dom_info);
1945 NT_STATUS_NOT_OK_RETURN(status);
1947 *info6 = dom_info->info6;
1950 if (info7) {
1951 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1952 domain_handle,
1954 &dom_info);
1955 NT_STATUS_NOT_OK_RETURN(status);
1957 *info7 = dom_info->info7;
1960 if (info12) {
1961 status = rpccli_samr_QueryDomainInfo2(pipe_cli, mem_ctx,
1962 domain_handle,
1964 &dom_info);
1965 NT_STATUS_NOT_OK_RETURN(status);
1967 *info12 = dom_info->info12;
1970 return NT_STATUS_OK;
1973 /****************************************************************
1974 ****************************************************************/
1976 static NTSTATUS query_USER_MODALS_INFO_0(TALLOC_CTX *mem_ctx,
1977 struct rpc_pipe_client *pipe_cli,
1978 struct policy_handle *domain_handle,
1979 struct USER_MODALS_INFO_0 *info0)
1981 NTSTATUS status;
1982 struct samr_DomInfo1 dom_info1;
1983 struct samr_DomInfo3 dom_info3;
1985 ZERO_STRUCTP(info0);
1987 status = query_USER_MODALS_INFO_rpc(mem_ctx,
1988 pipe_cli,
1989 domain_handle,
1990 &dom_info1,
1991 &dom_info3,
1992 NULL,
1993 NULL,
1994 NULL,
1995 NULL);
1996 NT_STATUS_NOT_OK_RETURN(status);
1998 info0->usrmod0_min_passwd_len =
1999 dom_info1.min_password_length;
2000 info0->usrmod0_max_passwd_age =
2001 nt_time_to_unix_abs((NTTIME *)&dom_info1.max_password_age);
2002 info0->usrmod0_min_passwd_age =
2003 nt_time_to_unix_abs((NTTIME *)&dom_info1.min_password_age);
2004 info0->usrmod0_password_hist_len =
2005 dom_info1.password_history_length;
2007 info0->usrmod0_force_logoff =
2008 nt_time_to_unix_abs(&dom_info3.force_logoff_time);
2010 return NT_STATUS_OK;
2013 /****************************************************************
2014 ****************************************************************/
2016 static NTSTATUS query_USER_MODALS_INFO_1(TALLOC_CTX *mem_ctx,
2017 struct rpc_pipe_client *pipe_cli,
2018 struct policy_handle *domain_handle,
2019 struct USER_MODALS_INFO_1 *info1)
2021 NTSTATUS status;
2022 struct samr_DomInfo6 dom_info6;
2023 struct samr_DomInfo7 dom_info7;
2025 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2026 pipe_cli,
2027 domain_handle,
2028 NULL,
2029 NULL,
2030 NULL,
2031 &dom_info6,
2032 &dom_info7,
2033 NULL);
2034 NT_STATUS_NOT_OK_RETURN(status);
2036 info1->usrmod1_primary =
2037 talloc_strdup(mem_ctx, dom_info6.primary.string);
2039 info1->usrmod1_role = dom_info7.role;
2041 return NT_STATUS_OK;
2044 /****************************************************************
2045 ****************************************************************/
2047 static NTSTATUS query_USER_MODALS_INFO_2(TALLOC_CTX *mem_ctx,
2048 struct rpc_pipe_client *pipe_cli,
2049 struct policy_handle *domain_handle,
2050 struct dom_sid *domain_sid,
2051 struct USER_MODALS_INFO_2 *info2)
2053 NTSTATUS status;
2054 struct samr_DomInfo5 dom_info5;
2056 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2057 pipe_cli,
2058 domain_handle,
2059 NULL,
2060 NULL,
2061 &dom_info5,
2062 NULL,
2063 NULL,
2064 NULL);
2065 NT_STATUS_NOT_OK_RETURN(status);
2067 info2->usrmod2_domain_name =
2068 talloc_strdup(mem_ctx, dom_info5.domain_name.string);
2069 info2->usrmod2_domain_id =
2070 (struct domsid *)dom_sid_dup(mem_ctx, domain_sid);
2072 NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_name);
2073 NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_id);
2075 return NT_STATUS_OK;
2078 /****************************************************************
2079 ****************************************************************/
2081 static NTSTATUS query_USER_MODALS_INFO_3(TALLOC_CTX *mem_ctx,
2082 struct rpc_pipe_client *pipe_cli,
2083 struct policy_handle *domain_handle,
2084 struct USER_MODALS_INFO_3 *info3)
2086 NTSTATUS status;
2087 struct samr_DomInfo12 dom_info12;
2089 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2090 pipe_cli,
2091 domain_handle,
2092 NULL,
2093 NULL,
2094 NULL,
2095 NULL,
2096 NULL,
2097 &dom_info12);
2098 NT_STATUS_NOT_OK_RETURN(status);
2100 info3->usrmod3_lockout_duration =
2101 nt_time_to_unix_abs(&dom_info12.lockout_duration);
2102 info3->usrmod3_lockout_observation_window =
2103 nt_time_to_unix_abs(&dom_info12.lockout_window);
2104 info3->usrmod3_lockout_threshold =
2105 dom_info12.lockout_threshold;
2107 return NT_STATUS_OK;
2110 /****************************************************************
2111 ****************************************************************/
2113 static NTSTATUS query_USER_MODALS_INFO_to_buffer(TALLOC_CTX *mem_ctx,
2114 struct rpc_pipe_client *pipe_cli,
2115 uint32_t level,
2116 struct policy_handle *domain_handle,
2117 struct dom_sid *domain_sid,
2118 uint8_t **buffer)
2120 NTSTATUS status;
2122 struct USER_MODALS_INFO_0 info0;
2123 struct USER_MODALS_INFO_1 info1;
2124 struct USER_MODALS_INFO_2 info2;
2125 struct USER_MODALS_INFO_3 info3;
2127 if (!buffer) {
2128 return ERROR_INSUFFICIENT_BUFFER;
2131 switch (level) {
2132 case 0:
2133 status = query_USER_MODALS_INFO_0(mem_ctx,
2134 pipe_cli,
2135 domain_handle,
2136 &info0);
2137 NT_STATUS_NOT_OK_RETURN(status);
2139 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0,
2140 sizeof(info0));
2141 break;
2143 case 1:
2144 status = query_USER_MODALS_INFO_1(mem_ctx,
2145 pipe_cli,
2146 domain_handle,
2147 &info1);
2148 NT_STATUS_NOT_OK_RETURN(status);
2150 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1,
2151 sizeof(info1));
2152 break;
2153 case 2:
2154 status = query_USER_MODALS_INFO_2(mem_ctx,
2155 pipe_cli,
2156 domain_handle,
2157 domain_sid,
2158 &info2);
2159 NT_STATUS_NOT_OK_RETURN(status);
2161 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2,
2162 sizeof(info2));
2163 break;
2164 case 3:
2165 status = query_USER_MODALS_INFO_3(mem_ctx,
2166 pipe_cli,
2167 domain_handle,
2168 &info3);
2169 NT_STATUS_NOT_OK_RETURN(status);
2171 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3,
2172 sizeof(info3));
2173 break;
2174 default:
2175 break;
2178 NT_STATUS_HAVE_NO_MEMORY(*buffer);
2180 return NT_STATUS_OK;
2183 /****************************************************************
2184 ****************************************************************/
2186 WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx,
2187 struct NetUserModalsGet *r)
2189 struct rpc_pipe_client *pipe_cli = NULL;
2190 NTSTATUS status;
2191 WERROR werr;
2193 struct policy_handle connect_handle, domain_handle;
2194 struct dom_sid2 *domain_sid = NULL;
2195 uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2197 ZERO_STRUCT(connect_handle);
2198 ZERO_STRUCT(domain_handle);
2200 if (!r->out.buffer) {
2201 return WERR_INVALID_PARAM;
2204 switch (r->in.level) {
2205 case 0:
2206 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2207 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2208 break;
2209 case 1:
2210 case 2:
2211 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2212 break;
2213 case 3:
2214 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1;
2215 break;
2216 default:
2217 werr = WERR_UNKNOWN_LEVEL;
2218 goto done;
2221 werr = libnetapi_open_pipe(ctx, r->in.server_name,
2222 &ndr_table_samr.syntax_id,
2223 &pipe_cli);
2224 if (!W_ERROR_IS_OK(werr)) {
2225 goto done;
2228 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2229 SAMR_ACCESS_ENUM_DOMAINS |
2230 SAMR_ACCESS_LOOKUP_DOMAIN,
2231 access_mask,
2232 &connect_handle,
2233 &domain_handle,
2234 &domain_sid);
2235 if (!W_ERROR_IS_OK(werr)) {
2236 goto done;
2239 /* 0: 1 + 3 */
2240 /* 1: 6 + 7 */
2241 /* 2: 5 */
2242 /* 3: 12 (DomainInfo2) */
2244 status = query_USER_MODALS_INFO_to_buffer(ctx,
2245 pipe_cli,
2246 r->in.level,
2247 &domain_handle,
2248 domain_sid,
2249 r->out.buffer);
2250 if (!NT_STATUS_IS_OK(status)) {
2251 werr = ntstatus_to_werror(status);
2252 goto done;
2255 done:
2256 if (ctx->disable_policy_handle_cache) {
2257 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2258 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2261 return werr;
2264 /****************************************************************
2265 ****************************************************************/
2267 WERROR NetUserModalsGet_l(struct libnetapi_ctx *ctx,
2268 struct NetUserModalsGet *r)
2270 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsGet);
2273 /****************************************************************
2274 ****************************************************************/
2276 static NTSTATUS set_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
2277 struct rpc_pipe_client *pipe_cli,
2278 struct policy_handle *domain_handle,
2279 struct samr_DomInfo1 *info1,
2280 struct samr_DomInfo3 *info3,
2281 struct samr_DomInfo12 *info12)
2283 NTSTATUS status;
2284 union samr_DomainInfo dom_info;
2286 if (info1) {
2288 ZERO_STRUCT(dom_info);
2290 dom_info.info1 = *info1;
2292 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2293 domain_handle,
2295 &dom_info);
2296 NT_STATUS_NOT_OK_RETURN(status);
2299 if (info3) {
2301 ZERO_STRUCT(dom_info);
2303 dom_info.info3 = *info3;
2305 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2306 domain_handle,
2308 &dom_info);
2310 NT_STATUS_NOT_OK_RETURN(status);
2313 if (info12) {
2315 ZERO_STRUCT(dom_info);
2317 dom_info.info12 = *info12;
2319 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2320 domain_handle,
2322 &dom_info);
2324 NT_STATUS_NOT_OK_RETURN(status);
2327 return NT_STATUS_OK;
2330 /****************************************************************
2331 ****************************************************************/
2333 static NTSTATUS set_USER_MODALS_INFO_0_buffer(TALLOC_CTX *mem_ctx,
2334 struct rpc_pipe_client *pipe_cli,
2335 struct policy_handle *domain_handle,
2336 struct USER_MODALS_INFO_0 *info0)
2338 NTSTATUS status;
2339 struct samr_DomInfo1 dom_info_1;
2340 struct samr_DomInfo3 dom_info_3;
2342 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2343 pipe_cli,
2344 domain_handle,
2345 &dom_info_1,
2346 &dom_info_3,
2347 NULL,
2348 NULL,
2349 NULL,
2350 NULL);
2351 NT_STATUS_NOT_OK_RETURN(status);
2353 dom_info_1.min_password_length =
2354 info0->usrmod0_min_passwd_len;
2355 dom_info_1.password_history_length =
2356 info0->usrmod0_password_hist_len;
2358 unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2359 info0->usrmod0_max_passwd_age);
2360 unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2361 info0->usrmod0_min_passwd_age);
2363 unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2364 info0->usrmod0_force_logoff);
2366 return set_USER_MODALS_INFO_rpc(mem_ctx,
2367 pipe_cli,
2368 domain_handle,
2369 &dom_info_1,
2370 &dom_info_3,
2371 NULL);
2374 /****************************************************************
2375 ****************************************************************/
2377 static NTSTATUS set_USER_MODALS_INFO_3_buffer(TALLOC_CTX *mem_ctx,
2378 struct rpc_pipe_client *pipe_cli,
2379 struct policy_handle *domain_handle,
2380 struct USER_MODALS_INFO_3 *info3)
2382 NTSTATUS status;
2383 struct samr_DomInfo12 dom_info_12;
2385 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2386 pipe_cli,
2387 domain_handle,
2388 NULL,
2389 NULL,
2390 NULL,
2391 NULL,
2392 NULL,
2393 &dom_info_12);
2394 NT_STATUS_NOT_OK_RETURN(status);
2396 unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_duration,
2397 info3->usrmod3_lockout_duration);
2398 unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_window,
2399 info3->usrmod3_lockout_observation_window);
2400 dom_info_12.lockout_threshold = info3->usrmod3_lockout_threshold;
2402 return set_USER_MODALS_INFO_rpc(mem_ctx,
2403 pipe_cli,
2404 domain_handle,
2405 NULL,
2406 NULL,
2407 &dom_info_12);
2410 /****************************************************************
2411 ****************************************************************/
2413 static NTSTATUS set_USER_MODALS_INFO_1001_buffer(TALLOC_CTX *mem_ctx,
2414 struct rpc_pipe_client *pipe_cli,
2415 struct policy_handle *domain_handle,
2416 struct USER_MODALS_INFO_1001 *info1001)
2418 NTSTATUS status;
2419 struct samr_DomInfo1 dom_info_1;
2421 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2422 pipe_cli,
2423 domain_handle,
2424 &dom_info_1,
2425 NULL,
2426 NULL,
2427 NULL,
2428 NULL,
2429 NULL);
2430 NT_STATUS_NOT_OK_RETURN(status);
2432 dom_info_1.min_password_length =
2433 info1001->usrmod1001_min_passwd_len;
2435 return set_USER_MODALS_INFO_rpc(mem_ctx,
2436 pipe_cli,
2437 domain_handle,
2438 &dom_info_1,
2439 NULL,
2440 NULL);
2443 /****************************************************************
2444 ****************************************************************/
2446 static NTSTATUS set_USER_MODALS_INFO_1002_buffer(TALLOC_CTX *mem_ctx,
2447 struct rpc_pipe_client *pipe_cli,
2448 struct policy_handle *domain_handle,
2449 struct USER_MODALS_INFO_1002 *info1002)
2451 NTSTATUS status;
2452 struct samr_DomInfo1 dom_info_1;
2454 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2455 pipe_cli,
2456 domain_handle,
2457 &dom_info_1,
2458 NULL,
2459 NULL,
2460 NULL,
2461 NULL,
2462 NULL);
2463 NT_STATUS_NOT_OK_RETURN(status);
2465 unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2466 info1002->usrmod1002_max_passwd_age);
2468 return set_USER_MODALS_INFO_rpc(mem_ctx,
2469 pipe_cli,
2470 domain_handle,
2471 &dom_info_1,
2472 NULL,
2473 NULL);
2476 /****************************************************************
2477 ****************************************************************/
2479 static NTSTATUS set_USER_MODALS_INFO_1003_buffer(TALLOC_CTX *mem_ctx,
2480 struct rpc_pipe_client *pipe_cli,
2481 struct policy_handle *domain_handle,
2482 struct USER_MODALS_INFO_1003 *info1003)
2484 NTSTATUS status;
2485 struct samr_DomInfo1 dom_info_1;
2487 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2488 pipe_cli,
2489 domain_handle,
2490 &dom_info_1,
2491 NULL,
2492 NULL,
2493 NULL,
2494 NULL,
2495 NULL);
2496 NT_STATUS_NOT_OK_RETURN(status);
2498 unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2499 info1003->usrmod1003_min_passwd_age);
2501 return set_USER_MODALS_INFO_rpc(mem_ctx,
2502 pipe_cli,
2503 domain_handle,
2504 &dom_info_1,
2505 NULL,
2506 NULL);
2509 /****************************************************************
2510 ****************************************************************/
2512 static NTSTATUS set_USER_MODALS_INFO_1004_buffer(TALLOC_CTX *mem_ctx,
2513 struct rpc_pipe_client *pipe_cli,
2514 struct policy_handle *domain_handle,
2515 struct USER_MODALS_INFO_1004 *info1004)
2517 NTSTATUS status;
2518 struct samr_DomInfo3 dom_info_3;
2520 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2521 pipe_cli,
2522 domain_handle,
2523 NULL,
2524 &dom_info_3,
2525 NULL,
2526 NULL,
2527 NULL,
2528 NULL);
2529 NT_STATUS_NOT_OK_RETURN(status);
2531 unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2532 info1004->usrmod1004_force_logoff);
2534 return set_USER_MODALS_INFO_rpc(mem_ctx,
2535 pipe_cli,
2536 domain_handle,
2537 NULL,
2538 &dom_info_3,
2539 NULL);
2542 /****************************************************************
2543 ****************************************************************/
2545 static NTSTATUS set_USER_MODALS_INFO_1005_buffer(TALLOC_CTX *mem_ctx,
2546 struct rpc_pipe_client *pipe_cli,
2547 struct policy_handle *domain_handle,
2548 struct USER_MODALS_INFO_1005 *info1005)
2550 NTSTATUS status;
2551 struct samr_DomInfo1 dom_info_1;
2553 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2554 pipe_cli,
2555 domain_handle,
2556 &dom_info_1,
2557 NULL,
2558 NULL,
2559 NULL,
2560 NULL,
2561 NULL);
2562 NT_STATUS_NOT_OK_RETURN(status);
2564 dom_info_1.password_history_length =
2565 info1005->usrmod1005_password_hist_len;
2567 return set_USER_MODALS_INFO_rpc(mem_ctx,
2568 pipe_cli,
2569 domain_handle,
2570 &dom_info_1,
2571 NULL,
2572 NULL);
2575 /****************************************************************
2576 ****************************************************************/
2578 static NTSTATUS set_USER_MODALS_INFO_buffer(TALLOC_CTX *mem_ctx,
2579 struct rpc_pipe_client *pipe_cli,
2580 uint32_t level,
2581 struct policy_handle *domain_handle,
2582 struct dom_sid *domain_sid,
2583 uint8_t *buffer)
2585 struct USER_MODALS_INFO_0 *info0;
2586 struct USER_MODALS_INFO_3 *info3;
2587 struct USER_MODALS_INFO_1001 *info1001;
2588 struct USER_MODALS_INFO_1002 *info1002;
2589 struct USER_MODALS_INFO_1003 *info1003;
2590 struct USER_MODALS_INFO_1004 *info1004;
2591 struct USER_MODALS_INFO_1005 *info1005;
2593 if (!buffer) {
2594 return ERROR_INSUFFICIENT_BUFFER;
2597 switch (level) {
2598 case 0:
2599 info0 = (struct USER_MODALS_INFO_0 *)buffer;
2600 return set_USER_MODALS_INFO_0_buffer(mem_ctx,
2601 pipe_cli,
2602 domain_handle,
2603 info0);
2604 case 3:
2605 info3 = (struct USER_MODALS_INFO_3 *)buffer;
2606 return set_USER_MODALS_INFO_3_buffer(mem_ctx,
2607 pipe_cli,
2608 domain_handle,
2609 info3);
2610 case 1001:
2611 info1001 = (struct USER_MODALS_INFO_1001 *)buffer;
2612 return set_USER_MODALS_INFO_1001_buffer(mem_ctx,
2613 pipe_cli,
2614 domain_handle,
2615 info1001);
2616 case 1002:
2617 info1002 = (struct USER_MODALS_INFO_1002 *)buffer;
2618 return set_USER_MODALS_INFO_1002_buffer(mem_ctx,
2619 pipe_cli,
2620 domain_handle,
2621 info1002);
2622 case 1003:
2623 info1003 = (struct USER_MODALS_INFO_1003 *)buffer;
2624 return set_USER_MODALS_INFO_1003_buffer(mem_ctx,
2625 pipe_cli,
2626 domain_handle,
2627 info1003);
2628 case 1004:
2629 info1004 = (struct USER_MODALS_INFO_1004 *)buffer;
2630 return set_USER_MODALS_INFO_1004_buffer(mem_ctx,
2631 pipe_cli,
2632 domain_handle,
2633 info1004);
2634 case 1005:
2635 info1005 = (struct USER_MODALS_INFO_1005 *)buffer;
2636 return set_USER_MODALS_INFO_1005_buffer(mem_ctx,
2637 pipe_cli,
2638 domain_handle,
2639 info1005);
2641 default:
2642 break;
2645 return NT_STATUS_OK;
2648 /****************************************************************
2649 ****************************************************************/
2651 WERROR NetUserModalsSet_r(struct libnetapi_ctx *ctx,
2652 struct NetUserModalsSet *r)
2654 struct rpc_pipe_client *pipe_cli = NULL;
2655 NTSTATUS status;
2656 WERROR werr;
2658 struct policy_handle connect_handle, domain_handle;
2659 struct dom_sid2 *domain_sid = NULL;
2660 uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2662 ZERO_STRUCT(connect_handle);
2663 ZERO_STRUCT(domain_handle);
2665 if (!r->in.buffer) {
2666 return WERR_INVALID_PARAM;
2669 switch (r->in.level) {
2670 case 0:
2671 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2672 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2673 SAMR_DOMAIN_ACCESS_SET_INFO_1 |
2674 SAMR_DOMAIN_ACCESS_SET_INFO_2;
2675 break;
2676 case 3:
2677 case 1001:
2678 case 1002:
2679 case 1003:
2680 case 1005:
2681 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2682 SAMR_DOMAIN_ACCESS_SET_INFO_1;
2683 break;
2684 case 1004:
2685 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2686 SAMR_DOMAIN_ACCESS_SET_INFO_2;
2687 break;
2688 case 1:
2689 case 2:
2690 case 1006:
2691 case 1007:
2692 werr = WERR_NOT_SUPPORTED;
2693 break;
2694 default:
2695 werr = WERR_UNKNOWN_LEVEL;
2696 goto done;
2699 werr = libnetapi_open_pipe(ctx, r->in.server_name,
2700 &ndr_table_samr.syntax_id,
2701 &pipe_cli);
2702 if (!W_ERROR_IS_OK(werr)) {
2703 goto done;
2706 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2707 SAMR_ACCESS_ENUM_DOMAINS |
2708 SAMR_ACCESS_LOOKUP_DOMAIN,
2709 access_mask,
2710 &connect_handle,
2711 &domain_handle,
2712 &domain_sid);
2713 if (!W_ERROR_IS_OK(werr)) {
2714 goto done;
2717 status = set_USER_MODALS_INFO_buffer(ctx,
2718 pipe_cli,
2719 r->in.level,
2720 &domain_handle,
2721 domain_sid,
2722 r->in.buffer);
2723 if (!NT_STATUS_IS_OK(status)) {
2724 werr = ntstatus_to_werror(status);
2725 goto done;
2728 done:
2729 if (ctx->disable_policy_handle_cache) {
2730 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2731 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2734 return werr;
2737 /****************************************************************
2738 ****************************************************************/
2740 WERROR NetUserModalsSet_l(struct libnetapi_ctx *ctx,
2741 struct NetUserModalsSet *r)
2743 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsSet);
2746 /****************************************************************
2747 ****************************************************************/
2749 NTSTATUS add_GROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
2750 uint32_t level,
2751 const char *group_name,
2752 uint32_t attributes,
2753 uint8_t **buffer,
2754 uint32_t *num_entries)
2756 struct GROUP_USERS_INFO_0 u0;
2757 struct GROUP_USERS_INFO_1 u1;
2759 switch (level) {
2760 case 0:
2761 if (group_name) {
2762 u0.grui0_name = talloc_strdup(mem_ctx, group_name);
2763 NT_STATUS_HAVE_NO_MEMORY(u0.grui0_name);
2764 } else {
2765 u0.grui0_name = NULL;
2768 ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_0, u0,
2769 (struct GROUP_USERS_INFO_0 **)buffer, num_entries);
2770 break;
2771 case 1:
2772 if (group_name) {
2773 u1.grui1_name = talloc_strdup(mem_ctx, group_name);
2774 NT_STATUS_HAVE_NO_MEMORY(u1.grui1_name);
2775 } else {
2776 u1.grui1_name = NULL;
2779 u1.grui1_attributes = attributes;
2781 ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_1, u1,
2782 (struct GROUP_USERS_INFO_1 **)buffer, num_entries);
2783 break;
2784 default:
2785 return NT_STATUS_INVALID_INFO_CLASS;
2788 return NT_STATUS_OK;
2791 /****************************************************************
2792 ****************************************************************/
2794 WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
2795 struct NetUserGetGroups *r)
2797 struct rpc_pipe_client *pipe_cli = NULL;
2798 struct policy_handle connect_handle, domain_handle, user_handle;
2799 struct lsa_String lsa_account_name;
2800 struct dom_sid2 *domain_sid = NULL;
2801 struct samr_Ids user_rids, name_types;
2802 struct samr_RidWithAttributeArray *rid_array = NULL;
2803 struct lsa_Strings names;
2804 struct samr_Ids types;
2805 uint32_t *rids = NULL;
2807 int i;
2808 uint32_t entries_read = 0;
2810 NTSTATUS status = NT_STATUS_OK;
2811 WERROR werr;
2813 ZERO_STRUCT(connect_handle);
2814 ZERO_STRUCT(domain_handle);
2816 if (!r->out.buffer) {
2817 return WERR_INVALID_PARAM;
2820 *r->out.buffer = NULL;
2821 *r->out.entries_read = 0;
2822 *r->out.total_entries = 0;
2824 switch (r->in.level) {
2825 case 0:
2826 case 1:
2827 break;
2828 default:
2829 return WERR_UNKNOWN_LEVEL;
2832 werr = libnetapi_open_pipe(ctx, r->in.server_name,
2833 &ndr_table_samr.syntax_id,
2834 &pipe_cli);
2835 if (!W_ERROR_IS_OK(werr)) {
2836 goto done;
2839 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2840 SAMR_ACCESS_ENUM_DOMAINS |
2841 SAMR_ACCESS_LOOKUP_DOMAIN,
2842 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2843 &connect_handle,
2844 &domain_handle,
2845 &domain_sid);
2846 if (!W_ERROR_IS_OK(werr)) {
2847 goto done;
2850 init_lsa_String(&lsa_account_name, r->in.user_name);
2852 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
2853 &domain_handle,
2855 &lsa_account_name,
2856 &user_rids,
2857 &name_types);
2858 if (!NT_STATUS_IS_OK(status)) {
2859 werr = ntstatus_to_werror(status);
2860 goto done;
2863 status = rpccli_samr_OpenUser(pipe_cli, talloc_tos(),
2864 &domain_handle,
2865 SAMR_USER_ACCESS_GET_GROUPS,
2866 user_rids.ids[0],
2867 &user_handle);
2868 if (!NT_STATUS_IS_OK(status)) {
2869 werr = ntstatus_to_werror(status);
2870 goto done;
2873 status = rpccli_samr_GetGroupsForUser(pipe_cli, talloc_tos(),
2874 &user_handle,
2875 &rid_array);
2876 if (!NT_STATUS_IS_OK(status)) {
2877 werr = ntstatus_to_werror(status);
2878 goto done;
2881 rids = talloc_array(ctx, uint32_t, rid_array->count);
2882 if (!rids) {
2883 werr = WERR_NOMEM;
2884 goto done;
2887 for (i=0; i < rid_array->count; i++) {
2888 rids[i] = rid_array->rids[i].rid;
2891 status = rpccli_samr_LookupRids(pipe_cli, talloc_tos(),
2892 &domain_handle,
2893 rid_array->count,
2894 rids,
2895 &names,
2896 &types);
2897 if (!NT_STATUS_IS_OK(status) &&
2898 !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
2899 werr = ntstatus_to_werror(status);
2900 goto done;
2903 for (i=0; i < names.count; i++) {
2904 status = add_GROUP_USERS_INFO_X_buffer(ctx,
2905 r->in.level,
2906 names.names[i].string,
2907 rid_array->rids[i].attributes,
2908 r->out.buffer,
2909 &entries_read);
2910 if (!NT_STATUS_IS_OK(status)) {
2911 werr = ntstatus_to_werror(status);
2912 goto done;
2916 *r->out.entries_read = entries_read;
2917 *r->out.total_entries = entries_read;
2919 done:
2920 if (ctx->disable_policy_handle_cache) {
2921 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2922 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2925 return werr;
2928 /****************************************************************
2929 ****************************************************************/
2931 WERROR NetUserGetGroups_l(struct libnetapi_ctx *ctx,
2932 struct NetUserGetGroups *r)
2934 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetGroups);
2937 /****************************************************************
2938 ****************************************************************/
2940 WERROR NetUserSetGroups_r(struct libnetapi_ctx *ctx,
2941 struct NetUserSetGroups *r)
2943 struct rpc_pipe_client *pipe_cli = NULL;
2944 struct policy_handle connect_handle, domain_handle, user_handle, group_handle;
2945 struct lsa_String lsa_account_name;
2946 struct dom_sid2 *domain_sid = NULL;
2947 struct samr_Ids user_rids, name_types;
2948 struct samr_Ids group_rids;
2949 struct samr_RidWithAttributeArray *rid_array = NULL;
2950 struct lsa_String *lsa_names = NULL;
2952 uint32_t *add_rids = NULL;
2953 uint32_t *del_rids = NULL;
2954 size_t num_add_rids = 0;
2955 size_t num_del_rids = 0;
2957 uint32_t *member_rids = NULL;
2958 size_t num_member_rids = 0;
2960 struct GROUP_USERS_INFO_0 *i0 = NULL;
2961 struct GROUP_USERS_INFO_1 *i1 = NULL;
2963 int i, k;
2965 NTSTATUS status = NT_STATUS_OK;
2966 WERROR werr;
2968 ZERO_STRUCT(connect_handle);
2969 ZERO_STRUCT(domain_handle);
2971 if (!r->in.buffer) {
2972 return WERR_INVALID_PARAM;
2975 switch (r->in.level) {
2976 case 0:
2977 case 1:
2978 break;
2979 default:
2980 return WERR_UNKNOWN_LEVEL;
2983 werr = libnetapi_open_pipe(ctx, r->in.server_name,
2984 &ndr_table_samr.syntax_id,
2985 &pipe_cli);
2986 if (!W_ERROR_IS_OK(werr)) {
2987 goto done;
2990 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2991 SAMR_ACCESS_ENUM_DOMAINS |
2992 SAMR_ACCESS_LOOKUP_DOMAIN,
2993 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2994 &connect_handle,
2995 &domain_handle,
2996 &domain_sid);
2997 if (!W_ERROR_IS_OK(werr)) {
2998 goto done;
3001 init_lsa_String(&lsa_account_name, r->in.user_name);
3003 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
3004 &domain_handle,
3006 &lsa_account_name,
3007 &user_rids,
3008 &name_types);
3009 if (!NT_STATUS_IS_OK(status)) {
3010 werr = ntstatus_to_werror(status);
3011 goto done;
3014 status = rpccli_samr_OpenUser(pipe_cli, talloc_tos(),
3015 &domain_handle,
3016 SAMR_USER_ACCESS_GET_GROUPS,
3017 user_rids.ids[0],
3018 &user_handle);
3019 if (!NT_STATUS_IS_OK(status)) {
3020 werr = ntstatus_to_werror(status);
3021 goto done;
3024 switch (r->in.level) {
3025 case 0:
3026 i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
3027 break;
3028 case 1:
3029 i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
3030 break;
3033 lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
3034 if (!lsa_names) {
3035 werr = WERR_NOMEM;
3036 goto done;
3039 for (i=0; i < r->in.num_entries; i++) {
3041 switch (r->in.level) {
3042 case 0:
3043 init_lsa_String(&lsa_names[i], i0->grui0_name);
3044 i0++;
3045 break;
3046 case 1:
3047 init_lsa_String(&lsa_names[i], i1->grui1_name);
3048 i1++;
3049 break;
3053 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
3054 &domain_handle,
3055 r->in.num_entries,
3056 lsa_names,
3057 &group_rids,
3058 &name_types);
3059 if (!NT_STATUS_IS_OK(status)) {
3060 werr = ntstatus_to_werror(status);
3061 goto done;
3064 member_rids = group_rids.ids;
3065 num_member_rids = group_rids.count;
3067 status = rpccli_samr_GetGroupsForUser(pipe_cli, talloc_tos(),
3068 &user_handle,
3069 &rid_array);
3070 if (!NT_STATUS_IS_OK(status)) {
3071 werr = ntstatus_to_werror(status);
3072 goto done;
3075 /* add list */
3077 for (i=0; i < r->in.num_entries; i++) {
3078 bool already_member = false;
3079 for (k=0; k < rid_array->count; k++) {
3080 if (member_rids[i] == rid_array->rids[k].rid) {
3081 already_member = true;
3082 break;
3085 if (!already_member) {
3086 if (!add_rid_to_array_unique(ctx,
3087 member_rids[i],
3088 &add_rids, &num_add_rids)) {
3089 werr = WERR_GENERAL_FAILURE;
3090 goto done;
3095 /* del list */
3097 for (k=0; k < rid_array->count; k++) {
3098 bool keep_member = false;
3099 for (i=0; i < r->in.num_entries; i++) {
3100 if (member_rids[i] == rid_array->rids[k].rid) {
3101 keep_member = true;
3102 break;
3105 if (!keep_member) {
3106 if (!add_rid_to_array_unique(ctx,
3107 rid_array->rids[k].rid,
3108 &del_rids, &num_del_rids)) {
3109 werr = WERR_GENERAL_FAILURE;
3110 goto done;
3115 /* add list */
3117 for (i=0; i < num_add_rids; i++) {
3118 status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(),
3119 &domain_handle,
3120 SAMR_GROUP_ACCESS_ADD_MEMBER,
3121 add_rids[i],
3122 &group_handle);
3123 if (!NT_STATUS_IS_OK(status)) {
3124 werr = ntstatus_to_werror(status);
3125 goto done;
3128 status = rpccli_samr_AddGroupMember(pipe_cli, talloc_tos(),
3129 &group_handle,
3130 user_rids.ids[0],
3131 7 /* ? */);
3132 if (!NT_STATUS_IS_OK(status)) {
3133 werr = ntstatus_to_werror(status);
3134 goto done;
3137 if (is_valid_policy_hnd(&group_handle)) {
3138 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle);
3142 /* del list */
3144 for (i=0; i < num_del_rids; i++) {
3145 status = rpccli_samr_OpenGroup(pipe_cli, talloc_tos(),
3146 &domain_handle,
3147 SAMR_GROUP_ACCESS_REMOVE_MEMBER,
3148 del_rids[i],
3149 &group_handle);
3150 if (!NT_STATUS_IS_OK(status)) {
3151 werr = ntstatus_to_werror(status);
3152 goto done;
3155 status = rpccli_samr_DeleteGroupMember(pipe_cli, talloc_tos(),
3156 &group_handle,
3157 user_rids.ids[0]);
3158 if (!NT_STATUS_IS_OK(status)) {
3159 werr = ntstatus_to_werror(status);
3160 goto done;
3163 if (is_valid_policy_hnd(&group_handle)) {
3164 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle);
3168 werr = WERR_OK;
3170 done:
3171 if (is_valid_policy_hnd(&group_handle)) {
3172 rpccli_samr_Close(pipe_cli, talloc_tos(), &group_handle);
3175 if (ctx->disable_policy_handle_cache) {
3176 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3177 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3180 return werr;
3183 /****************************************************************
3184 ****************************************************************/
3186 WERROR NetUserSetGroups_l(struct libnetapi_ctx *ctx,
3187 struct NetUserSetGroups *r)
3189 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetGroups);
3192 /****************************************************************
3193 ****************************************************************/
3195 static NTSTATUS add_LOCALGROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
3196 uint32_t level,
3197 const char *group_name,
3198 uint8_t **buffer,
3199 uint32_t *num_entries)
3201 struct LOCALGROUP_USERS_INFO_0 u0;
3203 switch (level) {
3204 case 0:
3205 u0.lgrui0_name = talloc_strdup(mem_ctx, group_name);
3206 NT_STATUS_HAVE_NO_MEMORY(u0.lgrui0_name);
3208 ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_USERS_INFO_0, u0,
3209 (struct LOCALGROUP_USERS_INFO_0 **)buffer, num_entries);
3210 break;
3211 default:
3212 return NT_STATUS_INVALID_INFO_CLASS;
3215 return NT_STATUS_OK;
3218 /****************************************************************
3219 ****************************************************************/
3221 WERROR NetUserGetLocalGroups_r(struct libnetapi_ctx *ctx,
3222 struct NetUserGetLocalGroups *r)
3224 struct rpc_pipe_client *pipe_cli = NULL;
3225 struct policy_handle connect_handle, domain_handle, user_handle,
3226 builtin_handle;
3227 struct lsa_String lsa_account_name;
3228 struct dom_sid2 *domain_sid = NULL;
3229 struct samr_Ids user_rids, name_types;
3230 struct samr_RidWithAttributeArray *rid_array = NULL;
3231 struct lsa_Strings names;
3232 struct samr_Ids types;
3233 uint32_t *rids = NULL;
3234 size_t num_rids = 0;
3235 struct dom_sid user_sid;
3236 struct lsa_SidArray sid_array;
3237 struct samr_Ids domain_rids;
3238 struct samr_Ids builtin_rids;
3240 int i;
3241 uint32_t entries_read = 0;
3243 NTSTATUS status = NT_STATUS_OK;
3244 WERROR werr;
3246 ZERO_STRUCT(connect_handle);
3247 ZERO_STRUCT(domain_handle);
3249 if (!r->out.buffer) {
3250 return WERR_INVALID_PARAM;
3253 *r->out.buffer = NULL;
3254 *r->out.entries_read = 0;
3255 *r->out.total_entries = 0;
3257 switch (r->in.level) {
3258 case 0:
3259 case 1:
3260 break;
3261 default:
3262 return WERR_UNKNOWN_LEVEL;
3265 werr = libnetapi_open_pipe(ctx, r->in.server_name,
3266 &ndr_table_samr.syntax_id,
3267 &pipe_cli);
3268 if (!W_ERROR_IS_OK(werr)) {
3269 goto done;
3272 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
3273 SAMR_ACCESS_ENUM_DOMAINS |
3274 SAMR_ACCESS_LOOKUP_DOMAIN,
3275 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
3276 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
3277 &connect_handle,
3278 &domain_handle,
3279 &domain_sid);
3280 if (!W_ERROR_IS_OK(werr)) {
3281 goto done;
3284 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
3285 SAMR_ACCESS_ENUM_DOMAINS |
3286 SAMR_ACCESS_LOOKUP_DOMAIN,
3287 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
3288 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
3289 &connect_handle,
3290 &builtin_handle);
3291 if (!W_ERROR_IS_OK(werr)) {
3292 goto done;
3295 init_lsa_String(&lsa_account_name, r->in.user_name);
3297 status = rpccli_samr_LookupNames(pipe_cli, talloc_tos(),
3298 &domain_handle,
3300 &lsa_account_name,
3301 &user_rids,
3302 &name_types);
3303 if (!NT_STATUS_IS_OK(status)) {
3304 werr = ntstatus_to_werror(status);
3305 goto done;
3308 status = rpccli_samr_OpenUser(pipe_cli, talloc_tos(),
3309 &domain_handle,
3310 SAMR_USER_ACCESS_GET_GROUPS,
3311 user_rids.ids[0],
3312 &user_handle);
3313 if (!NT_STATUS_IS_OK(status)) {
3314 werr = ntstatus_to_werror(status);
3315 goto done;
3318 status = rpccli_samr_GetGroupsForUser(pipe_cli, talloc_tos(),
3319 &user_handle,
3320 &rid_array);
3321 if (!NT_STATUS_IS_OK(status)) {
3322 werr = ntstatus_to_werror(status);
3323 goto done;
3326 if (!sid_compose(&user_sid, domain_sid, user_rids.ids[0])) {
3327 werr = WERR_NOMEM;
3328 goto done;
3331 sid_array.num_sids = rid_array->count + 1;
3332 sid_array.sids = TALLOC_ARRAY(ctx, struct lsa_SidPtr, sid_array.num_sids);
3333 if (!sid_array.sids) {
3334 werr = WERR_NOMEM;
3335 goto done;
3338 sid_array.sids[0].sid = dom_sid_dup(ctx, &user_sid);
3339 if (!sid_array.sids[0].sid) {
3340 werr = WERR_NOMEM;
3341 goto done;
3344 for (i=0; i < rid_array->count; i++) {
3345 struct dom_sid sid;
3347 if (!sid_compose(&sid, domain_sid, rid_array->rids[i].rid)) {
3348 werr = WERR_NOMEM;
3349 goto done;
3352 sid_array.sids[i+1].sid = dom_sid_dup(ctx, &sid);
3353 if (!sid_array.sids[i+1].sid) {
3354 werr = WERR_NOMEM;
3355 goto done;
3359 status = rpccli_samr_GetAliasMembership(pipe_cli, talloc_tos(),
3360 &domain_handle,
3361 &sid_array,
3362 &domain_rids);
3363 if (!NT_STATUS_IS_OK(status)) {
3364 werr = ntstatus_to_werror(status);
3365 goto done;
3368 for (i=0; i < domain_rids.count; i++) {
3369 if (!add_rid_to_array_unique(ctx, domain_rids.ids[i],
3370 &rids, &num_rids)) {
3371 werr = WERR_NOMEM;
3372 goto done;
3376 status = rpccli_samr_GetAliasMembership(pipe_cli, talloc_tos(),
3377 &builtin_handle,
3378 &sid_array,
3379 &builtin_rids);
3380 if (!NT_STATUS_IS_OK(status)) {
3381 werr = ntstatus_to_werror(status);
3382 goto done;
3385 for (i=0; i < builtin_rids.count; i++) {
3386 if (!add_rid_to_array_unique(ctx, builtin_rids.ids[i],
3387 &rids, &num_rids)) {
3388 werr = WERR_NOMEM;
3389 goto done;
3393 status = rpccli_samr_LookupRids(pipe_cli, talloc_tos(),
3394 &builtin_handle,
3395 num_rids,
3396 rids,
3397 &names,
3398 &types);
3399 if (!NT_STATUS_IS_OK(status)) {
3400 werr = ntstatus_to_werror(status);
3401 goto done;
3404 for (i=0; i < names.count; i++) {
3405 status = add_LOCALGROUP_USERS_INFO_X_buffer(ctx,
3406 r->in.level,
3407 names.names[i].string,
3408 r->out.buffer,
3409 &entries_read);
3410 if (!NT_STATUS_IS_OK(status)) {
3411 werr = ntstatus_to_werror(status);
3412 goto done;
3416 *r->out.entries_read = entries_read;
3417 *r->out.total_entries = entries_read;
3419 done:
3420 if (ctx->disable_policy_handle_cache) {
3421 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3422 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3425 return werr;
3428 /****************************************************************
3429 ****************************************************************/
3431 WERROR NetUserGetLocalGroups_l(struct libnetapi_ctx *ctx,
3432 struct NetUserGetLocalGroups *r)
3434 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetLocalGroups);