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