Merge branch 'v3-devel' of ssh://jra@git.samba.org/data/git/samba into v3-devel
[ira/wip.git] / source3 / lib / netapi / user.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  NetApi User Support
4  *  Copyright (C) Guenther Deschner 2008
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "includes.h"
21
22 #include "librpc/gen_ndr/libnetapi.h"
23 #include "lib/netapi/netapi.h"
24 #include "lib/netapi/netapi_private.h"
25 #include "lib/netapi/libnetapi.h"
26
27 /****************************************************************
28 ****************************************************************/
29
30 static void convert_USER_INFO_X_to_samr_user_info21(struct USER_INFO_X *infoX,
31                                                     struct samr_UserInfo21 *info21)
32 {
33         uint32_t fields_present = 0;
34         struct samr_LogonHours zero_logon_hours;
35         struct lsa_BinaryString zero_parameters;
36         NTTIME password_age;
37
38         ZERO_STRUCTP(info21);
39         ZERO_STRUCT(zero_logon_hours);
40         ZERO_STRUCT(zero_parameters);
41
42         if (infoX->usriX_flags) {
43                 fields_present |= SAMR_FIELD_ACCT_FLAGS;
44         }
45         if (infoX->usriX_name) {
46                 fields_present |= SAMR_FIELD_ACCOUNT_NAME;
47         }
48         if (infoX->usriX_password) {
49                 fields_present |= SAMR_FIELD_PASSWORD;
50         }
51         if (infoX->usriX_flags) {
52                 fields_present |= SAMR_FIELD_ACCT_FLAGS;
53         }
54         if (infoX->usriX_name) {
55                 fields_present |= SAMR_FIELD_FULL_NAME;
56         }
57         if (infoX->usriX_home_dir) {
58                 fields_present |= SAMR_FIELD_HOME_DIRECTORY;
59         }
60         if (infoX->usriX_script_path) {
61                 fields_present |= SAMR_FIELD_LOGON_SCRIPT;
62         }
63         if (infoX->usriX_comment) {
64                 fields_present |= SAMR_FIELD_DESCRIPTION;
65         }
66         if (infoX->usriX_password_age) {
67                 fields_present |= SAMR_FIELD_FORCE_PWD_CHANGE;
68         }
69         if (infoX->usriX_full_name) {
70                 fields_present |= SAMR_FIELD_FULL_NAME;
71         }
72         if (infoX->usriX_usr_comment) {
73                 fields_present |= SAMR_FIELD_COMMENT;
74         }
75         if (infoX->usriX_profile) {
76                 fields_present |= SAMR_FIELD_PROFILE_PATH;
77         }
78         if (infoX->usriX_home_dir_drive) {
79                 fields_present |= SAMR_FIELD_HOME_DRIVE;
80         }
81         if (infoX->usriX_primary_group_id) {
82                 fields_present |= SAMR_FIELD_PRIMARY_GID;
83         }
84         if (infoX->usriX_country_code) {
85                 fields_present |= SAMR_FIELD_COUNTRY_CODE;
86         }
87         if (infoX->usriX_workstations) {
88                 fields_present |= SAMR_FIELD_WORKSTATIONS;
89         }
90
91         unix_to_nt_time_abs(&password_age, infoX->usriX_password_age);
92
93         /* TODO: infoX->usriX_priv */
94         init_samr_user_info21(info21,
95                               0,
96                               0,
97                               0,
98                               0,
99                               0,
100                               password_age,
101                               infoX->usriX_name,
102                               infoX->usriX_full_name,
103                               infoX->usriX_home_dir,
104                               infoX->usriX_home_dir_drive,
105                               infoX->usriX_script_path,
106                               infoX->usriX_profile,
107                               infoX->usriX_comment,
108                               infoX->usriX_workstations,
109                               infoX->usriX_usr_comment,
110                               &zero_parameters,
111                               0,
112                               infoX->usriX_primary_group_id,
113                               infoX->usriX_flags,
114                               fields_present,
115                               zero_logon_hours,
116                               0,
117                               0,
118                               infoX->usriX_country_code,
119                               0,
120                               0,
121                               0,
122                               0);
123 }
124
125 /****************************************************************
126 ****************************************************************/
127
128 static NTSTATUS construct_USER_INFO_X(uint32_t level,
129                                       uint8_t *buffer,
130                                       struct USER_INFO_X *uX)
131 {
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;
146
147         if (!buffer || !uX) {
148                 return NT_STATUS_INVALID_PARAMETER;
149         }
150
151         ZERO_STRUCTP(uX);
152
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;
244         }
245
246         return NT_STATUS_OK;
247 }
248
249 /****************************************************************
250 ****************************************************************/
251
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)
257 {
258         union samr_UserInfo user_info;
259         struct samr_UserInfo21 info21;
260         NTSTATUS status;
261
262         if (!uX) {
263                 return NT_STATUS_INVALID_PARAMETER;
264         }
265
266         convert_USER_INFO_X_to_samr_user_info21(uX, &info21);
267
268         ZERO_STRUCT(user_info);
269
270         if (uX->usriX_password) {
271
272                 user_info.info25.info = info21;
273
274                 init_samr_CryptPasswordEx(uX->usriX_password,
275                                           session_key,
276                                           &user_info.info25.password);
277
278                 status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
279                                                   user_handle,
280                                                   25,
281                                                   &user_info);
282
283                 if (NT_STATUS_EQUAL(status, NT_STATUS(DCERPC_FAULT_INVALID_TAG))) {
284
285                         user_info.info23.info = info21;
286
287                         init_samr_CryptPassword(uX->usriX_password,
288                                                 session_key,
289                                                 &user_info.info23.password);
290
291                         status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
292                                                           user_handle,
293                                                           23,
294                                                           &user_info);
295                 }
296         } else {
297
298                 user_info.info21 = info21;
299
300                 status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
301                                                  user_handle,
302                                                  21,
303                                                  &user_info);
304         }
305
306         return status;
307 }
308
309 /****************************************************************
310 ****************************************************************/
311
312 WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
313                     struct NetUserAdd *r)
314 {
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;
327
328         ZERO_STRUCT(connect_handle);
329         ZERO_STRUCT(domain_handle);
330         ZERO_STRUCT(user_handle);
331
332         if (!r->in.buffer) {
333                 return WERR_INVALID_PARAM;
334         }
335
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;
345         }
346
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;
353         }
354
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;
359         }
360
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;
372         }
373
374         init_lsa_String(&lsa_account_name, uX.usriX_name);
375
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;
391         }
392
393         status = rpccli_samr_QueryUserInfo(pipe_cli, ctx,
394                                            &user_handle,
395                                            16,
396                                            &user_info);
397         if (!NT_STATUS_IS_OK(status)) {
398                 werr = ntstatus_to_werror(status);
399                 goto done;
400         }
401
402         if (!(user_info->info16.acct_flags & ACB_NORMAL)) {
403                 werr = WERR_INVALID_PARAM;
404                 goto done;
405         }
406
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;
413         }
414
415         uX.usriX_flags |= ACB_NORMAL;
416
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;
424         }
425
426         werr = WERR_OK;
427         goto done;
428
429  failed:
430         rpccli_samr_DeleteUser(pipe_cli, ctx,
431                                &user_handle);
432
433  done:
434         if (!cli) {
435                 return werr;
436         }
437
438         if (is_valid_policy_hnd(&user_handle)) {
439                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
440         }
441
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);
445         }
446
447         return werr;
448 }
449
450 /****************************************************************
451 ****************************************************************/
452
453 WERROR NetUserAdd_l(struct libnetapi_ctx *ctx,
454                     struct NetUserAdd *r)
455 {
456         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserAdd);
457 }
458
459 /****************************************************************
460 ****************************************************************/
461
462 WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
463                     struct NetUserDel *r)
464 {
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;
474
475         ZERO_STRUCT(connect_handle);
476         ZERO_STRUCT(builtin_handle);
477         ZERO_STRUCT(domain_handle);
478         ZERO_STRUCT(user_handle);
479
480         werr = libnetapi_open_pipe(ctx, r->in.server_name,
481                                    &ndr_table_samr.syntax_id,
482                                    &cli,
483                                    &pipe_cli);
484
485         if (!W_ERROR_IS_OK(werr)) {
486                 goto done;
487         }
488
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;
498         }
499
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;
508         }
509
510         init_lsa_String(&lsa_account_name, r->in.user_name);
511
512         status = rpccli_samr_LookupNames(pipe_cli, ctx,
513                                          &domain_handle,
514                                          1,
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;
521         }
522
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;
531         }
532
533         sid_compose(&user_sid, domain_sid, user_rids.ids[0]);
534
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;
541         }
542
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;
548         }
549
550         werr = WERR_OK;
551
552  done:
553         if (!cli) {
554                 return werr;
555         }
556
557         if (is_valid_policy_hnd(&user_handle)) {
558                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
559         }
560
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);
565         }
566
567         return werr;
568 }
569
570 /****************************************************************
571 ****************************************************************/
572
573 WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
574                     struct NetUserDel *r)
575 {
576         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserDel);
577 }
578
579 /****************************************************************
580 ****************************************************************/
581
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)
593 {
594         NTSTATUS status;
595
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;
602
603         ZERO_STRUCT(user_handle);
604
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;
626         }
627
628         if (level == 0) {
629                 return NT_STATUS_OK;
630         }
631
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;
639         }
640
641         status = rpccli_samr_QueryUserInfo(pipe_cli, mem_ctx,
642                                            &user_handle,
643                                            21,
644                                            &user_info);
645         if (!NT_STATUS_IS_OK(status)) {
646                 goto done;
647         }
648
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;
655         }
656
657         if (access_mask & SAMR_USER_ACCESS_GET_GROUPS) {
658
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;
664
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;
670                 }
671
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);
676
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);
681                 }
682
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);
686
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;
693                 }
694
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;
708                         }
709                 }
710
711                 if (auth_flag_p) {
712                         *auth_flag_p = auth_flag;
713                 }
714         }
715
716         *info21 = &user_info->info21;
717
718  done:
719         if (is_valid_policy_hnd(&user_handle)) {
720                 rpccli_samr_Close(pipe_cli, mem_ctx, &user_handle);
721         }
722
723         return status;
724 }
725
726 /****************************************************************
727 ****************************************************************/
728
729 static uint32_t samr_rid_to_priv_level(uint32_t rid)
730 {
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;
738         }
739 }
740
741 /****************************************************************
742 ****************************************************************/
743
744 static uint32_t samr_acb_flags_to_netapi_flags(uint32_t acb)
745 {
746         uint32_t fl = UF_SCRIPT; /* god knows why */
747
748         fl |= ads_acb2uf(acb);
749
750         return fl;
751 }
752
753 /****************************************************************
754 ****************************************************************/
755
756 static NTSTATUS info21_to_USER_INFO_1(TALLOC_CTX *mem_ctx,
757                                       const struct samr_UserInfo21 *i21,
758                                       struct USER_INFO_1 *i)
759 {
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);
770
771         return NT_STATUS_OK;
772 }
773
774 /****************************************************************
775 ****************************************************************/
776
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)
781 {
782         ZERO_STRUCTP(i);
783
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;
809
810         return NT_STATUS_OK;
811 }
812
813 /****************************************************************
814 ****************************************************************/
815
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)
820 {
821         ZERO_STRUCTP(i);
822
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;
852
853         return NT_STATUS_OK;
854 }
855
856 /****************************************************************
857 ****************************************************************/
858
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)
864 {
865         struct dom_sid sid;
866
867         ZERO_STRUCTP(i);
868
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;
896         }
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;
902
903         return NT_STATUS_OK;
904 }
905
906 /****************************************************************
907 ****************************************************************/
908
909 static NTSTATUS info21_to_USER_INFO_10(TALLOC_CTX *mem_ctx,
910                                        const struct samr_UserInfo21 *i21,
911                                        struct USER_INFO_10 *i)
912 {
913         ZERO_STRUCTP(i);
914
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);
920
921         return NT_STATUS_OK;
922 }
923
924 /****************************************************************
925 ****************************************************************/
926
927 static NTSTATUS info21_to_USER_INFO_11(TALLOC_CTX *mem_ctx,
928                                        const struct samr_UserInfo21 *i21,
929                                        uint32_t auth_flag,
930                                        struct USER_INFO_11 *i)
931 {
932         ZERO_STRUCTP(i);
933
934         i->usri11_name          = talloc_strdup(mem_ctx, i21->account_name.string);
935         NT_STATUS_HAVE_NO_MEMORY(i->usri11_name);
936         i->usri11_comment       = talloc_strdup(mem_ctx, i21->description.string);
937         i->usri11_usr_comment   = talloc_strdup(mem_ctx, i21->comment.string);
938         i->usri11_full_name     = talloc_strdup(mem_ctx, i21->full_name.string);
939         i->usri11_priv          = samr_rid_to_priv_level(i21->rid);
940         i->usri11_auth_flags    = auth_flag;
941         i->usri11_password_age  = time(NULL) - nt_time_to_unix(i21->last_password_change);
942         i->usri11_home_dir      = talloc_strdup(mem_ctx, i21->home_directory.string);
943         i->usri11_parms         = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
944         i->usri11_last_logon    = nt_time_to_unix(i21->last_logon);
945         i->usri11_last_logoff   = nt_time_to_unix(i21->last_logoff);
946         i->usri11_bad_pw_count  = i21->bad_password_count;
947         i->usri11_num_logons    = i21->logon_count;
948         i->usri11_logon_server  = talloc_strdup(mem_ctx, "\\\\*");
949         i->usri11_country_code  = i21->country_code;
950         i->usri11_workstations  = talloc_strdup(mem_ctx, i21->workstations.string);
951         i->usri11_max_storage   = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
952         i->usri11_units_per_week = i21->logon_hours.units_per_week;
953         i->usri11_logon_hours   = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
954         i->usri11_code_page     = i21->code_page;
955
956         return NT_STATUS_OK;
957 }
958
959 /****************************************************************
960 ****************************************************************/
961
962 static NTSTATUS info21_to_USER_INFO_20(TALLOC_CTX *mem_ctx,
963                                        const struct samr_UserInfo21 *i21,
964                                        struct USER_INFO_20 *i)
965 {
966         ZERO_STRUCTP(i);
967
968         i->usri20_name          = talloc_strdup(mem_ctx, i21->account_name.string);
969         NT_STATUS_HAVE_NO_MEMORY(i->usri20_name);
970         i->usri20_comment       = talloc_strdup(mem_ctx, i21->description.string);
971         i->usri20_full_name     = talloc_strdup(mem_ctx, i21->full_name.string);
972         i->usri20_flags         = samr_acb_flags_to_netapi_flags(i21->acct_flags);
973         i->usri20_user_id       = i21->rid;
974
975         return NT_STATUS_OK;
976 }
977
978 /****************************************************************
979 ****************************************************************/
980
981 static NTSTATUS info21_to_USER_INFO_23(TALLOC_CTX *mem_ctx,
982                                        const struct samr_UserInfo21 *i21,
983                                        struct dom_sid *domain_sid,
984                                        struct USER_INFO_23 *i)
985 {
986         struct dom_sid sid;
987
988         ZERO_STRUCTP(i);
989
990         i->usri23_name          = talloc_strdup(mem_ctx, i21->account_name.string);
991         NT_STATUS_HAVE_NO_MEMORY(i->usri23_name);
992         i->usri23_comment       = talloc_strdup(mem_ctx, i21->description.string);
993         i->usri23_full_name     = talloc_strdup(mem_ctx, i21->full_name.string);
994         i->usri23_flags         = samr_acb_flags_to_netapi_flags(i21->acct_flags);
995         if (!sid_compose(&sid, domain_sid, i21->rid)) {
996                 return NT_STATUS_NO_MEMORY;
997         }
998         i->usri23_user_sid      = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
999
1000         return NT_STATUS_OK;
1001 }
1002
1003 /****************************************************************
1004 ****************************************************************/
1005
1006 static NTSTATUS libnetapi_samr_lookup_user_map_USER_INFO(TALLOC_CTX *mem_ctx,
1007                                                          struct rpc_pipe_client *pipe_cli,
1008                                                          struct dom_sid *domain_sid,
1009                                                          struct policy_handle *domain_handle,
1010                                                          struct policy_handle *builtin_handle,
1011                                                          const char *user_name,
1012                                                          uint32_t rid,
1013                                                          uint32_t level,
1014                                                          uint8_t **buffer,
1015                                                          uint32_t *num_entries)
1016 {
1017         NTSTATUS status;
1018
1019         struct samr_UserInfo21 *info21 = NULL;
1020         struct sec_desc_buf *sec_desc = NULL;
1021         uint32_t auth_flag = 0;
1022
1023         struct USER_INFO_0 info0;
1024         struct USER_INFO_1 info1;
1025         struct USER_INFO_2 info2;
1026         struct USER_INFO_3 info3;
1027         struct USER_INFO_4 info4;
1028         struct USER_INFO_10 info10;
1029         struct USER_INFO_11 info11;
1030         struct USER_INFO_20 info20;
1031         struct USER_INFO_23 info23;
1032
1033         switch (level) {
1034                 case 0:
1035                 case 1:
1036                 case 2:
1037                 case 3:
1038                 case 4:
1039                 case 10:
1040                 case 11:
1041                 case 20:
1042                 case 23:
1043                         break;
1044                 default:
1045                         return NT_STATUS_INVALID_LEVEL;
1046         }
1047
1048         if (level == 0) {
1049                 info0.usri0_name = talloc_strdup(mem_ctx, user_name);
1050                 NT_STATUS_HAVE_NO_MEMORY(info0.usri0_name);
1051
1052                 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_0, info0,
1053                              (struct USER_INFO_0 **)buffer, num_entries);
1054
1055                 return NT_STATUS_OK;
1056         }
1057
1058         status = libnetapi_samr_lookup_user(mem_ctx, pipe_cli,
1059                                             domain_handle,
1060                                             builtin_handle,
1061                                             user_name,
1062                                             domain_sid,
1063                                             rid,
1064                                             level,
1065                                             &info21,
1066                                             &sec_desc,
1067                                             &auth_flag);
1068
1069         if (!NT_STATUS_IS_OK(status)) {
1070                 goto done;
1071         }
1072
1073         switch (level) {
1074                 case 0:
1075                         /* already returned above */
1076                         break;
1077                 case 1:
1078                         status = info21_to_USER_INFO_1(mem_ctx, info21, &info1);
1079                         NT_STATUS_NOT_OK_RETURN(status);
1080
1081                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_1, info1,
1082                                      (struct USER_INFO_1 **)buffer, num_entries);
1083
1084                         break;
1085                 case 2:
1086                         status = info21_to_USER_INFO_2(mem_ctx, info21, auth_flag, &info2);
1087                         NT_STATUS_NOT_OK_RETURN(status);
1088
1089                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_2, info2,
1090                                      (struct USER_INFO_2 **)buffer, num_entries);
1091
1092                         break;
1093                 case 3:
1094                         status = info21_to_USER_INFO_3(mem_ctx, info21, auth_flag, &info3);
1095                         NT_STATUS_NOT_OK_RETURN(status);
1096
1097                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_3, info3,
1098                                      (struct USER_INFO_3 **)buffer, num_entries);
1099
1100                         break;
1101                 case 4:
1102                         status = info21_to_USER_INFO_4(mem_ctx, info21, auth_flag, domain_sid, &info4);
1103                         NT_STATUS_NOT_OK_RETURN(status);
1104
1105                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_4, info4,
1106                                      (struct USER_INFO_4 **)buffer, num_entries);
1107
1108                         break;
1109                 case 10:
1110                         status = info21_to_USER_INFO_10(mem_ctx, info21, &info10);
1111                         NT_STATUS_NOT_OK_RETURN(status);
1112
1113                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_10, info10,
1114                                      (struct USER_INFO_10 **)buffer, num_entries);
1115
1116                         break;
1117                 case 11:
1118                         status = info21_to_USER_INFO_11(mem_ctx, info21, auth_flag, &info11);
1119                         NT_STATUS_NOT_OK_RETURN(status);
1120
1121                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_11, info11,
1122                                      (struct USER_INFO_11 **)buffer, num_entries);
1123
1124                         break;
1125                 case 20:
1126                         status = info21_to_USER_INFO_20(mem_ctx, info21, &info20);
1127                         NT_STATUS_NOT_OK_RETURN(status);
1128
1129                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_20, info20,
1130                                      (struct USER_INFO_20 **)buffer, num_entries);
1131
1132                         break;
1133                 case 23:
1134                         status = info21_to_USER_INFO_23(mem_ctx, info21, domain_sid, &info23);
1135                         NT_STATUS_NOT_OK_RETURN(status);
1136
1137                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_23, info23,
1138                                      (struct USER_INFO_23 **)buffer, num_entries);
1139                         break;
1140                 default:
1141                         return NT_STATUS_INVALID_LEVEL;
1142         }
1143
1144  done:
1145         return status;
1146 }
1147
1148 /****************************************************************
1149 ****************************************************************/
1150
1151 WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
1152                      struct NetUserEnum *r)
1153 {
1154         struct cli_state *cli = NULL;
1155         struct rpc_pipe_client *pipe_cli = NULL;
1156         struct policy_handle connect_handle;
1157         struct dom_sid2 *domain_sid = NULL;
1158         struct policy_handle domain_handle, builtin_handle;
1159         struct samr_SamArray *sam = NULL;
1160         uint32_t filter = ACB_NORMAL;
1161         int i;
1162         uint32_t entries_read = 0;
1163
1164         NTSTATUS status = NT_STATUS_OK;
1165         WERROR werr;
1166
1167         ZERO_STRUCT(connect_handle);
1168         ZERO_STRUCT(domain_handle);
1169         ZERO_STRUCT(builtin_handle);
1170
1171         if (!r->out.buffer) {
1172                 return WERR_INVALID_PARAM;
1173         }
1174
1175         *r->out.buffer = NULL;
1176         *r->out.entries_read = 0;
1177
1178         switch (r->in.level) {
1179                 case 0:
1180                 case 1:
1181                 case 2:
1182                 case 3:
1183                 case 4:
1184                 case 10:
1185                 case 11:
1186                 case 20:
1187                 case 23:
1188                         break;
1189                 default:
1190                         return WERR_UNKNOWN_LEVEL;
1191         }
1192
1193         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1194                                    &ndr_table_samr.syntax_id,
1195                                    &cli,
1196                                    &pipe_cli);
1197         if (!W_ERROR_IS_OK(werr)) {
1198                 goto done;
1199         }
1200
1201         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1202                                                   SAMR_ACCESS_ENUM_DOMAINS |
1203                                                   SAMR_ACCESS_OPEN_DOMAIN,
1204                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1205                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1206                                                   &connect_handle,
1207                                                   &builtin_handle);
1208         if (!W_ERROR_IS_OK(werr)) {
1209                 goto done;
1210         }
1211
1212         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1213                                           SAMR_ACCESS_ENUM_DOMAINS |
1214                                           SAMR_ACCESS_OPEN_DOMAIN,
1215                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1216                                           SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1217                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1218                                           &connect_handle,
1219                                           &domain_handle,
1220                                           &domain_sid);
1221         if (!W_ERROR_IS_OK(werr)) {
1222                 goto done;
1223         }
1224
1225         switch (r->in.filter) {
1226                 case FILTER_NORMAL_ACCOUNT:
1227                         filter = ACB_NORMAL;
1228                         break;
1229                 case FILTER_TEMP_DUPLICATE_ACCOUNT:
1230                         filter = ACB_TEMPDUP;
1231                         break;
1232                 case FILTER_INTERDOMAIN_TRUST_ACCOUNT:
1233                         filter = ACB_DOMTRUST;
1234                         break;
1235                 case FILTER_WORKSTATION_TRUST_ACCOUNT:
1236                         filter = ACB_WSTRUST;
1237                         break;
1238                 case FILTER_SERVER_TRUST_ACCOUNT:
1239                         filter = ACB_SVRTRUST;
1240                         break;
1241                 default:
1242                         break;
1243         }
1244
1245         status = rpccli_samr_EnumDomainUsers(pipe_cli,
1246                                              ctx,
1247                                              &domain_handle,
1248                                              r->in.resume_handle,
1249                                              filter,
1250                                              &sam,
1251                                              r->in.prefmaxlen,
1252                                              &entries_read);
1253         werr = ntstatus_to_werror(status);
1254         if (NT_STATUS_IS_ERR(status)) {
1255                 goto done;
1256         }
1257
1258         for (i=0; i < sam->count; i++) {
1259
1260                 status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1261                                                                   domain_sid,
1262                                                                   &domain_handle,
1263                                                                   &builtin_handle,
1264                                                                   sam->entries[i].name.string,
1265                                                                   sam->entries[i].idx,
1266                                                                   r->in.level,
1267                                                                   r->out.buffer,
1268                                                                   r->out.entries_read);
1269                 if (!NT_STATUS_IS_OK(status)) {
1270                         werr = ntstatus_to_werror(status);
1271                         goto done;
1272                 }
1273         }
1274
1275  done:
1276         if (!cli) {
1277                 return werr;
1278         }
1279
1280         /* if last query */
1281         if (NT_STATUS_IS_OK(status) ||
1282             NT_STATUS_IS_ERR(status)) {
1283
1284                 if (ctx->disable_policy_handle_cache) {
1285                         libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1286                         libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1287                         libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1288                 }
1289         }
1290
1291         return werr;
1292 }
1293
1294 /****************************************************************
1295 ****************************************************************/
1296
1297 WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
1298                      struct NetUserEnum *r)
1299 {
1300         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserEnum);
1301 }
1302
1303 /****************************************************************
1304 ****************************************************************/
1305
1306 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_USER(TALLOC_CTX *mem_ctx,
1307                                                         struct samr_DispInfoGeneral *info,
1308                                                         uint32_t *entries_read,
1309                                                         void **buffer)
1310 {
1311         struct NET_DISPLAY_USER *user = NULL;
1312         int i;
1313
1314         user = TALLOC_ZERO_ARRAY(mem_ctx,
1315                                  struct NET_DISPLAY_USER,
1316                                  info->count);
1317         W_ERROR_HAVE_NO_MEMORY(user);
1318
1319         for (i = 0; i < info->count; i++) {
1320                 user[i].usri1_name = talloc_strdup(mem_ctx,
1321                         info->entries[i].account_name.string);
1322                 user[i].usri1_comment = talloc_strdup(mem_ctx,
1323                         info->entries[i].description.string);
1324                 user[i].usri1_flags =
1325                         info->entries[i].acct_flags;
1326                 user[i].usri1_full_name = talloc_strdup(mem_ctx,
1327                         info->entries[i].full_name.string);
1328                 user[i].usri1_user_id =
1329                         info->entries[i].rid;
1330                 user[i].usri1_next_index =
1331                         info->entries[i].idx;
1332
1333                 if (!user[i].usri1_name) {
1334                         return WERR_NOMEM;
1335                 }
1336         }
1337
1338         *buffer = talloc_memdup(mem_ctx, user,
1339                 sizeof(struct NET_DISPLAY_USER) * info->count);
1340         W_ERROR_HAVE_NO_MEMORY(*buffer);
1341
1342         *entries_read = info->count;
1343
1344         return WERR_OK;
1345 }
1346
1347 /****************************************************************
1348 ****************************************************************/
1349
1350 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(TALLOC_CTX *mem_ctx,
1351                                                            struct samr_DispInfoFull *info,
1352                                                            uint32_t *entries_read,
1353                                                            void **buffer)
1354 {
1355         struct NET_DISPLAY_MACHINE *machine = NULL;
1356         int i;
1357
1358         machine = TALLOC_ZERO_ARRAY(mem_ctx,
1359                                     struct NET_DISPLAY_MACHINE,
1360                                     info->count);
1361         W_ERROR_HAVE_NO_MEMORY(machine);
1362
1363         for (i = 0; i < info->count; i++) {
1364                 machine[i].usri2_name = talloc_strdup(mem_ctx,
1365                         info->entries[i].account_name.string);
1366                 machine[i].usri2_comment = talloc_strdup(mem_ctx,
1367                         info->entries[i].description.string);
1368                 machine[i].usri2_flags =
1369                         info->entries[i].acct_flags;
1370                 machine[i].usri2_user_id =
1371                         info->entries[i].rid;
1372                 machine[i].usri2_next_index =
1373                         info->entries[i].idx;
1374
1375                 if (!machine[i].usri2_name) {
1376                         return WERR_NOMEM;
1377                 }
1378         }
1379
1380         *buffer = talloc_memdup(mem_ctx, machine,
1381                 sizeof(struct NET_DISPLAY_MACHINE) * info->count);
1382         W_ERROR_HAVE_NO_MEMORY(*buffer);
1383
1384         *entries_read = info->count;
1385
1386         return WERR_OK;
1387 }
1388
1389 /****************************************************************
1390 ****************************************************************/
1391
1392 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_GROUP(TALLOC_CTX *mem_ctx,
1393                                                          struct samr_DispInfoFullGroups *info,
1394                                                          uint32_t *entries_read,
1395                                                          void **buffer)
1396 {
1397         struct NET_DISPLAY_GROUP *group = NULL;
1398         int i;
1399
1400         group = TALLOC_ZERO_ARRAY(mem_ctx,
1401                                   struct NET_DISPLAY_GROUP,
1402                                   info->count);
1403         W_ERROR_HAVE_NO_MEMORY(group);
1404
1405         for (i = 0; i < info->count; i++) {
1406                 group[i].grpi3_name = talloc_strdup(mem_ctx,
1407                         info->entries[i].account_name.string);
1408                 group[i].grpi3_comment = talloc_strdup(mem_ctx,
1409                         info->entries[i].description.string);
1410                 group[i].grpi3_group_id =
1411                         info->entries[i].rid;
1412                 group[i].grpi3_attributes =
1413                         info->entries[i].acct_flags;
1414                 group[i].grpi3_next_index =
1415                         info->entries[i].idx;
1416
1417                 if (!group[i].grpi3_name) {
1418                         return WERR_NOMEM;
1419                 }
1420         }
1421
1422         *buffer = talloc_memdup(mem_ctx, group,
1423                 sizeof(struct NET_DISPLAY_GROUP) * info->count);
1424         W_ERROR_HAVE_NO_MEMORY(*buffer);
1425
1426         *entries_read = info->count;
1427
1428         return WERR_OK;
1429
1430 }
1431
1432 /****************************************************************
1433 ****************************************************************/
1434
1435 static WERROR convert_samr_dispinfo_to_NET_DISPLAY(TALLOC_CTX *mem_ctx,
1436                                                    union samr_DispInfo *info,
1437                                                    uint32_t level,
1438                                                    uint32_t *entries_read,
1439                                                    void **buffer)
1440 {
1441         switch (level) {
1442                 case 1:
1443                         return convert_samr_dispinfo_to_NET_DISPLAY_USER(mem_ctx,
1444                                                                          &info->info1,
1445                                                                          entries_read,
1446                                                                          buffer);
1447                 case 2:
1448                         return convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(mem_ctx,
1449                                                                             &info->info2,
1450                                                                             entries_read,
1451                                                                             buffer);
1452                 case 3:
1453                         return convert_samr_dispinfo_to_NET_DISPLAY_GROUP(mem_ctx,
1454                                                                           &info->info3,
1455                                                                           entries_read,
1456                                                                           buffer);
1457                 default:
1458                         return WERR_UNKNOWN_LEVEL;
1459         }
1460
1461         return WERR_OK;
1462 }
1463
1464 /****************************************************************
1465 ****************************************************************/
1466
1467 WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
1468                                     struct NetQueryDisplayInformation *r)
1469 {
1470         struct cli_state *cli = NULL;
1471         struct rpc_pipe_client *pipe_cli = NULL;
1472         struct policy_handle connect_handle;
1473         struct dom_sid2 *domain_sid = NULL;
1474         struct policy_handle domain_handle;
1475         union samr_DispInfo info;
1476
1477         uint32_t total_size = 0;
1478         uint32_t returned_size = 0;
1479
1480         NTSTATUS status = NT_STATUS_OK;
1481         WERROR werr;
1482
1483         ZERO_STRUCT(connect_handle);
1484         ZERO_STRUCT(domain_handle);
1485
1486         switch (r->in.level) {
1487                 case 1:
1488                 case 2:
1489                 case 3:
1490                         break;
1491                 default:
1492                         return WERR_UNKNOWN_LEVEL;
1493         }
1494
1495         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1496                                    &ndr_table_samr.syntax_id,
1497                                    &cli,
1498                                    &pipe_cli);
1499         if (!W_ERROR_IS_OK(werr)) {
1500                 goto done;
1501         }
1502
1503         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1504                                           SAMR_ACCESS_ENUM_DOMAINS |
1505                                           SAMR_ACCESS_OPEN_DOMAIN,
1506                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1507                                           SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1508                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1509                                           &connect_handle,
1510                                           &domain_handle,
1511                                           &domain_sid);
1512         if (!W_ERROR_IS_OK(werr)) {
1513                 goto done;
1514         }
1515
1516         status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
1517                                                ctx,
1518                                                &domain_handle,
1519                                                r->in.level,
1520                                                r->in.idx,
1521                                                r->in.entries_requested,
1522                                                r->in.prefmaxlen,
1523                                                &total_size,
1524                                                &returned_size,
1525                                                &info);
1526         if (!NT_STATUS_IS_OK(status)) {
1527                 werr = ntstatus_to_werror(status);
1528                 goto done;
1529         }
1530
1531         werr = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info,
1532                                                     r->in.level,
1533                                                     r->out.entries_read,
1534                                                     r->out.buffer);
1535  done:
1536         if (!cli) {
1537                 return werr;
1538         }
1539
1540         /* if last query */
1541         if (NT_STATUS_IS_OK(status) ||
1542             NT_STATUS_IS_ERR(status)) {
1543
1544                 if (ctx->disable_policy_handle_cache) {
1545                         libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1546                         libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1547                 }
1548         }
1549
1550         return werr;
1551
1552 }
1553
1554 /****************************************************************
1555 ****************************************************************/
1556
1557
1558 WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
1559                                     struct NetQueryDisplayInformation *r)
1560 {
1561         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetQueryDisplayInformation);
1562 }
1563
1564 /****************************************************************
1565 ****************************************************************/
1566
1567 WERROR NetUserChangePassword_r(struct libnetapi_ctx *ctx,
1568                                struct NetUserChangePassword *r)
1569 {
1570         return WERR_NOT_SUPPORTED;
1571 }
1572
1573 /****************************************************************
1574 ****************************************************************/
1575
1576 WERROR NetUserChangePassword_l(struct libnetapi_ctx *ctx,
1577                                struct NetUserChangePassword *r)
1578 {
1579         return WERR_NOT_SUPPORTED;
1580 }
1581
1582 /****************************************************************
1583 ****************************************************************/
1584
1585 WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx,
1586                         struct NetUserGetInfo *r)
1587 {
1588         struct cli_state *cli = NULL;
1589         struct rpc_pipe_client *pipe_cli = NULL;
1590         NTSTATUS status;
1591         WERROR werr;
1592
1593         struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1594         struct lsa_String lsa_account_name;
1595         struct dom_sid2 *domain_sid = NULL;
1596         struct samr_Ids user_rids, name_types;
1597         uint32_t num_entries = 0;
1598
1599         ZERO_STRUCT(connect_handle);
1600         ZERO_STRUCT(domain_handle);
1601         ZERO_STRUCT(builtin_handle);
1602         ZERO_STRUCT(user_handle);
1603
1604         if (!r->out.buffer) {
1605                 return WERR_INVALID_PARAM;
1606         }
1607
1608         switch (r->in.level) {
1609                 case 0:
1610                 case 1:
1611                 case 2:
1612                 case 3:
1613                 case 4:
1614                 case 10:
1615                 case 11:
1616                 case 20:
1617                 case 23:
1618                         break;
1619                 default:
1620                         werr = WERR_UNKNOWN_LEVEL;
1621                         goto done;
1622         }
1623
1624         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1625                                    &ndr_table_samr.syntax_id,
1626                                    &cli,
1627                                    &pipe_cli);
1628         if (!W_ERROR_IS_OK(werr)) {
1629                 goto done;
1630         }
1631
1632         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1633                                           SAMR_ACCESS_ENUM_DOMAINS |
1634                                           SAMR_ACCESS_OPEN_DOMAIN,
1635                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1636                                           &connect_handle,
1637                                           &domain_handle,
1638                                           &domain_sid);
1639         if (!W_ERROR_IS_OK(werr)) {
1640                 goto done;
1641         }
1642
1643         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1644                                                   SAMR_ACCESS_ENUM_DOMAINS |
1645                                                   SAMR_ACCESS_OPEN_DOMAIN,
1646                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1647                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1648                                                   &connect_handle,
1649                                                   &builtin_handle);
1650         if (!W_ERROR_IS_OK(werr)) {
1651                 goto done;
1652         }
1653
1654         init_lsa_String(&lsa_account_name, r->in.user_name);
1655
1656         status = rpccli_samr_LookupNames(pipe_cli, ctx,
1657                                          &domain_handle,
1658                                          1,
1659                                          &lsa_account_name,
1660                                          &user_rids,
1661                                          &name_types);
1662         if (!NT_STATUS_IS_OK(status)) {
1663                 werr = ntstatus_to_werror(status);
1664                 goto done;
1665         }
1666
1667         status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1668                                                           domain_sid,
1669                                                           &domain_handle,
1670                                                           &builtin_handle,
1671                                                           r->in.user_name,
1672                                                           user_rids.ids[0],
1673                                                           r->in.level,
1674                                                           r->out.buffer,
1675                                                           &num_entries);
1676         if (!NT_STATUS_IS_OK(status)) {
1677                 werr = ntstatus_to_werror(status);
1678                 goto done;
1679         }
1680
1681  done:
1682         if (!cli) {
1683                 return werr;
1684         }
1685
1686         if (is_valid_policy_hnd(&user_handle)) {
1687                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
1688         }
1689
1690         if (ctx->disable_policy_handle_cache) {
1691                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1692                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1693         }
1694
1695         return werr;
1696 }
1697
1698 /****************************************************************
1699 ****************************************************************/
1700
1701 WERROR NetUserGetInfo_l(struct libnetapi_ctx *ctx,
1702                         struct NetUserGetInfo *r)
1703 {
1704         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetInfo);
1705 }
1706
1707 /****************************************************************
1708 ****************************************************************/
1709
1710 WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
1711                         struct NetUserSetInfo *r)
1712 {
1713         struct cli_state *cli = NULL;
1714         struct rpc_pipe_client *pipe_cli = NULL;
1715         NTSTATUS status;
1716         WERROR werr;
1717
1718         struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1719         struct lsa_String lsa_account_name;
1720         struct dom_sid2 *domain_sid = NULL;
1721         struct samr_Ids user_rids, name_types;
1722         uint32_t user_mask = 0;
1723
1724         struct USER_INFO_X uX;
1725
1726         ZERO_STRUCT(connect_handle);
1727         ZERO_STRUCT(domain_handle);
1728         ZERO_STRUCT(builtin_handle);
1729         ZERO_STRUCT(user_handle);
1730
1731         if (!r->in.buffer) {
1732                 return WERR_INVALID_PARAM;
1733         }
1734
1735         switch (r->in.level) {
1736                 case 0:
1737                 case 1003:
1738                         user_mask = SAMR_USER_ACCESS_SET_PASSWORD;
1739                         break;
1740                 case 1006:
1741                 case 1007:
1742                 case 1009:
1743                 case 1011:
1744                 case 1014:
1745                 case 1052:
1746                 case 1053:
1747                         user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
1748                         break;
1749                 case 1012:
1750                 case 1024:
1751                         user_mask = SAMR_USER_ACCESS_SET_LOC_COM;
1752                 case 1051:
1753                         user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES |
1754                                     SAMR_USER_ACCESS_GET_GROUPS;
1755                         break;
1756                 case 1:
1757                 case 2:
1758                 case 3:
1759                 case 4:
1760                 case 21:
1761                 case 22:
1762                 case 1005:
1763                 case 1008:
1764                 case 1010:
1765                 case 1017:
1766                 case 1020:
1767                         werr = WERR_NOT_SUPPORTED;
1768                         goto done;
1769                 default:
1770                         werr = WERR_UNKNOWN_LEVEL;
1771                         goto done;
1772         }
1773
1774         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1775                                    &ndr_table_samr.syntax_id,
1776                                    &cli,
1777                                    &pipe_cli);
1778         if (!W_ERROR_IS_OK(werr)) {
1779                 goto done;
1780         }
1781
1782         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1783                                           SAMR_ACCESS_ENUM_DOMAINS |
1784                                           SAMR_ACCESS_OPEN_DOMAIN,
1785                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
1786                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1787                                           &connect_handle,
1788                                           &domain_handle,
1789                                           &domain_sid);
1790         if (!W_ERROR_IS_OK(werr)) {
1791                 goto done;
1792         }
1793
1794         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1795                                                   SAMR_ACCESS_ENUM_DOMAINS |
1796                                                   SAMR_ACCESS_OPEN_DOMAIN,
1797                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1798                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1799                                                   &connect_handle,
1800                                                   &builtin_handle);
1801         if (!W_ERROR_IS_OK(werr)) {
1802                 goto done;
1803         }
1804
1805         init_lsa_String(&lsa_account_name, r->in.user_name);
1806
1807         status = rpccli_samr_LookupNames(pipe_cli, ctx,
1808                                          &domain_handle,
1809                                          1,
1810                                          &lsa_account_name,
1811                                          &user_rids,
1812                                          &name_types);
1813         if (!NT_STATUS_IS_OK(status)) {
1814                 werr = ntstatus_to_werror(status);
1815                 goto done;
1816         }
1817
1818         status = rpccli_samr_OpenUser(pipe_cli, ctx,
1819                                       &domain_handle,
1820                                       user_mask,
1821                                       user_rids.ids[0],
1822                                       &user_handle);
1823         if (!NT_STATUS_IS_OK(status)) {
1824                 werr = ntstatus_to_werror(status);
1825                 goto done;
1826         }
1827
1828         status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
1829         if (!NT_STATUS_IS_OK(status)) {
1830                 werr = ntstatus_to_werror(status);
1831                 goto done;
1832         }
1833
1834         status = set_user_info_USER_INFO_X(ctx, pipe_cli,
1835                                            &cli->user_session_key,
1836                                            &user_handle,
1837                                            &uX);
1838         if (!NT_STATUS_IS_OK(status)) {
1839                 werr = ntstatus_to_werror(status);
1840                 goto done;
1841         }
1842
1843         werr = WERR_OK;
1844
1845  done:
1846         if (!cli) {
1847                 return werr;
1848         }
1849
1850         if (is_valid_policy_hnd(&user_handle)) {
1851                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
1852         }
1853
1854         if (ctx->disable_policy_handle_cache) {
1855                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1856                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1857                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1858         }
1859
1860         return werr;
1861 }
1862
1863 /****************************************************************
1864 ****************************************************************/
1865
1866 WERROR NetUserSetInfo_l(struct libnetapi_ctx *ctx,
1867                         struct NetUserSetInfo *r)
1868 {
1869         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetInfo);
1870 }
1871
1872 /****************************************************************
1873 ****************************************************************/
1874
1875 static NTSTATUS query_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
1876                                            struct rpc_pipe_client *pipe_cli,
1877                                            struct policy_handle *domain_handle,
1878                                            struct samr_DomInfo1 *info1,
1879                                            struct samr_DomInfo3 *info3,
1880                                            struct samr_DomInfo5 *info5,
1881                                            struct samr_DomInfo6 *info6,
1882                                            struct samr_DomInfo7 *info7,
1883                                            struct samr_DomInfo12 *info12)
1884 {
1885         NTSTATUS status;
1886         union samr_DomainInfo *dom_info = NULL;
1887
1888         if (info1) {
1889                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1890                                                      domain_handle,
1891                                                      1,
1892                                                      &dom_info);
1893                 NT_STATUS_NOT_OK_RETURN(status);
1894
1895                 *info1 = dom_info->info1;
1896         }
1897
1898         if (info3) {
1899                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1900                                                      domain_handle,
1901                                                      3,
1902                                                      &dom_info);
1903                 NT_STATUS_NOT_OK_RETURN(status);
1904
1905                 *info3 = dom_info->info3;
1906         }
1907
1908         if (info5) {
1909                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1910                                                      domain_handle,
1911                                                      5,
1912                                                      &dom_info);
1913                 NT_STATUS_NOT_OK_RETURN(status);
1914
1915                 *info5 = dom_info->info5;
1916         }
1917
1918         if (info6) {
1919                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1920                                                      domain_handle,
1921                                                      6,
1922                                                      &dom_info);
1923                 NT_STATUS_NOT_OK_RETURN(status);
1924
1925                 *info6 = dom_info->info6;
1926         }
1927
1928         if (info7) {
1929                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1930                                                      domain_handle,
1931                                                      7,
1932                                                      &dom_info);
1933                 NT_STATUS_NOT_OK_RETURN(status);
1934
1935                 *info7 = dom_info->info7;
1936         }
1937
1938         if (info12) {
1939                 status = rpccli_samr_QueryDomainInfo2(pipe_cli, mem_ctx,
1940                                                       domain_handle,
1941                                                       12,
1942                                                       &dom_info);
1943                 NT_STATUS_NOT_OK_RETURN(status);
1944
1945                 *info12 = dom_info->info12;
1946         }
1947
1948         return NT_STATUS_OK;
1949 }
1950
1951 /****************************************************************
1952 ****************************************************************/
1953
1954 static NTSTATUS query_USER_MODALS_INFO_0(TALLOC_CTX *mem_ctx,
1955                                          struct rpc_pipe_client *pipe_cli,
1956                                          struct policy_handle *domain_handle,
1957                                          struct USER_MODALS_INFO_0 *info0)
1958 {
1959         NTSTATUS status;
1960         struct samr_DomInfo1 dom_info1;
1961         struct samr_DomInfo3 dom_info3;
1962
1963         ZERO_STRUCTP(info0);
1964
1965         status = query_USER_MODALS_INFO_rpc(mem_ctx,
1966                                             pipe_cli,
1967                                             domain_handle,
1968                                             &dom_info1,
1969                                             &dom_info3,
1970                                             NULL,
1971                                             NULL,
1972                                             NULL,
1973                                             NULL);
1974         NT_STATUS_NOT_OK_RETURN(status);
1975
1976         info0->usrmod0_min_passwd_len =
1977                 dom_info1.min_password_length;
1978         info0->usrmod0_max_passwd_age =
1979                 nt_time_to_unix_abs((NTTIME *)&dom_info1.max_password_age);
1980         info0->usrmod0_min_passwd_age =
1981                 nt_time_to_unix_abs((NTTIME *)&dom_info1.min_password_age);
1982         info0->usrmod0_password_hist_len =
1983                 dom_info1.password_history_length;
1984
1985         info0->usrmod0_force_logoff =
1986                 nt_time_to_unix_abs(&dom_info3.force_logoff_time);
1987
1988         return NT_STATUS_OK;
1989 }
1990
1991 /****************************************************************
1992 ****************************************************************/
1993
1994 static NTSTATUS query_USER_MODALS_INFO_1(TALLOC_CTX *mem_ctx,
1995                                          struct rpc_pipe_client *pipe_cli,
1996                                          struct policy_handle *domain_handle,
1997                                          struct USER_MODALS_INFO_1 *info1)
1998 {
1999         NTSTATUS status;
2000         struct samr_DomInfo6 dom_info6;
2001         struct samr_DomInfo7 dom_info7;
2002
2003         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2004                                             pipe_cli,
2005                                             domain_handle,
2006                                             NULL,
2007                                             NULL,
2008                                             NULL,
2009                                             &dom_info6,
2010                                             &dom_info7,
2011                                             NULL);
2012         NT_STATUS_NOT_OK_RETURN(status);
2013
2014         info1->usrmod1_primary =
2015                 talloc_strdup(mem_ctx, dom_info6.primary.string);
2016
2017         info1->usrmod1_role = dom_info7.role;
2018
2019         return NT_STATUS_OK;
2020 }
2021
2022 /****************************************************************
2023 ****************************************************************/
2024
2025 static NTSTATUS query_USER_MODALS_INFO_2(TALLOC_CTX *mem_ctx,
2026                                          struct rpc_pipe_client *pipe_cli,
2027                                          struct policy_handle *domain_handle,
2028                                          struct dom_sid *domain_sid,
2029                                          struct USER_MODALS_INFO_2 *info2)
2030 {
2031         NTSTATUS status;
2032         struct samr_DomInfo5 dom_info5;
2033
2034         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2035                                             pipe_cli,
2036                                             domain_handle,
2037                                             NULL,
2038                                             NULL,
2039                                             &dom_info5,
2040                                             NULL,
2041                                             NULL,
2042                                             NULL);
2043         NT_STATUS_NOT_OK_RETURN(status);
2044
2045         info2->usrmod2_domain_name =
2046                 talloc_strdup(mem_ctx, dom_info5.domain_name.string);
2047         info2->usrmod2_domain_id =
2048                 (struct domsid *)sid_dup_talloc(mem_ctx, domain_sid);
2049
2050         NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_name);
2051         NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_id);
2052
2053         return NT_STATUS_OK;
2054 }
2055
2056 /****************************************************************
2057 ****************************************************************/
2058
2059 static NTSTATUS query_USER_MODALS_INFO_3(TALLOC_CTX *mem_ctx,
2060                                          struct rpc_pipe_client *pipe_cli,
2061                                          struct policy_handle *domain_handle,
2062                                          struct USER_MODALS_INFO_3 *info3)
2063 {
2064         NTSTATUS status;
2065         struct samr_DomInfo12 dom_info12;
2066
2067         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2068                                             pipe_cli,
2069                                             domain_handle,
2070                                             NULL,
2071                                             NULL,
2072                                             NULL,
2073                                             NULL,
2074                                             NULL,
2075                                             &dom_info12);
2076         NT_STATUS_NOT_OK_RETURN(status);
2077
2078         info3->usrmod3_lockout_duration =
2079                 nt_time_to_unix_abs(&dom_info12.lockout_duration);
2080         info3->usrmod3_lockout_observation_window =
2081                 nt_time_to_unix_abs(&dom_info12.lockout_window);
2082         info3->usrmod3_lockout_threshold =
2083                 dom_info12.lockout_threshold;
2084
2085         return NT_STATUS_OK;
2086 }
2087
2088 /****************************************************************
2089 ****************************************************************/
2090
2091 static NTSTATUS query_USER_MODALS_INFO_to_buffer(TALLOC_CTX *mem_ctx,
2092                                                  struct rpc_pipe_client *pipe_cli,
2093                                                  uint32_t level,
2094                                                  struct policy_handle *domain_handle,
2095                                                  struct dom_sid *domain_sid,
2096                                                  uint8_t **buffer)
2097 {
2098         NTSTATUS status;
2099
2100         struct USER_MODALS_INFO_0 info0;
2101         struct USER_MODALS_INFO_1 info1;
2102         struct USER_MODALS_INFO_2 info2;
2103         struct USER_MODALS_INFO_3 info3;
2104
2105         if (!buffer) {
2106                 return ERROR_INSUFFICIENT_BUFFER;
2107         }
2108
2109         switch (level) {
2110                 case 0:
2111                         status = query_USER_MODALS_INFO_0(mem_ctx,
2112                                                           pipe_cli,
2113                                                           domain_handle,
2114                                                           &info0);
2115                         NT_STATUS_NOT_OK_RETURN(status);
2116
2117                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0,
2118                                                            sizeof(info0));
2119                         break;
2120
2121                 case 1:
2122                         status = query_USER_MODALS_INFO_1(mem_ctx,
2123                                                           pipe_cli,
2124                                                           domain_handle,
2125                                                           &info1);
2126                         NT_STATUS_NOT_OK_RETURN(status);
2127
2128                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1,
2129                                                            sizeof(info1));
2130                         break;
2131                 case 2:
2132                         status = query_USER_MODALS_INFO_2(mem_ctx,
2133                                                           pipe_cli,
2134                                                           domain_handle,
2135                                                           domain_sid,
2136                                                           &info2);
2137                         NT_STATUS_NOT_OK_RETURN(status);
2138
2139                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2,
2140                                                            sizeof(info2));
2141                         break;
2142                 case 3:
2143                         status = query_USER_MODALS_INFO_3(mem_ctx,
2144                                                           pipe_cli,
2145                                                           domain_handle,
2146                                                           &info3);
2147                         NT_STATUS_NOT_OK_RETURN(status);
2148
2149                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3,
2150                                                            sizeof(info3));
2151                         break;
2152                 default:
2153                         break;
2154         }
2155
2156         NT_STATUS_HAVE_NO_MEMORY(*buffer);
2157
2158         return NT_STATUS_OK;
2159 }
2160
2161 /****************************************************************
2162 ****************************************************************/
2163
2164 WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx,
2165                           struct NetUserModalsGet *r)
2166 {
2167         struct cli_state *cli = NULL;
2168         struct rpc_pipe_client *pipe_cli = NULL;
2169         NTSTATUS status;
2170         WERROR werr;
2171
2172         struct policy_handle connect_handle, domain_handle;
2173         struct dom_sid2 *domain_sid = NULL;
2174         uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2175
2176         ZERO_STRUCT(connect_handle);
2177         ZERO_STRUCT(domain_handle);
2178
2179         if (!r->out.buffer) {
2180                 return WERR_INVALID_PARAM;
2181         }
2182
2183         switch (r->in.level) {
2184                 case 0:
2185                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2186                                        SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2187                         break;
2188                 case 1:
2189                 case 2:
2190                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2191                         break;
2192                 case 3:
2193                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1;
2194                         break;
2195                 default:
2196                         werr = WERR_UNKNOWN_LEVEL;
2197                         goto done;
2198         }
2199
2200         werr = libnetapi_open_pipe(ctx, r->in.server_name,
2201                                    &ndr_table_samr.syntax_id,
2202                                    &cli,
2203                                    &pipe_cli);
2204         if (!W_ERROR_IS_OK(werr)) {
2205                 goto done;
2206         }
2207
2208         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2209                                           SAMR_ACCESS_ENUM_DOMAINS |
2210                                           SAMR_ACCESS_OPEN_DOMAIN,
2211                                           access_mask,
2212                                           &connect_handle,
2213                                           &domain_handle,
2214                                           &domain_sid);
2215         if (!W_ERROR_IS_OK(werr)) {
2216                 goto done;
2217         }
2218
2219         /* 0:  1 + 3 */
2220         /* 1:  6 + 7 */
2221         /* 2:  5 */
2222         /* 3: 12 (DomainInfo2) */
2223
2224         status = query_USER_MODALS_INFO_to_buffer(ctx,
2225                                                   pipe_cli,
2226                                                   r->in.level,
2227                                                   &domain_handle,
2228                                                   domain_sid,
2229                                                   r->out.buffer);
2230         if (!NT_STATUS_IS_OK(status)) {
2231                 werr = ntstatus_to_werror(status);
2232                 goto done;
2233         }
2234
2235  done:
2236         if (!cli) {
2237                 return werr;
2238         }
2239
2240         if (ctx->disable_policy_handle_cache) {
2241                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2242                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2243         }
2244
2245         return werr;
2246 }
2247
2248 /****************************************************************
2249 ****************************************************************/
2250
2251 WERROR NetUserModalsGet_l(struct libnetapi_ctx *ctx,
2252                           struct NetUserModalsGet *r)
2253 {
2254         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsGet);
2255 }
2256
2257 /****************************************************************
2258 ****************************************************************/
2259
2260 static NTSTATUS set_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
2261                                          struct rpc_pipe_client *pipe_cli,
2262                                          struct policy_handle *domain_handle,
2263                                          struct samr_DomInfo1 *info1,
2264                                          struct samr_DomInfo3 *info3,
2265                                          struct samr_DomInfo12 *info12)
2266 {
2267         NTSTATUS status;
2268         union samr_DomainInfo dom_info;
2269
2270         if (info1) {
2271
2272                 ZERO_STRUCT(dom_info);
2273
2274                 dom_info.info1 = *info1;
2275
2276                 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2277                                                    domain_handle,
2278                                                    1,
2279                                                    &dom_info);
2280                 NT_STATUS_NOT_OK_RETURN(status);
2281         }
2282
2283         if (info3) {
2284
2285                 ZERO_STRUCT(dom_info);
2286
2287                 dom_info.info3 = *info3;
2288
2289                 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2290                                                    domain_handle,
2291                                                    3,
2292                                                    &dom_info);
2293
2294                 NT_STATUS_NOT_OK_RETURN(status);
2295         }
2296
2297         if (info12) {
2298
2299                 ZERO_STRUCT(dom_info);
2300
2301                 dom_info.info12 = *info12;
2302
2303                 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2304                                                    domain_handle,
2305                                                    12,
2306                                                    &dom_info);
2307
2308                 NT_STATUS_NOT_OK_RETURN(status);
2309         }
2310
2311         return NT_STATUS_OK;
2312 }
2313
2314 /****************************************************************
2315 ****************************************************************/
2316
2317 static NTSTATUS set_USER_MODALS_INFO_0_buffer(TALLOC_CTX *mem_ctx,
2318                                               struct rpc_pipe_client *pipe_cli,
2319                                               struct policy_handle *domain_handle,
2320                                               struct USER_MODALS_INFO_0 *info0)
2321 {
2322         NTSTATUS status;
2323         struct samr_DomInfo1 dom_info_1;
2324         struct samr_DomInfo3 dom_info_3;
2325
2326         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2327                                             pipe_cli,
2328                                             domain_handle,
2329                                             &dom_info_1,
2330                                             &dom_info_3,
2331                                             NULL,
2332                                             NULL,
2333                                             NULL,
2334                                             NULL);
2335         NT_STATUS_NOT_OK_RETURN(status);
2336
2337         dom_info_1.min_password_length =
2338                 info0->usrmod0_min_passwd_len;
2339         dom_info_1.password_history_length =
2340                 info0->usrmod0_password_hist_len;
2341
2342         unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2343                 info0->usrmod0_max_passwd_age);
2344         unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2345                 info0->usrmod0_min_passwd_age);
2346
2347         unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2348                 info0->usrmod0_force_logoff);
2349
2350         return set_USER_MODALS_INFO_rpc(mem_ctx,
2351                                         pipe_cli,
2352                                         domain_handle,
2353                                         &dom_info_1,
2354                                         &dom_info_3,
2355                                         NULL);
2356 }
2357
2358 /****************************************************************
2359 ****************************************************************/
2360
2361 static NTSTATUS set_USER_MODALS_INFO_3_buffer(TALLOC_CTX *mem_ctx,
2362                                               struct rpc_pipe_client *pipe_cli,
2363                                               struct policy_handle *domain_handle,
2364                                               struct USER_MODALS_INFO_3 *info3)
2365 {
2366         NTSTATUS status;
2367         struct samr_DomInfo12 dom_info_12;
2368
2369         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2370                                             pipe_cli,
2371                                             domain_handle,
2372                                             NULL,
2373                                             NULL,
2374                                             NULL,
2375                                             NULL,
2376                                             NULL,
2377                                             &dom_info_12);
2378         NT_STATUS_NOT_OK_RETURN(status);
2379
2380         unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_duration,
2381                 info3->usrmod3_lockout_duration);
2382         unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_window,
2383                 info3->usrmod3_lockout_observation_window);
2384         dom_info_12.lockout_threshold = info3->usrmod3_lockout_threshold;
2385
2386         return set_USER_MODALS_INFO_rpc(mem_ctx,
2387                                         pipe_cli,
2388                                         domain_handle,
2389                                         NULL,
2390                                         NULL,
2391                                         &dom_info_12);
2392 }
2393
2394 /****************************************************************
2395 ****************************************************************/
2396
2397 static NTSTATUS set_USER_MODALS_INFO_1001_buffer(TALLOC_CTX *mem_ctx,
2398                                                  struct rpc_pipe_client *pipe_cli,
2399                                                  struct policy_handle *domain_handle,
2400                                                  struct USER_MODALS_INFO_1001 *info1001)
2401 {
2402         NTSTATUS status;
2403         struct samr_DomInfo1 dom_info_1;
2404
2405         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2406                                             pipe_cli,
2407                                             domain_handle,
2408                                             &dom_info_1,
2409                                             NULL,
2410                                             NULL,
2411                                             NULL,
2412                                             NULL,
2413                                             NULL);
2414         NT_STATUS_NOT_OK_RETURN(status);
2415
2416         dom_info_1.min_password_length =
2417                 info1001->usrmod1001_min_passwd_len;
2418
2419         return set_USER_MODALS_INFO_rpc(mem_ctx,
2420                                         pipe_cli,
2421                                         domain_handle,
2422                                         &dom_info_1,
2423                                         NULL,
2424                                         NULL);
2425 }
2426
2427 /****************************************************************
2428 ****************************************************************/
2429
2430 static NTSTATUS set_USER_MODALS_INFO_1002_buffer(TALLOC_CTX *mem_ctx,
2431                                                  struct rpc_pipe_client *pipe_cli,
2432                                                  struct policy_handle *domain_handle,
2433                                                  struct USER_MODALS_INFO_1002 *info1002)
2434 {
2435         NTSTATUS status;
2436         struct samr_DomInfo1 dom_info_1;
2437
2438         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2439                                             pipe_cli,
2440                                             domain_handle,
2441                                             &dom_info_1,
2442                                             NULL,
2443                                             NULL,
2444                                             NULL,
2445                                             NULL,
2446                                             NULL);
2447         NT_STATUS_NOT_OK_RETURN(status);
2448
2449         unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2450                 info1002->usrmod1002_max_passwd_age);
2451
2452         return set_USER_MODALS_INFO_rpc(mem_ctx,
2453                                         pipe_cli,
2454                                         domain_handle,
2455                                         &dom_info_1,
2456                                         NULL,
2457                                         NULL);
2458 }
2459
2460 /****************************************************************
2461 ****************************************************************/
2462
2463 static NTSTATUS set_USER_MODALS_INFO_1003_buffer(TALLOC_CTX *mem_ctx,
2464                                                  struct rpc_pipe_client *pipe_cli,
2465                                                  struct policy_handle *domain_handle,
2466                                                  struct USER_MODALS_INFO_1003 *info1003)
2467 {
2468         NTSTATUS status;
2469         struct samr_DomInfo1 dom_info_1;
2470
2471         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2472                                             pipe_cli,
2473                                             domain_handle,
2474                                             &dom_info_1,
2475                                             NULL,
2476                                             NULL,
2477                                             NULL,
2478                                             NULL,
2479                                             NULL);
2480         NT_STATUS_NOT_OK_RETURN(status);
2481
2482         unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2483                 info1003->usrmod1003_min_passwd_age);
2484
2485         return set_USER_MODALS_INFO_rpc(mem_ctx,
2486                                         pipe_cli,
2487                                         domain_handle,
2488                                         &dom_info_1,
2489                                         NULL,
2490                                         NULL);
2491 }
2492
2493 /****************************************************************
2494 ****************************************************************/
2495
2496 static NTSTATUS set_USER_MODALS_INFO_1004_buffer(TALLOC_CTX *mem_ctx,
2497                                                  struct rpc_pipe_client *pipe_cli,
2498                                                  struct policy_handle *domain_handle,
2499                                                  struct USER_MODALS_INFO_1004 *info1004)
2500 {
2501         NTSTATUS status;
2502         struct samr_DomInfo3 dom_info_3;
2503
2504         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2505                                             pipe_cli,
2506                                             domain_handle,
2507                                             NULL,
2508                                             &dom_info_3,
2509                                             NULL,
2510                                             NULL,
2511                                             NULL,
2512                                             NULL);
2513         NT_STATUS_NOT_OK_RETURN(status);
2514
2515         unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2516                 info1004->usrmod1004_force_logoff);
2517
2518         return set_USER_MODALS_INFO_rpc(mem_ctx,
2519                                         pipe_cli,
2520                                         domain_handle,
2521                                         NULL,
2522                                         &dom_info_3,
2523                                         NULL);
2524 }
2525
2526 /****************************************************************
2527 ****************************************************************/
2528
2529 static NTSTATUS set_USER_MODALS_INFO_1005_buffer(TALLOC_CTX *mem_ctx,
2530                                                  struct rpc_pipe_client *pipe_cli,
2531                                                  struct policy_handle *domain_handle,
2532                                                  struct USER_MODALS_INFO_1005 *info1005)
2533 {
2534         NTSTATUS status;
2535         struct samr_DomInfo1 dom_info_1;
2536
2537         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2538                                             pipe_cli,
2539                                             domain_handle,
2540                                             &dom_info_1,
2541                                             NULL,
2542                                             NULL,
2543                                             NULL,
2544                                             NULL,
2545                                             NULL);
2546         NT_STATUS_NOT_OK_RETURN(status);
2547
2548         dom_info_1.password_history_length =
2549                 info1005->usrmod1005_password_hist_len;
2550
2551         return set_USER_MODALS_INFO_rpc(mem_ctx,
2552                                         pipe_cli,
2553                                         domain_handle,
2554                                         &dom_info_1,
2555                                         NULL,
2556                                         NULL);
2557 }
2558
2559 /****************************************************************
2560 ****************************************************************/
2561
2562 static NTSTATUS set_USER_MODALS_INFO_buffer(TALLOC_CTX *mem_ctx,
2563                                             struct rpc_pipe_client *pipe_cli,
2564                                             uint32_t level,
2565                                             struct policy_handle *domain_handle,
2566                                             struct dom_sid *domain_sid,
2567                                             uint8_t *buffer)
2568 {
2569         struct USER_MODALS_INFO_0 *info0;
2570         struct USER_MODALS_INFO_3 *info3;
2571         struct USER_MODALS_INFO_1001 *info1001;
2572         struct USER_MODALS_INFO_1002 *info1002;
2573         struct USER_MODALS_INFO_1003 *info1003;
2574         struct USER_MODALS_INFO_1004 *info1004;
2575         struct USER_MODALS_INFO_1005 *info1005;
2576
2577         if (!buffer) {
2578                 return ERROR_INSUFFICIENT_BUFFER;
2579         }
2580
2581         switch (level) {
2582                 case 0:
2583                         info0 = (struct USER_MODALS_INFO_0 *)buffer;
2584                         return set_USER_MODALS_INFO_0_buffer(mem_ctx,
2585                                                              pipe_cli,
2586                                                              domain_handle,
2587                                                              info0);
2588                 case 3:
2589                         info3 = (struct USER_MODALS_INFO_3 *)buffer;
2590                         return set_USER_MODALS_INFO_3_buffer(mem_ctx,
2591                                                              pipe_cli,
2592                                                              domain_handle,
2593                                                              info3);
2594                 case 1001:
2595                         info1001 = (struct USER_MODALS_INFO_1001 *)buffer;
2596                         return set_USER_MODALS_INFO_1001_buffer(mem_ctx,
2597                                                                 pipe_cli,
2598                                                                 domain_handle,
2599                                                                 info1001);
2600                 case 1002:
2601                         info1002 = (struct USER_MODALS_INFO_1002 *)buffer;
2602                         return set_USER_MODALS_INFO_1002_buffer(mem_ctx,
2603                                                                 pipe_cli,
2604                                                                 domain_handle,
2605                                                                 info1002);
2606                 case 1003:
2607                         info1003 = (struct USER_MODALS_INFO_1003 *)buffer;
2608                         return set_USER_MODALS_INFO_1003_buffer(mem_ctx,
2609                                                                 pipe_cli,
2610                                                                 domain_handle,
2611                                                                 info1003);
2612                 case 1004:
2613                         info1004 = (struct USER_MODALS_INFO_1004 *)buffer;
2614                         return set_USER_MODALS_INFO_1004_buffer(mem_ctx,
2615                                                                 pipe_cli,
2616                                                                 domain_handle,
2617                                                                 info1004);
2618                 case 1005:
2619                         info1005 = (struct USER_MODALS_INFO_1005 *)buffer;
2620                         return set_USER_MODALS_INFO_1005_buffer(mem_ctx,
2621                                                                 pipe_cli,
2622                                                                 domain_handle,
2623                                                                 info1005);
2624
2625                 default:
2626                         break;
2627         }
2628
2629         return NT_STATUS_OK;
2630 }
2631
2632 /****************************************************************
2633 ****************************************************************/
2634
2635 WERROR NetUserModalsSet_r(struct libnetapi_ctx *ctx,
2636                           struct NetUserModalsSet *r)
2637 {
2638         struct cli_state *cli = NULL;
2639         struct rpc_pipe_client *pipe_cli = NULL;
2640         NTSTATUS status;
2641         WERROR werr;
2642
2643         struct policy_handle connect_handle, domain_handle;
2644         struct dom_sid2 *domain_sid = NULL;
2645         uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2646
2647         ZERO_STRUCT(connect_handle);
2648         ZERO_STRUCT(domain_handle);
2649
2650         if (!r->in.buffer) {
2651                 return WERR_INVALID_PARAM;
2652         }
2653
2654         switch (r->in.level) {
2655                 case 0:
2656                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2657                                        SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2658                                        SAMR_DOMAIN_ACCESS_SET_INFO_1 |
2659                                        SAMR_DOMAIN_ACCESS_SET_INFO_2;
2660                         break;
2661                 case 3:
2662                 case 1001:
2663                 case 1002:
2664                 case 1003:
2665                 case 1005:
2666                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2667                                        SAMR_DOMAIN_ACCESS_SET_INFO_1;
2668                         break;
2669                 case 1004:
2670                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2671                                        SAMR_DOMAIN_ACCESS_SET_INFO_2;
2672                         break;
2673                 case 1:
2674                 case 2:
2675                 case 1006:
2676                 case 1007:
2677                         werr = WERR_NOT_SUPPORTED;
2678                         break;
2679                 default:
2680                         werr = WERR_UNKNOWN_LEVEL;
2681                         goto done;
2682         }
2683
2684         werr = libnetapi_open_pipe(ctx, r->in.server_name,
2685                                    &ndr_table_samr.syntax_id,
2686                                    &cli,
2687                                    &pipe_cli);
2688         if (!W_ERROR_IS_OK(werr)) {
2689                 goto done;
2690         }
2691
2692         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2693                                           SAMR_ACCESS_ENUM_DOMAINS |
2694                                           SAMR_ACCESS_OPEN_DOMAIN,
2695                                           access_mask,
2696                                           &connect_handle,
2697                                           &domain_handle,
2698                                           &domain_sid);
2699         if (!W_ERROR_IS_OK(werr)) {
2700                 goto done;
2701         }
2702
2703         status = set_USER_MODALS_INFO_buffer(ctx,
2704                                              pipe_cli,
2705                                              r->in.level,
2706                                              &domain_handle,
2707                                              domain_sid,
2708                                              r->in.buffer);
2709         if (!NT_STATUS_IS_OK(status)) {
2710                 werr = ntstatus_to_werror(status);
2711                 goto done;
2712         }
2713
2714  done:
2715         if (!cli) {
2716                 return werr;
2717         }
2718
2719         if (ctx->disable_policy_handle_cache) {
2720                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2721                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2722         }
2723
2724         return werr;
2725 }
2726
2727 /****************************************************************
2728 ****************************************************************/
2729
2730 WERROR NetUserModalsSet_l(struct libnetapi_ctx *ctx,
2731                           struct NetUserModalsSet *r)
2732 {
2733         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsSet);
2734 }
2735
2736 /****************************************************************
2737 ****************************************************************/
2738
2739 static NTSTATUS add_GROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
2740                                               uint32_t level,
2741                                               const char *group_name,
2742                                               uint32_t attributes,
2743                                               uint8_t **buffer,
2744                                               uint32_t *num_entries)
2745 {
2746         struct GROUP_USERS_INFO_0 u0;
2747         struct GROUP_USERS_INFO_1 u1;
2748
2749         switch (level) {
2750                 case 0:
2751                         u0.grui0_name = talloc_strdup(mem_ctx, group_name);
2752                         NT_STATUS_HAVE_NO_MEMORY(u0.grui0_name);
2753
2754                         ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_0, u0,
2755                                      (struct GROUP_USERS_INFO_0 **)buffer, num_entries);
2756                         break;
2757                 case 1:
2758                         u1.grui1_name = talloc_strdup(mem_ctx, group_name);
2759                         NT_STATUS_HAVE_NO_MEMORY(u1.grui1_name);
2760
2761                         u1.grui1_attributes = attributes;
2762
2763                         ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_1, u1,
2764                                      (struct GROUP_USERS_INFO_1 **)buffer, num_entries);
2765                         break;
2766                 default:
2767                         return NT_STATUS_INVALID_INFO_CLASS;
2768         }
2769
2770         return NT_STATUS_OK;
2771 }
2772
2773 /****************************************************************
2774 ****************************************************************/
2775
2776 WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
2777                           struct NetUserGetGroups *r)
2778 {
2779         struct cli_state *cli = NULL;
2780         struct rpc_pipe_client *pipe_cli = NULL;
2781         struct policy_handle connect_handle, domain_handle, user_handle;
2782         struct lsa_String lsa_account_name;
2783         struct dom_sid2 *domain_sid = NULL;
2784         struct samr_Ids user_rids, name_types;
2785         struct samr_RidWithAttributeArray *rid_array = NULL;
2786         struct lsa_Strings names;
2787         struct samr_Ids types;
2788         uint32_t *rids = NULL;
2789
2790         int i;
2791         uint32_t entries_read = 0;
2792
2793         NTSTATUS status = NT_STATUS_OK;
2794         WERROR werr;
2795
2796         ZERO_STRUCT(connect_handle);
2797         ZERO_STRUCT(domain_handle);
2798
2799         if (!r->out.buffer) {
2800                 return WERR_INVALID_PARAM;
2801         }
2802
2803         *r->out.buffer = NULL;
2804         *r->out.entries_read = 0;
2805
2806         switch (r->in.level) {
2807                 case 0:
2808                 case 1:
2809                         break;
2810                 default:
2811                         return WERR_UNKNOWN_LEVEL;
2812         }
2813
2814         werr = libnetapi_open_pipe(ctx, r->in.server_name,
2815                                    &ndr_table_samr.syntax_id,
2816                                    &cli,
2817                                    &pipe_cli);
2818         if (!W_ERROR_IS_OK(werr)) {
2819                 goto done;
2820         }
2821
2822         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2823                                           SAMR_ACCESS_ENUM_DOMAINS |
2824                                           SAMR_ACCESS_OPEN_DOMAIN,
2825                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2826                                           &connect_handle,
2827                                           &domain_handle,
2828                                           &domain_sid);
2829         if (!W_ERROR_IS_OK(werr)) {
2830                 goto done;
2831         }
2832
2833         init_lsa_String(&lsa_account_name, r->in.user_name);
2834
2835         status = rpccli_samr_LookupNames(pipe_cli, ctx,
2836                                          &domain_handle,
2837                                          1,
2838                                          &lsa_account_name,
2839                                          &user_rids,
2840                                          &name_types);
2841         if (!NT_STATUS_IS_OK(status)) {
2842                 werr = ntstatus_to_werror(status);
2843                 goto done;
2844         }
2845
2846         status = rpccli_samr_OpenUser(pipe_cli, ctx,
2847                                       &domain_handle,
2848                                       SAMR_USER_ACCESS_GET_GROUPS,
2849                                       user_rids.ids[0],
2850                                       &user_handle);
2851         if (!NT_STATUS_IS_OK(status)) {
2852                 werr = ntstatus_to_werror(status);
2853                 goto done;
2854         }
2855
2856         status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
2857                                               &user_handle,
2858                                               &rid_array);
2859         if (!NT_STATUS_IS_OK(status)) {
2860                 werr = ntstatus_to_werror(status);
2861                 goto done;
2862         }
2863
2864         rids = talloc_array(ctx, uint32_t, rid_array->count);
2865         if (!rids) {
2866                 werr = WERR_NOMEM;
2867                 goto done;
2868         }
2869
2870         for (i=0; i < rid_array->count; i++) {
2871                 rids[i] = rid_array->rids[i].rid;
2872         }
2873
2874         status = rpccli_samr_LookupRids(pipe_cli, ctx,
2875                                         &domain_handle,
2876                                         rid_array->count,
2877                                         rids,
2878                                         &names,
2879                                         &types);
2880         if (!NT_STATUS_IS_OK(status)) {
2881                 werr = ntstatus_to_werror(status);
2882                 goto done;
2883         }
2884
2885         for (i=0; i < rid_array->count; i++) {
2886                 status = add_GROUP_USERS_INFO_X_buffer(ctx,
2887                                                        r->in.level,
2888                                                        names.names[i].string,
2889                                                        rid_array->rids[i].attributes,
2890                                                        r->out.buffer,
2891                                                        &entries_read);
2892                 if (!NT_STATUS_IS_OK(status)) {
2893                         werr = ntstatus_to_werror(status);
2894                         goto done;
2895                 }
2896         }
2897
2898         if (r->out.entries_read) {
2899                 *r->out.entries_read = entries_read;
2900         }
2901         if (r->out.total_entries) {
2902                 *r->out.total_entries = entries_read;
2903         }
2904
2905  done:
2906         if (!cli) {
2907                 return werr;
2908         }
2909
2910         if (ctx->disable_policy_handle_cache) {
2911                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2912                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2913         }
2914
2915         return werr;
2916 }
2917
2918 /****************************************************************
2919 ****************************************************************/
2920
2921 WERROR NetUserGetGroups_l(struct libnetapi_ctx *ctx,
2922                           struct NetUserGetGroups *r)
2923 {
2924         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetGroups);
2925 }