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