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