netapi: add info21_to_USER_INFO_4 and support level 4 in NetUserEnum/GetInfo.
[Samba.git] / source / lib / netapi / user.c
blob1584a28be0f2d5c59411bccd02dd4cec2d96b402
1 /*
2 * Unix SMB/CIFS implementation.
3 * NetApi User Support
4 * Copyright (C) Guenther Deschner 2008
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
22 #include "librpc/gen_ndr/libnetapi.h"
23 #include "lib/netapi/netapi.h"
24 #include "lib/netapi/netapi_private.h"
25 #include "lib/netapi/libnetapi.h"
27 /****************************************************************
28 ****************************************************************/
30 static void convert_USER_INFO_X_to_samr_user_info21(struct USER_INFO_X *infoX,
31 struct samr_UserInfo21 *info21)
33 uint32_t fields_present = 0;
34 struct samr_LogonHours zero_logon_hours;
35 struct lsa_BinaryString zero_parameters;
36 NTTIME password_age;
38 ZERO_STRUCTP(info21);
39 ZERO_STRUCT(zero_logon_hours);
40 ZERO_STRUCT(zero_parameters);
42 if (infoX->usriX_flags) {
43 fields_present |= SAMR_FIELD_ACCT_FLAGS;
45 if (infoX->usriX_name) {
46 fields_present |= SAMR_FIELD_ACCOUNT_NAME;
48 if (infoX->usriX_password) {
49 fields_present |= SAMR_FIELD_PASSWORD;
51 if (infoX->usriX_flags) {
52 fields_present |= SAMR_FIELD_ACCT_FLAGS;
54 if (infoX->usriX_name) {
55 fields_present |= SAMR_FIELD_FULL_NAME;
57 if (infoX->usriX_home_dir) {
58 fields_present |= SAMR_FIELD_HOME_DIRECTORY;
60 if (infoX->usriX_script_path) {
61 fields_present |= SAMR_FIELD_LOGON_SCRIPT;
63 if (infoX->usriX_comment) {
64 fields_present |= SAMR_FIELD_DESCRIPTION;
66 if (infoX->usriX_password_age) {
67 fields_present |= SAMR_FIELD_FORCE_PWD_CHANGE;
69 if (infoX->usriX_full_name) {
70 fields_present |= SAMR_FIELD_FULL_NAME;
72 if (infoX->usriX_usr_comment) {
73 fields_present |= SAMR_FIELD_COMMENT;
75 if (infoX->usriX_profile) {
76 fields_present |= SAMR_FIELD_PROFILE_PATH;
78 if (infoX->usriX_home_dir_drive) {
79 fields_present |= SAMR_FIELD_HOME_DRIVE;
81 if (infoX->usriX_primary_group_id) {
82 fields_present |= SAMR_FIELD_PRIMARY_GID;
84 if (infoX->usriX_country_code) {
85 fields_present |= SAMR_FIELD_COUNTRY_CODE;
87 if (infoX->usriX_workstations) {
88 fields_present |= SAMR_FIELD_WORKSTATIONS;
91 unix_to_nt_time_abs(&password_age, infoX->usriX_password_age);
93 /* TODO: infoX->usriX_priv */
94 init_samr_user_info21(info21,
100 password_age,
101 infoX->usriX_name,
102 infoX->usriX_full_name,
103 infoX->usriX_home_dir,
104 infoX->usriX_home_dir_drive,
105 infoX->usriX_script_path,
106 infoX->usriX_profile,
107 infoX->usriX_comment,
108 infoX->usriX_workstations,
109 infoX->usriX_usr_comment,
110 &zero_parameters,
112 infoX->usriX_primary_group_id,
113 infoX->usriX_flags,
114 fields_present,
115 zero_logon_hours,
118 infoX->usriX_country_code,
125 /****************************************************************
126 ****************************************************************/
128 static NTSTATUS construct_USER_INFO_X(uint32_t level,
129 uint8_t *buffer,
130 struct USER_INFO_X *uX)
132 struct USER_INFO_0 *u0 = NULL;
133 struct USER_INFO_1 *u1 = NULL;
134 struct USER_INFO_2 *u2 = NULL;
135 struct USER_INFO_1003 *u1003 = NULL;
136 struct USER_INFO_1006 *u1006 = NULL;
137 struct USER_INFO_1007 *u1007 = NULL;
138 struct USER_INFO_1009 *u1009 = NULL;
139 struct USER_INFO_1011 *u1011 = NULL;
140 struct USER_INFO_1012 *u1012 = NULL;
141 struct USER_INFO_1014 *u1014 = NULL;
142 struct USER_INFO_1024 *u1024 = NULL;
143 struct USER_INFO_1051 *u1051 = NULL;
144 struct USER_INFO_1052 *u1052 = NULL;
145 struct USER_INFO_1053 *u1053 = NULL;
147 if (!buffer || !uX) {
148 return NT_STATUS_INVALID_PARAMETER;
151 ZERO_STRUCTP(uX);
153 switch (level) {
154 case 0:
155 u0 = (struct USER_INFO_0 *)buffer;
156 uX->usriX_name = u0->usri0_name;
157 break;
158 case 1:
159 u1 = (struct USER_INFO_1 *)buffer;
160 uX->usriX_name = u1->usri1_name;
161 uX->usriX_password = u1->usri1_password;
162 uX->usriX_password_age = u1->usri1_password_age;
163 uX->usriX_priv = u1->usri1_priv;
164 uX->usriX_home_dir = u1->usri1_home_dir;
165 uX->usriX_comment = u1->usri1_comment;
166 uX->usriX_flags = u1->usri1_flags;
167 uX->usriX_script_path = u1->usri1_script_path;
168 break;
169 case 2:
170 u2 = (struct USER_INFO_2 *)buffer;
171 uX->usriX_name = u2->usri2_name;
172 uX->usriX_password = u2->usri2_password;
173 uX->usriX_password_age = u2->usri2_password_age;
174 uX->usriX_priv = u2->usri2_priv;
175 uX->usriX_home_dir = u2->usri2_home_dir;
176 uX->usriX_comment = u2->usri2_comment;
177 uX->usriX_flags = u2->usri2_flags;
178 uX->usriX_script_path = u2->usri2_script_path;
179 uX->usriX_auth_flags = u2->usri2_auth_flags;
180 uX->usriX_full_name = u2->usri2_full_name;
181 uX->usriX_usr_comment = u2->usri2_usr_comment;
182 uX->usriX_parms = u2->usri2_parms;
183 uX->usriX_workstations = u2->usri2_workstations;
184 uX->usriX_last_logon = u2->usri2_last_logon;
185 uX->usriX_last_logoff = u2->usri2_last_logoff;
186 uX->usriX_acct_expires = u2->usri2_acct_expires;
187 uX->usriX_max_storage = u2->usri2_max_storage;
188 uX->usriX_units_per_week= u2->usri2_units_per_week;
189 uX->usriX_logon_hours = u2->usri2_logon_hours;
190 uX->usriX_bad_pw_count = u2->usri2_bad_pw_count;
191 uX->usriX_num_logons = u2->usri2_num_logons;
192 uX->usriX_logon_server = u2->usri2_logon_server;
193 uX->usriX_country_code = u2->usri2_country_code;
194 uX->usriX_code_page = u2->usri2_code_page;
195 break;
196 case 1003:
197 u1003 = (struct USER_INFO_1003 *)buffer;
198 uX->usriX_password = u1003->usri1003_password;
199 break;
200 case 1006:
201 u1006 = (struct USER_INFO_1006 *)buffer;
202 uX->usriX_home_dir = u1006->usri1006_home_dir;
203 break;
204 case 1007:
205 u1007 = (struct USER_INFO_1007 *)buffer;
206 uX->usriX_comment = u1007->usri1007_comment;
207 break;
208 case 1009:
209 u1009 = (struct USER_INFO_1009 *)buffer;
210 uX->usriX_script_path = u1009->usri1009_script_path;
211 break;
212 case 1011:
213 u1011 = (struct USER_INFO_1011 *)buffer;
214 uX->usriX_full_name = u1011->usri1011_full_name;
215 break;
216 case 1012:
217 u1012 = (struct USER_INFO_1012 *)buffer;
218 uX->usriX_usr_comment = u1012->usri1012_usr_comment;
219 break;
220 case 1014:
221 u1014 = (struct USER_INFO_1014 *)buffer;
222 uX->usriX_workstations = u1014->usri1014_workstations;
223 break;
224 case 1024:
225 u1024 = (struct USER_INFO_1024 *)buffer;
226 uX->usriX_country_code = u1024->usri1024_country_code;
227 break;
228 case 1051:
229 u1051 = (struct USER_INFO_1051 *)buffer;
230 uX->usriX_primary_group_id = u1051->usri1051_primary_group_id;
231 break;
232 case 1052:
233 u1052 = (struct USER_INFO_1052 *)buffer;
234 uX->usriX_profile = u1052->usri1052_profile;
235 break;
236 case 1053:
237 u1053 = (struct USER_INFO_1053 *)buffer;
238 uX->usriX_home_dir_drive = u1053->usri1053_home_dir_drive;
239 break;
240 case 3:
241 case 4:
242 default:
243 return NT_STATUS_INVALID_INFO_CLASS;
246 return NT_STATUS_OK;
249 /****************************************************************
250 ****************************************************************/
252 static NTSTATUS set_user_info_USER_INFO_X(TALLOC_CTX *ctx,
253 struct rpc_pipe_client *pipe_cli,
254 DATA_BLOB *session_key,
255 struct policy_handle *user_handle,
256 struct USER_INFO_X *uX)
258 union samr_UserInfo user_info;
259 struct samr_UserInfo21 info21;
260 NTSTATUS status;
262 if (!uX) {
263 return NT_STATUS_INVALID_PARAMETER;
266 convert_USER_INFO_X_to_samr_user_info21(uX, &info21);
268 ZERO_STRUCT(user_info);
270 if (uX->usriX_password) {
272 user_info.info25.info = info21;
274 init_samr_CryptPasswordEx(uX->usriX_password,
275 session_key,
276 &user_info.info25.password);
278 status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
279 user_handle,
281 &user_info);
283 if (NT_STATUS_EQUAL(status, NT_STATUS(DCERPC_FAULT_INVALID_TAG))) {
285 user_info.info23.info = info21;
287 init_samr_CryptPassword(uX->usriX_password,
288 session_key,
289 &user_info.info23.password);
291 status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
292 user_handle,
294 &user_info);
296 } else {
298 user_info.info21 = info21;
300 status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
301 user_handle,
303 &user_info);
306 return status;
309 /****************************************************************
310 ****************************************************************/
312 WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
313 struct NetUserAdd *r)
315 struct cli_state *cli = NULL;
316 struct rpc_pipe_client *pipe_cli = NULL;
317 NTSTATUS status;
318 WERROR werr;
319 POLICY_HND connect_handle, domain_handle, user_handle;
320 struct lsa_String lsa_account_name;
321 struct dom_sid2 *domain_sid = NULL;
322 union samr_UserInfo *user_info = NULL;
323 struct samr_PwInfo pw_info;
324 uint32_t access_granted = 0;
325 uint32_t rid = 0;
326 struct USER_INFO_X uX;
328 ZERO_STRUCT(connect_handle);
329 ZERO_STRUCT(domain_handle);
330 ZERO_STRUCT(user_handle);
332 if (!r->in.buffer) {
333 return WERR_INVALID_PARAM;
336 switch (r->in.level) {
337 case 1:
338 break;
339 case 2:
340 case 3:
341 case 4:
342 default:
343 werr = WERR_NOT_SUPPORTED;
344 goto done;
347 werr = libnetapi_open_pipe(ctx, r->in.server_name,
348 &ndr_table_samr.syntax_id,
349 &cli,
350 &pipe_cli);
351 if (!W_ERROR_IS_OK(werr)) {
352 goto done;
355 status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
356 if (!NT_STATUS_IS_OK(status)) {
357 werr = ntstatus_to_werror(status);
358 goto done;
361 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
362 SAMR_ACCESS_ENUM_DOMAINS |
363 SAMR_ACCESS_OPEN_DOMAIN,
364 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
365 SAMR_DOMAIN_ACCESS_CREATE_USER |
366 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
367 &connect_handle,
368 &domain_handle,
369 &domain_sid);
370 if (!W_ERROR_IS_OK(werr)) {
371 goto done;
374 init_lsa_String(&lsa_account_name, uX.usriX_name);
376 status = rpccli_samr_CreateUser2(pipe_cli, ctx,
377 &domain_handle,
378 &lsa_account_name,
379 ACB_NORMAL,
380 SEC_STD_WRITE_DAC |
381 SEC_STD_DELETE |
382 SAMR_USER_ACCESS_SET_PASSWORD |
383 SAMR_USER_ACCESS_SET_ATTRIBUTES |
384 SAMR_USER_ACCESS_GET_ATTRIBUTES,
385 &user_handle,
386 &access_granted,
387 &rid);
388 if (!NT_STATUS_IS_OK(status)) {
389 werr = ntstatus_to_werror(status);
390 goto done;
393 status = rpccli_samr_QueryUserInfo(pipe_cli, ctx,
394 &user_handle,
396 &user_info);
397 if (!NT_STATUS_IS_OK(status)) {
398 werr = ntstatus_to_werror(status);
399 goto done;
402 if (!(user_info->info16.acct_flags & ACB_NORMAL)) {
403 werr = WERR_INVALID_PARAM;
404 goto done;
407 status = rpccli_samr_GetUserPwInfo(pipe_cli, ctx,
408 &user_handle,
409 &pw_info);
410 if (!NT_STATUS_IS_OK(status)) {
411 werr = ntstatus_to_werror(status);
412 goto done;
415 uX.usriX_flags |= ACB_NORMAL;
417 status = set_user_info_USER_INFO_X(ctx, pipe_cli,
418 &cli->user_session_key,
419 &user_handle,
420 &uX);
421 if (!NT_STATUS_IS_OK(status)) {
422 werr = ntstatus_to_werror(status);
423 goto failed;
426 werr = WERR_OK;
427 goto done;
429 failed:
430 rpccli_samr_DeleteUser(pipe_cli, ctx,
431 &user_handle);
433 done:
434 if (!cli) {
435 return werr;
438 if (is_valid_policy_hnd(&user_handle)) {
439 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
442 if (ctx->disable_policy_handle_cache) {
443 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
444 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
447 return werr;
450 /****************************************************************
451 ****************************************************************/
453 WERROR NetUserAdd_l(struct libnetapi_ctx *ctx,
454 struct NetUserAdd *r)
456 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserAdd);
459 /****************************************************************
460 ****************************************************************/
462 WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
463 struct NetUserDel *r)
465 struct cli_state *cli = NULL;
466 struct rpc_pipe_client *pipe_cli = NULL;
467 NTSTATUS status;
468 WERROR werr;
469 POLICY_HND connect_handle, builtin_handle, domain_handle, user_handle;
470 struct lsa_String lsa_account_name;
471 struct samr_Ids user_rids, name_types;
472 struct dom_sid2 *domain_sid = NULL;
473 struct dom_sid2 user_sid;
475 ZERO_STRUCT(connect_handle);
476 ZERO_STRUCT(builtin_handle);
477 ZERO_STRUCT(domain_handle);
478 ZERO_STRUCT(user_handle);
480 werr = libnetapi_open_pipe(ctx, r->in.server_name,
481 &ndr_table_samr.syntax_id,
482 &cli,
483 &pipe_cli);
485 if (!W_ERROR_IS_OK(werr)) {
486 goto done;
489 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
490 SAMR_ACCESS_ENUM_DOMAINS |
491 SAMR_ACCESS_OPEN_DOMAIN,
492 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
493 &connect_handle,
494 &domain_handle,
495 &domain_sid);
496 if (!W_ERROR_IS_OK(werr)) {
497 goto done;
500 status = rpccli_samr_OpenDomain(pipe_cli, ctx,
501 &connect_handle,
502 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
503 CONST_DISCARD(DOM_SID *, &global_sid_Builtin),
504 &builtin_handle);
505 if (!NT_STATUS_IS_OK(status)) {
506 werr = ntstatus_to_werror(status);
507 goto done;
510 init_lsa_String(&lsa_account_name, r->in.user_name);
512 status = rpccli_samr_LookupNames(pipe_cli, ctx,
513 &domain_handle,
515 &lsa_account_name,
516 &user_rids,
517 &name_types);
518 if (!NT_STATUS_IS_OK(status)) {
519 werr = ntstatus_to_werror(status);
520 goto done;
523 status = rpccli_samr_OpenUser(pipe_cli, ctx,
524 &domain_handle,
525 STD_RIGHT_DELETE_ACCESS,
526 user_rids.ids[0],
527 &user_handle);
528 if (!NT_STATUS_IS_OK(status)) {
529 werr = ntstatus_to_werror(status);
530 goto done;
533 sid_compose(&user_sid, domain_sid, user_rids.ids[0]);
535 status = rpccli_samr_RemoveMemberFromForeignDomain(pipe_cli, ctx,
536 &builtin_handle,
537 &user_sid);
538 if (!NT_STATUS_IS_OK(status)) {
539 werr = ntstatus_to_werror(status);
540 goto done;
543 status = rpccli_samr_DeleteUser(pipe_cli, ctx,
544 &user_handle);
545 if (!NT_STATUS_IS_OK(status)) {
546 werr = ntstatus_to_werror(status);
547 goto done;
550 werr = WERR_OK;
552 done:
553 if (!cli) {
554 return werr;
557 if (is_valid_policy_hnd(&user_handle)) {
558 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
561 if (ctx->disable_policy_handle_cache) {
562 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
563 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
564 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
567 return werr;
570 /****************************************************************
571 ****************************************************************/
573 WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
574 struct NetUserDel *r)
576 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserDel);
579 /****************************************************************
580 ****************************************************************/
582 static NTSTATUS libnetapi_samr_lookup_user(TALLOC_CTX *mem_ctx,
583 struct rpc_pipe_client *pipe_cli,
584 struct policy_handle *domain_handle,
585 struct policy_handle *builtin_handle,
586 const char *user_name,
587 const struct dom_sid *domain_sid,
588 uint32_t rid,
589 uint32_t level,
590 struct samr_UserInfo21 **info21,
591 struct sec_desc_buf **sec_desc,
592 uint32_t *auth_flag_p)
594 NTSTATUS status;
596 struct policy_handle user_handle;
597 union samr_UserInfo *user_info = NULL;
598 struct samr_RidWithAttributeArray *rid_array = NULL;
599 uint32_t access_mask = SEC_STD_READ_CONTROL |
600 SAMR_USER_ACCESS_GET_ATTRIBUTES |
601 SAMR_USER_ACCESS_GET_NAME_ETC;
603 ZERO_STRUCT(user_handle);
605 switch (level) {
606 case 0:
607 break;
608 case 1:
609 access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
610 SAMR_USER_ACCESS_GET_GROUPS;
611 break;
612 case 2:
613 case 3:
614 case 4:
615 case 11:
616 access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
617 SAMR_USER_ACCESS_GET_GROUPS |
618 SAMR_USER_ACCESS_GET_LOCALE;
619 break;
620 case 10:
621 case 20:
622 case 23:
623 break;
624 default:
625 return NT_STATUS_INVALID_LEVEL;
628 if (level == 0) {
629 return NT_STATUS_OK;
632 status = rpccli_samr_OpenUser(pipe_cli, mem_ctx,
633 domain_handle,
634 access_mask,
635 rid,
636 &user_handle);
637 if (!NT_STATUS_IS_OK(status)) {
638 goto done;
641 status = rpccli_samr_QueryUserInfo(pipe_cli, mem_ctx,
642 &user_handle,
644 &user_info);
645 if (!NT_STATUS_IS_OK(status)) {
646 goto done;
649 status = rpccli_samr_QuerySecurity(pipe_cli, mem_ctx,
650 &user_handle,
651 SECINFO_DACL,
652 sec_desc);
653 if (!NT_STATUS_IS_OK(status)) {
654 goto done;
657 if (access_mask & SAMR_USER_ACCESS_GET_GROUPS) {
659 struct lsa_SidArray sid_array;
660 struct samr_Ids alias_rids;
661 int i;
662 uint32_t auth_flag = 0;
663 struct dom_sid sid;
665 status = rpccli_samr_GetGroupsForUser(pipe_cli, mem_ctx,
666 &user_handle,
667 &rid_array);
668 if (!NT_STATUS_IS_OK(status)) {
669 goto done;
672 sid_array.num_sids = rid_array->count + 1;
673 sid_array.sids = talloc_array(mem_ctx, struct lsa_SidPtr,
674 sid_array.num_sids);
675 NT_STATUS_HAVE_NO_MEMORY(sid_array.sids);
677 for (i=0; i<rid_array->count; i++) {
678 sid_compose(&sid, domain_sid, rid_array->rids[i].rid);
679 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sid);
680 NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
683 sid_compose(&sid, domain_sid, rid);
684 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sid);
685 NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
687 status = rpccli_samr_GetAliasMembership(pipe_cli, mem_ctx,
688 builtin_handle,
689 &sid_array,
690 &alias_rids);
691 if (!NT_STATUS_IS_OK(status)) {
692 goto done;
695 for (i=0; i<alias_rids.count; i++) {
696 switch (alias_rids.ids[i]) {
697 case 550: /* Print Operators */
698 auth_flag |= AF_OP_PRINT;
699 break;
700 case 549: /* Server Operators */
701 auth_flag |= AF_OP_SERVER;
702 break;
703 case 548: /* Account Operators */
704 auth_flag |= AF_OP_ACCOUNTS;
705 break;
706 default:
707 break;
711 if (auth_flag_p) {
712 *auth_flag_p = auth_flag;
716 *info21 = &user_info->info21;
718 done:
719 if (is_valid_policy_hnd(&user_handle)) {
720 rpccli_samr_Close(pipe_cli, mem_ctx, &user_handle);
723 return status;
726 /****************************************************************
727 ****************************************************************/
729 static uint32_t samr_rid_to_priv_level(uint32_t rid)
731 switch (rid) {
732 case DOMAIN_RID_ADMINISTRATOR:
733 return USER_PRIV_ADMIN;
734 case DOMAIN_RID_GUEST:
735 return USER_PRIV_GUEST;
736 default:
737 return USER_PRIV_USER;
741 /****************************************************************
742 ****************************************************************/
744 static uint32_t samr_acb_flags_to_netapi_flags(uint32_t acb)
746 uint32_t fl = UF_SCRIPT; /* god knows why */
748 fl |= ads_acb2uf(acb);
750 return fl;
753 /****************************************************************
754 ****************************************************************/
756 static NTSTATUS info21_to_USER_INFO_1(TALLOC_CTX *mem_ctx,
757 const struct samr_UserInfo21 *i21,
758 struct USER_INFO_1 *i)
760 ZERO_STRUCTP(i);
761 i->usri1_name = talloc_strdup(mem_ctx, i21->account_name.string);
762 NT_STATUS_HAVE_NO_MEMORY(i->usri1_name);
763 i->usri1_password = NULL;
764 i->usri1_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
765 i->usri1_priv = samr_rid_to_priv_level(i21->rid);
766 i->usri1_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
767 i->usri1_comment = talloc_strdup(mem_ctx, i21->description.string);
768 i->usri1_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
769 i->usri1_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
771 return NT_STATUS_OK;
774 /****************************************************************
775 ****************************************************************/
777 static NTSTATUS info21_to_USER_INFO_2(TALLOC_CTX *mem_ctx,
778 const struct samr_UserInfo21 *i21,
779 uint32_t auth_flag,
780 struct USER_INFO_2 *i)
782 ZERO_STRUCTP(i);
784 i->usri2_name = talloc_strdup(mem_ctx, i21->account_name.string);
785 NT_STATUS_HAVE_NO_MEMORY(i->usri2_name);
786 i->usri2_password = NULL;
787 i->usri2_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
788 i->usri2_priv = samr_rid_to_priv_level(i21->rid);
789 i->usri2_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
790 i->usri2_comment = talloc_strdup(mem_ctx, i21->description.string);
791 i->usri2_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
792 i->usri2_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
793 i->usri2_auth_flags = auth_flag;
794 i->usri2_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
795 i->usri2_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
796 i->usri2_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
797 i->usri2_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
798 i->usri2_last_logon = nt_time_to_unix(i21->last_logon);
799 i->usri2_last_logoff = nt_time_to_unix(i21->last_logoff);
800 i->usri2_acct_expires = nt_time_to_unix(i21->acct_expiry);
801 i->usri2_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
802 i->usri2_units_per_week = i21->logon_hours.units_per_week;
803 i->usri2_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
804 i->usri2_bad_pw_count = i21->bad_password_count;
805 i->usri2_num_logons = i21->logon_count;
806 i->usri2_logon_server = talloc_strdup(mem_ctx, "\\\\*");
807 i->usri2_country_code = i21->country_code;
808 i->usri2_code_page = i21->code_page;
810 return NT_STATUS_OK;
813 /****************************************************************
814 ****************************************************************/
816 static NTSTATUS info21_to_USER_INFO_3(TALLOC_CTX *mem_ctx,
817 const struct samr_UserInfo21 *i21,
818 uint32_t auth_flag,
819 struct USER_INFO_3 *i)
821 ZERO_STRUCTP(i);
823 i->usri3_name = talloc_strdup(mem_ctx, i21->account_name.string);
824 NT_STATUS_HAVE_NO_MEMORY(i->usri3_name);
825 i->usri3_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
826 i->usri3_priv = samr_rid_to_priv_level(i21->rid);
827 i->usri3_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
828 i->usri3_comment = talloc_strdup(mem_ctx, i21->description.string);
829 i->usri3_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
830 i->usri3_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
831 i->usri3_auth_flags = auth_flag;
832 i->usri3_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
833 i->usri3_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
834 i->usri3_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
835 i->usri3_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
836 i->usri3_last_logon = nt_time_to_unix(i21->last_logon);
837 i->usri3_last_logoff = nt_time_to_unix(i21->last_logoff);
838 i->usri3_acct_expires = nt_time_to_unix(i21->acct_expiry);
839 i->usri3_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
840 i->usri3_units_per_week = i21->logon_hours.units_per_week;
841 i->usri3_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
842 i->usri3_bad_pw_count = i21->bad_password_count;
843 i->usri3_num_logons = i21->logon_count;
844 i->usri3_logon_server = talloc_strdup(mem_ctx, "\\\\*");
845 i->usri3_country_code = i21->country_code;
846 i->usri3_code_page = i21->code_page;
847 i->usri3_user_id = i21->rid;
848 i->usri3_primary_group_id = i21->primary_gid;
849 i->usri3_profile = talloc_strdup(mem_ctx, i21->profile_path.string);
850 i->usri3_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
851 i->usri3_password_expired = i21->password_expired;
853 return NT_STATUS_OK;
856 /****************************************************************
857 ****************************************************************/
859 static NTSTATUS info21_to_USER_INFO_4(TALLOC_CTX *mem_ctx,
860 const struct samr_UserInfo21 *i21,
861 uint32_t auth_flag,
862 struct dom_sid *domain_sid,
863 struct USER_INFO_4 *i)
865 struct dom_sid sid;
867 ZERO_STRUCTP(i);
869 i->usri4_name = talloc_strdup(mem_ctx, i21->account_name.string);
870 NT_STATUS_HAVE_NO_MEMORY(i->usri4_name);
871 i->usri4_password_age = time(NULL) - nt_time_to_unix(i21->last_password_change);
872 i->usri4_password = NULL;
873 i->usri4_priv = samr_rid_to_priv_level(i21->rid);
874 i->usri4_home_dir = talloc_strdup(mem_ctx, i21->home_directory.string);
875 i->usri4_comment = talloc_strdup(mem_ctx, i21->description.string);
876 i->usri4_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
877 i->usri4_script_path = talloc_strdup(mem_ctx, i21->logon_script.string);
878 i->usri4_auth_flags = auth_flag;
879 i->usri4_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
880 i->usri4_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
881 i->usri4_parms = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
882 i->usri4_workstations = talloc_strdup(mem_ctx, i21->workstations.string);
883 i->usri4_last_logon = nt_time_to_unix(i21->last_logon);
884 i->usri4_last_logoff = nt_time_to_unix(i21->last_logoff);
885 i->usri4_acct_expires = nt_time_to_unix(i21->acct_expiry);
886 i->usri4_max_storage = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
887 i->usri4_units_per_week = i21->logon_hours.units_per_week;
888 i->usri4_logon_hours = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
889 i->usri4_bad_pw_count = i21->bad_password_count;
890 i->usri4_num_logons = i21->logon_count;
891 i->usri4_logon_server = talloc_strdup(mem_ctx, "\\\\*");
892 i->usri4_country_code = i21->country_code;
893 i->usri4_code_page = i21->code_page;
894 if (!sid_compose(&sid, domain_sid, i21->rid)) {
895 return NT_STATUS_NO_MEMORY;
897 i->usri4_user_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
898 i->usri4_primary_group_id = i21->primary_gid;
899 i->usri4_profile = talloc_strdup(mem_ctx, i21->profile_path.string);
900 i->usri4_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
901 i->usri4_password_expired = i21->password_expired;
903 return NT_STATUS_OK;
906 /****************************************************************
907 ****************************************************************/
909 static NTSTATUS info21_to_USER_INFO_10(TALLOC_CTX *mem_ctx,
910 const struct samr_UserInfo21 *i21,
911 struct USER_INFO_10 *i)
913 ZERO_STRUCTP(i);
915 i->usri10_name = talloc_strdup(mem_ctx, i21->account_name.string);
916 NT_STATUS_HAVE_NO_MEMORY(i->usri10_name);
917 i->usri10_comment = talloc_strdup(mem_ctx, i21->description.string);
918 i->usri10_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
919 i->usri10_usr_comment = talloc_strdup(mem_ctx, i21->comment.string);
921 return NT_STATUS_OK;
924 /****************************************************************
925 ****************************************************************/
927 static NTSTATUS info21_to_USER_INFO_20(TALLOC_CTX *mem_ctx,
928 const struct samr_UserInfo21 *i21,
929 struct USER_INFO_20 *i)
931 ZERO_STRUCTP(i);
933 i->usri20_name = talloc_strdup(mem_ctx, i21->account_name.string);
934 NT_STATUS_HAVE_NO_MEMORY(i->usri20_name);
935 i->usri20_comment = talloc_strdup(mem_ctx, i21->description.string);
936 i->usri20_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
937 i->usri20_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
938 i->usri20_user_id = i21->rid;
940 return NT_STATUS_OK;
943 /****************************************************************
944 ****************************************************************/
946 static NTSTATUS info21_to_USER_INFO_23(TALLOC_CTX *mem_ctx,
947 const struct samr_UserInfo21 *i21,
948 struct dom_sid *domain_sid,
949 struct USER_INFO_23 *i)
951 struct dom_sid sid;
953 ZERO_STRUCTP(i);
955 i->usri23_name = talloc_strdup(mem_ctx, i21->account_name.string);
956 NT_STATUS_HAVE_NO_MEMORY(i->usri23_name);
957 i->usri23_comment = talloc_strdup(mem_ctx, i21->description.string);
958 i->usri23_full_name = talloc_strdup(mem_ctx, i21->full_name.string);
959 i->usri23_flags = samr_acb_flags_to_netapi_flags(i21->acct_flags);
960 if (!sid_compose(&sid, domain_sid, i21->rid)) {
961 return NT_STATUS_NO_MEMORY;
963 i->usri23_user_sid = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
965 return NT_STATUS_OK;
968 /****************************************************************
969 ****************************************************************/
971 static NTSTATUS libnetapi_samr_lookup_user_map_USER_INFO(TALLOC_CTX *mem_ctx,
972 struct rpc_pipe_client *pipe_cli,
973 struct dom_sid *domain_sid,
974 struct policy_handle *domain_handle,
975 struct policy_handle *builtin_handle,
976 const char *user_name,
977 uint32_t rid,
978 uint32_t level,
979 uint8_t **buffer,
980 uint32_t *num_entries)
982 NTSTATUS status;
984 struct samr_UserInfo21 *info21 = NULL;
985 struct sec_desc_buf *sec_desc = NULL;
986 uint32_t auth_flag = 0;
988 struct USER_INFO_0 info0;
989 struct USER_INFO_1 info1;
990 struct USER_INFO_2 info2;
991 struct USER_INFO_3 info3;
992 struct USER_INFO_4 info4;
993 struct USER_INFO_10 info10;
994 struct USER_INFO_20 info20;
995 struct USER_INFO_23 info23;
997 switch (level) {
998 case 0:
999 case 1:
1000 case 2:
1001 case 3:
1002 case 4:
1003 case 10:
1004 case 11:
1005 case 20:
1006 case 23:
1007 break;
1008 default:
1009 return NT_STATUS_INVALID_LEVEL;
1012 if (level == 0) {
1013 info0.usri0_name = talloc_strdup(mem_ctx, user_name);
1014 NT_STATUS_HAVE_NO_MEMORY(info0.usri0_name);
1016 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_0, info0,
1017 (struct USER_INFO_0 **)buffer, num_entries);
1019 return NT_STATUS_OK;
1022 status = libnetapi_samr_lookup_user(mem_ctx, pipe_cli,
1023 domain_handle,
1024 builtin_handle,
1025 user_name,
1026 domain_sid,
1027 rid,
1028 level,
1029 &info21,
1030 &sec_desc,
1031 &auth_flag);
1033 if (!NT_STATUS_IS_OK(status)) {
1034 goto done;
1037 switch (level) {
1038 case 0:
1039 /* already returned above */
1040 break;
1041 case 1:
1042 status = info21_to_USER_INFO_1(mem_ctx, info21, &info1);
1043 NT_STATUS_NOT_OK_RETURN(status);
1045 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_1, info1,
1046 (struct USER_INFO_1 **)buffer, num_entries);
1048 break;
1049 case 2:
1050 status = info21_to_USER_INFO_2(mem_ctx, info21, auth_flag, &info2);
1051 NT_STATUS_NOT_OK_RETURN(status);
1053 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_2, info2,
1054 (struct USER_INFO_2 **)buffer, num_entries);
1056 break;
1057 case 3:
1058 status = info21_to_USER_INFO_3(mem_ctx, info21, auth_flag, &info3);
1059 NT_STATUS_NOT_OK_RETURN(status);
1061 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_3, info3,
1062 (struct USER_INFO_3 **)buffer, num_entries);
1064 break;
1065 case 4:
1066 status = info21_to_USER_INFO_4(mem_ctx, info21, auth_flag, domain_sid, &info4);
1067 NT_STATUS_NOT_OK_RETURN(status);
1069 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_4, info4,
1070 (struct USER_INFO_4 **)buffer, num_entries);
1072 break;
1073 case 10:
1074 status = info21_to_USER_INFO_10(mem_ctx, info21, &info10);
1075 NT_STATUS_NOT_OK_RETURN(status);
1077 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_10, info10,
1078 (struct USER_INFO_10 **)buffer, num_entries);
1080 break;
1082 case 20:
1083 status = info21_to_USER_INFO_20(mem_ctx, info21, &info20);
1084 NT_STATUS_NOT_OK_RETURN(status);
1086 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_20, info20,
1087 (struct USER_INFO_20 **)buffer, num_entries);
1089 break;
1090 case 23:
1091 status = info21_to_USER_INFO_23(mem_ctx, info21, domain_sid, &info23);
1092 NT_STATUS_NOT_OK_RETURN(status);
1094 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_23, info23,
1095 (struct USER_INFO_23 **)buffer, num_entries);
1096 break;
1097 default:
1098 return NT_STATUS_INVALID_LEVEL;
1101 done:
1102 return status;
1105 /****************************************************************
1106 ****************************************************************/
1108 WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
1109 struct NetUserEnum *r)
1111 struct cli_state *cli = NULL;
1112 struct rpc_pipe_client *pipe_cli = NULL;
1113 struct policy_handle connect_handle;
1114 struct dom_sid2 *domain_sid = NULL;
1115 struct policy_handle domain_handle, builtin_handle;
1116 struct samr_SamArray *sam = NULL;
1117 uint32_t filter = ACB_NORMAL;
1118 int i;
1119 uint32_t entries_read = 0;
1121 NTSTATUS status = NT_STATUS_OK;
1122 WERROR werr;
1124 ZERO_STRUCT(connect_handle);
1125 ZERO_STRUCT(domain_handle);
1126 ZERO_STRUCT(builtin_handle);
1128 if (!r->out.buffer) {
1129 return WERR_INVALID_PARAM;
1132 *r->out.buffer = NULL;
1133 *r->out.entries_read = 0;
1135 switch (r->in.level) {
1136 case 0:
1137 case 1:
1138 case 2:
1139 case 3:
1140 case 4:
1141 case 10:
1142 case 20:
1143 case 23:
1144 break;
1145 case 11:
1146 return WERR_NOT_SUPPORTED;
1147 default:
1148 return WERR_UNKNOWN_LEVEL;
1151 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1152 &ndr_table_samr.syntax_id,
1153 &cli,
1154 &pipe_cli);
1155 if (!W_ERROR_IS_OK(werr)) {
1156 goto done;
1159 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1160 SAMR_ACCESS_ENUM_DOMAINS |
1161 SAMR_ACCESS_OPEN_DOMAIN,
1162 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1163 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1164 &connect_handle,
1165 &builtin_handle);
1166 if (!W_ERROR_IS_OK(werr)) {
1167 goto done;
1170 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1171 SAMR_ACCESS_ENUM_DOMAINS |
1172 SAMR_ACCESS_OPEN_DOMAIN,
1173 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1174 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1175 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1176 &connect_handle,
1177 &domain_handle,
1178 &domain_sid);
1179 if (!W_ERROR_IS_OK(werr)) {
1180 goto done;
1183 switch (r->in.filter) {
1184 case FILTER_NORMAL_ACCOUNT:
1185 filter = ACB_NORMAL;
1186 break;
1187 case FILTER_TEMP_DUPLICATE_ACCOUNT:
1188 filter = ACB_TEMPDUP;
1189 break;
1190 case FILTER_INTERDOMAIN_TRUST_ACCOUNT:
1191 filter = ACB_DOMTRUST;
1192 break;
1193 case FILTER_WORKSTATION_TRUST_ACCOUNT:
1194 filter = ACB_WSTRUST;
1195 break;
1196 case FILTER_SERVER_TRUST_ACCOUNT:
1197 filter = ACB_SVRTRUST;
1198 break;
1199 default:
1200 break;
1203 status = rpccli_samr_EnumDomainUsers(pipe_cli,
1204 ctx,
1205 &domain_handle,
1206 r->in.resume_handle,
1207 filter,
1208 &sam,
1209 r->in.prefmaxlen,
1210 &entries_read);
1211 werr = ntstatus_to_werror(status);
1212 if (NT_STATUS_IS_ERR(status)) {
1213 goto done;
1216 for (i=0; i < sam->count; i++) {
1218 status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1219 domain_sid,
1220 &domain_handle,
1221 &builtin_handle,
1222 sam->entries[i].name.string,
1223 sam->entries[i].idx,
1224 r->in.level,
1225 r->out.buffer,
1226 r->out.entries_read);
1227 if (!NT_STATUS_IS_OK(status)) {
1228 werr = ntstatus_to_werror(status);
1229 goto done;
1233 done:
1234 if (!cli) {
1235 return werr;
1238 /* if last query */
1239 if (NT_STATUS_IS_OK(status) ||
1240 NT_STATUS_IS_ERR(status)) {
1242 if (ctx->disable_policy_handle_cache) {
1243 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1244 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1245 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1249 return werr;
1252 /****************************************************************
1253 ****************************************************************/
1255 WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
1256 struct NetUserEnum *r)
1258 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserEnum);
1261 /****************************************************************
1262 ****************************************************************/
1264 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_USER(TALLOC_CTX *mem_ctx,
1265 struct samr_DispInfoGeneral *info,
1266 uint32_t *entries_read,
1267 void **buffer)
1269 struct NET_DISPLAY_USER *user = NULL;
1270 int i;
1272 user = TALLOC_ZERO_ARRAY(mem_ctx,
1273 struct NET_DISPLAY_USER,
1274 info->count);
1275 W_ERROR_HAVE_NO_MEMORY(user);
1277 for (i = 0; i < info->count; i++) {
1278 user[i].usri1_name = talloc_strdup(mem_ctx,
1279 info->entries[i].account_name.string);
1280 user[i].usri1_comment = talloc_strdup(mem_ctx,
1281 info->entries[i].description.string);
1282 user[i].usri1_flags =
1283 info->entries[i].acct_flags;
1284 user[i].usri1_full_name = talloc_strdup(mem_ctx,
1285 info->entries[i].full_name.string);
1286 user[i].usri1_user_id =
1287 info->entries[i].rid;
1288 user[i].usri1_next_index =
1289 info->entries[i].idx;
1291 if (!user[i].usri1_name) {
1292 return WERR_NOMEM;
1296 *buffer = talloc_memdup(mem_ctx, user,
1297 sizeof(struct NET_DISPLAY_USER) * info->count);
1298 W_ERROR_HAVE_NO_MEMORY(*buffer);
1300 *entries_read = info->count;
1302 return WERR_OK;
1305 /****************************************************************
1306 ****************************************************************/
1308 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(TALLOC_CTX *mem_ctx,
1309 struct samr_DispInfoFull *info,
1310 uint32_t *entries_read,
1311 void **buffer)
1313 struct NET_DISPLAY_MACHINE *machine = NULL;
1314 int i;
1316 machine = TALLOC_ZERO_ARRAY(mem_ctx,
1317 struct NET_DISPLAY_MACHINE,
1318 info->count);
1319 W_ERROR_HAVE_NO_MEMORY(machine);
1321 for (i = 0; i < info->count; i++) {
1322 machine[i].usri2_name = talloc_strdup(mem_ctx,
1323 info->entries[i].account_name.string);
1324 machine[i].usri2_comment = talloc_strdup(mem_ctx,
1325 info->entries[i].description.string);
1326 machine[i].usri2_flags =
1327 info->entries[i].acct_flags;
1328 machine[i].usri2_user_id =
1329 info->entries[i].rid;
1330 machine[i].usri2_next_index =
1331 info->entries[i].idx;
1333 if (!machine[i].usri2_name) {
1334 return WERR_NOMEM;
1338 *buffer = talloc_memdup(mem_ctx, machine,
1339 sizeof(struct NET_DISPLAY_MACHINE) * info->count);
1340 W_ERROR_HAVE_NO_MEMORY(*buffer);
1342 *entries_read = info->count;
1344 return WERR_OK;
1347 /****************************************************************
1348 ****************************************************************/
1350 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_GROUP(TALLOC_CTX *mem_ctx,
1351 struct samr_DispInfoFullGroups *info,
1352 uint32_t *entries_read,
1353 void **buffer)
1355 struct NET_DISPLAY_GROUP *group = NULL;
1356 int i;
1358 group = TALLOC_ZERO_ARRAY(mem_ctx,
1359 struct NET_DISPLAY_GROUP,
1360 info->count);
1361 W_ERROR_HAVE_NO_MEMORY(group);
1363 for (i = 0; i < info->count; i++) {
1364 group[i].grpi3_name = talloc_strdup(mem_ctx,
1365 info->entries[i].account_name.string);
1366 group[i].grpi3_comment = talloc_strdup(mem_ctx,
1367 info->entries[i].description.string);
1368 group[i].grpi3_group_id =
1369 info->entries[i].rid;
1370 group[i].grpi3_attributes =
1371 info->entries[i].acct_flags;
1372 group[i].grpi3_next_index =
1373 info->entries[i].idx;
1375 if (!group[i].grpi3_name) {
1376 return WERR_NOMEM;
1380 *buffer = talloc_memdup(mem_ctx, group,
1381 sizeof(struct NET_DISPLAY_GROUP) * info->count);
1382 W_ERROR_HAVE_NO_MEMORY(*buffer);
1384 *entries_read = info->count;
1386 return WERR_OK;
1390 /****************************************************************
1391 ****************************************************************/
1393 static WERROR convert_samr_dispinfo_to_NET_DISPLAY(TALLOC_CTX *mem_ctx,
1394 union samr_DispInfo *info,
1395 uint32_t level,
1396 uint32_t *entries_read,
1397 void **buffer)
1399 switch (level) {
1400 case 1:
1401 return convert_samr_dispinfo_to_NET_DISPLAY_USER(mem_ctx,
1402 &info->info1,
1403 entries_read,
1404 buffer);
1405 case 2:
1406 return convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(mem_ctx,
1407 &info->info2,
1408 entries_read,
1409 buffer);
1410 case 3:
1411 return convert_samr_dispinfo_to_NET_DISPLAY_GROUP(mem_ctx,
1412 &info->info3,
1413 entries_read,
1414 buffer);
1415 default:
1416 return WERR_UNKNOWN_LEVEL;
1419 return WERR_OK;
1422 /****************************************************************
1423 ****************************************************************/
1425 WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
1426 struct NetQueryDisplayInformation *r)
1428 struct cli_state *cli = NULL;
1429 struct rpc_pipe_client *pipe_cli = NULL;
1430 struct policy_handle connect_handle;
1431 struct dom_sid2 *domain_sid = NULL;
1432 struct policy_handle domain_handle;
1433 union samr_DispInfo info;
1435 uint32_t total_size = 0;
1436 uint32_t returned_size = 0;
1438 NTSTATUS status = NT_STATUS_OK;
1439 WERROR werr;
1441 ZERO_STRUCT(connect_handle);
1442 ZERO_STRUCT(domain_handle);
1444 switch (r->in.level) {
1445 case 1:
1446 case 2:
1447 case 3:
1448 break;
1449 default:
1450 return WERR_UNKNOWN_LEVEL;
1453 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1454 &ndr_table_samr.syntax_id,
1455 &cli,
1456 &pipe_cli);
1457 if (!W_ERROR_IS_OK(werr)) {
1458 goto done;
1461 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1462 SAMR_ACCESS_ENUM_DOMAINS |
1463 SAMR_ACCESS_OPEN_DOMAIN,
1464 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1465 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1466 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1467 &connect_handle,
1468 &domain_handle,
1469 &domain_sid);
1470 if (!W_ERROR_IS_OK(werr)) {
1471 goto done;
1474 status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
1475 ctx,
1476 &domain_handle,
1477 r->in.level,
1478 r->in.idx,
1479 r->in.entries_requested,
1480 r->in.prefmaxlen,
1481 &total_size,
1482 &returned_size,
1483 &info);
1484 if (!NT_STATUS_IS_OK(status)) {
1485 werr = ntstatus_to_werror(status);
1486 goto done;
1489 werr = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info,
1490 r->in.level,
1491 r->out.entries_read,
1492 r->out.buffer);
1493 done:
1494 if (!cli) {
1495 return werr;
1498 /* if last query */
1499 if (NT_STATUS_IS_OK(status) ||
1500 NT_STATUS_IS_ERR(status)) {
1502 if (ctx->disable_policy_handle_cache) {
1503 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1504 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1508 return werr;
1512 /****************************************************************
1513 ****************************************************************/
1516 WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
1517 struct NetQueryDisplayInformation *r)
1519 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetQueryDisplayInformation);
1522 /****************************************************************
1523 ****************************************************************/
1525 WERROR NetUserChangePassword_r(struct libnetapi_ctx *ctx,
1526 struct NetUserChangePassword *r)
1528 return WERR_NOT_SUPPORTED;
1531 /****************************************************************
1532 ****************************************************************/
1534 WERROR NetUserChangePassword_l(struct libnetapi_ctx *ctx,
1535 struct NetUserChangePassword *r)
1537 return WERR_NOT_SUPPORTED;
1540 /****************************************************************
1541 ****************************************************************/
1543 WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx,
1544 struct NetUserGetInfo *r)
1546 struct cli_state *cli = NULL;
1547 struct rpc_pipe_client *pipe_cli = NULL;
1548 NTSTATUS status;
1549 WERROR werr;
1551 struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1552 struct lsa_String lsa_account_name;
1553 struct dom_sid2 *domain_sid = NULL;
1554 struct samr_Ids user_rids, name_types;
1555 uint32_t num_entries = 0;
1557 ZERO_STRUCT(connect_handle);
1558 ZERO_STRUCT(domain_handle);
1559 ZERO_STRUCT(builtin_handle);
1560 ZERO_STRUCT(user_handle);
1562 if (!r->out.buffer) {
1563 return WERR_INVALID_PARAM;
1566 switch (r->in.level) {
1567 case 0:
1568 case 1:
1569 case 2:
1570 case 3:
1571 case 4:
1572 case 10:
1573 case 20:
1574 case 23:
1575 break;
1576 case 11:
1577 werr = WERR_NOT_SUPPORTED;
1578 goto done;
1579 default:
1580 werr = WERR_UNKNOWN_LEVEL;
1581 goto done;
1584 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1585 &ndr_table_samr.syntax_id,
1586 &cli,
1587 &pipe_cli);
1588 if (!W_ERROR_IS_OK(werr)) {
1589 goto done;
1592 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1593 SAMR_ACCESS_ENUM_DOMAINS |
1594 SAMR_ACCESS_OPEN_DOMAIN,
1595 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1596 &connect_handle,
1597 &domain_handle,
1598 &domain_sid);
1599 if (!W_ERROR_IS_OK(werr)) {
1600 goto done;
1603 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1604 SAMR_ACCESS_ENUM_DOMAINS |
1605 SAMR_ACCESS_OPEN_DOMAIN,
1606 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1607 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1608 &connect_handle,
1609 &builtin_handle);
1610 if (!W_ERROR_IS_OK(werr)) {
1611 goto done;
1614 init_lsa_String(&lsa_account_name, r->in.user_name);
1616 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1617 &domain_handle,
1619 &lsa_account_name,
1620 &user_rids,
1621 &name_types);
1622 if (!NT_STATUS_IS_OK(status)) {
1623 werr = ntstatus_to_werror(status);
1624 goto done;
1627 status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1628 domain_sid,
1629 &domain_handle,
1630 &builtin_handle,
1631 r->in.user_name,
1632 user_rids.ids[0],
1633 r->in.level,
1634 r->out.buffer,
1635 &num_entries);
1636 if (!NT_STATUS_IS_OK(status)) {
1637 werr = ntstatus_to_werror(status);
1638 goto done;
1641 done:
1642 if (!cli) {
1643 return werr;
1646 if (is_valid_policy_hnd(&user_handle)) {
1647 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
1650 if (ctx->disable_policy_handle_cache) {
1651 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1652 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1655 return werr;
1658 /****************************************************************
1659 ****************************************************************/
1661 WERROR NetUserGetInfo_l(struct libnetapi_ctx *ctx,
1662 struct NetUserGetInfo *r)
1664 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetInfo);
1667 /****************************************************************
1668 ****************************************************************/
1670 WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
1671 struct NetUserSetInfo *r)
1673 struct cli_state *cli = NULL;
1674 struct rpc_pipe_client *pipe_cli = NULL;
1675 NTSTATUS status;
1676 WERROR werr;
1678 struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1679 struct lsa_String lsa_account_name;
1680 struct dom_sid2 *domain_sid = NULL;
1681 struct samr_Ids user_rids, name_types;
1682 uint32_t user_mask = 0;
1684 struct USER_INFO_X uX;
1686 ZERO_STRUCT(connect_handle);
1687 ZERO_STRUCT(domain_handle);
1688 ZERO_STRUCT(builtin_handle);
1689 ZERO_STRUCT(user_handle);
1691 if (!r->in.buffer) {
1692 return WERR_INVALID_PARAM;
1695 switch (r->in.level) {
1696 case 0:
1697 case 1003:
1698 user_mask = SAMR_USER_ACCESS_SET_PASSWORD;
1699 break;
1700 case 1006:
1701 case 1007:
1702 case 1009:
1703 case 1011:
1704 case 1014:
1705 case 1052:
1706 case 1053:
1707 user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
1708 break;
1709 case 1012:
1710 case 1024:
1711 user_mask = SAMR_USER_ACCESS_SET_LOC_COM;
1712 case 1051:
1713 user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES |
1714 SAMR_USER_ACCESS_GET_GROUPS;
1715 break;
1716 case 1:
1717 case 2:
1718 case 3:
1719 case 4:
1720 case 21:
1721 case 22:
1722 case 1005:
1723 case 1008:
1724 case 1010:
1725 case 1017:
1726 case 1020:
1727 werr = WERR_NOT_SUPPORTED;
1728 goto done;
1729 default:
1730 werr = WERR_UNKNOWN_LEVEL;
1731 goto done;
1734 werr = libnetapi_open_pipe(ctx, r->in.server_name,
1735 &ndr_table_samr.syntax_id,
1736 &cli,
1737 &pipe_cli);
1738 if (!W_ERROR_IS_OK(werr)) {
1739 goto done;
1742 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1743 SAMR_ACCESS_ENUM_DOMAINS |
1744 SAMR_ACCESS_OPEN_DOMAIN,
1745 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
1746 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1747 &connect_handle,
1748 &domain_handle,
1749 &domain_sid);
1750 if (!W_ERROR_IS_OK(werr)) {
1751 goto done;
1754 werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1755 SAMR_ACCESS_ENUM_DOMAINS |
1756 SAMR_ACCESS_OPEN_DOMAIN,
1757 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1758 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1759 &connect_handle,
1760 &builtin_handle);
1761 if (!W_ERROR_IS_OK(werr)) {
1762 goto done;
1765 init_lsa_String(&lsa_account_name, r->in.user_name);
1767 status = rpccli_samr_LookupNames(pipe_cli, ctx,
1768 &domain_handle,
1770 &lsa_account_name,
1771 &user_rids,
1772 &name_types);
1773 if (!NT_STATUS_IS_OK(status)) {
1774 werr = ntstatus_to_werror(status);
1775 goto done;
1778 status = rpccli_samr_OpenUser(pipe_cli, ctx,
1779 &domain_handle,
1780 user_mask,
1781 user_rids.ids[0],
1782 &user_handle);
1783 if (!NT_STATUS_IS_OK(status)) {
1784 werr = ntstatus_to_werror(status);
1785 goto done;
1788 status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
1789 if (!NT_STATUS_IS_OK(status)) {
1790 werr = ntstatus_to_werror(status);
1791 goto done;
1794 status = set_user_info_USER_INFO_X(ctx, pipe_cli,
1795 &cli->user_session_key,
1796 &user_handle,
1797 &uX);
1798 if (!NT_STATUS_IS_OK(status)) {
1799 werr = ntstatus_to_werror(status);
1800 goto done;
1803 werr = WERR_OK;
1805 done:
1806 if (!cli) {
1807 return werr;
1810 if (is_valid_policy_hnd(&user_handle)) {
1811 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
1814 if (ctx->disable_policy_handle_cache) {
1815 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1816 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1817 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1820 return werr;
1823 /****************************************************************
1824 ****************************************************************/
1826 WERROR NetUserSetInfo_l(struct libnetapi_ctx *ctx,
1827 struct NetUserSetInfo *r)
1829 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetInfo);
1832 /****************************************************************
1833 ****************************************************************/
1835 static NTSTATUS query_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
1836 struct rpc_pipe_client *pipe_cli,
1837 struct policy_handle *domain_handle,
1838 struct samr_DomInfo1 *info1,
1839 struct samr_DomInfo3 *info3,
1840 struct samr_DomInfo5 *info5,
1841 struct samr_DomInfo6 *info6,
1842 struct samr_DomInfo7 *info7,
1843 struct samr_DomInfo12 *info12)
1845 NTSTATUS status;
1846 union samr_DomainInfo *dom_info = NULL;
1848 if (info1) {
1849 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1850 domain_handle,
1852 &dom_info);
1853 NT_STATUS_NOT_OK_RETURN(status);
1855 *info1 = dom_info->info1;
1858 if (info3) {
1859 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1860 domain_handle,
1862 &dom_info);
1863 NT_STATUS_NOT_OK_RETURN(status);
1865 *info3 = dom_info->info3;
1868 if (info5) {
1869 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1870 domain_handle,
1872 &dom_info);
1873 NT_STATUS_NOT_OK_RETURN(status);
1875 *info5 = dom_info->info5;
1878 if (info6) {
1879 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1880 domain_handle,
1882 &dom_info);
1883 NT_STATUS_NOT_OK_RETURN(status);
1885 *info6 = dom_info->info6;
1888 if (info7) {
1889 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1890 domain_handle,
1892 &dom_info);
1893 NT_STATUS_NOT_OK_RETURN(status);
1895 *info7 = dom_info->info7;
1898 if (info12) {
1899 status = rpccli_samr_QueryDomainInfo2(pipe_cli, mem_ctx,
1900 domain_handle,
1902 &dom_info);
1903 NT_STATUS_NOT_OK_RETURN(status);
1905 *info12 = dom_info->info12;
1908 return NT_STATUS_OK;
1911 /****************************************************************
1912 ****************************************************************/
1914 static NTSTATUS query_USER_MODALS_INFO_0(TALLOC_CTX *mem_ctx,
1915 struct rpc_pipe_client *pipe_cli,
1916 struct policy_handle *domain_handle,
1917 struct USER_MODALS_INFO_0 *info0)
1919 NTSTATUS status;
1920 struct samr_DomInfo1 dom_info1;
1921 struct samr_DomInfo3 dom_info3;
1923 ZERO_STRUCTP(info0);
1925 status = query_USER_MODALS_INFO_rpc(mem_ctx,
1926 pipe_cli,
1927 domain_handle,
1928 &dom_info1,
1929 &dom_info3,
1930 NULL,
1931 NULL,
1932 NULL,
1933 NULL);
1934 NT_STATUS_NOT_OK_RETURN(status);
1936 info0->usrmod0_min_passwd_len =
1937 dom_info1.min_password_length;
1938 info0->usrmod0_max_passwd_age =
1939 nt_time_to_unix_abs((NTTIME *)&dom_info1.max_password_age);
1940 info0->usrmod0_min_passwd_age =
1941 nt_time_to_unix_abs((NTTIME *)&dom_info1.min_password_age);
1942 info0->usrmod0_password_hist_len =
1943 dom_info1.password_history_length;
1945 info0->usrmod0_force_logoff =
1946 nt_time_to_unix_abs(&dom_info3.force_logoff_time);
1948 return NT_STATUS_OK;
1951 /****************************************************************
1952 ****************************************************************/
1954 static NTSTATUS query_USER_MODALS_INFO_1(TALLOC_CTX *mem_ctx,
1955 struct rpc_pipe_client *pipe_cli,
1956 struct policy_handle *domain_handle,
1957 struct USER_MODALS_INFO_1 *info1)
1959 NTSTATUS status;
1960 struct samr_DomInfo6 dom_info6;
1961 struct samr_DomInfo7 dom_info7;
1963 status = query_USER_MODALS_INFO_rpc(mem_ctx,
1964 pipe_cli,
1965 domain_handle,
1966 NULL,
1967 NULL,
1968 NULL,
1969 &dom_info6,
1970 &dom_info7,
1971 NULL);
1972 NT_STATUS_NOT_OK_RETURN(status);
1974 info1->usrmod1_primary =
1975 talloc_strdup(mem_ctx, dom_info6.primary.string);
1977 info1->usrmod1_role = dom_info7.role;
1979 return NT_STATUS_OK;
1982 /****************************************************************
1983 ****************************************************************/
1985 static NTSTATUS query_USER_MODALS_INFO_2(TALLOC_CTX *mem_ctx,
1986 struct rpc_pipe_client *pipe_cli,
1987 struct policy_handle *domain_handle,
1988 struct dom_sid *domain_sid,
1989 struct USER_MODALS_INFO_2 *info2)
1991 NTSTATUS status;
1992 struct samr_DomInfo5 dom_info5;
1994 status = query_USER_MODALS_INFO_rpc(mem_ctx,
1995 pipe_cli,
1996 domain_handle,
1997 NULL,
1998 NULL,
1999 &dom_info5,
2000 NULL,
2001 NULL,
2002 NULL);
2003 NT_STATUS_NOT_OK_RETURN(status);
2005 info2->usrmod2_domain_name =
2006 talloc_strdup(mem_ctx, dom_info5.domain_name.string);
2007 info2->usrmod2_domain_id =
2008 (struct domsid *)sid_dup_talloc(mem_ctx, domain_sid);
2010 NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_name);
2011 NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_id);
2013 return NT_STATUS_OK;
2016 /****************************************************************
2017 ****************************************************************/
2019 static NTSTATUS query_USER_MODALS_INFO_3(TALLOC_CTX *mem_ctx,
2020 struct rpc_pipe_client *pipe_cli,
2021 struct policy_handle *domain_handle,
2022 struct USER_MODALS_INFO_3 *info3)
2024 NTSTATUS status;
2025 struct samr_DomInfo12 dom_info12;
2027 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2028 pipe_cli,
2029 domain_handle,
2030 NULL,
2031 NULL,
2032 NULL,
2033 NULL,
2034 NULL,
2035 &dom_info12);
2036 NT_STATUS_NOT_OK_RETURN(status);
2038 info3->usrmod3_lockout_duration =
2039 nt_time_to_unix_abs(&dom_info12.lockout_duration);
2040 info3->usrmod3_lockout_observation_window =
2041 nt_time_to_unix_abs(&dom_info12.lockout_window);
2042 info3->usrmod3_lockout_threshold =
2043 dom_info12.lockout_threshold;
2045 return NT_STATUS_OK;
2048 /****************************************************************
2049 ****************************************************************/
2051 static NTSTATUS query_USER_MODALS_INFO_to_buffer(TALLOC_CTX *mem_ctx,
2052 struct rpc_pipe_client *pipe_cli,
2053 uint32_t level,
2054 struct policy_handle *domain_handle,
2055 struct dom_sid *domain_sid,
2056 uint8_t **buffer)
2058 NTSTATUS status;
2060 struct USER_MODALS_INFO_0 info0;
2061 struct USER_MODALS_INFO_1 info1;
2062 struct USER_MODALS_INFO_2 info2;
2063 struct USER_MODALS_INFO_3 info3;
2065 if (!buffer) {
2066 return ERROR_INSUFFICIENT_BUFFER;
2069 switch (level) {
2070 case 0:
2071 status = query_USER_MODALS_INFO_0(mem_ctx,
2072 pipe_cli,
2073 domain_handle,
2074 &info0);
2075 NT_STATUS_NOT_OK_RETURN(status);
2077 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0,
2078 sizeof(info0));
2079 break;
2081 case 1:
2082 status = query_USER_MODALS_INFO_1(mem_ctx,
2083 pipe_cli,
2084 domain_handle,
2085 &info1);
2086 NT_STATUS_NOT_OK_RETURN(status);
2088 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1,
2089 sizeof(info1));
2090 break;
2091 case 2:
2092 status = query_USER_MODALS_INFO_2(mem_ctx,
2093 pipe_cli,
2094 domain_handle,
2095 domain_sid,
2096 &info2);
2097 NT_STATUS_NOT_OK_RETURN(status);
2099 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2,
2100 sizeof(info2));
2101 break;
2102 case 3:
2103 status = query_USER_MODALS_INFO_3(mem_ctx,
2104 pipe_cli,
2105 domain_handle,
2106 &info3);
2107 NT_STATUS_NOT_OK_RETURN(status);
2109 *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3,
2110 sizeof(info3));
2111 break;
2112 default:
2113 break;
2116 NT_STATUS_HAVE_NO_MEMORY(*buffer);
2118 return NT_STATUS_OK;
2121 /****************************************************************
2122 ****************************************************************/
2124 WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx,
2125 struct NetUserModalsGet *r)
2127 struct cli_state *cli = NULL;
2128 struct rpc_pipe_client *pipe_cli = NULL;
2129 NTSTATUS status;
2130 WERROR werr;
2132 struct policy_handle connect_handle, domain_handle;
2133 struct dom_sid2 *domain_sid = NULL;
2134 uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2136 ZERO_STRUCT(connect_handle);
2137 ZERO_STRUCT(domain_handle);
2139 if (!r->out.buffer) {
2140 return WERR_INVALID_PARAM;
2143 switch (r->in.level) {
2144 case 0:
2145 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2146 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2147 break;
2148 case 1:
2149 case 2:
2150 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2151 break;
2152 case 3:
2153 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1;
2154 break;
2155 default:
2156 werr = WERR_UNKNOWN_LEVEL;
2157 goto done;
2160 werr = libnetapi_open_pipe(ctx, r->in.server_name,
2161 &ndr_table_samr.syntax_id,
2162 &cli,
2163 &pipe_cli);
2164 if (!W_ERROR_IS_OK(werr)) {
2165 goto done;
2168 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2169 SAMR_ACCESS_ENUM_DOMAINS |
2170 SAMR_ACCESS_OPEN_DOMAIN,
2171 access_mask,
2172 &connect_handle,
2173 &domain_handle,
2174 &domain_sid);
2175 if (!W_ERROR_IS_OK(werr)) {
2176 goto done;
2179 /* 0: 1 + 3 */
2180 /* 1: 6 + 7 */
2181 /* 2: 5 */
2182 /* 3: 12 (DomainInfo2) */
2184 status = query_USER_MODALS_INFO_to_buffer(ctx,
2185 pipe_cli,
2186 r->in.level,
2187 &domain_handle,
2188 domain_sid,
2189 r->out.buffer);
2190 if (!NT_STATUS_IS_OK(status)) {
2191 werr = ntstatus_to_werror(status);
2192 goto done;
2195 done:
2196 if (!cli) {
2197 return werr;
2200 if (ctx->disable_policy_handle_cache) {
2201 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2202 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2205 return werr;
2208 /****************************************************************
2209 ****************************************************************/
2211 WERROR NetUserModalsGet_l(struct libnetapi_ctx *ctx,
2212 struct NetUserModalsGet *r)
2214 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsGet);
2217 /****************************************************************
2218 ****************************************************************/
2220 static NTSTATUS set_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
2221 struct rpc_pipe_client *pipe_cli,
2222 struct policy_handle *domain_handle,
2223 struct samr_DomInfo1 *info1,
2224 struct samr_DomInfo3 *info3,
2225 struct samr_DomInfo12 *info12)
2227 NTSTATUS status;
2228 union samr_DomainInfo dom_info;
2230 if (info1) {
2232 ZERO_STRUCT(dom_info);
2234 dom_info.info1 = *info1;
2236 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2237 domain_handle,
2239 &dom_info);
2240 NT_STATUS_NOT_OK_RETURN(status);
2243 if (info3) {
2245 ZERO_STRUCT(dom_info);
2247 dom_info.info3 = *info3;
2249 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2250 domain_handle,
2252 &dom_info);
2254 NT_STATUS_NOT_OK_RETURN(status);
2257 if (info12) {
2259 ZERO_STRUCT(dom_info);
2261 dom_info.info12 = *info12;
2263 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2264 domain_handle,
2266 &dom_info);
2268 NT_STATUS_NOT_OK_RETURN(status);
2271 return NT_STATUS_OK;
2274 /****************************************************************
2275 ****************************************************************/
2277 static NTSTATUS set_USER_MODALS_INFO_0_buffer(TALLOC_CTX *mem_ctx,
2278 struct rpc_pipe_client *pipe_cli,
2279 struct policy_handle *domain_handle,
2280 struct USER_MODALS_INFO_0 *info0)
2282 NTSTATUS status;
2283 struct samr_DomInfo1 dom_info_1;
2284 struct samr_DomInfo3 dom_info_3;
2286 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2287 pipe_cli,
2288 domain_handle,
2289 &dom_info_1,
2290 &dom_info_3,
2291 NULL,
2292 NULL,
2293 NULL,
2294 NULL);
2295 NT_STATUS_NOT_OK_RETURN(status);
2297 dom_info_1.min_password_length =
2298 info0->usrmod0_min_passwd_len;
2299 dom_info_1.password_history_length =
2300 info0->usrmod0_password_hist_len;
2302 unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2303 info0->usrmod0_max_passwd_age);
2304 unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2305 info0->usrmod0_min_passwd_age);
2307 unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2308 info0->usrmod0_force_logoff);
2310 return set_USER_MODALS_INFO_rpc(mem_ctx,
2311 pipe_cli,
2312 domain_handle,
2313 &dom_info_1,
2314 &dom_info_3,
2315 NULL);
2318 /****************************************************************
2319 ****************************************************************/
2321 static NTSTATUS set_USER_MODALS_INFO_3_buffer(TALLOC_CTX *mem_ctx,
2322 struct rpc_pipe_client *pipe_cli,
2323 struct policy_handle *domain_handle,
2324 struct USER_MODALS_INFO_3 *info3)
2326 NTSTATUS status;
2327 struct samr_DomInfo12 dom_info_12;
2329 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2330 pipe_cli,
2331 domain_handle,
2332 NULL,
2333 NULL,
2334 NULL,
2335 NULL,
2336 NULL,
2337 &dom_info_12);
2338 NT_STATUS_NOT_OK_RETURN(status);
2340 unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_duration,
2341 info3->usrmod3_lockout_duration);
2342 unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_window,
2343 info3->usrmod3_lockout_observation_window);
2344 dom_info_12.lockout_threshold = info3->usrmod3_lockout_threshold;
2346 return set_USER_MODALS_INFO_rpc(mem_ctx,
2347 pipe_cli,
2348 domain_handle,
2349 NULL,
2350 NULL,
2351 &dom_info_12);
2354 /****************************************************************
2355 ****************************************************************/
2357 static NTSTATUS set_USER_MODALS_INFO_1001_buffer(TALLOC_CTX *mem_ctx,
2358 struct rpc_pipe_client *pipe_cli,
2359 struct policy_handle *domain_handle,
2360 struct USER_MODALS_INFO_1001 *info1001)
2362 NTSTATUS status;
2363 struct samr_DomInfo1 dom_info_1;
2365 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2366 pipe_cli,
2367 domain_handle,
2368 &dom_info_1,
2369 NULL,
2370 NULL,
2371 NULL,
2372 NULL,
2373 NULL);
2374 NT_STATUS_NOT_OK_RETURN(status);
2376 dom_info_1.min_password_length =
2377 info1001->usrmod1001_min_passwd_len;
2379 return set_USER_MODALS_INFO_rpc(mem_ctx,
2380 pipe_cli,
2381 domain_handle,
2382 &dom_info_1,
2383 NULL,
2384 NULL);
2387 /****************************************************************
2388 ****************************************************************/
2390 static NTSTATUS set_USER_MODALS_INFO_1002_buffer(TALLOC_CTX *mem_ctx,
2391 struct rpc_pipe_client *pipe_cli,
2392 struct policy_handle *domain_handle,
2393 struct USER_MODALS_INFO_1002 *info1002)
2395 NTSTATUS status;
2396 struct samr_DomInfo1 dom_info_1;
2398 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2399 pipe_cli,
2400 domain_handle,
2401 &dom_info_1,
2402 NULL,
2403 NULL,
2404 NULL,
2405 NULL,
2406 NULL);
2407 NT_STATUS_NOT_OK_RETURN(status);
2409 unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2410 info1002->usrmod1002_max_passwd_age);
2412 return set_USER_MODALS_INFO_rpc(mem_ctx,
2413 pipe_cli,
2414 domain_handle,
2415 &dom_info_1,
2416 NULL,
2417 NULL);
2420 /****************************************************************
2421 ****************************************************************/
2423 static NTSTATUS set_USER_MODALS_INFO_1003_buffer(TALLOC_CTX *mem_ctx,
2424 struct rpc_pipe_client *pipe_cli,
2425 struct policy_handle *domain_handle,
2426 struct USER_MODALS_INFO_1003 *info1003)
2428 NTSTATUS status;
2429 struct samr_DomInfo1 dom_info_1;
2431 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2432 pipe_cli,
2433 domain_handle,
2434 &dom_info_1,
2435 NULL,
2436 NULL,
2437 NULL,
2438 NULL,
2439 NULL);
2440 NT_STATUS_NOT_OK_RETURN(status);
2442 unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2443 info1003->usrmod1003_min_passwd_age);
2445 return set_USER_MODALS_INFO_rpc(mem_ctx,
2446 pipe_cli,
2447 domain_handle,
2448 &dom_info_1,
2449 NULL,
2450 NULL);
2453 /****************************************************************
2454 ****************************************************************/
2456 static NTSTATUS set_USER_MODALS_INFO_1004_buffer(TALLOC_CTX *mem_ctx,
2457 struct rpc_pipe_client *pipe_cli,
2458 struct policy_handle *domain_handle,
2459 struct USER_MODALS_INFO_1004 *info1004)
2461 NTSTATUS status;
2462 struct samr_DomInfo3 dom_info_3;
2464 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2465 pipe_cli,
2466 domain_handle,
2467 NULL,
2468 &dom_info_3,
2469 NULL,
2470 NULL,
2471 NULL,
2472 NULL);
2473 NT_STATUS_NOT_OK_RETURN(status);
2475 unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2476 info1004->usrmod1004_force_logoff);
2478 return set_USER_MODALS_INFO_rpc(mem_ctx,
2479 pipe_cli,
2480 domain_handle,
2481 NULL,
2482 &dom_info_3,
2483 NULL);
2486 /****************************************************************
2487 ****************************************************************/
2489 static NTSTATUS set_USER_MODALS_INFO_1005_buffer(TALLOC_CTX *mem_ctx,
2490 struct rpc_pipe_client *pipe_cli,
2491 struct policy_handle *domain_handle,
2492 struct USER_MODALS_INFO_1005 *info1005)
2494 NTSTATUS status;
2495 struct samr_DomInfo1 dom_info_1;
2497 status = query_USER_MODALS_INFO_rpc(mem_ctx,
2498 pipe_cli,
2499 domain_handle,
2500 &dom_info_1,
2501 NULL,
2502 NULL,
2503 NULL,
2504 NULL,
2505 NULL);
2506 NT_STATUS_NOT_OK_RETURN(status);
2508 dom_info_1.password_history_length =
2509 info1005->usrmod1005_password_hist_len;
2511 return set_USER_MODALS_INFO_rpc(mem_ctx,
2512 pipe_cli,
2513 domain_handle,
2514 &dom_info_1,
2515 NULL,
2516 NULL);
2519 /****************************************************************
2520 ****************************************************************/
2522 static NTSTATUS set_USER_MODALS_INFO_buffer(TALLOC_CTX *mem_ctx,
2523 struct rpc_pipe_client *pipe_cli,
2524 uint32_t level,
2525 struct policy_handle *domain_handle,
2526 struct dom_sid *domain_sid,
2527 uint8_t *buffer)
2529 struct USER_MODALS_INFO_0 *info0;
2530 struct USER_MODALS_INFO_3 *info3;
2531 struct USER_MODALS_INFO_1001 *info1001;
2532 struct USER_MODALS_INFO_1002 *info1002;
2533 struct USER_MODALS_INFO_1003 *info1003;
2534 struct USER_MODALS_INFO_1004 *info1004;
2535 struct USER_MODALS_INFO_1005 *info1005;
2537 if (!buffer) {
2538 return ERROR_INSUFFICIENT_BUFFER;
2541 switch (level) {
2542 case 0:
2543 info0 = (struct USER_MODALS_INFO_0 *)buffer;
2544 return set_USER_MODALS_INFO_0_buffer(mem_ctx,
2545 pipe_cli,
2546 domain_handle,
2547 info0);
2548 case 3:
2549 info3 = (struct USER_MODALS_INFO_3 *)buffer;
2550 return set_USER_MODALS_INFO_3_buffer(mem_ctx,
2551 pipe_cli,
2552 domain_handle,
2553 info3);
2554 case 1001:
2555 info1001 = (struct USER_MODALS_INFO_1001 *)buffer;
2556 return set_USER_MODALS_INFO_1001_buffer(mem_ctx,
2557 pipe_cli,
2558 domain_handle,
2559 info1001);
2560 case 1002:
2561 info1002 = (struct USER_MODALS_INFO_1002 *)buffer;
2562 return set_USER_MODALS_INFO_1002_buffer(mem_ctx,
2563 pipe_cli,
2564 domain_handle,
2565 info1002);
2566 case 1003:
2567 info1003 = (struct USER_MODALS_INFO_1003 *)buffer;
2568 return set_USER_MODALS_INFO_1003_buffer(mem_ctx,
2569 pipe_cli,
2570 domain_handle,
2571 info1003);
2572 case 1004:
2573 info1004 = (struct USER_MODALS_INFO_1004 *)buffer;
2574 return set_USER_MODALS_INFO_1004_buffer(mem_ctx,
2575 pipe_cli,
2576 domain_handle,
2577 info1004);
2578 case 1005:
2579 info1005 = (struct USER_MODALS_INFO_1005 *)buffer;
2580 return set_USER_MODALS_INFO_1005_buffer(mem_ctx,
2581 pipe_cli,
2582 domain_handle,
2583 info1005);
2585 default:
2586 break;
2589 return NT_STATUS_OK;
2592 /****************************************************************
2593 ****************************************************************/
2595 WERROR NetUserModalsSet_r(struct libnetapi_ctx *ctx,
2596 struct NetUserModalsSet *r)
2598 struct cli_state *cli = NULL;
2599 struct rpc_pipe_client *pipe_cli = NULL;
2600 NTSTATUS status;
2601 WERROR werr;
2603 struct policy_handle connect_handle, domain_handle;
2604 struct dom_sid2 *domain_sid = NULL;
2605 uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2607 ZERO_STRUCT(connect_handle);
2608 ZERO_STRUCT(domain_handle);
2610 if (!r->in.buffer) {
2611 return WERR_INVALID_PARAM;
2614 switch (r->in.level) {
2615 case 0:
2616 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2617 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2618 SAMR_DOMAIN_ACCESS_SET_INFO_1 |
2619 SAMR_DOMAIN_ACCESS_SET_INFO_2;
2620 break;
2621 case 3:
2622 case 1001:
2623 case 1002:
2624 case 1003:
2625 case 1005:
2626 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2627 SAMR_DOMAIN_ACCESS_SET_INFO_1;
2628 break;
2629 case 1004:
2630 access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2631 SAMR_DOMAIN_ACCESS_SET_INFO_2;
2632 break;
2633 case 1:
2634 case 2:
2635 case 1006:
2636 case 1007:
2637 werr = WERR_NOT_SUPPORTED;
2638 break;
2639 default:
2640 werr = WERR_UNKNOWN_LEVEL;
2641 goto done;
2644 werr = libnetapi_open_pipe(ctx, r->in.server_name,
2645 &ndr_table_samr.syntax_id,
2646 &cli,
2647 &pipe_cli);
2648 if (!W_ERROR_IS_OK(werr)) {
2649 goto done;
2652 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2653 SAMR_ACCESS_ENUM_DOMAINS |
2654 SAMR_ACCESS_OPEN_DOMAIN,
2655 access_mask,
2656 &connect_handle,
2657 &domain_handle,
2658 &domain_sid);
2659 if (!W_ERROR_IS_OK(werr)) {
2660 goto done;
2663 status = set_USER_MODALS_INFO_buffer(ctx,
2664 pipe_cli,
2665 r->in.level,
2666 &domain_handle,
2667 domain_sid,
2668 r->in.buffer);
2669 if (!NT_STATUS_IS_OK(status)) {
2670 werr = ntstatus_to_werror(status);
2671 goto done;
2674 done:
2675 if (!cli) {
2676 return werr;
2679 if (ctx->disable_policy_handle_cache) {
2680 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2681 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2684 return werr;
2687 /****************************************************************
2688 ****************************************************************/
2690 WERROR NetUserModalsSet_l(struct libnetapi_ctx *ctx,
2691 struct NetUserModalsSet *r)
2693 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsSet);
2696 /****************************************************************
2697 ****************************************************************/
2699 static NTSTATUS add_GROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
2700 uint32_t level,
2701 const char *group_name,
2702 uint32_t attributes,
2703 uint8_t **buffer,
2704 uint32_t *num_entries)
2706 struct GROUP_USERS_INFO_0 u0;
2707 struct GROUP_USERS_INFO_1 u1;
2709 switch (level) {
2710 case 0:
2711 u0.grui0_name = talloc_strdup(mem_ctx, group_name);
2712 NT_STATUS_HAVE_NO_MEMORY(u0.grui0_name);
2714 ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_0, u0,
2715 (struct GROUP_USERS_INFO_0 **)buffer, num_entries);
2716 break;
2717 case 1:
2718 u1.grui1_name = talloc_strdup(mem_ctx, group_name);
2719 NT_STATUS_HAVE_NO_MEMORY(u1.grui1_name);
2721 u1.grui1_attributes = attributes;
2723 ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_1, u1,
2724 (struct GROUP_USERS_INFO_1 **)buffer, num_entries);
2725 break;
2726 default:
2727 return NT_STATUS_INVALID_INFO_CLASS;
2730 return NT_STATUS_OK;
2733 /****************************************************************
2734 ****************************************************************/
2736 WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
2737 struct NetUserGetGroups *r)
2739 struct cli_state *cli = NULL;
2740 struct rpc_pipe_client *pipe_cli = NULL;
2741 struct policy_handle connect_handle, domain_handle, user_handle;
2742 struct lsa_String lsa_account_name;
2743 struct dom_sid2 *domain_sid = NULL;
2744 struct samr_Ids user_rids, name_types;
2745 struct samr_RidWithAttributeArray *rid_array = NULL;
2746 struct lsa_Strings names;
2747 struct samr_Ids types;
2748 uint32_t *rids = NULL;
2750 int i;
2751 uint32_t entries_read = 0;
2753 NTSTATUS status = NT_STATUS_OK;
2754 WERROR werr;
2756 ZERO_STRUCT(connect_handle);
2757 ZERO_STRUCT(domain_handle);
2759 if (!r->out.buffer) {
2760 return WERR_INVALID_PARAM;
2763 *r->out.buffer = NULL;
2764 *r->out.entries_read = 0;
2766 switch (r->in.level) {
2767 case 0:
2768 case 1:
2769 break;
2770 default:
2771 return WERR_UNKNOWN_LEVEL;
2774 werr = libnetapi_open_pipe(ctx, r->in.server_name,
2775 &ndr_table_samr.syntax_id,
2776 &cli,
2777 &pipe_cli);
2778 if (!W_ERROR_IS_OK(werr)) {
2779 goto done;
2782 werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2783 SAMR_ACCESS_ENUM_DOMAINS |
2784 SAMR_ACCESS_OPEN_DOMAIN,
2785 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2786 &connect_handle,
2787 &domain_handle,
2788 &domain_sid);
2789 if (!W_ERROR_IS_OK(werr)) {
2790 goto done;
2793 init_lsa_String(&lsa_account_name, r->in.user_name);
2795 status = rpccli_samr_LookupNames(pipe_cli, ctx,
2796 &domain_handle,
2798 &lsa_account_name,
2799 &user_rids,
2800 &name_types);
2801 if (!NT_STATUS_IS_OK(status)) {
2802 werr = ntstatus_to_werror(status);
2803 goto done;
2806 status = rpccli_samr_OpenUser(pipe_cli, ctx,
2807 &domain_handle,
2808 SAMR_USER_ACCESS_GET_GROUPS,
2809 user_rids.ids[0],
2810 &user_handle);
2811 if (!NT_STATUS_IS_OK(status)) {
2812 werr = ntstatus_to_werror(status);
2813 goto done;
2816 status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
2817 &user_handle,
2818 &rid_array);
2819 if (!NT_STATUS_IS_OK(status)) {
2820 werr = ntstatus_to_werror(status);
2821 goto done;
2824 rids = talloc_array(ctx, uint32_t, rid_array->count);
2825 if (!rids) {
2826 werr = WERR_NOMEM;
2827 goto done;
2830 for (i=0; i < rid_array->count; i++) {
2831 rids[i] = rid_array->rids[i].rid;
2834 status = rpccli_samr_LookupRids(pipe_cli, ctx,
2835 &domain_handle,
2836 rid_array->count,
2837 rids,
2838 &names,
2839 &types);
2840 if (!NT_STATUS_IS_OK(status)) {
2841 werr = ntstatus_to_werror(status);
2842 goto done;
2845 for (i=0; i < rid_array->count; i++) {
2846 status = add_GROUP_USERS_INFO_X_buffer(ctx,
2847 r->in.level,
2848 names.names[i].string,
2849 rid_array->rids[i].attributes,
2850 r->out.buffer,
2851 &entries_read);
2852 if (!NT_STATUS_IS_OK(status)) {
2853 werr = ntstatus_to_werror(status);
2854 goto done;
2858 if (r->out.entries_read) {
2859 *r->out.entries_read = entries_read;
2861 if (r->out.total_entries) {
2862 *r->out.total_entries = entries_read;
2865 done:
2866 if (!cli) {
2867 return werr;
2870 if (ctx->disable_policy_handle_cache) {
2871 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2872 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2875 return werr;
2878 /****************************************************************
2879 ****************************************************************/
2881 WERROR NetUserGetGroups_l(struct libnetapi_ctx *ctx,
2882 struct NetUserGetGroups *r)
2884 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetGroups);