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