Merge branch 'master' of ssh://git.samba.org/data/git/samba into regsrv
[kai/samba-autobuild/.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                               infoX->usriX_user_id,
112                               infoX->usriX_primary_group_id,
113                               infoX->usriX_flags,
114                               fields_present,
115                               zero_logon_hours,
116                               infoX->usriX_bad_pw_count,
117                               infoX->usriX_num_logons,
118                               infoX->usriX_country_code,
119                               infoX->usriX_code_page,
120                               0,
121                               0,
122                               infoX->usriX_password_expired);
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_3 *u3 = NULL;
136         struct USER_INFO_1003 *u1003 = NULL;
137         struct USER_INFO_1006 *u1006 = NULL;
138         struct USER_INFO_1007 *u1007 = NULL;
139         struct USER_INFO_1009 *u1009 = NULL;
140         struct USER_INFO_1011 *u1011 = NULL;
141         struct USER_INFO_1012 *u1012 = NULL;
142         struct USER_INFO_1014 *u1014 = NULL;
143         struct USER_INFO_1024 *u1024 = NULL;
144         struct USER_INFO_1051 *u1051 = NULL;
145         struct USER_INFO_1052 *u1052 = NULL;
146         struct USER_INFO_1053 *u1053 = NULL;
147
148         if (!buffer || !uX) {
149                 return NT_STATUS_INVALID_PARAMETER;
150         }
151
152         ZERO_STRUCTP(uX);
153
154         switch (level) {
155                 case 0:
156                         u0 = (struct USER_INFO_0 *)buffer;
157                         uX->usriX_name          = u0->usri0_name;
158                         break;
159                 case 1:
160                         u1 = (struct USER_INFO_1 *)buffer;
161                         uX->usriX_name          = u1->usri1_name;
162                         uX->usriX_password      = u1->usri1_password;
163                         uX->usriX_password_age  = u1->usri1_password_age;
164                         uX->usriX_priv          = u1->usri1_priv;
165                         uX->usriX_home_dir      = u1->usri1_home_dir;
166                         uX->usriX_comment       = u1->usri1_comment;
167                         uX->usriX_flags         = u1->usri1_flags;
168                         uX->usriX_script_path   = u1->usri1_script_path;
169                         break;
170                 case 2:
171                         u2 = (struct USER_INFO_2 *)buffer;
172                         uX->usriX_name          = u2->usri2_name;
173                         uX->usriX_password      = u2->usri2_password;
174                         uX->usriX_password_age  = u2->usri2_password_age;
175                         uX->usriX_priv          = u2->usri2_priv;
176                         uX->usriX_home_dir      = u2->usri2_home_dir;
177                         uX->usriX_comment       = u2->usri2_comment;
178                         uX->usriX_flags         = u2->usri2_flags;
179                         uX->usriX_script_path   = u2->usri2_script_path;
180                         uX->usriX_auth_flags    = u2->usri2_auth_flags;
181                         uX->usriX_full_name     = u2->usri2_full_name;
182                         uX->usriX_usr_comment   = u2->usri2_usr_comment;
183                         uX->usriX_parms         = u2->usri2_parms;
184                         uX->usriX_workstations  = u2->usri2_workstations;
185                         uX->usriX_last_logon    = u2->usri2_last_logon;
186                         uX->usriX_last_logoff   = u2->usri2_last_logoff;
187                         uX->usriX_acct_expires  = u2->usri2_acct_expires;
188                         uX->usriX_max_storage   = u2->usri2_max_storage;
189                         uX->usriX_units_per_week= u2->usri2_units_per_week;
190                         uX->usriX_logon_hours   = u2->usri2_logon_hours;
191                         uX->usriX_bad_pw_count  = u2->usri2_bad_pw_count;
192                         uX->usriX_num_logons    = u2->usri2_num_logons;
193                         uX->usriX_logon_server  = u2->usri2_logon_server;
194                         uX->usriX_country_code  = u2->usri2_country_code;
195                         uX->usriX_code_page     = u2->usri2_code_page;
196                         break;
197                 case 3:
198                         u3 = (struct USER_INFO_3 *)buffer;
199                         uX->usriX_name          = u3->usri3_name;
200                         uX->usriX_password_age  = u3->usri3_password_age;
201                         uX->usriX_priv          = u3->usri3_priv;
202                         uX->usriX_home_dir      = u3->usri3_home_dir;
203                         uX->usriX_comment       = u3->usri3_comment;
204                         uX->usriX_flags         = u3->usri3_flags;
205                         uX->usriX_script_path   = u3->usri3_script_path;
206                         uX->usriX_auth_flags    = u3->usri3_auth_flags;
207                         uX->usriX_full_name     = u3->usri3_full_name;
208                         uX->usriX_usr_comment   = u3->usri3_usr_comment;
209                         uX->usriX_parms         = u3->usri3_parms;
210                         uX->usriX_workstations  = u3->usri3_workstations;
211                         uX->usriX_last_logon    = u3->usri3_last_logon;
212                         uX->usriX_last_logoff   = u3->usri3_last_logoff;
213                         uX->usriX_acct_expires  = u3->usri3_acct_expires;
214                         uX->usriX_max_storage   = u3->usri3_max_storage;
215                         uX->usriX_units_per_week= u3->usri3_units_per_week;
216                         uX->usriX_logon_hours   = u3->usri3_logon_hours;
217                         uX->usriX_bad_pw_count  = u3->usri3_bad_pw_count;
218                         uX->usriX_num_logons    = u3->usri3_num_logons;
219                         uX->usriX_logon_server  = u3->usri3_logon_server;
220                         uX->usriX_country_code  = u3->usri3_country_code;
221                         uX->usriX_code_page     = u3->usri3_code_page;
222                         uX->usriX_user_id       = u3->usri3_user_id;
223                         uX->usriX_primary_group_id = u3->usri3_primary_group_id;
224                         uX->usriX_profile       = u3->usri3_profile;
225                         uX->usriX_home_dir_drive = u3->usri3_home_dir_drive;
226                         uX->usriX_password_expired = u3->usri3_password_expired;
227                         break;
228                 case 1003:
229                         u1003 = (struct USER_INFO_1003 *)buffer;
230                         uX->usriX_password      = u1003->usri1003_password;
231                         break;
232                 case 1006:
233                         u1006 = (struct USER_INFO_1006 *)buffer;
234                         uX->usriX_home_dir      = u1006->usri1006_home_dir;
235                         break;
236                 case 1007:
237                         u1007 = (struct USER_INFO_1007 *)buffer;
238                         uX->usriX_comment       = u1007->usri1007_comment;
239                         break;
240                 case 1009:
241                         u1009 = (struct USER_INFO_1009 *)buffer;
242                         uX->usriX_script_path   = u1009->usri1009_script_path;
243                         break;
244                 case 1011:
245                         u1011 = (struct USER_INFO_1011 *)buffer;
246                         uX->usriX_full_name     = u1011->usri1011_full_name;
247                         break;
248                 case 1012:
249                         u1012 = (struct USER_INFO_1012 *)buffer;
250                         uX->usriX_usr_comment   = u1012->usri1012_usr_comment;
251                         break;
252                 case 1014:
253                         u1014 = (struct USER_INFO_1014 *)buffer;
254                         uX->usriX_workstations  = u1014->usri1014_workstations;
255                         break;
256                 case 1024:
257                         u1024 = (struct USER_INFO_1024 *)buffer;
258                         uX->usriX_country_code  = u1024->usri1024_country_code;
259                         break;
260                 case 1051:
261                         u1051 = (struct USER_INFO_1051 *)buffer;
262                         uX->usriX_primary_group_id = u1051->usri1051_primary_group_id;
263                         break;
264                 case 1052:
265                         u1052 = (struct USER_INFO_1052 *)buffer;
266                         uX->usriX_profile       = u1052->usri1052_profile;
267                         break;
268                 case 1053:
269                         u1053 = (struct USER_INFO_1053 *)buffer;
270                         uX->usriX_home_dir_drive = u1053->usri1053_home_dir_drive;
271                         break;
272                 case 4:
273                 default:
274                         return NT_STATUS_INVALID_INFO_CLASS;
275         }
276
277         return NT_STATUS_OK;
278 }
279
280 /****************************************************************
281 ****************************************************************/
282
283 static NTSTATUS set_user_info_USER_INFO_X(TALLOC_CTX *ctx,
284                                           struct rpc_pipe_client *pipe_cli,
285                                           DATA_BLOB *session_key,
286                                           struct policy_handle *user_handle,
287                                           struct USER_INFO_X *uX)
288 {
289         union samr_UserInfo user_info;
290         struct samr_UserInfo21 info21;
291         NTSTATUS status;
292
293         if (!uX) {
294                 return NT_STATUS_INVALID_PARAMETER;
295         }
296
297         convert_USER_INFO_X_to_samr_user_info21(uX, &info21);
298
299         ZERO_STRUCT(user_info);
300
301         if (uX->usriX_password) {
302
303                 user_info.info25.info = info21;
304
305                 init_samr_CryptPasswordEx(uX->usriX_password,
306                                           session_key,
307                                           &user_info.info25.password);
308
309                 status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
310                                                   user_handle,
311                                                   25,
312                                                   &user_info);
313
314                 if (NT_STATUS_EQUAL(status, NT_STATUS(DCERPC_FAULT_INVALID_TAG))) {
315
316                         user_info.info23.info = info21;
317
318                         init_samr_CryptPassword(uX->usriX_password,
319                                                 session_key,
320                                                 &user_info.info23.password);
321
322                         status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
323                                                           user_handle,
324                                                           23,
325                                                           &user_info);
326                 }
327         } else {
328
329                 user_info.info21 = info21;
330
331                 status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
332                                                  user_handle,
333                                                  21,
334                                                  &user_info);
335         }
336
337         return status;
338 }
339
340 /****************************************************************
341 ****************************************************************/
342
343 WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
344                     struct NetUserAdd *r)
345 {
346         struct cli_state *cli = NULL;
347         struct rpc_pipe_client *pipe_cli = NULL;
348         NTSTATUS status;
349         WERROR werr;
350         POLICY_HND connect_handle, domain_handle, user_handle;
351         struct lsa_String lsa_account_name;
352         struct dom_sid2 *domain_sid = NULL;
353         union samr_UserInfo *user_info = NULL;
354         struct samr_PwInfo pw_info;
355         uint32_t access_granted = 0;
356         uint32_t rid = 0;
357         struct USER_INFO_X uX;
358
359         ZERO_STRUCT(connect_handle);
360         ZERO_STRUCT(domain_handle);
361         ZERO_STRUCT(user_handle);
362
363         if (!r->in.buffer) {
364                 return WERR_INVALID_PARAM;
365         }
366
367         switch (r->in.level) {
368                 case 1:
369                         break;
370                 case 2:
371                 case 3:
372                 case 4:
373                 default:
374                         werr = WERR_NOT_SUPPORTED;
375                         goto done;
376         }
377
378         werr = libnetapi_open_pipe(ctx, r->in.server_name,
379                                    &ndr_table_samr.syntax_id,
380                                    &cli,
381                                    &pipe_cli);
382         if (!W_ERROR_IS_OK(werr)) {
383                 goto done;
384         }
385
386         status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
387         if (!NT_STATUS_IS_OK(status)) {
388                 werr = ntstatus_to_werror(status);
389                 goto done;
390         }
391
392         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
393                                           SAMR_ACCESS_ENUM_DOMAINS |
394                                           SAMR_ACCESS_OPEN_DOMAIN,
395                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
396                                           SAMR_DOMAIN_ACCESS_CREATE_USER |
397                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
398                                           &connect_handle,
399                                           &domain_handle,
400                                           &domain_sid);
401         if (!W_ERROR_IS_OK(werr)) {
402                 goto done;
403         }
404
405         init_lsa_String(&lsa_account_name, uX.usriX_name);
406
407         status = rpccli_samr_CreateUser2(pipe_cli, ctx,
408                                          &domain_handle,
409                                          &lsa_account_name,
410                                          ACB_NORMAL,
411                                          SEC_STD_WRITE_DAC |
412                                          SEC_STD_DELETE |
413                                          SAMR_USER_ACCESS_SET_PASSWORD |
414                                          SAMR_USER_ACCESS_SET_ATTRIBUTES |
415                                          SAMR_USER_ACCESS_GET_ATTRIBUTES,
416                                          &user_handle,
417                                          &access_granted,
418                                          &rid);
419         if (!NT_STATUS_IS_OK(status)) {
420                 werr = ntstatus_to_werror(status);
421                 goto done;
422         }
423
424         status = rpccli_samr_QueryUserInfo(pipe_cli, ctx,
425                                            &user_handle,
426                                            16,
427                                            &user_info);
428         if (!NT_STATUS_IS_OK(status)) {
429                 werr = ntstatus_to_werror(status);
430                 goto done;
431         }
432
433         if (!(user_info->info16.acct_flags & ACB_NORMAL)) {
434                 werr = WERR_INVALID_PARAM;
435                 goto done;
436         }
437
438         status = rpccli_samr_GetUserPwInfo(pipe_cli, ctx,
439                                            &user_handle,
440                                            &pw_info);
441         if (!NT_STATUS_IS_OK(status)) {
442                 werr = ntstatus_to_werror(status);
443                 goto done;
444         }
445
446         uX.usriX_flags |= ACB_NORMAL;
447
448         status = set_user_info_USER_INFO_X(ctx, pipe_cli,
449                                            &cli->user_session_key,
450                                            &user_handle,
451                                            &uX);
452         if (!NT_STATUS_IS_OK(status)) {
453                 werr = ntstatus_to_werror(status);
454                 goto failed;
455         }
456
457         werr = WERR_OK;
458         goto done;
459
460  failed:
461         rpccli_samr_DeleteUser(pipe_cli, ctx,
462                                &user_handle);
463
464  done:
465         if (!cli) {
466                 return werr;
467         }
468
469         if (is_valid_policy_hnd(&user_handle)) {
470                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
471         }
472
473         if (ctx->disable_policy_handle_cache) {
474                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
475                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
476         }
477
478         return werr;
479 }
480
481 /****************************************************************
482 ****************************************************************/
483
484 WERROR NetUserAdd_l(struct libnetapi_ctx *ctx,
485                     struct NetUserAdd *r)
486 {
487         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserAdd);
488 }
489
490 /****************************************************************
491 ****************************************************************/
492
493 WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
494                     struct NetUserDel *r)
495 {
496         struct cli_state *cli = NULL;
497         struct rpc_pipe_client *pipe_cli = NULL;
498         NTSTATUS status;
499         WERROR werr;
500         POLICY_HND connect_handle, builtin_handle, domain_handle, user_handle;
501         struct lsa_String lsa_account_name;
502         struct samr_Ids user_rids, name_types;
503         struct dom_sid2 *domain_sid = NULL;
504         struct dom_sid2 user_sid;
505
506         ZERO_STRUCT(connect_handle);
507         ZERO_STRUCT(builtin_handle);
508         ZERO_STRUCT(domain_handle);
509         ZERO_STRUCT(user_handle);
510
511         werr = libnetapi_open_pipe(ctx, r->in.server_name,
512                                    &ndr_table_samr.syntax_id,
513                                    &cli,
514                                    &pipe_cli);
515
516         if (!W_ERROR_IS_OK(werr)) {
517                 goto done;
518         }
519
520         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
521                                           SAMR_ACCESS_ENUM_DOMAINS |
522                                           SAMR_ACCESS_OPEN_DOMAIN,
523                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
524                                           &connect_handle,
525                                           &domain_handle,
526                                           &domain_sid);
527         if (!W_ERROR_IS_OK(werr)) {
528                 goto done;
529         }
530
531         status = rpccli_samr_OpenDomain(pipe_cli, ctx,
532                                         &connect_handle,
533                                         SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
534                                         CONST_DISCARD(DOM_SID *, &global_sid_Builtin),
535                                         &builtin_handle);
536         if (!NT_STATUS_IS_OK(status)) {
537                 werr = ntstatus_to_werror(status);
538                 goto done;
539         }
540
541         init_lsa_String(&lsa_account_name, r->in.user_name);
542
543         status = rpccli_samr_LookupNames(pipe_cli, ctx,
544                                          &domain_handle,
545                                          1,
546                                          &lsa_account_name,
547                                          &user_rids,
548                                          &name_types);
549         if (!NT_STATUS_IS_OK(status)) {
550                 werr = ntstatus_to_werror(status);
551                 goto done;
552         }
553
554         status = rpccli_samr_OpenUser(pipe_cli, ctx,
555                                       &domain_handle,
556                                       STD_RIGHT_DELETE_ACCESS,
557                                       user_rids.ids[0],
558                                       &user_handle);
559         if (!NT_STATUS_IS_OK(status)) {
560                 werr = ntstatus_to_werror(status);
561                 goto done;
562         }
563
564         sid_compose(&user_sid, domain_sid, user_rids.ids[0]);
565
566         status = rpccli_samr_RemoveMemberFromForeignDomain(pipe_cli, ctx,
567                                                            &builtin_handle,
568                                                            &user_sid);
569         if (!NT_STATUS_IS_OK(status)) {
570                 werr = ntstatus_to_werror(status);
571                 goto done;
572         }
573
574         status = rpccli_samr_DeleteUser(pipe_cli, ctx,
575                                         &user_handle);
576         if (!NT_STATUS_IS_OK(status)) {
577                 werr = ntstatus_to_werror(status);
578                 goto done;
579         }
580
581         werr = WERR_OK;
582
583  done:
584         if (!cli) {
585                 return werr;
586         }
587
588         if (is_valid_policy_hnd(&user_handle)) {
589                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
590         }
591
592         if (ctx->disable_policy_handle_cache) {
593                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
594                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
595                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
596         }
597
598         return werr;
599 }
600
601 /****************************************************************
602 ****************************************************************/
603
604 WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
605                     struct NetUserDel *r)
606 {
607         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserDel);
608 }
609
610 /****************************************************************
611 ****************************************************************/
612
613 static NTSTATUS libnetapi_samr_lookup_user(TALLOC_CTX *mem_ctx,
614                                            struct rpc_pipe_client *pipe_cli,
615                                            struct policy_handle *domain_handle,
616                                            struct policy_handle *builtin_handle,
617                                            const char *user_name,
618                                            const struct dom_sid *domain_sid,
619                                            uint32_t rid,
620                                            uint32_t level,
621                                            struct samr_UserInfo21 **info21,
622                                            struct sec_desc_buf **sec_desc,
623                                            uint32_t *auth_flag_p)
624 {
625         NTSTATUS status;
626
627         struct policy_handle user_handle;
628         union samr_UserInfo *user_info = NULL;
629         struct samr_RidWithAttributeArray *rid_array = NULL;
630         uint32_t access_mask = SEC_STD_READ_CONTROL |
631                                SAMR_USER_ACCESS_GET_ATTRIBUTES |
632                                SAMR_USER_ACCESS_GET_NAME_ETC;
633
634         ZERO_STRUCT(user_handle);
635
636         switch (level) {
637                 case 0:
638                         break;
639                 case 1:
640                         access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
641                                        SAMR_USER_ACCESS_GET_GROUPS;
642                         break;
643                 case 2:
644                 case 3:
645                 case 4:
646                 case 11:
647                         access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
648                                        SAMR_USER_ACCESS_GET_GROUPS |
649                                        SAMR_USER_ACCESS_GET_LOCALE;
650                         break;
651                 case 10:
652                 case 20:
653                 case 23:
654                         break;
655                 default:
656                         return NT_STATUS_INVALID_LEVEL;
657         }
658
659         if (level == 0) {
660                 return NT_STATUS_OK;
661         }
662
663         status = rpccli_samr_OpenUser(pipe_cli, mem_ctx,
664                                       domain_handle,
665                                       access_mask,
666                                       rid,
667                                       &user_handle);
668         if (!NT_STATUS_IS_OK(status)) {
669                 goto done;
670         }
671
672         status = rpccli_samr_QueryUserInfo(pipe_cli, mem_ctx,
673                                            &user_handle,
674                                            21,
675                                            &user_info);
676         if (!NT_STATUS_IS_OK(status)) {
677                 goto done;
678         }
679
680         status = rpccli_samr_QuerySecurity(pipe_cli, mem_ctx,
681                                            &user_handle,
682                                            SECINFO_DACL,
683                                            sec_desc);
684         if (!NT_STATUS_IS_OK(status)) {
685                 goto done;
686         }
687
688         if (access_mask & SAMR_USER_ACCESS_GET_GROUPS) {
689
690                 struct lsa_SidArray sid_array;
691                 struct samr_Ids alias_rids;
692                 int i;
693                 uint32_t auth_flag = 0;
694                 struct dom_sid sid;
695
696                 status = rpccli_samr_GetGroupsForUser(pipe_cli, mem_ctx,
697                                                       &user_handle,
698                                                       &rid_array);
699                 if (!NT_STATUS_IS_OK(status)) {
700                         goto done;
701                 }
702
703                 sid_array.num_sids = rid_array->count + 1;
704                 sid_array.sids = talloc_array(mem_ctx, struct lsa_SidPtr,
705                                               sid_array.num_sids);
706                 NT_STATUS_HAVE_NO_MEMORY(sid_array.sids);
707
708                 for (i=0; i<rid_array->count; i++) {
709                         sid_compose(&sid, domain_sid, rid_array->rids[i].rid);
710                         sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sid);
711                         NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
712                 }
713
714                 sid_compose(&sid, domain_sid, rid);
715                 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sid);
716                 NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
717
718                 status = rpccli_samr_GetAliasMembership(pipe_cli, mem_ctx,
719                                                         builtin_handle,
720                                                         &sid_array,
721                                                         &alias_rids);
722                 if (!NT_STATUS_IS_OK(status)) {
723                         goto done;
724                 }
725
726                 for (i=0; i<alias_rids.count; i++) {
727                         switch (alias_rids.ids[i]) {
728                                 case 550: /* Print Operators */
729                                         auth_flag |= AF_OP_PRINT;
730                                         break;
731                                 case 549: /* Server Operators */
732                                         auth_flag |= AF_OP_SERVER;
733                                         break;
734                                 case 548: /* Account Operators */
735                                         auth_flag |= AF_OP_ACCOUNTS;
736                                         break;
737                                 default:
738                                         break;
739                         }
740                 }
741
742                 if (auth_flag_p) {
743                         *auth_flag_p = auth_flag;
744                 }
745         }
746
747         *info21 = &user_info->info21;
748
749  done:
750         if (is_valid_policy_hnd(&user_handle)) {
751                 rpccli_samr_Close(pipe_cli, mem_ctx, &user_handle);
752         }
753
754         return status;
755 }
756
757 /****************************************************************
758 ****************************************************************/
759
760 static uint32_t samr_rid_to_priv_level(uint32_t rid)
761 {
762         switch (rid) {
763                 case DOMAIN_RID_ADMINISTRATOR:
764                         return USER_PRIV_ADMIN;
765                 case DOMAIN_RID_GUEST:
766                         return USER_PRIV_GUEST;
767                 default:
768                         return USER_PRIV_USER;
769         }
770 }
771
772 /****************************************************************
773 ****************************************************************/
774
775 static uint32_t samr_acb_flags_to_netapi_flags(uint32_t acb)
776 {
777         uint32_t fl = UF_SCRIPT; /* god knows why */
778
779         fl |= ads_acb2uf(acb);
780
781         return fl;
782 }
783
784 /****************************************************************
785 ****************************************************************/
786
787 static NTSTATUS info21_to_USER_INFO_1(TALLOC_CTX *mem_ctx,
788                                       const struct samr_UserInfo21 *i21,
789                                       struct USER_INFO_1 *i)
790 {
791         ZERO_STRUCTP(i);
792         i->usri1_name           = talloc_strdup(mem_ctx, i21->account_name.string);
793         NT_STATUS_HAVE_NO_MEMORY(i->usri1_name);
794         i->usri1_password       = NULL;
795         i->usri1_password_age   = time(NULL) - nt_time_to_unix(i21->last_password_change);
796         i->usri1_priv           = samr_rid_to_priv_level(i21->rid);
797         i->usri1_home_dir       = talloc_strdup(mem_ctx, i21->home_directory.string);
798         i->usri1_comment        = talloc_strdup(mem_ctx, i21->description.string);
799         i->usri1_flags          = samr_acb_flags_to_netapi_flags(i21->acct_flags);
800         i->usri1_script_path    = talloc_strdup(mem_ctx, i21->logon_script.string);
801
802         return NT_STATUS_OK;
803 }
804
805 /****************************************************************
806 ****************************************************************/
807
808 static NTSTATUS info21_to_USER_INFO_2(TALLOC_CTX *mem_ctx,
809                                       const struct samr_UserInfo21 *i21,
810                                       uint32_t auth_flag,
811                                       struct USER_INFO_2 *i)
812 {
813         ZERO_STRUCTP(i);
814
815         i->usri2_name           = talloc_strdup(mem_ctx, i21->account_name.string);
816         NT_STATUS_HAVE_NO_MEMORY(i->usri2_name);
817         i->usri2_password       = NULL;
818         i->usri2_password_age   = time(NULL) - nt_time_to_unix(i21->last_password_change);
819         i->usri2_priv           = samr_rid_to_priv_level(i21->rid);
820         i->usri2_home_dir       = talloc_strdup(mem_ctx, i21->home_directory.string);
821         i->usri2_comment        = talloc_strdup(mem_ctx, i21->description.string);
822         i->usri2_flags          = samr_acb_flags_to_netapi_flags(i21->acct_flags);
823         i->usri2_script_path    = talloc_strdup(mem_ctx, i21->logon_script.string);
824         i->usri2_auth_flags     = auth_flag;
825         i->usri2_full_name      = talloc_strdup(mem_ctx, i21->full_name.string);
826         i->usri2_usr_comment    = talloc_strdup(mem_ctx, i21->comment.string);
827         i->usri2_parms          = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
828         i->usri2_workstations   = talloc_strdup(mem_ctx, i21->workstations.string);
829         i->usri2_last_logon     = nt_time_to_unix(i21->last_logon);
830         i->usri2_last_logoff    = nt_time_to_unix(i21->last_logoff);
831         i->usri2_acct_expires   = nt_time_to_unix(i21->acct_expiry);
832         i->usri2_max_storage    = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
833         i->usri2_units_per_week = i21->logon_hours.units_per_week;
834         i->usri2_logon_hours    = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
835         i->usri2_bad_pw_count   = i21->bad_password_count;
836         i->usri2_num_logons     = i21->logon_count;
837         i->usri2_logon_server   = talloc_strdup(mem_ctx, "\\\\*");
838         i->usri2_country_code   = i21->country_code;
839         i->usri2_code_page      = i21->code_page;
840
841         return NT_STATUS_OK;
842 }
843
844 /****************************************************************
845 ****************************************************************/
846
847 static NTSTATUS info21_to_USER_INFO_3(TALLOC_CTX *mem_ctx,
848                                       const struct samr_UserInfo21 *i21,
849                                       uint32_t auth_flag,
850                                       struct USER_INFO_3 *i)
851 {
852         ZERO_STRUCTP(i);
853
854         i->usri3_name           = talloc_strdup(mem_ctx, i21->account_name.string);
855         NT_STATUS_HAVE_NO_MEMORY(i->usri3_name);
856         i->usri3_password_age   = time(NULL) - nt_time_to_unix(i21->last_password_change);
857         i->usri3_priv           = samr_rid_to_priv_level(i21->rid);
858         i->usri3_home_dir       = talloc_strdup(mem_ctx, i21->home_directory.string);
859         i->usri3_comment        = talloc_strdup(mem_ctx, i21->description.string);
860         i->usri3_flags          = samr_acb_flags_to_netapi_flags(i21->acct_flags);
861         i->usri3_script_path    = talloc_strdup(mem_ctx, i21->logon_script.string);
862         i->usri3_auth_flags     = auth_flag;
863         i->usri3_full_name      = talloc_strdup(mem_ctx, i21->full_name.string);
864         i->usri3_usr_comment    = talloc_strdup(mem_ctx, i21->comment.string);
865         i->usri3_parms          = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
866         i->usri3_workstations   = talloc_strdup(mem_ctx, i21->workstations.string);
867         i->usri3_last_logon     = nt_time_to_unix(i21->last_logon);
868         i->usri3_last_logoff    = nt_time_to_unix(i21->last_logoff);
869         i->usri3_acct_expires   = nt_time_to_unix(i21->acct_expiry);
870         i->usri3_max_storage    = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
871         i->usri3_units_per_week = i21->logon_hours.units_per_week;
872         i->usri3_logon_hours    = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
873         i->usri3_bad_pw_count   = i21->bad_password_count;
874         i->usri3_num_logons     = i21->logon_count;
875         i->usri3_logon_server   = talloc_strdup(mem_ctx, "\\\\*");
876         i->usri3_country_code   = i21->country_code;
877         i->usri3_code_page      = i21->code_page;
878         i->usri3_user_id        = i21->rid;
879         i->usri3_primary_group_id = i21->primary_gid;
880         i->usri3_profile        = talloc_strdup(mem_ctx, i21->profile_path.string);
881         i->usri3_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
882         i->usri3_password_expired = i21->password_expired;
883
884         return NT_STATUS_OK;
885 }
886
887 /****************************************************************
888 ****************************************************************/
889
890 static NTSTATUS info21_to_USER_INFO_4(TALLOC_CTX *mem_ctx,
891                                       const struct samr_UserInfo21 *i21,
892                                       uint32_t auth_flag,
893                                       struct dom_sid *domain_sid,
894                                       struct USER_INFO_4 *i)
895 {
896         struct dom_sid sid;
897
898         ZERO_STRUCTP(i);
899
900         i->usri4_name           = talloc_strdup(mem_ctx, i21->account_name.string);
901         NT_STATUS_HAVE_NO_MEMORY(i->usri4_name);
902         i->usri4_password_age   = time(NULL) - nt_time_to_unix(i21->last_password_change);
903         i->usri4_password       = NULL;
904         i->usri4_priv           = samr_rid_to_priv_level(i21->rid);
905         i->usri4_home_dir       = talloc_strdup(mem_ctx, i21->home_directory.string);
906         i->usri4_comment        = talloc_strdup(mem_ctx, i21->description.string);
907         i->usri4_flags          = samr_acb_flags_to_netapi_flags(i21->acct_flags);
908         i->usri4_script_path    = talloc_strdup(mem_ctx, i21->logon_script.string);
909         i->usri4_auth_flags     = auth_flag;
910         i->usri4_full_name      = talloc_strdup(mem_ctx, i21->full_name.string);
911         i->usri4_usr_comment    = talloc_strdup(mem_ctx, i21->comment.string);
912         i->usri4_parms          = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
913         i->usri4_workstations   = talloc_strdup(mem_ctx, i21->workstations.string);
914         i->usri4_last_logon     = nt_time_to_unix(i21->last_logon);
915         i->usri4_last_logoff    = nt_time_to_unix(i21->last_logoff);
916         i->usri4_acct_expires   = nt_time_to_unix(i21->acct_expiry);
917         i->usri4_max_storage    = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
918         i->usri4_units_per_week = i21->logon_hours.units_per_week;
919         i->usri4_logon_hours    = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
920         i->usri4_bad_pw_count   = i21->bad_password_count;
921         i->usri4_num_logons     = i21->logon_count;
922         i->usri4_logon_server   = talloc_strdup(mem_ctx, "\\\\*");
923         i->usri4_country_code   = i21->country_code;
924         i->usri4_code_page      = i21->code_page;
925         if (!sid_compose(&sid, domain_sid, i21->rid)) {
926                 return NT_STATUS_NO_MEMORY;
927         }
928         i->usri4_user_sid       = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
929         i->usri4_primary_group_id = i21->primary_gid;
930         i->usri4_profile        = talloc_strdup(mem_ctx, i21->profile_path.string);
931         i->usri4_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
932         i->usri4_password_expired = i21->password_expired;
933
934         return NT_STATUS_OK;
935 }
936
937 /****************************************************************
938 ****************************************************************/
939
940 static NTSTATUS info21_to_USER_INFO_10(TALLOC_CTX *mem_ctx,
941                                        const struct samr_UserInfo21 *i21,
942                                        struct USER_INFO_10 *i)
943 {
944         ZERO_STRUCTP(i);
945
946         i->usri10_name          = talloc_strdup(mem_ctx, i21->account_name.string);
947         NT_STATUS_HAVE_NO_MEMORY(i->usri10_name);
948         i->usri10_comment       = talloc_strdup(mem_ctx, i21->description.string);
949         i->usri10_full_name     = talloc_strdup(mem_ctx, i21->full_name.string);
950         i->usri10_usr_comment   = talloc_strdup(mem_ctx, i21->comment.string);
951
952         return NT_STATUS_OK;
953 }
954
955 /****************************************************************
956 ****************************************************************/
957
958 static NTSTATUS info21_to_USER_INFO_11(TALLOC_CTX *mem_ctx,
959                                        const struct samr_UserInfo21 *i21,
960                                        uint32_t auth_flag,
961                                        struct USER_INFO_11 *i)
962 {
963         ZERO_STRUCTP(i);
964
965         i->usri11_name          = talloc_strdup(mem_ctx, i21->account_name.string);
966         NT_STATUS_HAVE_NO_MEMORY(i->usri11_name);
967         i->usri11_comment       = talloc_strdup(mem_ctx, i21->description.string);
968         i->usri11_usr_comment   = talloc_strdup(mem_ctx, i21->comment.string);
969         i->usri11_full_name     = talloc_strdup(mem_ctx, i21->full_name.string);
970         i->usri11_priv          = samr_rid_to_priv_level(i21->rid);
971         i->usri11_auth_flags    = auth_flag;
972         i->usri11_password_age  = time(NULL) - nt_time_to_unix(i21->last_password_change);
973         i->usri11_home_dir      = talloc_strdup(mem_ctx, i21->home_directory.string);
974         i->usri11_parms         = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
975         i->usri11_last_logon    = nt_time_to_unix(i21->last_logon);
976         i->usri11_last_logoff   = nt_time_to_unix(i21->last_logoff);
977         i->usri11_bad_pw_count  = i21->bad_password_count;
978         i->usri11_num_logons    = i21->logon_count;
979         i->usri11_logon_server  = talloc_strdup(mem_ctx, "\\\\*");
980         i->usri11_country_code  = i21->country_code;
981         i->usri11_workstations  = talloc_strdup(mem_ctx, i21->workstations.string);
982         i->usri11_max_storage   = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
983         i->usri11_units_per_week = i21->logon_hours.units_per_week;
984         i->usri11_logon_hours   = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
985         i->usri11_code_page     = i21->code_page;
986
987         return NT_STATUS_OK;
988 }
989
990 /****************************************************************
991 ****************************************************************/
992
993 static NTSTATUS info21_to_USER_INFO_20(TALLOC_CTX *mem_ctx,
994                                        const struct samr_UserInfo21 *i21,
995                                        struct USER_INFO_20 *i)
996 {
997         ZERO_STRUCTP(i);
998
999         i->usri20_name          = talloc_strdup(mem_ctx, i21->account_name.string);
1000         NT_STATUS_HAVE_NO_MEMORY(i->usri20_name);
1001         i->usri20_comment       = talloc_strdup(mem_ctx, i21->description.string);
1002         i->usri20_full_name     = talloc_strdup(mem_ctx, i21->full_name.string);
1003         i->usri20_flags         = samr_acb_flags_to_netapi_flags(i21->acct_flags);
1004         i->usri20_user_id       = i21->rid;
1005
1006         return NT_STATUS_OK;
1007 }
1008
1009 /****************************************************************
1010 ****************************************************************/
1011
1012 static NTSTATUS info21_to_USER_INFO_23(TALLOC_CTX *mem_ctx,
1013                                        const struct samr_UserInfo21 *i21,
1014                                        struct dom_sid *domain_sid,
1015                                        struct USER_INFO_23 *i)
1016 {
1017         struct dom_sid sid;
1018
1019         ZERO_STRUCTP(i);
1020
1021         i->usri23_name          = talloc_strdup(mem_ctx, i21->account_name.string);
1022         NT_STATUS_HAVE_NO_MEMORY(i->usri23_name);
1023         i->usri23_comment       = talloc_strdup(mem_ctx, i21->description.string);
1024         i->usri23_full_name     = talloc_strdup(mem_ctx, i21->full_name.string);
1025         i->usri23_flags         = samr_acb_flags_to_netapi_flags(i21->acct_flags);
1026         if (!sid_compose(&sid, domain_sid, i21->rid)) {
1027                 return NT_STATUS_NO_MEMORY;
1028         }
1029         i->usri23_user_sid      = (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
1030
1031         return NT_STATUS_OK;
1032 }
1033
1034 /****************************************************************
1035 ****************************************************************/
1036
1037 static NTSTATUS libnetapi_samr_lookup_user_map_USER_INFO(TALLOC_CTX *mem_ctx,
1038                                                          struct rpc_pipe_client *pipe_cli,
1039                                                          struct dom_sid *domain_sid,
1040                                                          struct policy_handle *domain_handle,
1041                                                          struct policy_handle *builtin_handle,
1042                                                          const char *user_name,
1043                                                          uint32_t rid,
1044                                                          uint32_t level,
1045                                                          uint8_t **buffer,
1046                                                          uint32_t *num_entries)
1047 {
1048         NTSTATUS status;
1049
1050         struct samr_UserInfo21 *info21 = NULL;
1051         struct sec_desc_buf *sec_desc = NULL;
1052         uint32_t auth_flag = 0;
1053
1054         struct USER_INFO_0 info0;
1055         struct USER_INFO_1 info1;
1056         struct USER_INFO_2 info2;
1057         struct USER_INFO_3 info3;
1058         struct USER_INFO_4 info4;
1059         struct USER_INFO_10 info10;
1060         struct USER_INFO_11 info11;
1061         struct USER_INFO_20 info20;
1062         struct USER_INFO_23 info23;
1063
1064         switch (level) {
1065                 case 0:
1066                 case 1:
1067                 case 2:
1068                 case 3:
1069                 case 4:
1070                 case 10:
1071                 case 11:
1072                 case 20:
1073                 case 23:
1074                         break;
1075                 default:
1076                         return NT_STATUS_INVALID_LEVEL;
1077         }
1078
1079         if (level == 0) {
1080                 info0.usri0_name = talloc_strdup(mem_ctx, user_name);
1081                 NT_STATUS_HAVE_NO_MEMORY(info0.usri0_name);
1082
1083                 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_0, info0,
1084                              (struct USER_INFO_0 **)buffer, num_entries);
1085
1086                 return NT_STATUS_OK;
1087         }
1088
1089         status = libnetapi_samr_lookup_user(mem_ctx, pipe_cli,
1090                                             domain_handle,
1091                                             builtin_handle,
1092                                             user_name,
1093                                             domain_sid,
1094                                             rid,
1095                                             level,
1096                                             &info21,
1097                                             &sec_desc,
1098                                             &auth_flag);
1099
1100         if (!NT_STATUS_IS_OK(status)) {
1101                 goto done;
1102         }
1103
1104         switch (level) {
1105                 case 0:
1106                         /* already returned above */
1107                         break;
1108                 case 1:
1109                         status = info21_to_USER_INFO_1(mem_ctx, info21, &info1);
1110                         NT_STATUS_NOT_OK_RETURN(status);
1111
1112                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_1, info1,
1113                                      (struct USER_INFO_1 **)buffer, num_entries);
1114
1115                         break;
1116                 case 2:
1117                         status = info21_to_USER_INFO_2(mem_ctx, info21, auth_flag, &info2);
1118                         NT_STATUS_NOT_OK_RETURN(status);
1119
1120                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_2, info2,
1121                                      (struct USER_INFO_2 **)buffer, num_entries);
1122
1123                         break;
1124                 case 3:
1125                         status = info21_to_USER_INFO_3(mem_ctx, info21, auth_flag, &info3);
1126                         NT_STATUS_NOT_OK_RETURN(status);
1127
1128                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_3, info3,
1129                                      (struct USER_INFO_3 **)buffer, num_entries);
1130
1131                         break;
1132                 case 4:
1133                         status = info21_to_USER_INFO_4(mem_ctx, info21, auth_flag, domain_sid, &info4);
1134                         NT_STATUS_NOT_OK_RETURN(status);
1135
1136                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_4, info4,
1137                                      (struct USER_INFO_4 **)buffer, num_entries);
1138
1139                         break;
1140                 case 10:
1141                         status = info21_to_USER_INFO_10(mem_ctx, info21, &info10);
1142                         NT_STATUS_NOT_OK_RETURN(status);
1143
1144                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_10, info10,
1145                                      (struct USER_INFO_10 **)buffer, num_entries);
1146
1147                         break;
1148                 case 11:
1149                         status = info21_to_USER_INFO_11(mem_ctx, info21, auth_flag, &info11);
1150                         NT_STATUS_NOT_OK_RETURN(status);
1151
1152                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_11, info11,
1153                                      (struct USER_INFO_11 **)buffer, num_entries);
1154
1155                         break;
1156                 case 20:
1157                         status = info21_to_USER_INFO_20(mem_ctx, info21, &info20);
1158                         NT_STATUS_NOT_OK_RETURN(status);
1159
1160                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_20, info20,
1161                                      (struct USER_INFO_20 **)buffer, num_entries);
1162
1163                         break;
1164                 case 23:
1165                         status = info21_to_USER_INFO_23(mem_ctx, info21, domain_sid, &info23);
1166                         NT_STATUS_NOT_OK_RETURN(status);
1167
1168                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_23, info23,
1169                                      (struct USER_INFO_23 **)buffer, num_entries);
1170                         break;
1171                 default:
1172                         return NT_STATUS_INVALID_LEVEL;
1173         }
1174
1175  done:
1176         return status;
1177 }
1178
1179 /****************************************************************
1180 ****************************************************************/
1181
1182 WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
1183                      struct NetUserEnum *r)
1184 {
1185         struct cli_state *cli = NULL;
1186         struct rpc_pipe_client *pipe_cli = NULL;
1187         struct policy_handle connect_handle;
1188         struct dom_sid2 *domain_sid = NULL;
1189         struct policy_handle domain_handle, builtin_handle;
1190         struct samr_SamArray *sam = NULL;
1191         uint32_t filter = ACB_NORMAL;
1192         int i;
1193         uint32_t entries_read = 0;
1194
1195         NTSTATUS status = NT_STATUS_OK;
1196         WERROR werr;
1197
1198         ZERO_STRUCT(connect_handle);
1199         ZERO_STRUCT(domain_handle);
1200         ZERO_STRUCT(builtin_handle);
1201
1202         if (!r->out.buffer) {
1203                 return WERR_INVALID_PARAM;
1204         }
1205
1206         *r->out.buffer = NULL;
1207         *r->out.entries_read = 0;
1208
1209         switch (r->in.level) {
1210                 case 0:
1211                 case 1:
1212                 case 2:
1213                 case 3:
1214                 case 4:
1215                 case 10:
1216                 case 11:
1217                 case 20:
1218                 case 23:
1219                         break;
1220                 default:
1221                         return WERR_UNKNOWN_LEVEL;
1222         }
1223
1224         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1225                                    &ndr_table_samr.syntax_id,
1226                                    &cli,
1227                                    &pipe_cli);
1228         if (!W_ERROR_IS_OK(werr)) {
1229                 goto done;
1230         }
1231
1232         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1233                                                   SAMR_ACCESS_ENUM_DOMAINS |
1234                                                   SAMR_ACCESS_OPEN_DOMAIN,
1235                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1236                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1237                                                   &connect_handle,
1238                                                   &builtin_handle);
1239         if (!W_ERROR_IS_OK(werr)) {
1240                 goto done;
1241         }
1242
1243         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1244                                           SAMR_ACCESS_ENUM_DOMAINS |
1245                                           SAMR_ACCESS_OPEN_DOMAIN,
1246                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1247                                           SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1248                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1249                                           &connect_handle,
1250                                           &domain_handle,
1251                                           &domain_sid);
1252         if (!W_ERROR_IS_OK(werr)) {
1253                 goto done;
1254         }
1255
1256         switch (r->in.filter) {
1257                 case FILTER_NORMAL_ACCOUNT:
1258                         filter = ACB_NORMAL;
1259                         break;
1260                 case FILTER_TEMP_DUPLICATE_ACCOUNT:
1261                         filter = ACB_TEMPDUP;
1262                         break;
1263                 case FILTER_INTERDOMAIN_TRUST_ACCOUNT:
1264                         filter = ACB_DOMTRUST;
1265                         break;
1266                 case FILTER_WORKSTATION_TRUST_ACCOUNT:
1267                         filter = ACB_WSTRUST;
1268                         break;
1269                 case FILTER_SERVER_TRUST_ACCOUNT:
1270                         filter = ACB_SVRTRUST;
1271                         break;
1272                 default:
1273                         break;
1274         }
1275
1276         status = rpccli_samr_EnumDomainUsers(pipe_cli,
1277                                              ctx,
1278                                              &domain_handle,
1279                                              r->in.resume_handle,
1280                                              filter,
1281                                              &sam,
1282                                              r->in.prefmaxlen,
1283                                              &entries_read);
1284         werr = ntstatus_to_werror(status);
1285         if (NT_STATUS_IS_ERR(status)) {
1286                 goto done;
1287         }
1288
1289         for (i=0; i < sam->count; i++) {
1290
1291                 status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1292                                                                   domain_sid,
1293                                                                   &domain_handle,
1294                                                                   &builtin_handle,
1295                                                                   sam->entries[i].name.string,
1296                                                                   sam->entries[i].idx,
1297                                                                   r->in.level,
1298                                                                   r->out.buffer,
1299                                                                   r->out.entries_read);
1300                 if (!NT_STATUS_IS_OK(status)) {
1301                         werr = ntstatus_to_werror(status);
1302                         goto done;
1303                 }
1304         }
1305
1306  done:
1307         if (!cli) {
1308                 return werr;
1309         }
1310
1311         /* if last query */
1312         if (NT_STATUS_IS_OK(status) ||
1313             NT_STATUS_IS_ERR(status)) {
1314
1315                 if (ctx->disable_policy_handle_cache) {
1316                         libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1317                         libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1318                         libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1319                 }
1320         }
1321
1322         return werr;
1323 }
1324
1325 /****************************************************************
1326 ****************************************************************/
1327
1328 WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
1329                      struct NetUserEnum *r)
1330 {
1331         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserEnum);
1332 }
1333
1334 /****************************************************************
1335 ****************************************************************/
1336
1337 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_USER(TALLOC_CTX *mem_ctx,
1338                                                         struct samr_DispInfoGeneral *info,
1339                                                         uint32_t *entries_read,
1340                                                         void **buffer)
1341 {
1342         struct NET_DISPLAY_USER *user = NULL;
1343         int i;
1344
1345         user = TALLOC_ZERO_ARRAY(mem_ctx,
1346                                  struct NET_DISPLAY_USER,
1347                                  info->count);
1348         W_ERROR_HAVE_NO_MEMORY(user);
1349
1350         for (i = 0; i < info->count; i++) {
1351                 user[i].usri1_name = talloc_strdup(mem_ctx,
1352                         info->entries[i].account_name.string);
1353                 user[i].usri1_comment = talloc_strdup(mem_ctx,
1354                         info->entries[i].description.string);
1355                 user[i].usri1_flags =
1356                         info->entries[i].acct_flags;
1357                 user[i].usri1_full_name = talloc_strdup(mem_ctx,
1358                         info->entries[i].full_name.string);
1359                 user[i].usri1_user_id =
1360                         info->entries[i].rid;
1361                 user[i].usri1_next_index =
1362                         info->entries[i].idx;
1363
1364                 if (!user[i].usri1_name) {
1365                         return WERR_NOMEM;
1366                 }
1367         }
1368
1369         *buffer = talloc_memdup(mem_ctx, user,
1370                 sizeof(struct NET_DISPLAY_USER) * info->count);
1371         W_ERROR_HAVE_NO_MEMORY(*buffer);
1372
1373         *entries_read = info->count;
1374
1375         return WERR_OK;
1376 }
1377
1378 /****************************************************************
1379 ****************************************************************/
1380
1381 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(TALLOC_CTX *mem_ctx,
1382                                                            struct samr_DispInfoFull *info,
1383                                                            uint32_t *entries_read,
1384                                                            void **buffer)
1385 {
1386         struct NET_DISPLAY_MACHINE *machine = NULL;
1387         int i;
1388
1389         machine = TALLOC_ZERO_ARRAY(mem_ctx,
1390                                     struct NET_DISPLAY_MACHINE,
1391                                     info->count);
1392         W_ERROR_HAVE_NO_MEMORY(machine);
1393
1394         for (i = 0; i < info->count; i++) {
1395                 machine[i].usri2_name = talloc_strdup(mem_ctx,
1396                         info->entries[i].account_name.string);
1397                 machine[i].usri2_comment = talloc_strdup(mem_ctx,
1398                         info->entries[i].description.string);
1399                 machine[i].usri2_flags =
1400                         info->entries[i].acct_flags;
1401                 machine[i].usri2_user_id =
1402                         info->entries[i].rid;
1403                 machine[i].usri2_next_index =
1404                         info->entries[i].idx;
1405
1406                 if (!machine[i].usri2_name) {
1407                         return WERR_NOMEM;
1408                 }
1409         }
1410
1411         *buffer = talloc_memdup(mem_ctx, machine,
1412                 sizeof(struct NET_DISPLAY_MACHINE) * info->count);
1413         W_ERROR_HAVE_NO_MEMORY(*buffer);
1414
1415         *entries_read = info->count;
1416
1417         return WERR_OK;
1418 }
1419
1420 /****************************************************************
1421 ****************************************************************/
1422
1423 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_GROUP(TALLOC_CTX *mem_ctx,
1424                                                          struct samr_DispInfoFullGroups *info,
1425                                                          uint32_t *entries_read,
1426                                                          void **buffer)
1427 {
1428         struct NET_DISPLAY_GROUP *group = NULL;
1429         int i;
1430
1431         group = TALLOC_ZERO_ARRAY(mem_ctx,
1432                                   struct NET_DISPLAY_GROUP,
1433                                   info->count);
1434         W_ERROR_HAVE_NO_MEMORY(group);
1435
1436         for (i = 0; i < info->count; i++) {
1437                 group[i].grpi3_name = talloc_strdup(mem_ctx,
1438                         info->entries[i].account_name.string);
1439                 group[i].grpi3_comment = talloc_strdup(mem_ctx,
1440                         info->entries[i].description.string);
1441                 group[i].grpi3_group_id =
1442                         info->entries[i].rid;
1443                 group[i].grpi3_attributes =
1444                         info->entries[i].acct_flags;
1445                 group[i].grpi3_next_index =
1446                         info->entries[i].idx;
1447
1448                 if (!group[i].grpi3_name) {
1449                         return WERR_NOMEM;
1450                 }
1451         }
1452
1453         *buffer = talloc_memdup(mem_ctx, group,
1454                 sizeof(struct NET_DISPLAY_GROUP) * info->count);
1455         W_ERROR_HAVE_NO_MEMORY(*buffer);
1456
1457         *entries_read = info->count;
1458
1459         return WERR_OK;
1460
1461 }
1462
1463 /****************************************************************
1464 ****************************************************************/
1465
1466 static WERROR convert_samr_dispinfo_to_NET_DISPLAY(TALLOC_CTX *mem_ctx,
1467                                                    union samr_DispInfo *info,
1468                                                    uint32_t level,
1469                                                    uint32_t *entries_read,
1470                                                    void **buffer)
1471 {
1472         switch (level) {
1473                 case 1:
1474                         return convert_samr_dispinfo_to_NET_DISPLAY_USER(mem_ctx,
1475                                                                          &info->info1,
1476                                                                          entries_read,
1477                                                                          buffer);
1478                 case 2:
1479                         return convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(mem_ctx,
1480                                                                             &info->info2,
1481                                                                             entries_read,
1482                                                                             buffer);
1483                 case 3:
1484                         return convert_samr_dispinfo_to_NET_DISPLAY_GROUP(mem_ctx,
1485                                                                           &info->info3,
1486                                                                           entries_read,
1487                                                                           buffer);
1488                 default:
1489                         return WERR_UNKNOWN_LEVEL;
1490         }
1491
1492         return WERR_OK;
1493 }
1494
1495 /****************************************************************
1496 ****************************************************************/
1497
1498 WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
1499                                     struct NetQueryDisplayInformation *r)
1500 {
1501         struct cli_state *cli = NULL;
1502         struct rpc_pipe_client *pipe_cli = NULL;
1503         struct policy_handle connect_handle;
1504         struct dom_sid2 *domain_sid = NULL;
1505         struct policy_handle domain_handle;
1506         union samr_DispInfo info;
1507
1508         uint32_t total_size = 0;
1509         uint32_t returned_size = 0;
1510
1511         NTSTATUS status = NT_STATUS_OK;
1512         WERROR werr;
1513
1514         ZERO_STRUCT(connect_handle);
1515         ZERO_STRUCT(domain_handle);
1516
1517         switch (r->in.level) {
1518                 case 1:
1519                 case 2:
1520                 case 3:
1521                         break;
1522                 default:
1523                         return WERR_UNKNOWN_LEVEL;
1524         }
1525
1526         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1527                                    &ndr_table_samr.syntax_id,
1528                                    &cli,
1529                                    &pipe_cli);
1530         if (!W_ERROR_IS_OK(werr)) {
1531                 goto done;
1532         }
1533
1534         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1535                                           SAMR_ACCESS_ENUM_DOMAINS |
1536                                           SAMR_ACCESS_OPEN_DOMAIN,
1537                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1538                                           SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1539                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1540                                           &connect_handle,
1541                                           &domain_handle,
1542                                           &domain_sid);
1543         if (!W_ERROR_IS_OK(werr)) {
1544                 goto done;
1545         }
1546
1547         status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
1548                                                ctx,
1549                                                &domain_handle,
1550                                                r->in.level,
1551                                                r->in.idx,
1552                                                r->in.entries_requested,
1553                                                r->in.prefmaxlen,
1554                                                &total_size,
1555                                                &returned_size,
1556                                                &info);
1557         if (!NT_STATUS_IS_OK(status)) {
1558                 werr = ntstatus_to_werror(status);
1559                 goto done;
1560         }
1561
1562         werr = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info,
1563                                                     r->in.level,
1564                                                     r->out.entries_read,
1565                                                     r->out.buffer);
1566  done:
1567         if (!cli) {
1568                 return werr;
1569         }
1570
1571         /* if last query */
1572         if (NT_STATUS_IS_OK(status) ||
1573             NT_STATUS_IS_ERR(status)) {
1574
1575                 if (ctx->disable_policy_handle_cache) {
1576                         libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1577                         libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1578                 }
1579         }
1580
1581         return werr;
1582
1583 }
1584
1585 /****************************************************************
1586 ****************************************************************/
1587
1588
1589 WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
1590                                     struct NetQueryDisplayInformation *r)
1591 {
1592         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetQueryDisplayInformation);
1593 }
1594
1595 /****************************************************************
1596 ****************************************************************/
1597
1598 WERROR NetUserChangePassword_r(struct libnetapi_ctx *ctx,
1599                                struct NetUserChangePassword *r)
1600 {
1601         return WERR_NOT_SUPPORTED;
1602 }
1603
1604 /****************************************************************
1605 ****************************************************************/
1606
1607 WERROR NetUserChangePassword_l(struct libnetapi_ctx *ctx,
1608                                struct NetUserChangePassword *r)
1609 {
1610         return WERR_NOT_SUPPORTED;
1611 }
1612
1613 /****************************************************************
1614 ****************************************************************/
1615
1616 WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx,
1617                         struct NetUserGetInfo *r)
1618 {
1619         struct cli_state *cli = NULL;
1620         struct rpc_pipe_client *pipe_cli = NULL;
1621         NTSTATUS status;
1622         WERROR werr;
1623
1624         struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1625         struct lsa_String lsa_account_name;
1626         struct dom_sid2 *domain_sid = NULL;
1627         struct samr_Ids user_rids, name_types;
1628         uint32_t num_entries = 0;
1629
1630         ZERO_STRUCT(connect_handle);
1631         ZERO_STRUCT(domain_handle);
1632         ZERO_STRUCT(builtin_handle);
1633         ZERO_STRUCT(user_handle);
1634
1635         if (!r->out.buffer) {
1636                 return WERR_INVALID_PARAM;
1637         }
1638
1639         switch (r->in.level) {
1640                 case 0:
1641                 case 1:
1642                 case 2:
1643                 case 3:
1644                 case 4:
1645                 case 10:
1646                 case 11:
1647                 case 20:
1648                 case 23:
1649                         break;
1650                 default:
1651                         werr = WERR_UNKNOWN_LEVEL;
1652                         goto done;
1653         }
1654
1655         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1656                                    &ndr_table_samr.syntax_id,
1657                                    &cli,
1658                                    &pipe_cli);
1659         if (!W_ERROR_IS_OK(werr)) {
1660                 goto done;
1661         }
1662
1663         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1664                                           SAMR_ACCESS_ENUM_DOMAINS |
1665                                           SAMR_ACCESS_OPEN_DOMAIN,
1666                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1667                                           &connect_handle,
1668                                           &domain_handle,
1669                                           &domain_sid);
1670         if (!W_ERROR_IS_OK(werr)) {
1671                 goto done;
1672         }
1673
1674         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1675                                                   SAMR_ACCESS_ENUM_DOMAINS |
1676                                                   SAMR_ACCESS_OPEN_DOMAIN,
1677                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1678                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1679                                                   &connect_handle,
1680                                                   &builtin_handle);
1681         if (!W_ERROR_IS_OK(werr)) {
1682                 goto done;
1683         }
1684
1685         init_lsa_String(&lsa_account_name, r->in.user_name);
1686
1687         status = rpccli_samr_LookupNames(pipe_cli, ctx,
1688                                          &domain_handle,
1689                                          1,
1690                                          &lsa_account_name,
1691                                          &user_rids,
1692                                          &name_types);
1693         if (!NT_STATUS_IS_OK(status)) {
1694                 werr = ntstatus_to_werror(status);
1695                 goto done;
1696         }
1697
1698         status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1699                                                           domain_sid,
1700                                                           &domain_handle,
1701                                                           &builtin_handle,
1702                                                           r->in.user_name,
1703                                                           user_rids.ids[0],
1704                                                           r->in.level,
1705                                                           r->out.buffer,
1706                                                           &num_entries);
1707         if (!NT_STATUS_IS_OK(status)) {
1708                 werr = ntstatus_to_werror(status);
1709                 goto done;
1710         }
1711
1712  done:
1713         if (!cli) {
1714                 return werr;
1715         }
1716
1717         if (is_valid_policy_hnd(&user_handle)) {
1718                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
1719         }
1720
1721         if (ctx->disable_policy_handle_cache) {
1722                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1723                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1724         }
1725
1726         return werr;
1727 }
1728
1729 /****************************************************************
1730 ****************************************************************/
1731
1732 WERROR NetUserGetInfo_l(struct libnetapi_ctx *ctx,
1733                         struct NetUserGetInfo *r)
1734 {
1735         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetInfo);
1736 }
1737
1738 /****************************************************************
1739 ****************************************************************/
1740
1741 WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
1742                         struct NetUserSetInfo *r)
1743 {
1744         struct cli_state *cli = NULL;
1745         struct rpc_pipe_client *pipe_cli = NULL;
1746         NTSTATUS status;
1747         WERROR werr;
1748
1749         struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1750         struct lsa_String lsa_account_name;
1751         struct dom_sid2 *domain_sid = NULL;
1752         struct samr_Ids user_rids, name_types;
1753         uint32_t user_mask = 0;
1754
1755         struct USER_INFO_X uX;
1756
1757         ZERO_STRUCT(connect_handle);
1758         ZERO_STRUCT(domain_handle);
1759         ZERO_STRUCT(builtin_handle);
1760         ZERO_STRUCT(user_handle);
1761
1762         if (!r->in.buffer) {
1763                 return WERR_INVALID_PARAM;
1764         }
1765
1766         switch (r->in.level) {
1767                 case 0:
1768                 case 1003:
1769                         user_mask = SAMR_USER_ACCESS_SET_PASSWORD;
1770                         break;
1771                 case 1006:
1772                 case 1007:
1773                 case 1009:
1774                 case 1011:
1775                 case 1014:
1776                 case 1052:
1777                 case 1053:
1778                         user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
1779                         break;
1780                 case 1012:
1781                 case 1024:
1782                         user_mask = SAMR_USER_ACCESS_SET_LOC_COM;
1783                 case 1051:
1784                         user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES |
1785                                     SAMR_USER_ACCESS_GET_GROUPS;
1786                         break;
1787                 case 3:
1788                         user_mask = STD_RIGHT_READ_CONTROL_ACCESS |
1789                                     STD_RIGHT_WRITE_DAC_ACCESS |
1790                                     SAMR_USER_ACCESS_GET_GROUPS |
1791                                     SAMR_USER_ACCESS_SET_PASSWORD |
1792                                     SAMR_USER_ACCESS_SET_ATTRIBUTES |
1793                                     SAMR_USER_ACCESS_GET_ATTRIBUTES |
1794                                     SAMR_USER_ACCESS_SET_LOC_COM;
1795                         break;
1796                 case 1:
1797                 case 2:
1798                 case 4:
1799                 case 21:
1800                 case 22:
1801                 case 1005:
1802                 case 1008:
1803                 case 1010:
1804                 case 1017:
1805                 case 1020:
1806                         werr = WERR_NOT_SUPPORTED;
1807                         goto done;
1808                 default:
1809                         werr = WERR_UNKNOWN_LEVEL;
1810                         goto done;
1811         }
1812
1813         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1814                                    &ndr_table_samr.syntax_id,
1815                                    &cli,
1816                                    &pipe_cli);
1817         if (!W_ERROR_IS_OK(werr)) {
1818                 goto done;
1819         }
1820
1821         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1822                                           SAMR_ACCESS_ENUM_DOMAINS |
1823                                           SAMR_ACCESS_OPEN_DOMAIN,
1824                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
1825                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1826                                           &connect_handle,
1827                                           &domain_handle,
1828                                           &domain_sid);
1829         if (!W_ERROR_IS_OK(werr)) {
1830                 goto done;
1831         }
1832
1833         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1834                                                   SAMR_ACCESS_ENUM_DOMAINS |
1835                                                   SAMR_ACCESS_OPEN_DOMAIN,
1836                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1837                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1838                                                   &connect_handle,
1839                                                   &builtin_handle);
1840         if (!W_ERROR_IS_OK(werr)) {
1841                 goto done;
1842         }
1843
1844         init_lsa_String(&lsa_account_name, r->in.user_name);
1845
1846         status = rpccli_samr_LookupNames(pipe_cli, ctx,
1847                                          &domain_handle,
1848                                          1,
1849                                          &lsa_account_name,
1850                                          &user_rids,
1851                                          &name_types);
1852         if (!NT_STATUS_IS_OK(status)) {
1853                 werr = ntstatus_to_werror(status);
1854                 goto done;
1855         }
1856
1857         status = rpccli_samr_OpenUser(pipe_cli, ctx,
1858                                       &domain_handle,
1859                                       user_mask,
1860                                       user_rids.ids[0],
1861                                       &user_handle);
1862         if (!NT_STATUS_IS_OK(status)) {
1863                 werr = ntstatus_to_werror(status);
1864                 goto done;
1865         }
1866
1867         status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
1868         if (!NT_STATUS_IS_OK(status)) {
1869                 werr = ntstatus_to_werror(status);
1870                 goto done;
1871         }
1872
1873         status = set_user_info_USER_INFO_X(ctx, pipe_cli,
1874                                            &cli->user_session_key,
1875                                            &user_handle,
1876                                            &uX);
1877         if (!NT_STATUS_IS_OK(status)) {
1878                 werr = ntstatus_to_werror(status);
1879                 goto done;
1880         }
1881
1882         werr = WERR_OK;
1883
1884  done:
1885         if (!cli) {
1886                 return werr;
1887         }
1888
1889         if (is_valid_policy_hnd(&user_handle)) {
1890                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
1891         }
1892
1893         if (ctx->disable_policy_handle_cache) {
1894                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1895                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1896                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1897         }
1898
1899         return werr;
1900 }
1901
1902 /****************************************************************
1903 ****************************************************************/
1904
1905 WERROR NetUserSetInfo_l(struct libnetapi_ctx *ctx,
1906                         struct NetUserSetInfo *r)
1907 {
1908         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetInfo);
1909 }
1910
1911 /****************************************************************
1912 ****************************************************************/
1913
1914 static NTSTATUS query_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
1915                                            struct rpc_pipe_client *pipe_cli,
1916                                            struct policy_handle *domain_handle,
1917                                            struct samr_DomInfo1 *info1,
1918                                            struct samr_DomInfo3 *info3,
1919                                            struct samr_DomInfo5 *info5,
1920                                            struct samr_DomInfo6 *info6,
1921                                            struct samr_DomInfo7 *info7,
1922                                            struct samr_DomInfo12 *info12)
1923 {
1924         NTSTATUS status;
1925         union samr_DomainInfo *dom_info = NULL;
1926
1927         if (info1) {
1928                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1929                                                      domain_handle,
1930                                                      1,
1931                                                      &dom_info);
1932                 NT_STATUS_NOT_OK_RETURN(status);
1933
1934                 *info1 = dom_info->info1;
1935         }
1936
1937         if (info3) {
1938                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1939                                                      domain_handle,
1940                                                      3,
1941                                                      &dom_info);
1942                 NT_STATUS_NOT_OK_RETURN(status);
1943
1944                 *info3 = dom_info->info3;
1945         }
1946
1947         if (info5) {
1948                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1949                                                      domain_handle,
1950                                                      5,
1951                                                      &dom_info);
1952                 NT_STATUS_NOT_OK_RETURN(status);
1953
1954                 *info5 = dom_info->info5;
1955         }
1956
1957         if (info6) {
1958                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1959                                                      domain_handle,
1960                                                      6,
1961                                                      &dom_info);
1962                 NT_STATUS_NOT_OK_RETURN(status);
1963
1964                 *info6 = dom_info->info6;
1965         }
1966
1967         if (info7) {
1968                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1969                                                      domain_handle,
1970                                                      7,
1971                                                      &dom_info);
1972                 NT_STATUS_NOT_OK_RETURN(status);
1973
1974                 *info7 = dom_info->info7;
1975         }
1976
1977         if (info12) {
1978                 status = rpccli_samr_QueryDomainInfo2(pipe_cli, mem_ctx,
1979                                                       domain_handle,
1980                                                       12,
1981                                                       &dom_info);
1982                 NT_STATUS_NOT_OK_RETURN(status);
1983
1984                 *info12 = dom_info->info12;
1985         }
1986
1987         return NT_STATUS_OK;
1988 }
1989
1990 /****************************************************************
1991 ****************************************************************/
1992
1993 static NTSTATUS query_USER_MODALS_INFO_0(TALLOC_CTX *mem_ctx,
1994                                          struct rpc_pipe_client *pipe_cli,
1995                                          struct policy_handle *domain_handle,
1996                                          struct USER_MODALS_INFO_0 *info0)
1997 {
1998         NTSTATUS status;
1999         struct samr_DomInfo1 dom_info1;
2000         struct samr_DomInfo3 dom_info3;
2001
2002         ZERO_STRUCTP(info0);
2003
2004         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2005                                             pipe_cli,
2006                                             domain_handle,
2007                                             &dom_info1,
2008                                             &dom_info3,
2009                                             NULL,
2010                                             NULL,
2011                                             NULL,
2012                                             NULL);
2013         NT_STATUS_NOT_OK_RETURN(status);
2014
2015         info0->usrmod0_min_passwd_len =
2016                 dom_info1.min_password_length;
2017         info0->usrmod0_max_passwd_age =
2018                 nt_time_to_unix_abs((NTTIME *)&dom_info1.max_password_age);
2019         info0->usrmod0_min_passwd_age =
2020                 nt_time_to_unix_abs((NTTIME *)&dom_info1.min_password_age);
2021         info0->usrmod0_password_hist_len =
2022                 dom_info1.password_history_length;
2023
2024         info0->usrmod0_force_logoff =
2025                 nt_time_to_unix_abs(&dom_info3.force_logoff_time);
2026
2027         return NT_STATUS_OK;
2028 }
2029
2030 /****************************************************************
2031 ****************************************************************/
2032
2033 static NTSTATUS query_USER_MODALS_INFO_1(TALLOC_CTX *mem_ctx,
2034                                          struct rpc_pipe_client *pipe_cli,
2035                                          struct policy_handle *domain_handle,
2036                                          struct USER_MODALS_INFO_1 *info1)
2037 {
2038         NTSTATUS status;
2039         struct samr_DomInfo6 dom_info6;
2040         struct samr_DomInfo7 dom_info7;
2041
2042         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2043                                             pipe_cli,
2044                                             domain_handle,
2045                                             NULL,
2046                                             NULL,
2047                                             NULL,
2048                                             &dom_info6,
2049                                             &dom_info7,
2050                                             NULL);
2051         NT_STATUS_NOT_OK_RETURN(status);
2052
2053         info1->usrmod1_primary =
2054                 talloc_strdup(mem_ctx, dom_info6.primary.string);
2055
2056         info1->usrmod1_role = dom_info7.role;
2057
2058         return NT_STATUS_OK;
2059 }
2060
2061 /****************************************************************
2062 ****************************************************************/
2063
2064 static NTSTATUS query_USER_MODALS_INFO_2(TALLOC_CTX *mem_ctx,
2065                                          struct rpc_pipe_client *pipe_cli,
2066                                          struct policy_handle *domain_handle,
2067                                          struct dom_sid *domain_sid,
2068                                          struct USER_MODALS_INFO_2 *info2)
2069 {
2070         NTSTATUS status;
2071         struct samr_DomInfo5 dom_info5;
2072
2073         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2074                                             pipe_cli,
2075                                             domain_handle,
2076                                             NULL,
2077                                             NULL,
2078                                             &dom_info5,
2079                                             NULL,
2080                                             NULL,
2081                                             NULL);
2082         NT_STATUS_NOT_OK_RETURN(status);
2083
2084         info2->usrmod2_domain_name =
2085                 talloc_strdup(mem_ctx, dom_info5.domain_name.string);
2086         info2->usrmod2_domain_id =
2087                 (struct domsid *)sid_dup_talloc(mem_ctx, domain_sid);
2088
2089         NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_name);
2090         NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_id);
2091
2092         return NT_STATUS_OK;
2093 }
2094
2095 /****************************************************************
2096 ****************************************************************/
2097
2098 static NTSTATUS query_USER_MODALS_INFO_3(TALLOC_CTX *mem_ctx,
2099                                          struct rpc_pipe_client *pipe_cli,
2100                                          struct policy_handle *domain_handle,
2101                                          struct USER_MODALS_INFO_3 *info3)
2102 {
2103         NTSTATUS status;
2104         struct samr_DomInfo12 dom_info12;
2105
2106         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2107                                             pipe_cli,
2108                                             domain_handle,
2109                                             NULL,
2110                                             NULL,
2111                                             NULL,
2112                                             NULL,
2113                                             NULL,
2114                                             &dom_info12);
2115         NT_STATUS_NOT_OK_RETURN(status);
2116
2117         info3->usrmod3_lockout_duration =
2118                 nt_time_to_unix_abs(&dom_info12.lockout_duration);
2119         info3->usrmod3_lockout_observation_window =
2120                 nt_time_to_unix_abs(&dom_info12.lockout_window);
2121         info3->usrmod3_lockout_threshold =
2122                 dom_info12.lockout_threshold;
2123
2124         return NT_STATUS_OK;
2125 }
2126
2127 /****************************************************************
2128 ****************************************************************/
2129
2130 static NTSTATUS query_USER_MODALS_INFO_to_buffer(TALLOC_CTX *mem_ctx,
2131                                                  struct rpc_pipe_client *pipe_cli,
2132                                                  uint32_t level,
2133                                                  struct policy_handle *domain_handle,
2134                                                  struct dom_sid *domain_sid,
2135                                                  uint8_t **buffer)
2136 {
2137         NTSTATUS status;
2138
2139         struct USER_MODALS_INFO_0 info0;
2140         struct USER_MODALS_INFO_1 info1;
2141         struct USER_MODALS_INFO_2 info2;
2142         struct USER_MODALS_INFO_3 info3;
2143
2144         if (!buffer) {
2145                 return ERROR_INSUFFICIENT_BUFFER;
2146         }
2147
2148         switch (level) {
2149                 case 0:
2150                         status = query_USER_MODALS_INFO_0(mem_ctx,
2151                                                           pipe_cli,
2152                                                           domain_handle,
2153                                                           &info0);
2154                         NT_STATUS_NOT_OK_RETURN(status);
2155
2156                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0,
2157                                                            sizeof(info0));
2158                         break;
2159
2160                 case 1:
2161                         status = query_USER_MODALS_INFO_1(mem_ctx,
2162                                                           pipe_cli,
2163                                                           domain_handle,
2164                                                           &info1);
2165                         NT_STATUS_NOT_OK_RETURN(status);
2166
2167                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1,
2168                                                            sizeof(info1));
2169                         break;
2170                 case 2:
2171                         status = query_USER_MODALS_INFO_2(mem_ctx,
2172                                                           pipe_cli,
2173                                                           domain_handle,
2174                                                           domain_sid,
2175                                                           &info2);
2176                         NT_STATUS_NOT_OK_RETURN(status);
2177
2178                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2,
2179                                                            sizeof(info2));
2180                         break;
2181                 case 3:
2182                         status = query_USER_MODALS_INFO_3(mem_ctx,
2183                                                           pipe_cli,
2184                                                           domain_handle,
2185                                                           &info3);
2186                         NT_STATUS_NOT_OK_RETURN(status);
2187
2188                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3,
2189                                                            sizeof(info3));
2190                         break;
2191                 default:
2192                         break;
2193         }
2194
2195         NT_STATUS_HAVE_NO_MEMORY(*buffer);
2196
2197         return NT_STATUS_OK;
2198 }
2199
2200 /****************************************************************
2201 ****************************************************************/
2202
2203 WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx,
2204                           struct NetUserModalsGet *r)
2205 {
2206         struct cli_state *cli = NULL;
2207         struct rpc_pipe_client *pipe_cli = NULL;
2208         NTSTATUS status;
2209         WERROR werr;
2210
2211         struct policy_handle connect_handle, domain_handle;
2212         struct dom_sid2 *domain_sid = NULL;
2213         uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2214
2215         ZERO_STRUCT(connect_handle);
2216         ZERO_STRUCT(domain_handle);
2217
2218         if (!r->out.buffer) {
2219                 return WERR_INVALID_PARAM;
2220         }
2221
2222         switch (r->in.level) {
2223                 case 0:
2224                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2225                                        SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2226                         break;
2227                 case 1:
2228                 case 2:
2229                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2230                         break;
2231                 case 3:
2232                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1;
2233                         break;
2234                 default:
2235                         werr = WERR_UNKNOWN_LEVEL;
2236                         goto done;
2237         }
2238
2239         werr = libnetapi_open_pipe(ctx, r->in.server_name,
2240                                    &ndr_table_samr.syntax_id,
2241                                    &cli,
2242                                    &pipe_cli);
2243         if (!W_ERROR_IS_OK(werr)) {
2244                 goto done;
2245         }
2246
2247         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2248                                           SAMR_ACCESS_ENUM_DOMAINS |
2249                                           SAMR_ACCESS_OPEN_DOMAIN,
2250                                           access_mask,
2251                                           &connect_handle,
2252                                           &domain_handle,
2253                                           &domain_sid);
2254         if (!W_ERROR_IS_OK(werr)) {
2255                 goto done;
2256         }
2257
2258         /* 0:  1 + 3 */
2259         /* 1:  6 + 7 */
2260         /* 2:  5 */
2261         /* 3: 12 (DomainInfo2) */
2262
2263         status = query_USER_MODALS_INFO_to_buffer(ctx,
2264                                                   pipe_cli,
2265                                                   r->in.level,
2266                                                   &domain_handle,
2267                                                   domain_sid,
2268                                                   r->out.buffer);
2269         if (!NT_STATUS_IS_OK(status)) {
2270                 werr = ntstatus_to_werror(status);
2271                 goto done;
2272         }
2273
2274  done:
2275         if (!cli) {
2276                 return werr;
2277         }
2278
2279         if (ctx->disable_policy_handle_cache) {
2280                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2281                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2282         }
2283
2284         return werr;
2285 }
2286
2287 /****************************************************************
2288 ****************************************************************/
2289
2290 WERROR NetUserModalsGet_l(struct libnetapi_ctx *ctx,
2291                           struct NetUserModalsGet *r)
2292 {
2293         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsGet);
2294 }
2295
2296 /****************************************************************
2297 ****************************************************************/
2298
2299 static NTSTATUS set_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
2300                                          struct rpc_pipe_client *pipe_cli,
2301                                          struct policy_handle *domain_handle,
2302                                          struct samr_DomInfo1 *info1,
2303                                          struct samr_DomInfo3 *info3,
2304                                          struct samr_DomInfo12 *info12)
2305 {
2306         NTSTATUS status;
2307         union samr_DomainInfo dom_info;
2308
2309         if (info1) {
2310
2311                 ZERO_STRUCT(dom_info);
2312
2313                 dom_info.info1 = *info1;
2314
2315                 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2316                                                    domain_handle,
2317                                                    1,
2318                                                    &dom_info);
2319                 NT_STATUS_NOT_OK_RETURN(status);
2320         }
2321
2322         if (info3) {
2323
2324                 ZERO_STRUCT(dom_info);
2325
2326                 dom_info.info3 = *info3;
2327
2328                 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2329                                                    domain_handle,
2330                                                    3,
2331                                                    &dom_info);
2332
2333                 NT_STATUS_NOT_OK_RETURN(status);
2334         }
2335
2336         if (info12) {
2337
2338                 ZERO_STRUCT(dom_info);
2339
2340                 dom_info.info12 = *info12;
2341
2342                 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2343                                                    domain_handle,
2344                                                    12,
2345                                                    &dom_info);
2346
2347                 NT_STATUS_NOT_OK_RETURN(status);
2348         }
2349
2350         return NT_STATUS_OK;
2351 }
2352
2353 /****************************************************************
2354 ****************************************************************/
2355
2356 static NTSTATUS set_USER_MODALS_INFO_0_buffer(TALLOC_CTX *mem_ctx,
2357                                               struct rpc_pipe_client *pipe_cli,
2358                                               struct policy_handle *domain_handle,
2359                                               struct USER_MODALS_INFO_0 *info0)
2360 {
2361         NTSTATUS status;
2362         struct samr_DomInfo1 dom_info_1;
2363         struct samr_DomInfo3 dom_info_3;
2364
2365         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2366                                             pipe_cli,
2367                                             domain_handle,
2368                                             &dom_info_1,
2369                                             &dom_info_3,
2370                                             NULL,
2371                                             NULL,
2372                                             NULL,
2373                                             NULL);
2374         NT_STATUS_NOT_OK_RETURN(status);
2375
2376         dom_info_1.min_password_length =
2377                 info0->usrmod0_min_passwd_len;
2378         dom_info_1.password_history_length =
2379                 info0->usrmod0_password_hist_len;
2380
2381         unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2382                 info0->usrmod0_max_passwd_age);
2383         unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2384                 info0->usrmod0_min_passwd_age);
2385
2386         unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2387                 info0->usrmod0_force_logoff);
2388
2389         return set_USER_MODALS_INFO_rpc(mem_ctx,
2390                                         pipe_cli,
2391                                         domain_handle,
2392                                         &dom_info_1,
2393                                         &dom_info_3,
2394                                         NULL);
2395 }
2396
2397 /****************************************************************
2398 ****************************************************************/
2399
2400 static NTSTATUS set_USER_MODALS_INFO_3_buffer(TALLOC_CTX *mem_ctx,
2401                                               struct rpc_pipe_client *pipe_cli,
2402                                               struct policy_handle *domain_handle,
2403                                               struct USER_MODALS_INFO_3 *info3)
2404 {
2405         NTSTATUS status;
2406         struct samr_DomInfo12 dom_info_12;
2407
2408         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2409                                             pipe_cli,
2410                                             domain_handle,
2411                                             NULL,
2412                                             NULL,
2413                                             NULL,
2414                                             NULL,
2415                                             NULL,
2416                                             &dom_info_12);
2417         NT_STATUS_NOT_OK_RETURN(status);
2418
2419         unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_duration,
2420                 info3->usrmod3_lockout_duration);
2421         unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_window,
2422                 info3->usrmod3_lockout_observation_window);
2423         dom_info_12.lockout_threshold = info3->usrmod3_lockout_threshold;
2424
2425         return set_USER_MODALS_INFO_rpc(mem_ctx,
2426                                         pipe_cli,
2427                                         domain_handle,
2428                                         NULL,
2429                                         NULL,
2430                                         &dom_info_12);
2431 }
2432
2433 /****************************************************************
2434 ****************************************************************/
2435
2436 static NTSTATUS set_USER_MODALS_INFO_1001_buffer(TALLOC_CTX *mem_ctx,
2437                                                  struct rpc_pipe_client *pipe_cli,
2438                                                  struct policy_handle *domain_handle,
2439                                                  struct USER_MODALS_INFO_1001 *info1001)
2440 {
2441         NTSTATUS status;
2442         struct samr_DomInfo1 dom_info_1;
2443
2444         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2445                                             pipe_cli,
2446                                             domain_handle,
2447                                             &dom_info_1,
2448                                             NULL,
2449                                             NULL,
2450                                             NULL,
2451                                             NULL,
2452                                             NULL);
2453         NT_STATUS_NOT_OK_RETURN(status);
2454
2455         dom_info_1.min_password_length =
2456                 info1001->usrmod1001_min_passwd_len;
2457
2458         return set_USER_MODALS_INFO_rpc(mem_ctx,
2459                                         pipe_cli,
2460                                         domain_handle,
2461                                         &dom_info_1,
2462                                         NULL,
2463                                         NULL);
2464 }
2465
2466 /****************************************************************
2467 ****************************************************************/
2468
2469 static NTSTATUS set_USER_MODALS_INFO_1002_buffer(TALLOC_CTX *mem_ctx,
2470                                                  struct rpc_pipe_client *pipe_cli,
2471                                                  struct policy_handle *domain_handle,
2472                                                  struct USER_MODALS_INFO_1002 *info1002)
2473 {
2474         NTSTATUS status;
2475         struct samr_DomInfo1 dom_info_1;
2476
2477         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2478                                             pipe_cli,
2479                                             domain_handle,
2480                                             &dom_info_1,
2481                                             NULL,
2482                                             NULL,
2483                                             NULL,
2484                                             NULL,
2485                                             NULL);
2486         NT_STATUS_NOT_OK_RETURN(status);
2487
2488         unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2489                 info1002->usrmod1002_max_passwd_age);
2490
2491         return set_USER_MODALS_INFO_rpc(mem_ctx,
2492                                         pipe_cli,
2493                                         domain_handle,
2494                                         &dom_info_1,
2495                                         NULL,
2496                                         NULL);
2497 }
2498
2499 /****************************************************************
2500 ****************************************************************/
2501
2502 static NTSTATUS set_USER_MODALS_INFO_1003_buffer(TALLOC_CTX *mem_ctx,
2503                                                  struct rpc_pipe_client *pipe_cli,
2504                                                  struct policy_handle *domain_handle,
2505                                                  struct USER_MODALS_INFO_1003 *info1003)
2506 {
2507         NTSTATUS status;
2508         struct samr_DomInfo1 dom_info_1;
2509
2510         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2511                                             pipe_cli,
2512                                             domain_handle,
2513                                             &dom_info_1,
2514                                             NULL,
2515                                             NULL,
2516                                             NULL,
2517                                             NULL,
2518                                             NULL);
2519         NT_STATUS_NOT_OK_RETURN(status);
2520
2521         unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2522                 info1003->usrmod1003_min_passwd_age);
2523
2524         return set_USER_MODALS_INFO_rpc(mem_ctx,
2525                                         pipe_cli,
2526                                         domain_handle,
2527                                         &dom_info_1,
2528                                         NULL,
2529                                         NULL);
2530 }
2531
2532 /****************************************************************
2533 ****************************************************************/
2534
2535 static NTSTATUS set_USER_MODALS_INFO_1004_buffer(TALLOC_CTX *mem_ctx,
2536                                                  struct rpc_pipe_client *pipe_cli,
2537                                                  struct policy_handle *domain_handle,
2538                                                  struct USER_MODALS_INFO_1004 *info1004)
2539 {
2540         NTSTATUS status;
2541         struct samr_DomInfo3 dom_info_3;
2542
2543         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2544                                             pipe_cli,
2545                                             domain_handle,
2546                                             NULL,
2547                                             &dom_info_3,
2548                                             NULL,
2549                                             NULL,
2550                                             NULL,
2551                                             NULL);
2552         NT_STATUS_NOT_OK_RETURN(status);
2553
2554         unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2555                 info1004->usrmod1004_force_logoff);
2556
2557         return set_USER_MODALS_INFO_rpc(mem_ctx,
2558                                         pipe_cli,
2559                                         domain_handle,
2560                                         NULL,
2561                                         &dom_info_3,
2562                                         NULL);
2563 }
2564
2565 /****************************************************************
2566 ****************************************************************/
2567
2568 static NTSTATUS set_USER_MODALS_INFO_1005_buffer(TALLOC_CTX *mem_ctx,
2569                                                  struct rpc_pipe_client *pipe_cli,
2570                                                  struct policy_handle *domain_handle,
2571                                                  struct USER_MODALS_INFO_1005 *info1005)
2572 {
2573         NTSTATUS status;
2574         struct samr_DomInfo1 dom_info_1;
2575
2576         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2577                                             pipe_cli,
2578                                             domain_handle,
2579                                             &dom_info_1,
2580                                             NULL,
2581                                             NULL,
2582                                             NULL,
2583                                             NULL,
2584                                             NULL);
2585         NT_STATUS_NOT_OK_RETURN(status);
2586
2587         dom_info_1.password_history_length =
2588                 info1005->usrmod1005_password_hist_len;
2589
2590         return set_USER_MODALS_INFO_rpc(mem_ctx,
2591                                         pipe_cli,
2592                                         domain_handle,
2593                                         &dom_info_1,
2594                                         NULL,
2595                                         NULL);
2596 }
2597
2598 /****************************************************************
2599 ****************************************************************/
2600
2601 static NTSTATUS set_USER_MODALS_INFO_buffer(TALLOC_CTX *mem_ctx,
2602                                             struct rpc_pipe_client *pipe_cli,
2603                                             uint32_t level,
2604                                             struct policy_handle *domain_handle,
2605                                             struct dom_sid *domain_sid,
2606                                             uint8_t *buffer)
2607 {
2608         struct USER_MODALS_INFO_0 *info0;
2609         struct USER_MODALS_INFO_3 *info3;
2610         struct USER_MODALS_INFO_1001 *info1001;
2611         struct USER_MODALS_INFO_1002 *info1002;
2612         struct USER_MODALS_INFO_1003 *info1003;
2613         struct USER_MODALS_INFO_1004 *info1004;
2614         struct USER_MODALS_INFO_1005 *info1005;
2615
2616         if (!buffer) {
2617                 return ERROR_INSUFFICIENT_BUFFER;
2618         }
2619
2620         switch (level) {
2621                 case 0:
2622                         info0 = (struct USER_MODALS_INFO_0 *)buffer;
2623                         return set_USER_MODALS_INFO_0_buffer(mem_ctx,
2624                                                              pipe_cli,
2625                                                              domain_handle,
2626                                                              info0);
2627                 case 3:
2628                         info3 = (struct USER_MODALS_INFO_3 *)buffer;
2629                         return set_USER_MODALS_INFO_3_buffer(mem_ctx,
2630                                                              pipe_cli,
2631                                                              domain_handle,
2632                                                              info3);
2633                 case 1001:
2634                         info1001 = (struct USER_MODALS_INFO_1001 *)buffer;
2635                         return set_USER_MODALS_INFO_1001_buffer(mem_ctx,
2636                                                                 pipe_cli,
2637                                                                 domain_handle,
2638                                                                 info1001);
2639                 case 1002:
2640                         info1002 = (struct USER_MODALS_INFO_1002 *)buffer;
2641                         return set_USER_MODALS_INFO_1002_buffer(mem_ctx,
2642                                                                 pipe_cli,
2643                                                                 domain_handle,
2644                                                                 info1002);
2645                 case 1003:
2646                         info1003 = (struct USER_MODALS_INFO_1003 *)buffer;
2647                         return set_USER_MODALS_INFO_1003_buffer(mem_ctx,
2648                                                                 pipe_cli,
2649                                                                 domain_handle,
2650                                                                 info1003);
2651                 case 1004:
2652                         info1004 = (struct USER_MODALS_INFO_1004 *)buffer;
2653                         return set_USER_MODALS_INFO_1004_buffer(mem_ctx,
2654                                                                 pipe_cli,
2655                                                                 domain_handle,
2656                                                                 info1004);
2657                 case 1005:
2658                         info1005 = (struct USER_MODALS_INFO_1005 *)buffer;
2659                         return set_USER_MODALS_INFO_1005_buffer(mem_ctx,
2660                                                                 pipe_cli,
2661                                                                 domain_handle,
2662                                                                 info1005);
2663
2664                 default:
2665                         break;
2666         }
2667
2668         return NT_STATUS_OK;
2669 }
2670
2671 /****************************************************************
2672 ****************************************************************/
2673
2674 WERROR NetUserModalsSet_r(struct libnetapi_ctx *ctx,
2675                           struct NetUserModalsSet *r)
2676 {
2677         struct cli_state *cli = NULL;
2678         struct rpc_pipe_client *pipe_cli = NULL;
2679         NTSTATUS status;
2680         WERROR werr;
2681
2682         struct policy_handle connect_handle, domain_handle;
2683         struct dom_sid2 *domain_sid = NULL;
2684         uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2685
2686         ZERO_STRUCT(connect_handle);
2687         ZERO_STRUCT(domain_handle);
2688
2689         if (!r->in.buffer) {
2690                 return WERR_INVALID_PARAM;
2691         }
2692
2693         switch (r->in.level) {
2694                 case 0:
2695                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2696                                        SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2697                                        SAMR_DOMAIN_ACCESS_SET_INFO_1 |
2698                                        SAMR_DOMAIN_ACCESS_SET_INFO_2;
2699                         break;
2700                 case 3:
2701                 case 1001:
2702                 case 1002:
2703                 case 1003:
2704                 case 1005:
2705                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2706                                        SAMR_DOMAIN_ACCESS_SET_INFO_1;
2707                         break;
2708                 case 1004:
2709                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2710                                        SAMR_DOMAIN_ACCESS_SET_INFO_2;
2711                         break;
2712                 case 1:
2713                 case 2:
2714                 case 1006:
2715                 case 1007:
2716                         werr = WERR_NOT_SUPPORTED;
2717                         break;
2718                 default:
2719                         werr = WERR_UNKNOWN_LEVEL;
2720                         goto done;
2721         }
2722
2723         werr = libnetapi_open_pipe(ctx, r->in.server_name,
2724                                    &ndr_table_samr.syntax_id,
2725                                    &cli,
2726                                    &pipe_cli);
2727         if (!W_ERROR_IS_OK(werr)) {
2728                 goto done;
2729         }
2730
2731         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2732                                           SAMR_ACCESS_ENUM_DOMAINS |
2733                                           SAMR_ACCESS_OPEN_DOMAIN,
2734                                           access_mask,
2735                                           &connect_handle,
2736                                           &domain_handle,
2737                                           &domain_sid);
2738         if (!W_ERROR_IS_OK(werr)) {
2739                 goto done;
2740         }
2741
2742         status = set_USER_MODALS_INFO_buffer(ctx,
2743                                              pipe_cli,
2744                                              r->in.level,
2745                                              &domain_handle,
2746                                              domain_sid,
2747                                              r->in.buffer);
2748         if (!NT_STATUS_IS_OK(status)) {
2749                 werr = ntstatus_to_werror(status);
2750                 goto done;
2751         }
2752
2753  done:
2754         if (!cli) {
2755                 return werr;
2756         }
2757
2758         if (ctx->disable_policy_handle_cache) {
2759                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2760                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2761         }
2762
2763         return werr;
2764 }
2765
2766 /****************************************************************
2767 ****************************************************************/
2768
2769 WERROR NetUserModalsSet_l(struct libnetapi_ctx *ctx,
2770                           struct NetUserModalsSet *r)
2771 {
2772         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsSet);
2773 }
2774
2775 /****************************************************************
2776 ****************************************************************/
2777
2778 NTSTATUS add_GROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
2779                                        uint32_t level,
2780                                        const char *group_name,
2781                                        uint32_t attributes,
2782                                        uint8_t **buffer,
2783                                        uint32_t *num_entries)
2784 {
2785         struct GROUP_USERS_INFO_0 u0;
2786         struct GROUP_USERS_INFO_1 u1;
2787
2788         switch (level) {
2789                 case 0:
2790                         u0.grui0_name = talloc_strdup(mem_ctx, group_name);
2791                         NT_STATUS_HAVE_NO_MEMORY(u0.grui0_name);
2792
2793                         ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_0, u0,
2794                                      (struct GROUP_USERS_INFO_0 **)buffer, num_entries);
2795                         break;
2796                 case 1:
2797                         u1.grui1_name = talloc_strdup(mem_ctx, group_name);
2798                         NT_STATUS_HAVE_NO_MEMORY(u1.grui1_name);
2799
2800                         u1.grui1_attributes = attributes;
2801
2802                         ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_1, u1,
2803                                      (struct GROUP_USERS_INFO_1 **)buffer, num_entries);
2804                         break;
2805                 default:
2806                         return NT_STATUS_INVALID_INFO_CLASS;
2807         }
2808
2809         return NT_STATUS_OK;
2810 }
2811
2812 /****************************************************************
2813 ****************************************************************/
2814
2815 WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
2816                           struct NetUserGetGroups *r)
2817 {
2818         struct cli_state *cli = NULL;
2819         struct rpc_pipe_client *pipe_cli = NULL;
2820         struct policy_handle connect_handle, domain_handle, user_handle;
2821         struct lsa_String lsa_account_name;
2822         struct dom_sid2 *domain_sid = NULL;
2823         struct samr_Ids user_rids, name_types;
2824         struct samr_RidWithAttributeArray *rid_array = NULL;
2825         struct lsa_Strings names;
2826         struct samr_Ids types;
2827         uint32_t *rids = NULL;
2828
2829         int i;
2830         uint32_t entries_read = 0;
2831
2832         NTSTATUS status = NT_STATUS_OK;
2833         WERROR werr;
2834
2835         ZERO_STRUCT(connect_handle);
2836         ZERO_STRUCT(domain_handle);
2837
2838         if (!r->out.buffer) {
2839                 return WERR_INVALID_PARAM;
2840         }
2841
2842         *r->out.buffer = NULL;
2843         *r->out.entries_read = 0;
2844
2845         switch (r->in.level) {
2846                 case 0:
2847                 case 1:
2848                         break;
2849                 default:
2850                         return WERR_UNKNOWN_LEVEL;
2851         }
2852
2853         werr = libnetapi_open_pipe(ctx, r->in.server_name,
2854                                    &ndr_table_samr.syntax_id,
2855                                    &cli,
2856                                    &pipe_cli);
2857         if (!W_ERROR_IS_OK(werr)) {
2858                 goto done;
2859         }
2860
2861         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2862                                           SAMR_ACCESS_ENUM_DOMAINS |
2863                                           SAMR_ACCESS_OPEN_DOMAIN,
2864                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2865                                           &connect_handle,
2866                                           &domain_handle,
2867                                           &domain_sid);
2868         if (!W_ERROR_IS_OK(werr)) {
2869                 goto done;
2870         }
2871
2872         init_lsa_String(&lsa_account_name, r->in.user_name);
2873
2874         status = rpccli_samr_LookupNames(pipe_cli, ctx,
2875                                          &domain_handle,
2876                                          1,
2877                                          &lsa_account_name,
2878                                          &user_rids,
2879                                          &name_types);
2880         if (!NT_STATUS_IS_OK(status)) {
2881                 werr = ntstatus_to_werror(status);
2882                 goto done;
2883         }
2884
2885         status = rpccli_samr_OpenUser(pipe_cli, ctx,
2886                                       &domain_handle,
2887                                       SAMR_USER_ACCESS_GET_GROUPS,
2888                                       user_rids.ids[0],
2889                                       &user_handle);
2890         if (!NT_STATUS_IS_OK(status)) {
2891                 werr = ntstatus_to_werror(status);
2892                 goto done;
2893         }
2894
2895         status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
2896                                               &user_handle,
2897                                               &rid_array);
2898         if (!NT_STATUS_IS_OK(status)) {
2899                 werr = ntstatus_to_werror(status);
2900                 goto done;
2901         }
2902
2903         rids = talloc_array(ctx, uint32_t, rid_array->count);
2904         if (!rids) {
2905                 werr = WERR_NOMEM;
2906                 goto done;
2907         }
2908
2909         for (i=0; i < rid_array->count; i++) {
2910                 rids[i] = rid_array->rids[i].rid;
2911         }
2912
2913         status = rpccli_samr_LookupRids(pipe_cli, ctx,
2914                                         &domain_handle,
2915                                         rid_array->count,
2916                                         rids,
2917                                         &names,
2918                                         &types);
2919         if (!NT_STATUS_IS_OK(status)) {
2920                 werr = ntstatus_to_werror(status);
2921                 goto done;
2922         }
2923
2924         for (i=0; i < rid_array->count; i++) {
2925                 status = add_GROUP_USERS_INFO_X_buffer(ctx,
2926                                                        r->in.level,
2927                                                        names.names[i].string,
2928                                                        rid_array->rids[i].attributes,
2929                                                        r->out.buffer,
2930                                                        &entries_read);
2931                 if (!NT_STATUS_IS_OK(status)) {
2932                         werr = ntstatus_to_werror(status);
2933                         goto done;
2934                 }
2935         }
2936
2937         if (r->out.entries_read) {
2938                 *r->out.entries_read = entries_read;
2939         }
2940         if (r->out.total_entries) {
2941                 *r->out.total_entries = entries_read;
2942         }
2943
2944  done:
2945         if (!cli) {
2946                 return werr;
2947         }
2948
2949         if (ctx->disable_policy_handle_cache) {
2950                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2951                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2952         }
2953
2954         return werr;
2955 }
2956
2957 /****************************************************************
2958 ****************************************************************/
2959
2960 WERROR NetUserGetGroups_l(struct libnetapi_ctx *ctx,
2961                           struct NetUserGetGroups *r)
2962 {
2963         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetGroups);
2964 }
2965
2966 /****************************************************************
2967 ****************************************************************/
2968
2969 WERROR NetUserSetGroups_r(struct libnetapi_ctx *ctx,
2970                           struct NetUserSetGroups *r)
2971 {
2972         struct cli_state *cli = NULL;
2973         struct rpc_pipe_client *pipe_cli = NULL;
2974         struct policy_handle connect_handle, domain_handle, user_handle, group_handle;
2975         struct lsa_String lsa_account_name;
2976         struct dom_sid2 *domain_sid = NULL;
2977         struct samr_Ids user_rids, name_types;
2978         struct samr_Ids group_rids;
2979         struct samr_RidWithAttributeArray *rid_array = NULL;
2980         struct lsa_String *lsa_names = NULL;
2981
2982         uint32_t *add_rids = NULL;
2983         uint32_t *del_rids = NULL;
2984         size_t num_add_rids = 0;
2985         size_t num_del_rids = 0;
2986
2987         uint32_t *member_rids = NULL;
2988         size_t num_member_rids = 0;
2989
2990         struct GROUP_USERS_INFO_0 *i0 = NULL;
2991         struct GROUP_USERS_INFO_1 *i1 = NULL;
2992
2993         int i, k;
2994
2995         NTSTATUS status = NT_STATUS_OK;
2996         WERROR werr;
2997
2998         ZERO_STRUCT(connect_handle);
2999         ZERO_STRUCT(domain_handle);
3000
3001         if (!r->in.buffer) {
3002                 return WERR_INVALID_PARAM;
3003         }
3004
3005         switch (r->in.level) {
3006                 case 0:
3007                 case 1:
3008                         break;
3009                 default:
3010                         return WERR_UNKNOWN_LEVEL;
3011         }
3012
3013         werr = libnetapi_open_pipe(ctx, r->in.server_name,
3014                                    &ndr_table_samr.syntax_id,
3015                                    &cli,
3016                                    &pipe_cli);
3017         if (!W_ERROR_IS_OK(werr)) {
3018                 goto done;
3019         }
3020
3021         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
3022                                           SAMR_ACCESS_ENUM_DOMAINS |
3023                                           SAMR_ACCESS_OPEN_DOMAIN,
3024                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
3025                                           &connect_handle,
3026                                           &domain_handle,
3027                                           &domain_sid);
3028         if (!W_ERROR_IS_OK(werr)) {
3029                 goto done;
3030         }
3031
3032         init_lsa_String(&lsa_account_name, r->in.user_name);
3033
3034         status = rpccli_samr_LookupNames(pipe_cli, ctx,
3035                                          &domain_handle,
3036                                          1,
3037                                          &lsa_account_name,
3038                                          &user_rids,
3039                                          &name_types);
3040         if (!NT_STATUS_IS_OK(status)) {
3041                 werr = ntstatus_to_werror(status);
3042                 goto done;
3043         }
3044
3045         status = rpccli_samr_OpenUser(pipe_cli, ctx,
3046                                       &domain_handle,
3047                                       SAMR_USER_ACCESS_GET_GROUPS,
3048                                       user_rids.ids[0],
3049                                       &user_handle);
3050         if (!NT_STATUS_IS_OK(status)) {
3051                 werr = ntstatus_to_werror(status);
3052                 goto done;
3053         }
3054
3055         switch (r->in.level) {
3056                 case 0:
3057                         i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
3058                         break;
3059                 case 1:
3060                         i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
3061                         break;
3062         }
3063
3064         lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
3065         if (!lsa_names) {
3066                 werr = WERR_NOMEM;
3067                 goto done;
3068         }
3069
3070         for (i=0; i < r->in.num_entries; i++) {
3071
3072                 switch (r->in.level) {
3073                         case 0:
3074                                 init_lsa_String(&lsa_names[i], i0->grui0_name);
3075                                 i0++;
3076                                 break;
3077                         case 1:
3078                                 init_lsa_String(&lsa_names[i], i1->grui1_name);
3079                                 i1++;
3080                                 break;
3081                 }
3082         }
3083
3084         status = rpccli_samr_LookupNames(pipe_cli, ctx,
3085                                          &domain_handle,
3086                                          r->in.num_entries,
3087                                          lsa_names,
3088                                          &group_rids,
3089                                          &name_types);
3090         if (!NT_STATUS_IS_OK(status)) {
3091                 werr = ntstatus_to_werror(status);
3092                 goto done;
3093         }
3094
3095         member_rids = group_rids.ids;
3096         num_member_rids = group_rids.count;
3097
3098         status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
3099                                               &user_handle,
3100                                               &rid_array);
3101         if (!NT_STATUS_IS_OK(status)) {
3102                 werr = ntstatus_to_werror(status);
3103                 goto done;
3104         }
3105
3106         /* add list */
3107
3108         for (i=0; i < r->in.num_entries; i++) {
3109                 bool already_member = false;
3110                 for (k=0; k < rid_array->count; k++) {
3111                         if (member_rids[i] == rid_array->rids[k].rid) {
3112                                 already_member = true;
3113                                 break;
3114                         }
3115                 }
3116                 if (!already_member) {
3117                         if (!add_rid_to_array_unique(ctx,
3118                                                      member_rids[i],
3119                                                      &add_rids, &num_add_rids)) {
3120                                 werr = WERR_GENERAL_FAILURE;
3121                                 goto done;
3122                         }
3123                 }
3124         }
3125
3126         /* del list */
3127
3128         for (k=0; k < rid_array->count; k++) {
3129                 bool keep_member = false;
3130                 for (i=0; i < r->in.num_entries; i++) {
3131                         if (member_rids[i] == rid_array->rids[k].rid) {
3132                                 keep_member = true;
3133                                 break;
3134                         }
3135                 }
3136                 if (!keep_member) {
3137                         if (!add_rid_to_array_unique(ctx,
3138                                                      rid_array->rids[k].rid,
3139                                                      &del_rids, &num_del_rids)) {
3140                                 werr = WERR_GENERAL_FAILURE;
3141                                 goto done;
3142                         }
3143                 }
3144         }
3145
3146         /* add list */
3147
3148         for (i=0; i < num_add_rids; i++) {
3149                 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
3150                                                &domain_handle,
3151                                                SAMR_GROUP_ACCESS_ADD_MEMBER,
3152                                                add_rids[i],
3153                                                &group_handle);
3154                 if (!NT_STATUS_IS_OK(status)) {
3155                         werr = ntstatus_to_werror(status);
3156                         goto done;
3157                 }
3158
3159                 status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
3160                                                     &group_handle,
3161                                                     user_rids.ids[0],
3162                                                     7 /* ? */);
3163                 if (!NT_STATUS_IS_OK(status)) {
3164                         werr = ntstatus_to_werror(status);
3165                         goto done;
3166                 }
3167
3168                 if (is_valid_policy_hnd(&group_handle)) {
3169                         rpccli_samr_Close(pipe_cli, ctx, &group_handle);
3170                 }
3171         }
3172
3173         /* del list */
3174
3175         for (i=0; i < num_del_rids; i++) {
3176                 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
3177                                                &domain_handle,
3178                                                SAMR_GROUP_ACCESS_REMOVE_MEMBER,
3179                                                del_rids[i],
3180                                                &group_handle);
3181                 if (!NT_STATUS_IS_OK(status)) {
3182                         werr = ntstatus_to_werror(status);
3183                         goto done;
3184                 }
3185
3186                 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
3187                                                        &group_handle,
3188                                                        user_rids.ids[0]);
3189                 if (!NT_STATUS_IS_OK(status)) {
3190                         werr = ntstatus_to_werror(status);
3191                         goto done;
3192                 }
3193
3194                 if (is_valid_policy_hnd(&group_handle)) {
3195                         rpccli_samr_Close(pipe_cli, ctx, &group_handle);
3196                 }
3197         }
3198
3199         werr = WERR_OK;
3200
3201  done:
3202         if (!cli) {
3203                 return werr;
3204         }
3205
3206         if (is_valid_policy_hnd(&group_handle)) {
3207                 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
3208         }
3209
3210         if (ctx->disable_policy_handle_cache) {
3211                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3212                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3213         }
3214
3215         return werr;
3216 }
3217
3218 /****************************************************************
3219 ****************************************************************/
3220
3221 WERROR NetUserSetGroups_l(struct libnetapi_ctx *ctx,
3222                           struct NetUserSetGroups *r)
3223 {
3224         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetGroups);
3225 }
3226
3227 /****************************************************************
3228 ****************************************************************/
3229
3230 static NTSTATUS add_LOCALGROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
3231                                                    uint32_t level,
3232                                                    const char *group_name,
3233                                                    uint8_t **buffer,
3234                                                    uint32_t *num_entries)
3235 {
3236         struct LOCALGROUP_USERS_INFO_0 u0;
3237
3238         switch (level) {
3239                 case 0:
3240                         u0.lgrui0_name = talloc_strdup(mem_ctx, group_name);
3241                         NT_STATUS_HAVE_NO_MEMORY(u0.lgrui0_name);
3242
3243                         ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_USERS_INFO_0, u0,
3244                                      (struct LOCALGROUP_USERS_INFO_0 **)buffer, num_entries);
3245                         break;
3246                 default:
3247                         return NT_STATUS_INVALID_INFO_CLASS;
3248         }
3249
3250         return NT_STATUS_OK;
3251 }
3252
3253 /****************************************************************
3254 ****************************************************************/
3255
3256 WERROR NetUserGetLocalGroups_r(struct libnetapi_ctx *ctx,
3257                                struct NetUserGetLocalGroups *r)
3258 {
3259         struct cli_state *cli = NULL;
3260         struct rpc_pipe_client *pipe_cli = NULL;
3261         struct policy_handle connect_handle, domain_handle, user_handle,
3262         builtin_handle;
3263         struct lsa_String lsa_account_name;
3264         struct dom_sid2 *domain_sid = NULL;
3265         struct samr_Ids user_rids, name_types;
3266         struct samr_RidWithAttributeArray *rid_array = NULL;
3267         struct lsa_Strings names;
3268         struct samr_Ids types;
3269         uint32_t *rids = NULL;
3270         size_t num_rids = 0;
3271         struct dom_sid user_sid;
3272         struct lsa_SidArray sid_array;
3273         struct samr_Ids domain_rids;
3274         struct samr_Ids builtin_rids;
3275
3276         int i;
3277         uint32_t entries_read = 0;
3278
3279         NTSTATUS status = NT_STATUS_OK;
3280         WERROR werr;
3281
3282         ZERO_STRUCT(connect_handle);
3283         ZERO_STRUCT(domain_handle);
3284
3285         if (!r->out.buffer) {
3286                 return WERR_INVALID_PARAM;
3287         }
3288
3289         *r->out.buffer = NULL;
3290         *r->out.entries_read = 0;
3291
3292         switch (r->in.level) {
3293                 case 0:
3294                 case 1:
3295                         break;
3296                 default:
3297                         return WERR_UNKNOWN_LEVEL;
3298         }
3299
3300         werr = libnetapi_open_pipe(ctx, r->in.server_name,
3301                                    &ndr_table_samr.syntax_id,
3302                                    &cli,
3303                                    &pipe_cli);
3304         if (!W_ERROR_IS_OK(werr)) {
3305                 goto done;
3306         }
3307
3308         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
3309                                           SAMR_ACCESS_ENUM_DOMAINS |
3310                                           SAMR_ACCESS_OPEN_DOMAIN,
3311                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
3312                                           SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
3313                                           &connect_handle,
3314                                           &domain_handle,
3315                                           &domain_sid);
3316         if (!W_ERROR_IS_OK(werr)) {
3317                 goto done;
3318         }
3319
3320         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
3321                                                   SAMR_ACCESS_ENUM_DOMAINS |
3322                                                   SAMR_ACCESS_OPEN_DOMAIN,
3323                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
3324                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
3325                                                   &connect_handle,
3326                                                   &builtin_handle);
3327         if (!W_ERROR_IS_OK(werr)) {
3328                 goto done;
3329         }
3330
3331         init_lsa_String(&lsa_account_name, r->in.user_name);
3332
3333         status = rpccli_samr_LookupNames(pipe_cli, ctx,
3334                                          &domain_handle,
3335                                          1,
3336                                          &lsa_account_name,
3337                                          &user_rids,
3338                                          &name_types);
3339         if (!NT_STATUS_IS_OK(status)) {
3340                 werr = ntstatus_to_werror(status);
3341                 goto done;
3342         }
3343
3344         status = rpccli_samr_OpenUser(pipe_cli, ctx,
3345                                       &domain_handle,
3346                                       SAMR_USER_ACCESS_GET_GROUPS,
3347                                       user_rids.ids[0],
3348                                       &user_handle);
3349         if (!NT_STATUS_IS_OK(status)) {
3350                 werr = ntstatus_to_werror(status);
3351                 goto done;
3352         }
3353
3354         status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
3355                                               &user_handle,
3356                                               &rid_array);
3357         if (!NT_STATUS_IS_OK(status)) {
3358                 werr = ntstatus_to_werror(status);
3359                 goto done;
3360         }
3361
3362         if (!sid_compose(&user_sid, domain_sid, user_rids.ids[0])) {
3363                 werr = WERR_NOMEM;
3364                 goto done;
3365         }
3366
3367         sid_array.num_sids = rid_array->count + 1;
3368         sid_array.sids = TALLOC_ARRAY(ctx, struct lsa_SidPtr, sid_array.num_sids);
3369         if (!sid_array.sids) {
3370                 werr = WERR_NOMEM;
3371                 goto done;
3372         }
3373
3374         sid_array.sids[0].sid = sid_dup_talloc(ctx, &user_sid);
3375         if (!sid_array.sids[0].sid) {
3376                 werr = WERR_NOMEM;
3377                 goto done;
3378         }
3379
3380         for (i=0; i < rid_array->count; i++) {
3381                 struct dom_sid sid;
3382
3383                 if (!sid_compose(&sid, domain_sid, rid_array->rids[i].rid)) {
3384                         werr = WERR_NOMEM;
3385                         goto done;
3386                 }
3387
3388                 sid_array.sids[i+1].sid = sid_dup_talloc(ctx, &sid);
3389                 if (!sid_array.sids[i+1].sid) {
3390                         werr = WERR_NOMEM;
3391                         goto done;
3392                 }
3393         }
3394
3395         status = rpccli_samr_GetAliasMembership(pipe_cli, ctx,
3396                                                 &domain_handle,
3397                                                 &sid_array,
3398                                                 &domain_rids);
3399         if (!NT_STATUS_IS_OK(status)) {
3400                 werr = ntstatus_to_werror(status);
3401                 goto done;
3402         }
3403
3404         for (i=0; i < domain_rids.count; i++) {
3405                 if (!add_rid_to_array_unique(ctx, domain_rids.ids[i],
3406                                              &rids, &num_rids)) {
3407                         werr = WERR_NOMEM;
3408                         goto done;
3409                 }
3410         }
3411
3412         status = rpccli_samr_GetAliasMembership(pipe_cli, ctx,
3413                                                 &builtin_handle,
3414                                                 &sid_array,
3415                                                 &builtin_rids);
3416         if (!NT_STATUS_IS_OK(status)) {
3417                 werr = ntstatus_to_werror(status);
3418                 goto done;
3419         }
3420
3421         for (i=0; i < builtin_rids.count; i++) {
3422                 if (!add_rid_to_array_unique(ctx, builtin_rids.ids[i],
3423                                              &rids, &num_rids)) {
3424                         werr = WERR_NOMEM;
3425                         goto done;
3426                 }
3427         }
3428
3429         status = rpccli_samr_LookupRids(pipe_cli, ctx,
3430                                         &builtin_handle,
3431                                         num_rids,
3432                                         rids,
3433                                         &names,
3434                                         &types);
3435         if (!NT_STATUS_IS_OK(status)) {
3436                 werr = ntstatus_to_werror(status);
3437                 goto done;
3438         }
3439
3440         for (i=0; i < names.count; i++) {
3441                 status = add_LOCALGROUP_USERS_INFO_X_buffer(ctx,
3442                                                             r->in.level,
3443                                                             names.names[i].string,
3444                                                             r->out.buffer,
3445                                                             &entries_read);
3446                 if (!NT_STATUS_IS_OK(status)) {
3447                         werr = ntstatus_to_werror(status);
3448                         goto done;
3449                 }
3450         }
3451
3452         if (r->out.entries_read) {
3453                 *r->out.entries_read = entries_read;
3454         }
3455         if (r->out.total_entries) {
3456                 *r->out.total_entries = entries_read;
3457         }
3458
3459  done:
3460         if (!cli) {
3461                 return werr;
3462         }
3463
3464         if (ctx->disable_policy_handle_cache) {
3465                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3466                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3467         }
3468
3469         return werr;
3470 }
3471
3472 /****************************************************************
3473 ****************************************************************/
3474
3475 WERROR NetUserGetLocalGroups_l(struct libnetapi_ctx *ctx,
3476                                struct NetUserGetLocalGroups *r)
3477 {
3478         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetLocalGroups);
3479 }