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