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