s3-netapi: Fix Coverity #670: FORWARD_NULL.
[ira/wip.git] / source3 / lib / netapi / user.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  NetApi User Support
4  *  Copyright (C) Guenther Deschner 2008
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "includes.h"
21
22 #include "librpc/gen_ndr/libnetapi.h"
23 #include "lib/netapi/netapi.h"
24 #include "lib/netapi/netapi_private.h"
25 #include "lib/netapi/libnetapi.h"
26
27 /****************************************************************
28 ****************************************************************/
29
30 static void convert_USER_INFO_X_to_samr_user_info21(struct USER_INFO_X *infoX,
31                                                     struct samr_UserInfo21 *info21)
32 {
33         uint32_t fields_present = 0;
34         struct samr_LogonHours zero_logon_hours;
35         struct lsa_BinaryString zero_parameters;
36         NTTIME password_age;
37
38         ZERO_STRUCTP(info21);
39         ZERO_STRUCT(zero_logon_hours);
40         ZERO_STRUCT(zero_parameters);
41
42         if (infoX->usriX_flags) {
43                 fields_present |= SAMR_FIELD_ACCT_FLAGS;
44         }
45         if (infoX->usriX_name) {
46                 fields_present |= SAMR_FIELD_ACCOUNT_NAME;
47         }
48         if (infoX->usriX_password) {
49                 fields_present |= SAMR_FIELD_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_LOOKUP_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_LOOKUP_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 |= ds_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_LOOKUP_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_LOOKUP_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                         break;
1478         }
1479
1480         return WERR_UNKNOWN_LEVEL;
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_LOOKUP_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_LOOKUP_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_LOOKUP_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                         user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
1750                         break;
1751                 case 1003:
1752                         user_mask = SAMR_USER_ACCESS_SET_PASSWORD;
1753                         break;
1754                 case 1006:
1755                 case 1007:
1756                 case 1009:
1757                 case 1011:
1758                 case 1014:
1759                 case 1052:
1760                 case 1053:
1761                         user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
1762                         break;
1763                 case 1012:
1764                 case 1024:
1765                         user_mask = SAMR_USER_ACCESS_SET_LOC_COM;
1766                 case 1051:
1767                         user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES |
1768                                     SAMR_USER_ACCESS_GET_GROUPS;
1769                         break;
1770                 case 3:
1771                         user_mask = STD_RIGHT_READ_CONTROL_ACCESS |
1772                                     STD_RIGHT_WRITE_DAC_ACCESS |
1773                                     SAMR_USER_ACCESS_GET_GROUPS |
1774                                     SAMR_USER_ACCESS_SET_PASSWORD |
1775                                     SAMR_USER_ACCESS_SET_ATTRIBUTES |
1776                                     SAMR_USER_ACCESS_GET_ATTRIBUTES |
1777                                     SAMR_USER_ACCESS_SET_LOC_COM;
1778                         break;
1779                 case 1:
1780                 case 2:
1781                 case 4:
1782                 case 21:
1783                 case 22:
1784                 case 1005:
1785                 case 1008:
1786                 case 1010:
1787                 case 1017:
1788                 case 1020:
1789                         werr = WERR_NOT_SUPPORTED;
1790                         goto done;
1791                 default:
1792                         werr = WERR_UNKNOWN_LEVEL;
1793                         goto done;
1794         }
1795
1796         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1797                                    &ndr_table_samr.syntax_id,
1798                                    &pipe_cli);
1799         if (!W_ERROR_IS_OK(werr)) {
1800                 goto done;
1801         }
1802
1803         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1804                                           SAMR_ACCESS_ENUM_DOMAINS |
1805                                           SAMR_ACCESS_LOOKUP_DOMAIN,
1806                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
1807                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1808                                           &connect_handle,
1809                                           &domain_handle,
1810                                           &domain_sid);
1811         if (!W_ERROR_IS_OK(werr)) {
1812                 goto done;
1813         }
1814
1815         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1816                                                   SAMR_ACCESS_ENUM_DOMAINS |
1817                                                   SAMR_ACCESS_LOOKUP_DOMAIN,
1818                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1819                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1820                                                   &connect_handle,
1821                                                   &builtin_handle);
1822         if (!W_ERROR_IS_OK(werr)) {
1823                 goto done;
1824         }
1825
1826         init_lsa_String(&lsa_account_name, r->in.user_name);
1827
1828         status = rpccli_samr_LookupNames(pipe_cli, ctx,
1829                                          &domain_handle,
1830                                          1,
1831                                          &lsa_account_name,
1832                                          &user_rids,
1833                                          &name_types);
1834         if (!NT_STATUS_IS_OK(status)) {
1835                 werr = ntstatus_to_werror(status);
1836                 goto done;
1837         }
1838
1839         status = rpccli_samr_OpenUser(pipe_cli, ctx,
1840                                       &domain_handle,
1841                                       user_mask,
1842                                       user_rids.ids[0],
1843                                       &user_handle);
1844         if (!NT_STATUS_IS_OK(status)) {
1845                 werr = ntstatus_to_werror(status);
1846                 goto done;
1847         }
1848
1849         status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
1850         if (!NT_STATUS_IS_OK(status)) {
1851                 werr = ntstatus_to_werror(status);
1852                 goto done;
1853         }
1854
1855         status = set_user_info_USER_INFO_X(ctx, pipe_cli,
1856                                            &pipe_cli->auth->user_session_key,
1857                                            &user_handle,
1858                                            &uX);
1859         if (!NT_STATUS_IS_OK(status)) {
1860                 werr = ntstatus_to_werror(status);
1861                 goto done;
1862         }
1863
1864         werr = WERR_OK;
1865
1866  done:
1867         if (is_valid_policy_hnd(&user_handle) && pipe_cli) {
1868                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
1869         }
1870
1871         if (ctx->disable_policy_handle_cache) {
1872                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1873                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1874                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1875         }
1876
1877         return werr;
1878 }
1879
1880 /****************************************************************
1881 ****************************************************************/
1882
1883 WERROR NetUserSetInfo_l(struct libnetapi_ctx *ctx,
1884                         struct NetUserSetInfo *r)
1885 {
1886         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetInfo);
1887 }
1888
1889 /****************************************************************
1890 ****************************************************************/
1891
1892 static NTSTATUS query_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
1893                                            struct rpc_pipe_client *pipe_cli,
1894                                            struct policy_handle *domain_handle,
1895                                            struct samr_DomInfo1 *info1,
1896                                            struct samr_DomInfo3 *info3,
1897                                            struct samr_DomInfo5 *info5,
1898                                            struct samr_DomInfo6 *info6,
1899                                            struct samr_DomInfo7 *info7,
1900                                            struct samr_DomInfo12 *info12)
1901 {
1902         NTSTATUS status;
1903         union samr_DomainInfo *dom_info = NULL;
1904
1905         if (info1) {
1906                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1907                                                      domain_handle,
1908                                                      1,
1909                                                      &dom_info);
1910                 NT_STATUS_NOT_OK_RETURN(status);
1911
1912                 *info1 = dom_info->info1;
1913         }
1914
1915         if (info3) {
1916                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1917                                                      domain_handle,
1918                                                      3,
1919                                                      &dom_info);
1920                 NT_STATUS_NOT_OK_RETURN(status);
1921
1922                 *info3 = dom_info->info3;
1923         }
1924
1925         if (info5) {
1926                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1927                                                      domain_handle,
1928                                                      5,
1929                                                      &dom_info);
1930                 NT_STATUS_NOT_OK_RETURN(status);
1931
1932                 *info5 = dom_info->info5;
1933         }
1934
1935         if (info6) {
1936                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1937                                                      domain_handle,
1938                                                      6,
1939                                                      &dom_info);
1940                 NT_STATUS_NOT_OK_RETURN(status);
1941
1942                 *info6 = dom_info->info6;
1943         }
1944
1945         if (info7) {
1946                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1947                                                      domain_handle,
1948                                                      7,
1949                                                      &dom_info);
1950                 NT_STATUS_NOT_OK_RETURN(status);
1951
1952                 *info7 = dom_info->info7;
1953         }
1954
1955         if (info12) {
1956                 status = rpccli_samr_QueryDomainInfo2(pipe_cli, mem_ctx,
1957                                                       domain_handle,
1958                                                       12,
1959                                                       &dom_info);
1960                 NT_STATUS_NOT_OK_RETURN(status);
1961
1962                 *info12 = dom_info->info12;
1963         }
1964
1965         return NT_STATUS_OK;
1966 }
1967
1968 /****************************************************************
1969 ****************************************************************/
1970
1971 static NTSTATUS query_USER_MODALS_INFO_0(TALLOC_CTX *mem_ctx,
1972                                          struct rpc_pipe_client *pipe_cli,
1973                                          struct policy_handle *domain_handle,
1974                                          struct USER_MODALS_INFO_0 *info0)
1975 {
1976         NTSTATUS status;
1977         struct samr_DomInfo1 dom_info1;
1978         struct samr_DomInfo3 dom_info3;
1979
1980         ZERO_STRUCTP(info0);
1981
1982         status = query_USER_MODALS_INFO_rpc(mem_ctx,
1983                                             pipe_cli,
1984                                             domain_handle,
1985                                             &dom_info1,
1986                                             &dom_info3,
1987                                             NULL,
1988                                             NULL,
1989                                             NULL,
1990                                             NULL);
1991         NT_STATUS_NOT_OK_RETURN(status);
1992
1993         info0->usrmod0_min_passwd_len =
1994                 dom_info1.min_password_length;
1995         info0->usrmod0_max_passwd_age =
1996                 nt_time_to_unix_abs((NTTIME *)&dom_info1.max_password_age);
1997         info0->usrmod0_min_passwd_age =
1998                 nt_time_to_unix_abs((NTTIME *)&dom_info1.min_password_age);
1999         info0->usrmod0_password_hist_len =
2000                 dom_info1.password_history_length;
2001
2002         info0->usrmod0_force_logoff =
2003                 nt_time_to_unix_abs(&dom_info3.force_logoff_time);
2004
2005         return NT_STATUS_OK;
2006 }
2007
2008 /****************************************************************
2009 ****************************************************************/
2010
2011 static NTSTATUS query_USER_MODALS_INFO_1(TALLOC_CTX *mem_ctx,
2012                                          struct rpc_pipe_client *pipe_cli,
2013                                          struct policy_handle *domain_handle,
2014                                          struct USER_MODALS_INFO_1 *info1)
2015 {
2016         NTSTATUS status;
2017         struct samr_DomInfo6 dom_info6;
2018         struct samr_DomInfo7 dom_info7;
2019
2020         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2021                                             pipe_cli,
2022                                             domain_handle,
2023                                             NULL,
2024                                             NULL,
2025                                             NULL,
2026                                             &dom_info6,
2027                                             &dom_info7,
2028                                             NULL);
2029         NT_STATUS_NOT_OK_RETURN(status);
2030
2031         info1->usrmod1_primary =
2032                 talloc_strdup(mem_ctx, dom_info6.primary.string);
2033
2034         info1->usrmod1_role = dom_info7.role;
2035
2036         return NT_STATUS_OK;
2037 }
2038
2039 /****************************************************************
2040 ****************************************************************/
2041
2042 static NTSTATUS query_USER_MODALS_INFO_2(TALLOC_CTX *mem_ctx,
2043                                          struct rpc_pipe_client *pipe_cli,
2044                                          struct policy_handle *domain_handle,
2045                                          struct dom_sid *domain_sid,
2046                                          struct USER_MODALS_INFO_2 *info2)
2047 {
2048         NTSTATUS status;
2049         struct samr_DomInfo5 dom_info5;
2050
2051         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2052                                             pipe_cli,
2053                                             domain_handle,
2054                                             NULL,
2055                                             NULL,
2056                                             &dom_info5,
2057                                             NULL,
2058                                             NULL,
2059                                             NULL);
2060         NT_STATUS_NOT_OK_RETURN(status);
2061
2062         info2->usrmod2_domain_name =
2063                 talloc_strdup(mem_ctx, dom_info5.domain_name.string);
2064         info2->usrmod2_domain_id =
2065                 (struct domsid *)sid_dup_talloc(mem_ctx, domain_sid);
2066
2067         NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_name);
2068         NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_id);
2069
2070         return NT_STATUS_OK;
2071 }
2072
2073 /****************************************************************
2074 ****************************************************************/
2075
2076 static NTSTATUS query_USER_MODALS_INFO_3(TALLOC_CTX *mem_ctx,
2077                                          struct rpc_pipe_client *pipe_cli,
2078                                          struct policy_handle *domain_handle,
2079                                          struct USER_MODALS_INFO_3 *info3)
2080 {
2081         NTSTATUS status;
2082         struct samr_DomInfo12 dom_info12;
2083
2084         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2085                                             pipe_cli,
2086                                             domain_handle,
2087                                             NULL,
2088                                             NULL,
2089                                             NULL,
2090                                             NULL,
2091                                             NULL,
2092                                             &dom_info12);
2093         NT_STATUS_NOT_OK_RETURN(status);
2094
2095         info3->usrmod3_lockout_duration =
2096                 nt_time_to_unix_abs(&dom_info12.lockout_duration);
2097         info3->usrmod3_lockout_observation_window =
2098                 nt_time_to_unix_abs(&dom_info12.lockout_window);
2099         info3->usrmod3_lockout_threshold =
2100                 dom_info12.lockout_threshold;
2101
2102         return NT_STATUS_OK;
2103 }
2104
2105 /****************************************************************
2106 ****************************************************************/
2107
2108 static NTSTATUS query_USER_MODALS_INFO_to_buffer(TALLOC_CTX *mem_ctx,
2109                                                  struct rpc_pipe_client *pipe_cli,
2110                                                  uint32_t level,
2111                                                  struct policy_handle *domain_handle,
2112                                                  struct dom_sid *domain_sid,
2113                                                  uint8_t **buffer)
2114 {
2115         NTSTATUS status;
2116
2117         struct USER_MODALS_INFO_0 info0;
2118         struct USER_MODALS_INFO_1 info1;
2119         struct USER_MODALS_INFO_2 info2;
2120         struct USER_MODALS_INFO_3 info3;
2121
2122         if (!buffer) {
2123                 return ERROR_INSUFFICIENT_BUFFER;
2124         }
2125
2126         switch (level) {
2127                 case 0:
2128                         status = query_USER_MODALS_INFO_0(mem_ctx,
2129                                                           pipe_cli,
2130                                                           domain_handle,
2131                                                           &info0);
2132                         NT_STATUS_NOT_OK_RETURN(status);
2133
2134                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0,
2135                                                            sizeof(info0));
2136                         break;
2137
2138                 case 1:
2139                         status = query_USER_MODALS_INFO_1(mem_ctx,
2140                                                           pipe_cli,
2141                                                           domain_handle,
2142                                                           &info1);
2143                         NT_STATUS_NOT_OK_RETURN(status);
2144
2145                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1,
2146                                                            sizeof(info1));
2147                         break;
2148                 case 2:
2149                         status = query_USER_MODALS_INFO_2(mem_ctx,
2150                                                           pipe_cli,
2151                                                           domain_handle,
2152                                                           domain_sid,
2153                                                           &info2);
2154                         NT_STATUS_NOT_OK_RETURN(status);
2155
2156                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2,
2157                                                            sizeof(info2));
2158                         break;
2159                 case 3:
2160                         status = query_USER_MODALS_INFO_3(mem_ctx,
2161                                                           pipe_cli,
2162                                                           domain_handle,
2163                                                           &info3);
2164                         NT_STATUS_NOT_OK_RETURN(status);
2165
2166                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3,
2167                                                            sizeof(info3));
2168                         break;
2169                 default:
2170                         break;
2171         }
2172
2173         NT_STATUS_HAVE_NO_MEMORY(*buffer);
2174
2175         return NT_STATUS_OK;
2176 }
2177
2178 /****************************************************************
2179 ****************************************************************/
2180
2181 WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx,
2182                           struct NetUserModalsGet *r)
2183 {
2184         struct rpc_pipe_client *pipe_cli = NULL;
2185         NTSTATUS status;
2186         WERROR werr;
2187
2188         struct policy_handle connect_handle, domain_handle;
2189         struct dom_sid2 *domain_sid = NULL;
2190         uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2191
2192         ZERO_STRUCT(connect_handle);
2193         ZERO_STRUCT(domain_handle);
2194
2195         if (!r->out.buffer) {
2196                 return WERR_INVALID_PARAM;
2197         }
2198
2199         switch (r->in.level) {
2200                 case 0:
2201                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2202                                        SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2203                         break;
2204                 case 1:
2205                 case 2:
2206                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2207                         break;
2208                 case 3:
2209                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1;
2210                         break;
2211                 default:
2212                         werr = WERR_UNKNOWN_LEVEL;
2213                         goto done;
2214         }
2215
2216         werr = libnetapi_open_pipe(ctx, r->in.server_name,
2217                                    &ndr_table_samr.syntax_id,
2218                                    &pipe_cli);
2219         if (!W_ERROR_IS_OK(werr)) {
2220                 goto done;
2221         }
2222
2223         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2224                                           SAMR_ACCESS_ENUM_DOMAINS |
2225                                           SAMR_ACCESS_LOOKUP_DOMAIN,
2226                                           access_mask,
2227                                           &connect_handle,
2228                                           &domain_handle,
2229                                           &domain_sid);
2230         if (!W_ERROR_IS_OK(werr)) {
2231                 goto done;
2232         }
2233
2234         /* 0:  1 + 3 */
2235         /* 1:  6 + 7 */
2236         /* 2:  5 */
2237         /* 3: 12 (DomainInfo2) */
2238
2239         status = query_USER_MODALS_INFO_to_buffer(ctx,
2240                                                   pipe_cli,
2241                                                   r->in.level,
2242                                                   &domain_handle,
2243                                                   domain_sid,
2244                                                   r->out.buffer);
2245         if (!NT_STATUS_IS_OK(status)) {
2246                 werr = ntstatus_to_werror(status);
2247                 goto done;
2248         }
2249
2250  done:
2251         if (ctx->disable_policy_handle_cache) {
2252                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2253                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2254         }
2255
2256         return werr;
2257 }
2258
2259 /****************************************************************
2260 ****************************************************************/
2261
2262 WERROR NetUserModalsGet_l(struct libnetapi_ctx *ctx,
2263                           struct NetUserModalsGet *r)
2264 {
2265         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsGet);
2266 }
2267
2268 /****************************************************************
2269 ****************************************************************/
2270
2271 static NTSTATUS set_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
2272                                          struct rpc_pipe_client *pipe_cli,
2273                                          struct policy_handle *domain_handle,
2274                                          struct samr_DomInfo1 *info1,
2275                                          struct samr_DomInfo3 *info3,
2276                                          struct samr_DomInfo12 *info12)
2277 {
2278         NTSTATUS status;
2279         union samr_DomainInfo dom_info;
2280
2281         if (info1) {
2282
2283                 ZERO_STRUCT(dom_info);
2284
2285                 dom_info.info1 = *info1;
2286
2287                 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2288                                                    domain_handle,
2289                                                    1,
2290                                                    &dom_info);
2291                 NT_STATUS_NOT_OK_RETURN(status);
2292         }
2293
2294         if (info3) {
2295
2296                 ZERO_STRUCT(dom_info);
2297
2298                 dom_info.info3 = *info3;
2299
2300                 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2301                                                    domain_handle,
2302                                                    3,
2303                                                    &dom_info);
2304
2305                 NT_STATUS_NOT_OK_RETURN(status);
2306         }
2307
2308         if (info12) {
2309
2310                 ZERO_STRUCT(dom_info);
2311
2312                 dom_info.info12 = *info12;
2313
2314                 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
2315                                                    domain_handle,
2316                                                    12,
2317                                                    &dom_info);
2318
2319                 NT_STATUS_NOT_OK_RETURN(status);
2320         }
2321
2322         return NT_STATUS_OK;
2323 }
2324
2325 /****************************************************************
2326 ****************************************************************/
2327
2328 static NTSTATUS set_USER_MODALS_INFO_0_buffer(TALLOC_CTX *mem_ctx,
2329                                               struct rpc_pipe_client *pipe_cli,
2330                                               struct policy_handle *domain_handle,
2331                                               struct USER_MODALS_INFO_0 *info0)
2332 {
2333         NTSTATUS status;
2334         struct samr_DomInfo1 dom_info_1;
2335         struct samr_DomInfo3 dom_info_3;
2336
2337         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2338                                             pipe_cli,
2339                                             domain_handle,
2340                                             &dom_info_1,
2341                                             &dom_info_3,
2342                                             NULL,
2343                                             NULL,
2344                                             NULL,
2345                                             NULL);
2346         NT_STATUS_NOT_OK_RETURN(status);
2347
2348         dom_info_1.min_password_length =
2349                 info0->usrmod0_min_passwd_len;
2350         dom_info_1.password_history_length =
2351                 info0->usrmod0_password_hist_len;
2352
2353         unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2354                 info0->usrmod0_max_passwd_age);
2355         unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2356                 info0->usrmod0_min_passwd_age);
2357
2358         unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2359                 info0->usrmod0_force_logoff);
2360
2361         return set_USER_MODALS_INFO_rpc(mem_ctx,
2362                                         pipe_cli,
2363                                         domain_handle,
2364                                         &dom_info_1,
2365                                         &dom_info_3,
2366                                         NULL);
2367 }
2368
2369 /****************************************************************
2370 ****************************************************************/
2371
2372 static NTSTATUS set_USER_MODALS_INFO_3_buffer(TALLOC_CTX *mem_ctx,
2373                                               struct rpc_pipe_client *pipe_cli,
2374                                               struct policy_handle *domain_handle,
2375                                               struct USER_MODALS_INFO_3 *info3)
2376 {
2377         NTSTATUS status;
2378         struct samr_DomInfo12 dom_info_12;
2379
2380         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2381                                             pipe_cli,
2382                                             domain_handle,
2383                                             NULL,
2384                                             NULL,
2385                                             NULL,
2386                                             NULL,
2387                                             NULL,
2388                                             &dom_info_12);
2389         NT_STATUS_NOT_OK_RETURN(status);
2390
2391         unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_duration,
2392                 info3->usrmod3_lockout_duration);
2393         unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_window,
2394                 info3->usrmod3_lockout_observation_window);
2395         dom_info_12.lockout_threshold = info3->usrmod3_lockout_threshold;
2396
2397         return set_USER_MODALS_INFO_rpc(mem_ctx,
2398                                         pipe_cli,
2399                                         domain_handle,
2400                                         NULL,
2401                                         NULL,
2402                                         &dom_info_12);
2403 }
2404
2405 /****************************************************************
2406 ****************************************************************/
2407
2408 static NTSTATUS set_USER_MODALS_INFO_1001_buffer(TALLOC_CTX *mem_ctx,
2409                                                  struct rpc_pipe_client *pipe_cli,
2410                                                  struct policy_handle *domain_handle,
2411                                                  struct USER_MODALS_INFO_1001 *info1001)
2412 {
2413         NTSTATUS status;
2414         struct samr_DomInfo1 dom_info_1;
2415
2416         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2417                                             pipe_cli,
2418                                             domain_handle,
2419                                             &dom_info_1,
2420                                             NULL,
2421                                             NULL,
2422                                             NULL,
2423                                             NULL,
2424                                             NULL);
2425         NT_STATUS_NOT_OK_RETURN(status);
2426
2427         dom_info_1.min_password_length =
2428                 info1001->usrmod1001_min_passwd_len;
2429
2430         return set_USER_MODALS_INFO_rpc(mem_ctx,
2431                                         pipe_cli,
2432                                         domain_handle,
2433                                         &dom_info_1,
2434                                         NULL,
2435                                         NULL);
2436 }
2437
2438 /****************************************************************
2439 ****************************************************************/
2440
2441 static NTSTATUS set_USER_MODALS_INFO_1002_buffer(TALLOC_CTX *mem_ctx,
2442                                                  struct rpc_pipe_client *pipe_cli,
2443                                                  struct policy_handle *domain_handle,
2444                                                  struct USER_MODALS_INFO_1002 *info1002)
2445 {
2446         NTSTATUS status;
2447         struct samr_DomInfo1 dom_info_1;
2448
2449         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2450                                             pipe_cli,
2451                                             domain_handle,
2452                                             &dom_info_1,
2453                                             NULL,
2454                                             NULL,
2455                                             NULL,
2456                                             NULL,
2457                                             NULL);
2458         NT_STATUS_NOT_OK_RETURN(status);
2459
2460         unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2461                 info1002->usrmod1002_max_passwd_age);
2462
2463         return set_USER_MODALS_INFO_rpc(mem_ctx,
2464                                         pipe_cli,
2465                                         domain_handle,
2466                                         &dom_info_1,
2467                                         NULL,
2468                                         NULL);
2469 }
2470
2471 /****************************************************************
2472 ****************************************************************/
2473
2474 static NTSTATUS set_USER_MODALS_INFO_1003_buffer(TALLOC_CTX *mem_ctx,
2475                                                  struct rpc_pipe_client *pipe_cli,
2476                                                  struct policy_handle *domain_handle,
2477                                                  struct USER_MODALS_INFO_1003 *info1003)
2478 {
2479         NTSTATUS status;
2480         struct samr_DomInfo1 dom_info_1;
2481
2482         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2483                                             pipe_cli,
2484                                             domain_handle,
2485                                             &dom_info_1,
2486                                             NULL,
2487                                             NULL,
2488                                             NULL,
2489                                             NULL,
2490                                             NULL);
2491         NT_STATUS_NOT_OK_RETURN(status);
2492
2493         unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2494                 info1003->usrmod1003_min_passwd_age);
2495
2496         return set_USER_MODALS_INFO_rpc(mem_ctx,
2497                                         pipe_cli,
2498                                         domain_handle,
2499                                         &dom_info_1,
2500                                         NULL,
2501                                         NULL);
2502 }
2503
2504 /****************************************************************
2505 ****************************************************************/
2506
2507 static NTSTATUS set_USER_MODALS_INFO_1004_buffer(TALLOC_CTX *mem_ctx,
2508                                                  struct rpc_pipe_client *pipe_cli,
2509                                                  struct policy_handle *domain_handle,
2510                                                  struct USER_MODALS_INFO_1004 *info1004)
2511 {
2512         NTSTATUS status;
2513         struct samr_DomInfo3 dom_info_3;
2514
2515         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2516                                             pipe_cli,
2517                                             domain_handle,
2518                                             NULL,
2519                                             &dom_info_3,
2520                                             NULL,
2521                                             NULL,
2522                                             NULL,
2523                                             NULL);
2524         NT_STATUS_NOT_OK_RETURN(status);
2525
2526         unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2527                 info1004->usrmod1004_force_logoff);
2528
2529         return set_USER_MODALS_INFO_rpc(mem_ctx,
2530                                         pipe_cli,
2531                                         domain_handle,
2532                                         NULL,
2533                                         &dom_info_3,
2534                                         NULL);
2535 }
2536
2537 /****************************************************************
2538 ****************************************************************/
2539
2540 static NTSTATUS set_USER_MODALS_INFO_1005_buffer(TALLOC_CTX *mem_ctx,
2541                                                  struct rpc_pipe_client *pipe_cli,
2542                                                  struct policy_handle *domain_handle,
2543                                                  struct USER_MODALS_INFO_1005 *info1005)
2544 {
2545         NTSTATUS status;
2546         struct samr_DomInfo1 dom_info_1;
2547
2548         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2549                                             pipe_cli,
2550                                             domain_handle,
2551                                             &dom_info_1,
2552                                             NULL,
2553                                             NULL,
2554                                             NULL,
2555                                             NULL,
2556                                             NULL);
2557         NT_STATUS_NOT_OK_RETURN(status);
2558
2559         dom_info_1.password_history_length =
2560                 info1005->usrmod1005_password_hist_len;
2561
2562         return set_USER_MODALS_INFO_rpc(mem_ctx,
2563                                         pipe_cli,
2564                                         domain_handle,
2565                                         &dom_info_1,
2566                                         NULL,
2567                                         NULL);
2568 }
2569
2570 /****************************************************************
2571 ****************************************************************/
2572
2573 static NTSTATUS set_USER_MODALS_INFO_buffer(TALLOC_CTX *mem_ctx,
2574                                             struct rpc_pipe_client *pipe_cli,
2575                                             uint32_t level,
2576                                             struct policy_handle *domain_handle,
2577                                             struct dom_sid *domain_sid,
2578                                             uint8_t *buffer)
2579 {
2580         struct USER_MODALS_INFO_0 *info0;
2581         struct USER_MODALS_INFO_3 *info3;
2582         struct USER_MODALS_INFO_1001 *info1001;
2583         struct USER_MODALS_INFO_1002 *info1002;
2584         struct USER_MODALS_INFO_1003 *info1003;
2585         struct USER_MODALS_INFO_1004 *info1004;
2586         struct USER_MODALS_INFO_1005 *info1005;
2587
2588         if (!buffer) {
2589                 return ERROR_INSUFFICIENT_BUFFER;
2590         }
2591
2592         switch (level) {
2593                 case 0:
2594                         info0 = (struct USER_MODALS_INFO_0 *)buffer;
2595                         return set_USER_MODALS_INFO_0_buffer(mem_ctx,
2596                                                              pipe_cli,
2597                                                              domain_handle,
2598                                                              info0);
2599                 case 3:
2600                         info3 = (struct USER_MODALS_INFO_3 *)buffer;
2601                         return set_USER_MODALS_INFO_3_buffer(mem_ctx,
2602                                                              pipe_cli,
2603                                                              domain_handle,
2604                                                              info3);
2605                 case 1001:
2606                         info1001 = (struct USER_MODALS_INFO_1001 *)buffer;
2607                         return set_USER_MODALS_INFO_1001_buffer(mem_ctx,
2608                                                                 pipe_cli,
2609                                                                 domain_handle,
2610                                                                 info1001);
2611                 case 1002:
2612                         info1002 = (struct USER_MODALS_INFO_1002 *)buffer;
2613                         return set_USER_MODALS_INFO_1002_buffer(mem_ctx,
2614                                                                 pipe_cli,
2615                                                                 domain_handle,
2616                                                                 info1002);
2617                 case 1003:
2618                         info1003 = (struct USER_MODALS_INFO_1003 *)buffer;
2619                         return set_USER_MODALS_INFO_1003_buffer(mem_ctx,
2620                                                                 pipe_cli,
2621                                                                 domain_handle,
2622                                                                 info1003);
2623                 case 1004:
2624                         info1004 = (struct USER_MODALS_INFO_1004 *)buffer;
2625                         return set_USER_MODALS_INFO_1004_buffer(mem_ctx,
2626                                                                 pipe_cli,
2627                                                                 domain_handle,
2628                                                                 info1004);
2629                 case 1005:
2630                         info1005 = (struct USER_MODALS_INFO_1005 *)buffer;
2631                         return set_USER_MODALS_INFO_1005_buffer(mem_ctx,
2632                                                                 pipe_cli,
2633                                                                 domain_handle,
2634                                                                 info1005);
2635
2636                 default:
2637                         break;
2638         }
2639
2640         return NT_STATUS_OK;
2641 }
2642
2643 /****************************************************************
2644 ****************************************************************/
2645
2646 WERROR NetUserModalsSet_r(struct libnetapi_ctx *ctx,
2647                           struct NetUserModalsSet *r)
2648 {
2649         struct rpc_pipe_client *pipe_cli = NULL;
2650         NTSTATUS status;
2651         WERROR werr;
2652
2653         struct policy_handle connect_handle, domain_handle;
2654         struct dom_sid2 *domain_sid = NULL;
2655         uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2656
2657         ZERO_STRUCT(connect_handle);
2658         ZERO_STRUCT(domain_handle);
2659
2660         if (!r->in.buffer) {
2661                 return WERR_INVALID_PARAM;
2662         }
2663
2664         switch (r->in.level) {
2665                 case 0:
2666                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2667                                        SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2668                                        SAMR_DOMAIN_ACCESS_SET_INFO_1 |
2669                                        SAMR_DOMAIN_ACCESS_SET_INFO_2;
2670                         break;
2671                 case 3:
2672                 case 1001:
2673                 case 1002:
2674                 case 1003:
2675                 case 1005:
2676                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2677                                        SAMR_DOMAIN_ACCESS_SET_INFO_1;
2678                         break;
2679                 case 1004:
2680                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2681                                        SAMR_DOMAIN_ACCESS_SET_INFO_2;
2682                         break;
2683                 case 1:
2684                 case 2:
2685                 case 1006:
2686                 case 1007:
2687                         werr = WERR_NOT_SUPPORTED;
2688                         break;
2689                 default:
2690                         werr = WERR_UNKNOWN_LEVEL;
2691                         goto done;
2692         }
2693
2694         werr = libnetapi_open_pipe(ctx, r->in.server_name,
2695                                    &ndr_table_samr.syntax_id,
2696                                    &pipe_cli);
2697         if (!W_ERROR_IS_OK(werr)) {
2698                 goto done;
2699         }
2700
2701         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2702                                           SAMR_ACCESS_ENUM_DOMAINS |
2703                                           SAMR_ACCESS_LOOKUP_DOMAIN,
2704                                           access_mask,
2705                                           &connect_handle,
2706                                           &domain_handle,
2707                                           &domain_sid);
2708         if (!W_ERROR_IS_OK(werr)) {
2709                 goto done;
2710         }
2711
2712         status = set_USER_MODALS_INFO_buffer(ctx,
2713                                              pipe_cli,
2714                                              r->in.level,
2715                                              &domain_handle,
2716                                              domain_sid,
2717                                              r->in.buffer);
2718         if (!NT_STATUS_IS_OK(status)) {
2719                 werr = ntstatus_to_werror(status);
2720                 goto done;
2721         }
2722
2723  done:
2724         if (ctx->disable_policy_handle_cache) {
2725                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2726                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2727         }
2728
2729         return werr;
2730 }
2731
2732 /****************************************************************
2733 ****************************************************************/
2734
2735 WERROR NetUserModalsSet_l(struct libnetapi_ctx *ctx,
2736                           struct NetUserModalsSet *r)
2737 {
2738         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsSet);
2739 }
2740
2741 /****************************************************************
2742 ****************************************************************/
2743
2744 NTSTATUS add_GROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
2745                                        uint32_t level,
2746                                        const char *group_name,
2747                                        uint32_t attributes,
2748                                        uint8_t **buffer,
2749                                        uint32_t *num_entries)
2750 {
2751         struct GROUP_USERS_INFO_0 u0;
2752         struct GROUP_USERS_INFO_1 u1;
2753
2754         switch (level) {
2755                 case 0:
2756                         if (group_name) {
2757                                 u0.grui0_name = talloc_strdup(mem_ctx, group_name);
2758                                 NT_STATUS_HAVE_NO_MEMORY(u0.grui0_name);
2759                         } else {
2760                                 u0.grui0_name = NULL;
2761                         }
2762
2763                         ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_0, u0,
2764                                      (struct GROUP_USERS_INFO_0 **)buffer, num_entries);
2765                         break;
2766                 case 1:
2767                         if (group_name) {
2768                                 u1.grui1_name = talloc_strdup(mem_ctx, group_name);
2769                                 NT_STATUS_HAVE_NO_MEMORY(u1.grui1_name);
2770                         } else {
2771                                 u1.grui1_name = NULL;
2772                         }
2773
2774                         u1.grui1_attributes = attributes;
2775
2776                         ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_1, u1,
2777                                      (struct GROUP_USERS_INFO_1 **)buffer, num_entries);
2778                         break;
2779                 default:
2780                         return NT_STATUS_INVALID_INFO_CLASS;
2781         }
2782
2783         return NT_STATUS_OK;
2784 }
2785
2786 /****************************************************************
2787 ****************************************************************/
2788
2789 WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
2790                           struct NetUserGetGroups *r)
2791 {
2792         struct rpc_pipe_client *pipe_cli = NULL;
2793         struct policy_handle connect_handle, domain_handle, user_handle;
2794         struct lsa_String lsa_account_name;
2795         struct dom_sid2 *domain_sid = NULL;
2796         struct samr_Ids user_rids, name_types;
2797         struct samr_RidWithAttributeArray *rid_array = NULL;
2798         struct lsa_Strings names;
2799         struct samr_Ids types;
2800         uint32_t *rids = NULL;
2801
2802         int i;
2803         uint32_t entries_read = 0;
2804
2805         NTSTATUS status = NT_STATUS_OK;
2806         WERROR werr;
2807
2808         ZERO_STRUCT(connect_handle);
2809         ZERO_STRUCT(domain_handle);
2810
2811         if (!r->out.buffer) {
2812                 return WERR_INVALID_PARAM;
2813         }
2814
2815         *r->out.buffer = NULL;
2816         *r->out.entries_read = 0;
2817         *r->out.total_entries = 0;
2818
2819         switch (r->in.level) {
2820                 case 0:
2821                 case 1:
2822                         break;
2823                 default:
2824                         return WERR_UNKNOWN_LEVEL;
2825         }
2826
2827         werr = libnetapi_open_pipe(ctx, r->in.server_name,
2828                                    &ndr_table_samr.syntax_id,
2829                                    &pipe_cli);
2830         if (!W_ERROR_IS_OK(werr)) {
2831                 goto done;
2832         }
2833
2834         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2835                                           SAMR_ACCESS_ENUM_DOMAINS |
2836                                           SAMR_ACCESS_LOOKUP_DOMAIN,
2837                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2838                                           &connect_handle,
2839                                           &domain_handle,
2840                                           &domain_sid);
2841         if (!W_ERROR_IS_OK(werr)) {
2842                 goto done;
2843         }
2844
2845         init_lsa_String(&lsa_account_name, r->in.user_name);
2846
2847         status = rpccli_samr_LookupNames(pipe_cli, ctx,
2848                                          &domain_handle,
2849                                          1,
2850                                          &lsa_account_name,
2851                                          &user_rids,
2852                                          &name_types);
2853         if (!NT_STATUS_IS_OK(status)) {
2854                 werr = ntstatus_to_werror(status);
2855                 goto done;
2856         }
2857
2858         status = rpccli_samr_OpenUser(pipe_cli, ctx,
2859                                       &domain_handle,
2860                                       SAMR_USER_ACCESS_GET_GROUPS,
2861                                       user_rids.ids[0],
2862                                       &user_handle);
2863         if (!NT_STATUS_IS_OK(status)) {
2864                 werr = ntstatus_to_werror(status);
2865                 goto done;
2866         }
2867
2868         status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
2869                                               &user_handle,
2870                                               &rid_array);
2871         if (!NT_STATUS_IS_OK(status)) {
2872                 werr = ntstatus_to_werror(status);
2873                 goto done;
2874         }
2875
2876         rids = talloc_array(ctx, uint32_t, rid_array->count);
2877         if (!rids) {
2878                 werr = WERR_NOMEM;
2879                 goto done;
2880         }
2881
2882         for (i=0; i < rid_array->count; i++) {
2883                 rids[i] = rid_array->rids[i].rid;
2884         }
2885
2886         status = rpccli_samr_LookupRids(pipe_cli, ctx,
2887                                         &domain_handle,
2888                                         rid_array->count,
2889                                         rids,
2890                                         &names,
2891                                         &types);
2892         if (!NT_STATUS_IS_OK(status) &&
2893             !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
2894                 werr = ntstatus_to_werror(status);
2895                 goto done;
2896         }
2897
2898         for (i=0; i < names.count; i++) {
2899                 status = add_GROUP_USERS_INFO_X_buffer(ctx,
2900                                                        r->in.level,
2901                                                        names.names[i].string,
2902                                                        rid_array->rids[i].attributes,
2903                                                        r->out.buffer,
2904                                                        &entries_read);
2905                 if (!NT_STATUS_IS_OK(status)) {
2906                         werr = ntstatus_to_werror(status);
2907                         goto done;
2908                 }
2909         }
2910
2911         *r->out.entries_read = entries_read;
2912         *r->out.total_entries = entries_read;
2913
2914  done:
2915         if (ctx->disable_policy_handle_cache) {
2916                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2917                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2918         }
2919
2920         return werr;
2921 }
2922
2923 /****************************************************************
2924 ****************************************************************/
2925
2926 WERROR NetUserGetGroups_l(struct libnetapi_ctx *ctx,
2927                           struct NetUserGetGroups *r)
2928 {
2929         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetGroups);
2930 }
2931
2932 /****************************************************************
2933 ****************************************************************/
2934
2935 WERROR NetUserSetGroups_r(struct libnetapi_ctx *ctx,
2936                           struct NetUserSetGroups *r)
2937 {
2938         struct rpc_pipe_client *pipe_cli = NULL;
2939         struct policy_handle connect_handle, domain_handle, user_handle, group_handle;
2940         struct lsa_String lsa_account_name;
2941         struct dom_sid2 *domain_sid = NULL;
2942         struct samr_Ids user_rids, name_types;
2943         struct samr_Ids group_rids;
2944         struct samr_RidWithAttributeArray *rid_array = NULL;
2945         struct lsa_String *lsa_names = NULL;
2946
2947         uint32_t *add_rids = NULL;
2948         uint32_t *del_rids = NULL;
2949         size_t num_add_rids = 0;
2950         size_t num_del_rids = 0;
2951
2952         uint32_t *member_rids = NULL;
2953         size_t num_member_rids = 0;
2954
2955         struct GROUP_USERS_INFO_0 *i0 = NULL;
2956         struct GROUP_USERS_INFO_1 *i1 = NULL;
2957
2958         int i, k;
2959
2960         NTSTATUS status = NT_STATUS_OK;
2961         WERROR werr;
2962
2963         ZERO_STRUCT(connect_handle);
2964         ZERO_STRUCT(domain_handle);
2965
2966         if (!r->in.buffer) {
2967                 return WERR_INVALID_PARAM;
2968         }
2969
2970         switch (r->in.level) {
2971                 case 0:
2972                 case 1:
2973                         break;
2974                 default:
2975                         return WERR_UNKNOWN_LEVEL;
2976         }
2977
2978         werr = libnetapi_open_pipe(ctx, r->in.server_name,
2979                                    &ndr_table_samr.syntax_id,
2980                                    &pipe_cli);
2981         if (!W_ERROR_IS_OK(werr)) {
2982                 goto done;
2983         }
2984
2985         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2986                                           SAMR_ACCESS_ENUM_DOMAINS |
2987                                           SAMR_ACCESS_LOOKUP_DOMAIN,
2988                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2989                                           &connect_handle,
2990                                           &domain_handle,
2991                                           &domain_sid);
2992         if (!W_ERROR_IS_OK(werr)) {
2993                 goto done;
2994         }
2995
2996         init_lsa_String(&lsa_account_name, r->in.user_name);
2997
2998         status = rpccli_samr_LookupNames(pipe_cli, ctx,
2999                                          &domain_handle,
3000                                          1,
3001                                          &lsa_account_name,
3002                                          &user_rids,
3003                                          &name_types);
3004         if (!NT_STATUS_IS_OK(status)) {
3005                 werr = ntstatus_to_werror(status);
3006                 goto done;
3007         }
3008
3009         status = rpccli_samr_OpenUser(pipe_cli, ctx,
3010                                       &domain_handle,
3011                                       SAMR_USER_ACCESS_GET_GROUPS,
3012                                       user_rids.ids[0],
3013                                       &user_handle);
3014         if (!NT_STATUS_IS_OK(status)) {
3015                 werr = ntstatus_to_werror(status);
3016                 goto done;
3017         }
3018
3019         switch (r->in.level) {
3020                 case 0:
3021                         i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
3022                         break;
3023                 case 1:
3024                         i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
3025                         break;
3026         }
3027
3028         lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
3029         if (!lsa_names) {
3030                 werr = WERR_NOMEM;
3031                 goto done;
3032         }
3033
3034         for (i=0; i < r->in.num_entries; i++) {
3035
3036                 switch (r->in.level) {
3037                         case 0:
3038                                 init_lsa_String(&lsa_names[i], i0->grui0_name);
3039                                 i0++;
3040                                 break;
3041                         case 1:
3042                                 init_lsa_String(&lsa_names[i], i1->grui1_name);
3043                                 i1++;
3044                                 break;
3045                 }
3046         }
3047
3048         status = rpccli_samr_LookupNames(pipe_cli, ctx,
3049                                          &domain_handle,
3050                                          r->in.num_entries,
3051                                          lsa_names,
3052                                          &group_rids,
3053                                          &name_types);
3054         if (!NT_STATUS_IS_OK(status)) {
3055                 werr = ntstatus_to_werror(status);
3056                 goto done;
3057         }
3058
3059         member_rids = group_rids.ids;
3060         num_member_rids = group_rids.count;
3061
3062         status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
3063                                               &user_handle,
3064                                               &rid_array);
3065         if (!NT_STATUS_IS_OK(status)) {
3066                 werr = ntstatus_to_werror(status);
3067                 goto done;
3068         }
3069
3070         /* add list */
3071
3072         for (i=0; i < r->in.num_entries; i++) {
3073                 bool already_member = false;
3074                 for (k=0; k < rid_array->count; k++) {
3075                         if (member_rids[i] == rid_array->rids[k].rid) {
3076                                 already_member = true;
3077                                 break;
3078                         }
3079                 }
3080                 if (!already_member) {
3081                         if (!add_rid_to_array_unique(ctx,
3082                                                      member_rids[i],
3083                                                      &add_rids, &num_add_rids)) {
3084                                 werr = WERR_GENERAL_FAILURE;
3085                                 goto done;
3086                         }
3087                 }
3088         }
3089
3090         /* del list */
3091
3092         for (k=0; k < rid_array->count; k++) {
3093                 bool keep_member = false;
3094                 for (i=0; i < r->in.num_entries; i++) {
3095                         if (member_rids[i] == rid_array->rids[k].rid) {
3096                                 keep_member = true;
3097                                 break;
3098                         }
3099                 }
3100                 if (!keep_member) {
3101                         if (!add_rid_to_array_unique(ctx,
3102                                                      rid_array->rids[k].rid,
3103                                                      &del_rids, &num_del_rids)) {
3104                                 werr = WERR_GENERAL_FAILURE;
3105                                 goto done;
3106                         }
3107                 }
3108         }
3109
3110         /* add list */
3111
3112         for (i=0; i < num_add_rids; i++) {
3113                 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
3114                                                &domain_handle,
3115                                                SAMR_GROUP_ACCESS_ADD_MEMBER,
3116                                                add_rids[i],
3117                                                &group_handle);
3118                 if (!NT_STATUS_IS_OK(status)) {
3119                         werr = ntstatus_to_werror(status);
3120                         goto done;
3121                 }
3122
3123                 status = rpccli_samr_AddGroupMember(pipe_cli, ctx,
3124                                                     &group_handle,
3125                                                     user_rids.ids[0],
3126                                                     7 /* ? */);
3127                 if (!NT_STATUS_IS_OK(status)) {
3128                         werr = ntstatus_to_werror(status);
3129                         goto done;
3130                 }
3131
3132                 if (is_valid_policy_hnd(&group_handle)) {
3133                         rpccli_samr_Close(pipe_cli, ctx, &group_handle);
3134                 }
3135         }
3136
3137         /* del list */
3138
3139         for (i=0; i < num_del_rids; i++) {
3140                 status = rpccli_samr_OpenGroup(pipe_cli, ctx,
3141                                                &domain_handle,
3142                                                SAMR_GROUP_ACCESS_REMOVE_MEMBER,
3143                                                del_rids[i],
3144                                                &group_handle);
3145                 if (!NT_STATUS_IS_OK(status)) {
3146                         werr = ntstatus_to_werror(status);
3147                         goto done;
3148                 }
3149
3150                 status = rpccli_samr_DeleteGroupMember(pipe_cli, ctx,
3151                                                        &group_handle,
3152                                                        user_rids.ids[0]);
3153                 if (!NT_STATUS_IS_OK(status)) {
3154                         werr = ntstatus_to_werror(status);
3155                         goto done;
3156                 }
3157
3158                 if (is_valid_policy_hnd(&group_handle)) {
3159                         rpccli_samr_Close(pipe_cli, ctx, &group_handle);
3160                 }
3161         }
3162
3163         werr = WERR_OK;
3164
3165  done:
3166         if (is_valid_policy_hnd(&group_handle)) {
3167                 rpccli_samr_Close(pipe_cli, ctx, &group_handle);
3168         }
3169
3170         if (ctx->disable_policy_handle_cache) {
3171                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3172                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3173         }
3174
3175         return werr;
3176 }
3177
3178 /****************************************************************
3179 ****************************************************************/
3180
3181 WERROR NetUserSetGroups_l(struct libnetapi_ctx *ctx,
3182                           struct NetUserSetGroups *r)
3183 {
3184         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetGroups);
3185 }
3186
3187 /****************************************************************
3188 ****************************************************************/
3189
3190 static NTSTATUS add_LOCALGROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
3191                                                    uint32_t level,
3192                                                    const char *group_name,
3193                                                    uint8_t **buffer,
3194                                                    uint32_t *num_entries)
3195 {
3196         struct LOCALGROUP_USERS_INFO_0 u0;
3197
3198         switch (level) {
3199                 case 0:
3200                         u0.lgrui0_name = talloc_strdup(mem_ctx, group_name);
3201                         NT_STATUS_HAVE_NO_MEMORY(u0.lgrui0_name);
3202
3203                         ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_USERS_INFO_0, u0,
3204                                      (struct LOCALGROUP_USERS_INFO_0 **)buffer, num_entries);
3205                         break;
3206                 default:
3207                         return NT_STATUS_INVALID_INFO_CLASS;
3208         }
3209
3210         return NT_STATUS_OK;
3211 }
3212
3213 /****************************************************************
3214 ****************************************************************/
3215
3216 WERROR NetUserGetLocalGroups_r(struct libnetapi_ctx *ctx,
3217                                struct NetUserGetLocalGroups *r)
3218 {
3219         struct rpc_pipe_client *pipe_cli = NULL;
3220         struct policy_handle connect_handle, domain_handle, user_handle,
3221         builtin_handle;
3222         struct lsa_String lsa_account_name;
3223         struct dom_sid2 *domain_sid = NULL;
3224         struct samr_Ids user_rids, name_types;
3225         struct samr_RidWithAttributeArray *rid_array = NULL;
3226         struct lsa_Strings names;
3227         struct samr_Ids types;
3228         uint32_t *rids = NULL;
3229         size_t num_rids = 0;
3230         struct dom_sid user_sid;
3231         struct lsa_SidArray sid_array;
3232         struct samr_Ids domain_rids;
3233         struct samr_Ids builtin_rids;
3234
3235         int i;
3236         uint32_t entries_read = 0;
3237
3238         NTSTATUS status = NT_STATUS_OK;
3239         WERROR werr;
3240
3241         ZERO_STRUCT(connect_handle);
3242         ZERO_STRUCT(domain_handle);
3243
3244         if (!r->out.buffer) {
3245                 return WERR_INVALID_PARAM;
3246         }
3247
3248         *r->out.buffer = NULL;
3249         *r->out.entries_read = 0;
3250         *r->out.total_entries = 0;
3251
3252         switch (r->in.level) {
3253                 case 0:
3254                 case 1:
3255                         break;
3256                 default:
3257                         return WERR_UNKNOWN_LEVEL;
3258         }
3259
3260         werr = libnetapi_open_pipe(ctx, r->in.server_name,
3261                                    &ndr_table_samr.syntax_id,
3262                                    &pipe_cli);
3263         if (!W_ERROR_IS_OK(werr)) {
3264                 goto done;
3265         }
3266
3267         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
3268                                           SAMR_ACCESS_ENUM_DOMAINS |
3269                                           SAMR_ACCESS_LOOKUP_DOMAIN,
3270                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
3271                                           SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
3272                                           &connect_handle,
3273                                           &domain_handle,
3274                                           &domain_sid);
3275         if (!W_ERROR_IS_OK(werr)) {
3276                 goto done;
3277         }
3278
3279         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
3280                                                   SAMR_ACCESS_ENUM_DOMAINS |
3281                                                   SAMR_ACCESS_LOOKUP_DOMAIN,
3282                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
3283                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
3284                                                   &connect_handle,
3285                                                   &builtin_handle);
3286         if (!W_ERROR_IS_OK(werr)) {
3287                 goto done;
3288         }
3289
3290         init_lsa_String(&lsa_account_name, r->in.user_name);
3291
3292         status = rpccli_samr_LookupNames(pipe_cli, ctx,
3293                                          &domain_handle,
3294                                          1,
3295                                          &lsa_account_name,
3296                                          &user_rids,
3297                                          &name_types);
3298         if (!NT_STATUS_IS_OK(status)) {
3299                 werr = ntstatus_to_werror(status);
3300                 goto done;
3301         }
3302
3303         status = rpccli_samr_OpenUser(pipe_cli, ctx,
3304                                       &domain_handle,
3305                                       SAMR_USER_ACCESS_GET_GROUPS,
3306                                       user_rids.ids[0],
3307                                       &user_handle);
3308         if (!NT_STATUS_IS_OK(status)) {
3309                 werr = ntstatus_to_werror(status);
3310                 goto done;
3311         }
3312
3313         status = rpccli_samr_GetGroupsForUser(pipe_cli, ctx,
3314                                               &user_handle,
3315                                               &rid_array);
3316         if (!NT_STATUS_IS_OK(status)) {
3317                 werr = ntstatus_to_werror(status);
3318                 goto done;
3319         }
3320
3321         if (!sid_compose(&user_sid, domain_sid, user_rids.ids[0])) {
3322                 werr = WERR_NOMEM;
3323                 goto done;
3324         }
3325
3326         sid_array.num_sids = rid_array->count + 1;
3327         sid_array.sids = TALLOC_ARRAY(ctx, struct lsa_SidPtr, sid_array.num_sids);
3328         if (!sid_array.sids) {
3329                 werr = WERR_NOMEM;
3330                 goto done;
3331         }
3332
3333         sid_array.sids[0].sid = sid_dup_talloc(ctx, &user_sid);
3334         if (!sid_array.sids[0].sid) {
3335                 werr = WERR_NOMEM;
3336                 goto done;
3337         }
3338
3339         for (i=0; i < rid_array->count; i++) {
3340                 struct dom_sid sid;
3341
3342                 if (!sid_compose(&sid, domain_sid, rid_array->rids[i].rid)) {
3343                         werr = WERR_NOMEM;
3344                         goto done;
3345                 }
3346
3347                 sid_array.sids[i+1].sid = sid_dup_talloc(ctx, &sid);
3348                 if (!sid_array.sids[i+1].sid) {
3349                         werr = WERR_NOMEM;
3350                         goto done;
3351                 }
3352         }
3353
3354         status = rpccli_samr_GetAliasMembership(pipe_cli, ctx,
3355                                                 &domain_handle,
3356                                                 &sid_array,
3357                                                 &domain_rids);
3358         if (!NT_STATUS_IS_OK(status)) {
3359                 werr = ntstatus_to_werror(status);
3360                 goto done;
3361         }
3362
3363         for (i=0; i < domain_rids.count; i++) {
3364                 if (!add_rid_to_array_unique(ctx, domain_rids.ids[i],
3365                                              &rids, &num_rids)) {
3366                         werr = WERR_NOMEM;
3367                         goto done;
3368                 }
3369         }
3370
3371         status = rpccli_samr_GetAliasMembership(pipe_cli, ctx,
3372                                                 &builtin_handle,
3373                                                 &sid_array,
3374                                                 &builtin_rids);
3375         if (!NT_STATUS_IS_OK(status)) {
3376                 werr = ntstatus_to_werror(status);
3377                 goto done;
3378         }
3379
3380         for (i=0; i < builtin_rids.count; i++) {
3381                 if (!add_rid_to_array_unique(ctx, builtin_rids.ids[i],
3382                                              &rids, &num_rids)) {
3383                         werr = WERR_NOMEM;
3384                         goto done;
3385                 }
3386         }
3387
3388         status = rpccli_samr_LookupRids(pipe_cli, ctx,
3389                                         &builtin_handle,
3390                                         num_rids,
3391                                         rids,
3392                                         &names,
3393                                         &types);
3394         if (!NT_STATUS_IS_OK(status)) {
3395                 werr = ntstatus_to_werror(status);
3396                 goto done;
3397         }
3398
3399         for (i=0; i < names.count; i++) {
3400                 status = add_LOCALGROUP_USERS_INFO_X_buffer(ctx,
3401                                                             r->in.level,
3402                                                             names.names[i].string,
3403                                                             r->out.buffer,
3404                                                             &entries_read);
3405                 if (!NT_STATUS_IS_OK(status)) {
3406                         werr = ntstatus_to_werror(status);
3407                         goto done;
3408                 }
3409         }
3410
3411         *r->out.entries_read = entries_read;
3412         *r->out.total_entries = entries_read;
3413
3414  done:
3415         if (ctx->disable_policy_handle_cache) {
3416                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3417                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3418         }
3419
3420         return werr;
3421 }
3422
3423 /****************************************************************
3424 ****************************************************************/
3425
3426 WERROR NetUserGetLocalGroups_l(struct libnetapi_ctx *ctx,
3427                                struct NetUserGetLocalGroups *r)
3428 {
3429         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetLocalGroups);
3430 }