netapi: make set_user_info_USER_INFO_X a separate function.
[samba.git] / source3 / lib / netapi / user.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  NetApi User Support
4  *  Copyright (C) Guenther Deschner 2008
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "includes.h"
21
22 #include "librpc/gen_ndr/libnetapi.h"
23 #include "lib/netapi/netapi.h"
24 #include "lib/netapi/netapi_private.h"
25 #include "lib/netapi/libnetapi.h"
26
27 /****************************************************************
28 ****************************************************************/
29
30 static void convert_USER_INFO_X_to_samr_user_info21(struct USER_INFO_X *infoX,
31                                                     struct samr_UserInfo21 *info21)
32 {
33         uint32_t fields_present = SAMR_FIELD_ACCT_FLAGS;
34         struct samr_LogonHours zero_logon_hours;
35         struct lsa_BinaryString zero_parameters;
36         uint32_t acct_flags = 0;
37         NTTIME password_age;
38
39         ZERO_STRUCTP(info21);
40         ZERO_STRUCT(zero_logon_hours);
41         ZERO_STRUCT(zero_parameters);
42
43         if (infoX->usriX_name) {
44                 fields_present |= SAMR_FIELD_FULL_NAME;
45         }
46         if (infoX->usriX_password) {
47                 fields_present |= SAMR_FIELD_PASSWORD;
48         }
49         if (infoX->usriX_flags) {
50                 fields_present |= SAMR_FIELD_ACCT_FLAGS;
51         }
52         if (infoX->usriX_name) {
53                 fields_present |= SAMR_FIELD_FULL_NAME;
54         }
55         if (infoX->usriX_home_dir) {
56                 fields_present |= SAMR_FIELD_HOME_DIRECTORY;
57         }
58         if (infoX->usriX_script_path) {
59                 fields_present |= SAMR_FIELD_LOGON_SCRIPT;
60         }
61         if (infoX->usriX_comment) {
62                 fields_present |= SAMR_FIELD_DESCRIPTION;
63         }
64         if (infoX->usriX_password_age) {
65                 fields_present |= SAMR_FIELD_FORCE_PWD_CHANGE;
66         }
67
68         acct_flags |= infoX->usriX_flags | ACB_NORMAL;
69
70         unix_to_nt_time_abs(&password_age, infoX->usriX_password_age);
71
72         /* TODO: infoX->usriX_priv */
73         init_samr_user_info21(info21,
74                               0,
75                               0,
76                               0,
77                               0,
78                               0,
79                               password_age,
80                               NULL,
81                               infoX->usriX_name,
82                               infoX->usriX_home_dir,
83                               NULL,
84                               infoX->usriX_script_path,
85                               NULL,
86                               infoX->usriX_comment,
87                               NULL,
88                               NULL,
89                               &zero_parameters,
90                               0,
91                               0,
92                               acct_flags,
93                               fields_present,
94                               zero_logon_hours,
95                               0,
96                               0,
97                               0,
98                               0,
99                               0,
100                               0,
101                               0);
102 }
103
104 /****************************************************************
105 ****************************************************************/
106
107 static NTSTATUS construct_USER_INFO_X(uint32_t level,
108                                       uint8_t *buffer,
109                                       struct USER_INFO_X *uX)
110 {
111         struct USER_INFO_0 *u0 = NULL;
112         struct USER_INFO_1 *u1 = NULL;
113         struct USER_INFO_2 *u2 = NULL;
114         struct USER_INFO_1007 *u1007 = NULL;
115
116         if (!buffer || !uX) {
117                 return NT_STATUS_INVALID_PARAMETER;
118         }
119
120         ZERO_STRUCTP(uX);
121
122         switch (level) {
123                 case 0:
124                         u0 = (struct USER_INFO_0 *)buffer;
125                         uX->usriX_name          = u0->usri0_name;
126                         break;
127                 case 1:
128                         u1 = (struct USER_INFO_1 *)buffer;
129                         uX->usriX_name          = u1->usri1_name;
130                         uX->usriX_password      = u1->usri1_password;
131                         uX->usriX_password_age  = u1->usri1_password_age;
132                         uX->usriX_priv          = u1->usri1_priv;
133                         uX->usriX_home_dir      = u1->usri1_home_dir;
134                         uX->usriX_comment       = u1->usri1_comment;
135                         uX->usriX_flags         = u1->usri1_flags;
136                         uX->usriX_script_path   = u1->usri1_script_path;
137                         break;
138                 case 2:
139                         u2 = (struct USER_INFO_2 *)buffer;
140                         uX->usriX_name          = u2->usri2_name;
141                         uX->usriX_password      = u2->usri2_password;
142                         uX->usriX_password_age  = u2->usri2_password_age;
143                         uX->usriX_priv          = u2->usri2_priv;
144                         uX->usriX_home_dir      = u2->usri2_home_dir;
145                         uX->usriX_comment       = u2->usri2_comment;
146                         uX->usriX_flags         = u2->usri2_flags;
147                         uX->usriX_script_path   = u2->usri2_script_path;
148                         uX->usriX_auth_flags    = u2->usri2_auth_flags;
149                         uX->usriX_full_name     = u2->usri2_full_name;
150                         uX->usriX_usr_comment   = u2->usri2_usr_comment;
151                         uX->usriX_parms         = u2->usri2_parms;
152                         uX->usriX_workstations  = u2->usri2_workstations;
153                         uX->usriX_last_logon    = u2->usri2_last_logon;
154                         uX->usriX_last_logoff   = u2->usri2_last_logoff;
155                         uX->usriX_acct_expires  = u2->usri2_acct_expires;
156                         uX->usriX_max_storage   = u2->usri2_max_storage;
157                         uX->usriX_units_per_week= u2->usri2_units_per_week;
158                         uX->usriX_logon_hours   = u2->usri2_logon_hours;
159                         uX->usriX_bad_pw_count  = u2->usri2_bad_pw_count;
160                         uX->usriX_num_logons    = u2->usri2_num_logons;
161                         uX->usriX_logon_server  = u2->usri2_logon_server;
162                         uX->usriX_country_code  = u2->usri2_country_code;
163                         uX->usriX_code_page     = u2->usri2_code_page;
164                         break;
165                 case 1007:
166                         u1007 = (struct USER_INFO_1007 *)buffer;
167                         uX->usriX_comment       = u1007->usri1007_comment;
168                         break;
169                 case 3:
170                 case 4:
171                 default:
172                         return NT_STATUS_INVALID_INFO_CLASS;
173         }
174
175         return NT_STATUS_OK;
176 }
177
178 /****************************************************************
179 ****************************************************************/
180
181 static NTSTATUS set_user_info_USER_INFO_X(TALLOC_CTX *ctx,
182                                           struct rpc_pipe_client *pipe_cli,
183                                           DATA_BLOB *session_key,
184                                           struct policy_handle *user_handle,
185                                           struct USER_INFO_X *uX)
186 {
187         union samr_UserInfo user_info;
188         struct samr_UserInfo21 info21;
189         NTSTATUS status;
190
191         if (!uX) {
192                 return NT_STATUS_INVALID_PARAMETER;
193         }
194
195         convert_USER_INFO_X_to_samr_user_info21(uX, &info21);
196
197         ZERO_STRUCT(user_info);
198
199         if (uX->usriX_password) {
200
201                 user_info.info25.info = info21;
202
203                 init_samr_CryptPasswordEx(uX->usriX_password,
204                                           session_key,
205                                           &user_info.info25.password);
206
207                 status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
208                                                   user_handle,
209                                                   25,
210                                                   &user_info);
211
212                 if (NT_STATUS_EQUAL(status, NT_STATUS(DCERPC_FAULT_INVALID_TAG))) {
213
214                         user_info.info23.info = info21;
215
216                         init_samr_CryptPassword(uX->usriX_password,
217                                                 session_key,
218                                                 &user_info.info23.password);
219
220                         status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
221                                                           user_handle,
222                                                           23,
223                                                           &user_info);
224                 }
225         } else {
226
227                 user_info.info21 = info21;
228
229                 status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
230                                                  user_handle,
231                                                  21,
232                                                  &user_info);
233         }
234
235         return status;
236 }
237
238 /****************************************************************
239 ****************************************************************/
240
241 WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
242                     struct NetUserAdd *r)
243 {
244         struct cli_state *cli = NULL;
245         struct rpc_pipe_client *pipe_cli = NULL;
246         NTSTATUS status;
247         WERROR werr;
248         POLICY_HND connect_handle, domain_handle, user_handle;
249         struct lsa_String lsa_account_name;
250         struct dom_sid2 *domain_sid = NULL;
251         union samr_UserInfo *user_info = NULL;
252         struct samr_PwInfo pw_info;
253         uint32_t access_granted = 0;
254         uint32_t rid = 0;
255         struct USER_INFO_X uX;
256
257         ZERO_STRUCT(connect_handle);
258         ZERO_STRUCT(domain_handle);
259         ZERO_STRUCT(user_handle);
260
261         if (!r->in.buffer) {
262                 return WERR_INVALID_PARAM;
263         }
264
265         switch (r->in.level) {
266                 case 1:
267                         break;
268                 case 2:
269                 case 3:
270                 case 4:
271                 default:
272                         werr = WERR_NOT_SUPPORTED;
273                         goto done;
274         }
275
276         werr = libnetapi_open_pipe(ctx, r->in.server_name,
277                                    &ndr_table_samr.syntax_id,
278                                    &cli,
279                                    &pipe_cli);
280         if (!W_ERROR_IS_OK(werr)) {
281                 goto done;
282         }
283
284         status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
285         if (!NT_STATUS_IS_OK(status)) {
286                 werr = ntstatus_to_werror(status);
287                 goto done;
288         }
289
290         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
291                                           SAMR_ACCESS_ENUM_DOMAINS |
292                                           SAMR_ACCESS_OPEN_DOMAIN,
293                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
294                                           SAMR_DOMAIN_ACCESS_CREATE_USER |
295                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
296                                           &connect_handle,
297                                           &domain_handle,
298                                           &domain_sid);
299         if (!W_ERROR_IS_OK(werr)) {
300                 goto done;
301         }
302
303         init_lsa_String(&lsa_account_name, uX.usriX_name);
304
305         status = rpccli_samr_CreateUser2(pipe_cli, ctx,
306                                          &domain_handle,
307                                          &lsa_account_name,
308                                          ACB_NORMAL,
309                                          SEC_STD_WRITE_DAC |
310                                          SEC_STD_DELETE |
311                                          SAMR_USER_ACCESS_SET_PASSWORD |
312                                          SAMR_USER_ACCESS_SET_ATTRIBUTES |
313                                          SAMR_USER_ACCESS_GET_ATTRIBUTES,
314                                          &user_handle,
315                                          &access_granted,
316                                          &rid);
317         if (!NT_STATUS_IS_OK(status)) {
318                 werr = ntstatus_to_werror(status);
319                 goto done;
320         }
321
322         status = rpccli_samr_QueryUserInfo(pipe_cli, ctx,
323                                            &user_handle,
324                                            16,
325                                            &user_info);
326         if (!NT_STATUS_IS_OK(status)) {
327                 werr = ntstatus_to_werror(status);
328                 goto done;
329         }
330
331         if (!(user_info->info16.acct_flags & ACB_NORMAL)) {
332                 werr = WERR_INVALID_PARAM;
333                 goto done;
334         }
335
336         status = rpccli_samr_GetUserPwInfo(pipe_cli, ctx,
337                                            &user_handle,
338                                            &pw_info);
339         if (!NT_STATUS_IS_OK(status)) {
340                 werr = ntstatus_to_werror(status);
341                 goto done;
342         }
343
344         status = set_user_info_USER_INFO_X(ctx, pipe_cli,
345                                            &cli->user_session_key,
346                                            &user_handle,
347                                            &uX);
348         if (!NT_STATUS_IS_OK(status)) {
349                 werr = ntstatus_to_werror(status);
350                 goto failed;
351         }
352
353         werr = WERR_OK;
354         goto done;
355
356  failed:
357         rpccli_samr_DeleteUser(pipe_cli, ctx,
358                                &user_handle);
359
360  done:
361         if (!cli) {
362                 return werr;
363         }
364
365         if (is_valid_policy_hnd(&user_handle)) {
366                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
367         }
368
369         if (ctx->disable_policy_handle_cache) {
370                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
371                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
372         }
373
374         return werr;
375 }
376
377 /****************************************************************
378 ****************************************************************/
379
380 WERROR NetUserAdd_l(struct libnetapi_ctx *ctx,
381                     struct NetUserAdd *r)
382 {
383         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserAdd);
384 }
385
386 /****************************************************************
387 ****************************************************************/
388
389 WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
390                     struct NetUserDel *r)
391 {
392         struct cli_state *cli = NULL;
393         struct rpc_pipe_client *pipe_cli = NULL;
394         NTSTATUS status;
395         WERROR werr;
396         POLICY_HND connect_handle, builtin_handle, domain_handle, user_handle;
397         struct lsa_String lsa_account_name;
398         struct samr_Ids user_rids, name_types;
399         struct dom_sid2 *domain_sid = NULL;
400         struct dom_sid2 user_sid;
401
402         ZERO_STRUCT(connect_handle);
403         ZERO_STRUCT(builtin_handle);
404         ZERO_STRUCT(domain_handle);
405         ZERO_STRUCT(user_handle);
406
407         werr = libnetapi_open_pipe(ctx, r->in.server_name,
408                                    &ndr_table_samr.syntax_id,
409                                    &cli,
410                                    &pipe_cli);
411
412         if (!W_ERROR_IS_OK(werr)) {
413                 goto done;
414         }
415
416         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
417                                           SAMR_ACCESS_ENUM_DOMAINS |
418                                           SAMR_ACCESS_OPEN_DOMAIN,
419                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
420                                           &connect_handle,
421                                           &domain_handle,
422                                           &domain_sid);
423         if (!W_ERROR_IS_OK(werr)) {
424                 goto done;
425         }
426
427         status = rpccli_samr_OpenDomain(pipe_cli, ctx,
428                                         &connect_handle,
429                                         SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
430                                         CONST_DISCARD(DOM_SID *, &global_sid_Builtin),
431                                         &builtin_handle);
432         if (!NT_STATUS_IS_OK(status)) {
433                 werr = ntstatus_to_werror(status);
434                 goto done;
435         }
436
437         init_lsa_String(&lsa_account_name, r->in.user_name);
438
439         status = rpccli_samr_LookupNames(pipe_cli, ctx,
440                                          &domain_handle,
441                                          1,
442                                          &lsa_account_name,
443                                          &user_rids,
444                                          &name_types);
445         if (!NT_STATUS_IS_OK(status)) {
446                 werr = ntstatus_to_werror(status);
447                 goto done;
448         }
449
450         status = rpccli_samr_OpenUser(pipe_cli, ctx,
451                                       &domain_handle,
452                                       STD_RIGHT_DELETE_ACCESS,
453                                       user_rids.ids[0],
454                                       &user_handle);
455         if (!NT_STATUS_IS_OK(status)) {
456                 werr = ntstatus_to_werror(status);
457                 goto done;
458         }
459
460         sid_compose(&user_sid, domain_sid, user_rids.ids[0]);
461
462         status = rpccli_samr_RemoveMemberFromForeignDomain(pipe_cli, ctx,
463                                                            &builtin_handle,
464                                                            &user_sid);
465         if (!NT_STATUS_IS_OK(status)) {
466                 werr = ntstatus_to_werror(status);
467                 goto done;
468         }
469
470         status = rpccli_samr_DeleteUser(pipe_cli, ctx,
471                                         &user_handle);
472         if (!NT_STATUS_IS_OK(status)) {
473                 werr = ntstatus_to_werror(status);
474                 goto done;
475         }
476
477         werr = WERR_OK;
478
479  done:
480         if (!cli) {
481                 return werr;
482         }
483
484         if (is_valid_policy_hnd(&user_handle)) {
485                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
486         }
487
488         if (ctx->disable_policy_handle_cache) {
489                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
490                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
491                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
492         }
493
494         return werr;
495 }
496
497 /****************************************************************
498 ****************************************************************/
499
500 WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
501                     struct NetUserDel *r)
502 {
503         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserDel);
504 }
505
506 /****************************************************************
507 ****************************************************************/
508
509 static NTSTATUS libnetapi_samr_lookup_user(TALLOC_CTX *mem_ctx,
510                                            struct rpc_pipe_client *pipe_cli,
511                                            struct policy_handle *domain_handle,
512                                            struct policy_handle *builtin_handle,
513                                            const char *user_name,
514                                            uint32_t rid,
515                                            uint32_t level,
516                                            struct samr_UserInfo21 **info21,
517                                            struct sec_desc_buf **sec_desc)
518 {
519         NTSTATUS status;
520
521         struct policy_handle user_handle;
522         union samr_UserInfo *user_info = NULL;
523         struct samr_RidWithAttributeArray *rid_array = NULL;
524         uint32_t access_mask = SEC_STD_READ_CONTROL |
525                                SAMR_USER_ACCESS_GET_ATTRIBUTES |
526                                SAMR_USER_ACCESS_GET_NAME_ETC;
527
528         ZERO_STRUCT(user_handle);
529
530         switch (level) {
531                 case 0:
532                 case 1:
533                 case 2:
534                 case 3:
535                 case 10:
536                 case 11:
537                 case 20:
538                 case 23:
539                         break;
540                 default:
541                         return NT_STATUS_INVALID_LEVEL;
542         }
543
544         if (level == 0) {
545                 return NT_STATUS_OK;
546         }
547
548         status = rpccli_samr_OpenUser(pipe_cli, mem_ctx,
549                                       domain_handle,
550                                       access_mask,
551                                       rid,
552                                       &user_handle);
553         if (!NT_STATUS_IS_OK(status)) {
554                 goto done;
555         }
556
557         status = rpccli_samr_QueryUserInfo(pipe_cli, mem_ctx,
558                                            &user_handle,
559                                            21,
560                                            &user_info);
561         if (!NT_STATUS_IS_OK(status)) {
562                 goto done;
563         }
564
565         status = rpccli_samr_QuerySecurity(pipe_cli, mem_ctx,
566                                            &user_handle,
567                                            SECINFO_DACL,
568                                            sec_desc);
569         if (!NT_STATUS_IS_OK(status)) {
570                 goto done;
571         }
572
573         if (level == 1) {
574                 status = rpccli_samr_GetGroupsForUser(pipe_cli, mem_ctx,
575                                                       &user_handle,
576                                                       &rid_array);
577                 if (!NT_STATUS_IS_OK(status)) {
578                         goto done;
579                 }
580
581 #if 0
582                 status = rpccli_samr_GetAliasMembership(pipe_cli, ctx,
583                                                         &builtin_handle,
584                                                         &sids,
585                                                         &rids);
586                 if (!NT_STATUS_IS_OK(status)) {
587                         goto done;
588                 }
589 #endif
590         }
591
592         *info21 = &user_info->info21;
593
594  done:
595         if (is_valid_policy_hnd(&user_handle)) {
596                 rpccli_samr_Close(pipe_cli, mem_ctx, &user_handle);
597         }
598
599         return status;
600 }
601
602 /****************************************************************
603 ****************************************************************/
604
605 static NTSTATUS libnetapi_samr_lookup_user_map_USER_INFO(TALLOC_CTX *mem_ctx,
606                                                          struct rpc_pipe_client *pipe_cli,
607                                                          struct dom_sid *domain_sid,
608                                                          struct policy_handle *domain_handle,
609                                                          struct policy_handle *builtin_handle,
610                                                          const char *user_name,
611                                                          uint32_t rid,
612                                                          uint32_t level,
613                                                          uint8_t **buffer,
614                                                          uint32_t *num_entries)
615 {
616         NTSTATUS status;
617
618         struct samr_UserInfo21 *info21 = NULL;
619         struct sec_desc_buf *sec_desc = NULL;
620         struct dom_sid sid;
621
622         struct USER_INFO_0 info0;
623         struct USER_INFO_10 info10;
624         struct USER_INFO_20 info20;
625         struct USER_INFO_23 info23;
626
627         switch (level) {
628                 case 0:
629                 case 1:
630                 case 2:
631                 case 3:
632                 case 10:
633                 case 11:
634                 case 20:
635                 case 23:
636                         break;
637                 default:
638                         return NT_STATUS_INVALID_LEVEL;
639         }
640
641         if (level == 0) {
642                 info0.usri0_name = talloc_strdup(mem_ctx, user_name);
643                 NT_STATUS_HAVE_NO_MEMORY(info0.usri0_name);
644
645                 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_0, info0,
646                              (struct USER_INFO_0 **)buffer, num_entries);
647
648                 return NT_STATUS_OK;
649         }
650
651         status = libnetapi_samr_lookup_user(mem_ctx, pipe_cli,
652                                             domain_handle,
653                                             builtin_handle,
654                                             user_name,
655                                             rid,
656                                             level,
657                                             &info21,
658                                             &sec_desc);
659
660         if (!NT_STATUS_IS_OK(status)) {
661                 goto done;
662         }
663
664         switch (level) {
665                 case 10:
666                         info10.usri10_name = talloc_strdup(mem_ctx, user_name);
667                         NT_STATUS_HAVE_NO_MEMORY(info10.usri10_name);
668
669                         info10.usri10_comment = talloc_strdup(mem_ctx,
670                                 info21->description.string);
671
672                         info10.usri10_full_name = talloc_strdup(mem_ctx,
673                                 info21->full_name.string);
674
675                         info10.usri10_usr_comment = talloc_strdup(mem_ctx,
676                                 info21->comment.string);
677
678                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_10, info10,
679                                      (struct USER_INFO_10 **)buffer, num_entries);
680
681                         break;
682
683                 case 20:
684                         info20.usri20_name = talloc_strdup(mem_ctx, user_name);
685                         NT_STATUS_HAVE_NO_MEMORY(info20.usri20_name);
686
687                         info20.usri20_comment = talloc_strdup(mem_ctx,
688                                 info21->description.string);
689
690                         info20.usri20_full_name = talloc_strdup(mem_ctx,
691                                 info21->full_name.string);
692
693                         info20.usri20_flags = info21->acct_flags;
694                         info20.usri20_user_id = rid;
695
696                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_20, info20,
697                                      (struct USER_INFO_20 **)buffer, num_entries);
698
699                         break;
700                 case 23:
701                         info23.usri23_name = talloc_strdup(mem_ctx, user_name);
702                         NT_STATUS_HAVE_NO_MEMORY(info23.usri23_name);
703
704                         info23.usri23_comment = talloc_strdup(mem_ctx,
705                                 info21->description.string);
706
707                         info23.usri23_full_name = talloc_strdup(mem_ctx,
708                                 info21->full_name.string);
709
710                         info23.usri23_flags = info21->acct_flags;
711
712                         if (!sid_compose(&sid, domain_sid, rid)) {
713                                 return NT_STATUS_NO_MEMORY;
714                         }
715
716                         info23.usri23_user_sid =
717                                 (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
718
719                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_23, info23,
720                                      (struct USER_INFO_23 **)buffer, num_entries);
721                         break;
722         }
723
724  done:
725         return status;
726 }
727
728 /****************************************************************
729 ****************************************************************/
730
731 WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
732                      struct NetUserEnum *r)
733 {
734         struct cli_state *cli = NULL;
735         struct rpc_pipe_client *pipe_cli = NULL;
736         struct policy_handle connect_handle;
737         struct dom_sid2 *domain_sid = NULL;
738         struct policy_handle domain_handle;
739         struct samr_SamArray *sam = NULL;
740         uint32_t filter = ACB_NORMAL;
741         int i;
742         uint32_t entries_read = 0;
743
744         NTSTATUS status = NT_STATUS_OK;
745         WERROR werr;
746
747         ZERO_STRUCT(connect_handle);
748         ZERO_STRUCT(domain_handle);
749
750         if (!r->out.buffer) {
751                 return WERR_INVALID_PARAM;
752         }
753
754         *r->out.buffer = NULL;
755         *r->out.entries_read = 0;
756
757         switch (r->in.level) {
758                 case 0:
759                 case 10:
760                 case 20:
761                 case 23:
762                         break;
763                 case 1:
764                 case 2:
765                 case 3:
766                 case 11:
767                 default:
768                         return WERR_NOT_SUPPORTED;
769         }
770
771         werr = libnetapi_open_pipe(ctx, r->in.server_name,
772                                    &ndr_table_samr.syntax_id,
773                                    &cli,
774                                    &pipe_cli);
775         if (!W_ERROR_IS_OK(werr)) {
776                 goto done;
777         }
778
779         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
780                                           SAMR_ACCESS_ENUM_DOMAINS |
781                                           SAMR_ACCESS_OPEN_DOMAIN,
782                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
783                                           SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
784                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
785                                           &connect_handle,
786                                           &domain_handle,
787                                           &domain_sid);
788         if (!W_ERROR_IS_OK(werr)) {
789                 goto done;
790         }
791
792         switch (r->in.filter) {
793                 case FILTER_NORMAL_ACCOUNT:
794                         filter = ACB_NORMAL;
795                         break;
796                 case FILTER_TEMP_DUPLICATE_ACCOUNT:
797                         filter = ACB_TEMPDUP;
798                         break;
799                 case FILTER_INTERDOMAIN_TRUST_ACCOUNT:
800                         filter = ACB_DOMTRUST;
801                         break;
802                 case FILTER_WORKSTATION_TRUST_ACCOUNT:
803                         filter = ACB_WSTRUST;
804                         break;
805                 case FILTER_SERVER_TRUST_ACCOUNT:
806                         filter = ACB_SVRTRUST;
807                         break;
808                 default:
809                         break;
810         }
811
812         status = rpccli_samr_EnumDomainUsers(pipe_cli,
813                                              ctx,
814                                              &domain_handle,
815                                              r->in.resume_handle,
816                                              filter,
817                                              &sam,
818                                              r->in.prefmaxlen,
819                                              &entries_read);
820         werr = ntstatus_to_werror(status);
821         if (NT_STATUS_IS_ERR(status)) {
822                 goto done;
823         }
824
825         for (i=0; i < sam->count; i++) {
826
827                 status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
828                                                                   domain_sid,
829                                                                   &domain_handle,
830                                                                   NULL, /*&builtin_handle, */
831                                                                   sam->entries[i].name.string,
832                                                                   sam->entries[i].idx,
833                                                                   r->in.level,
834                                                                   r->out.buffer,
835                                                                   r->out.entries_read);
836                 if (!NT_STATUS_IS_OK(status)) {
837                         werr = ntstatus_to_werror(status);
838                         goto done;
839                 }
840         }
841
842  done:
843         if (!cli) {
844                 return werr;
845         }
846
847         /* if last query */
848         if (NT_STATUS_IS_OK(status) ||
849             NT_STATUS_IS_ERR(status)) {
850
851                 if (ctx->disable_policy_handle_cache) {
852                         libnetapi_samr_close_domain_handle(ctx, &domain_handle);
853                         libnetapi_samr_close_connect_handle(ctx, &connect_handle);
854                 }
855         }
856
857         return werr;
858 }
859
860 /****************************************************************
861 ****************************************************************/
862
863 WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
864                      struct NetUserEnum *r)
865 {
866         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserEnum);
867 }
868
869 /****************************************************************
870 ****************************************************************/
871
872 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_USER(TALLOC_CTX *mem_ctx,
873                                                         struct samr_DispInfoGeneral *info,
874                                                         uint32_t *entries_read,
875                                                         void **buffer)
876 {
877         struct NET_DISPLAY_USER *user = NULL;
878         int i;
879
880         user = TALLOC_ZERO_ARRAY(mem_ctx,
881                                  struct NET_DISPLAY_USER,
882                                  info->count);
883         W_ERROR_HAVE_NO_MEMORY(user);
884
885         for (i = 0; i < info->count; i++) {
886                 user[i].usri1_name = talloc_strdup(mem_ctx,
887                         info->entries[i].account_name.string);
888                 user[i].usri1_comment = talloc_strdup(mem_ctx,
889                         info->entries[i].description.string);
890                 user[i].usri1_flags =
891                         info->entries[i].acct_flags;
892                 user[i].usri1_full_name = talloc_strdup(mem_ctx,
893                         info->entries[i].full_name.string);
894                 user[i].usri1_user_id =
895                         info->entries[i].rid;
896                 user[i].usri1_next_index =
897                         info->entries[i].idx;
898
899                 if (!user[i].usri1_name) {
900                         return WERR_NOMEM;
901                 }
902         }
903
904         *buffer = talloc_memdup(mem_ctx, user,
905                 sizeof(struct NET_DISPLAY_USER) * info->count);
906         W_ERROR_HAVE_NO_MEMORY(*buffer);
907
908         *entries_read = info->count;
909
910         return WERR_OK;
911 }
912
913 /****************************************************************
914 ****************************************************************/
915
916 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(TALLOC_CTX *mem_ctx,
917                                                            struct samr_DispInfoFull *info,
918                                                            uint32_t *entries_read,
919                                                            void **buffer)
920 {
921         struct NET_DISPLAY_MACHINE *machine = NULL;
922         int i;
923
924         machine = TALLOC_ZERO_ARRAY(mem_ctx,
925                                     struct NET_DISPLAY_MACHINE,
926                                     info->count);
927         W_ERROR_HAVE_NO_MEMORY(machine);
928
929         for (i = 0; i < info->count; i++) {
930                 machine[i].usri2_name = talloc_strdup(mem_ctx,
931                         info->entries[i].account_name.string);
932                 machine[i].usri2_comment = talloc_strdup(mem_ctx,
933                         info->entries[i].description.string);
934                 machine[i].usri2_flags =
935                         info->entries[i].acct_flags;
936                 machine[i].usri2_user_id =
937                         info->entries[i].rid;
938                 machine[i].usri2_next_index =
939                         info->entries[i].idx;
940
941                 if (!machine[i].usri2_name) {
942                         return WERR_NOMEM;
943                 }
944         }
945
946         *buffer = talloc_memdup(mem_ctx, machine,
947                 sizeof(struct NET_DISPLAY_MACHINE) * info->count);
948         W_ERROR_HAVE_NO_MEMORY(*buffer);
949
950         *entries_read = info->count;
951
952         return WERR_OK;
953 }
954
955 /****************************************************************
956 ****************************************************************/
957
958 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_GROUP(TALLOC_CTX *mem_ctx,
959                                                          struct samr_DispInfoFullGroups *info,
960                                                          uint32_t *entries_read,
961                                                          void **buffer)
962 {
963         struct NET_DISPLAY_GROUP *group = NULL;
964         int i;
965
966         group = TALLOC_ZERO_ARRAY(mem_ctx,
967                                   struct NET_DISPLAY_GROUP,
968                                   info->count);
969         W_ERROR_HAVE_NO_MEMORY(group);
970
971         for (i = 0; i < info->count; i++) {
972                 group[i].grpi3_name = talloc_strdup(mem_ctx,
973                         info->entries[i].account_name.string);
974                 group[i].grpi3_comment = talloc_strdup(mem_ctx,
975                         info->entries[i].description.string);
976                 group[i].grpi3_group_id =
977                         info->entries[i].rid;
978                 group[i].grpi3_attributes =
979                         info->entries[i].acct_flags;
980                 group[i].grpi3_next_index =
981                         info->entries[i].idx;
982
983                 if (!group[i].grpi3_name) {
984                         return WERR_NOMEM;
985                 }
986         }
987
988         *buffer = talloc_memdup(mem_ctx, group,
989                 sizeof(struct NET_DISPLAY_GROUP) * info->count);
990         W_ERROR_HAVE_NO_MEMORY(*buffer);
991
992         *entries_read = info->count;
993
994         return WERR_OK;
995
996 }
997
998 /****************************************************************
999 ****************************************************************/
1000
1001 static WERROR convert_samr_dispinfo_to_NET_DISPLAY(TALLOC_CTX *mem_ctx,
1002                                                    union samr_DispInfo *info,
1003                                                    uint32_t level,
1004                                                    uint32_t *entries_read,
1005                                                    void **buffer)
1006 {
1007         switch (level) {
1008                 case 1:
1009                         return convert_samr_dispinfo_to_NET_DISPLAY_USER(mem_ctx,
1010                                                                          &info->info1,
1011                                                                          entries_read,
1012                                                                          buffer);
1013                 case 2:
1014                         return convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(mem_ctx,
1015                                                                             &info->info2,
1016                                                                             entries_read,
1017                                                                             buffer);
1018                 case 3:
1019                         return convert_samr_dispinfo_to_NET_DISPLAY_GROUP(mem_ctx,
1020                                                                           &info->info3,
1021                                                                           entries_read,
1022                                                                           buffer);
1023                 default:
1024                         return WERR_UNKNOWN_LEVEL;
1025         }
1026
1027         return WERR_OK;
1028 }
1029
1030 /****************************************************************
1031 ****************************************************************/
1032
1033 WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
1034                                     struct NetQueryDisplayInformation *r)
1035 {
1036         struct cli_state *cli = NULL;
1037         struct rpc_pipe_client *pipe_cli = NULL;
1038         struct policy_handle connect_handle;
1039         struct dom_sid2 *domain_sid = NULL;
1040         struct policy_handle domain_handle;
1041         union samr_DispInfo info;
1042
1043         uint32_t total_size = 0;
1044         uint32_t returned_size = 0;
1045
1046         NTSTATUS status = NT_STATUS_OK;
1047         WERROR werr;
1048
1049         ZERO_STRUCT(connect_handle);
1050         ZERO_STRUCT(domain_handle);
1051
1052         switch (r->in.level) {
1053                 case 1:
1054                 case 2:
1055                 case 3:
1056                         break;
1057                 default:
1058                         return WERR_UNKNOWN_LEVEL;
1059         }
1060
1061         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1062                                    &ndr_table_samr.syntax_id,
1063                                    &cli,
1064                                    &pipe_cli);
1065         if (!W_ERROR_IS_OK(werr)) {
1066                 goto done;
1067         }
1068
1069         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1070                                           SAMR_ACCESS_ENUM_DOMAINS |
1071                                           SAMR_ACCESS_OPEN_DOMAIN,
1072                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1073                                           SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1074                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1075                                           &connect_handle,
1076                                           &domain_handle,
1077                                           &domain_sid);
1078         if (!W_ERROR_IS_OK(werr)) {
1079                 goto done;
1080         }
1081
1082         status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
1083                                                ctx,
1084                                                &domain_handle,
1085                                                r->in.level,
1086                                                r->in.idx,
1087                                                r->in.entries_requested,
1088                                                r->in.prefmaxlen,
1089                                                &total_size,
1090                                                &returned_size,
1091                                                &info);
1092         if (!NT_STATUS_IS_OK(status)) {
1093                 werr = ntstatus_to_werror(status);
1094                 goto done;
1095         }
1096
1097         werr = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info,
1098                                                     r->in.level,
1099                                                     r->out.entries_read,
1100                                                     r->out.buffer);
1101  done:
1102         if (!cli) {
1103                 return werr;
1104         }
1105
1106         /* if last query */
1107         if (NT_STATUS_IS_OK(status) ||
1108             NT_STATUS_IS_ERR(status)) {
1109
1110                 if (ctx->disable_policy_handle_cache) {
1111                         libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1112                         libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1113                 }
1114         }
1115
1116         return werr;
1117
1118 }
1119
1120 /****************************************************************
1121 ****************************************************************/
1122
1123
1124 WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
1125                                     struct NetQueryDisplayInformation *r)
1126 {
1127         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetQueryDisplayInformation);
1128 }
1129
1130 /****************************************************************
1131 ****************************************************************/
1132
1133 WERROR NetUserChangePassword_r(struct libnetapi_ctx *ctx,
1134                                struct NetUserChangePassword *r)
1135 {
1136         return WERR_NOT_SUPPORTED;
1137 }
1138
1139 /****************************************************************
1140 ****************************************************************/
1141
1142 WERROR NetUserChangePassword_l(struct libnetapi_ctx *ctx,
1143                                struct NetUserChangePassword *r)
1144 {
1145         return WERR_NOT_SUPPORTED;
1146 }
1147
1148 /****************************************************************
1149 ****************************************************************/
1150
1151 WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx,
1152                         struct NetUserGetInfo *r)
1153 {
1154         struct cli_state *cli = NULL;
1155         struct rpc_pipe_client *pipe_cli = NULL;
1156         NTSTATUS status;
1157         WERROR werr;
1158
1159         struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1160         struct lsa_String lsa_account_name;
1161         struct dom_sid2 *domain_sid = NULL;
1162         struct samr_Ids user_rids, name_types;
1163         uint32_t num_entries = 0;
1164
1165         ZERO_STRUCT(connect_handle);
1166         ZERO_STRUCT(domain_handle);
1167         ZERO_STRUCT(builtin_handle);
1168         ZERO_STRUCT(user_handle);
1169
1170         if (!r->out.buffer) {
1171                 return WERR_INVALID_PARAM;
1172         }
1173
1174         switch (r->in.level) {
1175                 case 0:
1176                 /* case 1: */
1177                 case 10:
1178                 case 20:
1179                 case 23:
1180                         break;
1181                 default:
1182                         werr = WERR_NOT_SUPPORTED;
1183                         goto done;
1184         }
1185
1186         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1187                                    &ndr_table_samr.syntax_id,
1188                                    &cli,
1189                                    &pipe_cli);
1190         if (!W_ERROR_IS_OK(werr)) {
1191                 goto done;
1192         }
1193
1194         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1195                                           SAMR_ACCESS_ENUM_DOMAINS |
1196                                           SAMR_ACCESS_OPEN_DOMAIN,
1197                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1198                                           &connect_handle,
1199                                           &domain_handle,
1200                                           &domain_sid);
1201         if (!W_ERROR_IS_OK(werr)) {
1202                 goto done;
1203         }
1204
1205         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1206                                                   SAMR_ACCESS_ENUM_DOMAINS |
1207                                                   SAMR_ACCESS_OPEN_DOMAIN,
1208                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1209                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1210                                                   &connect_handle,
1211                                                   &builtin_handle);
1212         if (!W_ERROR_IS_OK(werr)) {
1213                 goto done;
1214         }
1215
1216         init_lsa_String(&lsa_account_name, r->in.user_name);
1217
1218         status = rpccli_samr_LookupNames(pipe_cli, ctx,
1219                                          &domain_handle,
1220                                          1,
1221                                          &lsa_account_name,
1222                                          &user_rids,
1223                                          &name_types);
1224         if (!NT_STATUS_IS_OK(status)) {
1225                 werr = ntstatus_to_werror(status);
1226                 goto done;
1227         }
1228
1229         status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1230                                                           domain_sid,
1231                                                           &domain_handle,
1232                                                           &builtin_handle,
1233                                                           r->in.user_name,
1234                                                           user_rids.ids[0],
1235                                                           r->in.level,
1236                                                           r->out.buffer,
1237                                                           &num_entries);
1238         if (!NT_STATUS_IS_OK(status)) {
1239                 werr = ntstatus_to_werror(status);
1240                 goto done;
1241         }
1242
1243  done:
1244         if (!cli) {
1245                 return werr;
1246         }
1247
1248         if (is_valid_policy_hnd(&user_handle)) {
1249                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
1250         }
1251
1252         if (ctx->disable_policy_handle_cache) {
1253                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1254                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1255         }
1256
1257         return werr;
1258 }
1259
1260 /****************************************************************
1261 ****************************************************************/
1262
1263 WERROR NetUserGetInfo_l(struct libnetapi_ctx *ctx,
1264                         struct NetUserGetInfo *r)
1265 {
1266         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetInfo);
1267 }
1268
1269 /****************************************************************
1270 ****************************************************************/
1271
1272 WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
1273                         struct NetUserSetInfo *r)
1274 {
1275         struct cli_state *cli = NULL;
1276         struct rpc_pipe_client *pipe_cli = NULL;
1277         NTSTATUS status;
1278         WERROR werr;
1279
1280         struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1281         struct lsa_String lsa_account_name;
1282         struct dom_sid2 *domain_sid = NULL;
1283         struct samr_Ids user_rids, name_types;
1284         union samr_UserInfo user_info;
1285
1286         struct USER_INFO_X uX;
1287
1288         ZERO_STRUCT(connect_handle);
1289         ZERO_STRUCT(domain_handle);
1290         ZERO_STRUCT(builtin_handle);
1291         ZERO_STRUCT(user_handle);
1292
1293         if (!r->in.buffer) {
1294                 return WERR_INVALID_PARAM;
1295         }
1296
1297         switch (r->in.level) {
1298                 case 0:
1299                 case 1007:
1300                         break;
1301                 default:
1302                         werr = WERR_NOT_SUPPORTED;
1303                         goto done;
1304         }
1305
1306         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1307                                    &ndr_table_samr.syntax_id,
1308                                    &cli,
1309                                    &pipe_cli);
1310         if (!W_ERROR_IS_OK(werr)) {
1311                 goto done;
1312         }
1313
1314         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1315                                           SAMR_ACCESS_ENUM_DOMAINS |
1316                                           SAMR_ACCESS_OPEN_DOMAIN,
1317                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
1318                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1319                                           &connect_handle,
1320                                           &domain_handle,
1321                                           &domain_sid);
1322         if (!W_ERROR_IS_OK(werr)) {
1323                 goto done;
1324         }
1325
1326         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1327                                                   SAMR_ACCESS_ENUM_DOMAINS |
1328                                                   SAMR_ACCESS_OPEN_DOMAIN,
1329                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1330                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1331                                                   &connect_handle,
1332                                                   &builtin_handle);
1333         if (!W_ERROR_IS_OK(werr)) {
1334                 goto done;
1335         }
1336
1337         init_lsa_String(&lsa_account_name, r->in.user_name);
1338
1339         status = rpccli_samr_LookupNames(pipe_cli, ctx,
1340                                          &domain_handle,
1341                                          1,
1342                                          &lsa_account_name,
1343                                          &user_rids,
1344                                          &name_types);
1345         if (!NT_STATUS_IS_OK(status)) {
1346                 werr = ntstatus_to_werror(status);
1347                 goto done;
1348         }
1349
1350         status = rpccli_samr_OpenUser(pipe_cli, ctx,
1351                                       &domain_handle,
1352                                       SAMR_USER_ACCESS_SET_ATTRIBUTES,
1353                                       user_rids.ids[0],
1354                                       &user_handle);
1355         if (!NT_STATUS_IS_OK(status)) {
1356                 werr = ntstatus_to_werror(status);
1357                 goto done;
1358         }
1359
1360         status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
1361         if (!NT_STATUS_IS_OK(status)) {
1362                 werr = ntstatus_to_werror(status);
1363                 goto done;
1364         }
1365
1366         convert_USER_INFO_X_to_samr_user_info21(&uX, &user_info.info21);
1367
1368         status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
1369                                          &user_handle,
1370                                          21,
1371                                          &user_info);
1372         if (!NT_STATUS_IS_OK(status)) {
1373                 werr = ntstatus_to_werror(status);
1374                 goto done;
1375         }
1376
1377         werr = WERR_OK;
1378
1379  done:
1380         if (!cli) {
1381                 return werr;
1382         }
1383
1384         if (is_valid_policy_hnd(&user_handle)) {
1385                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
1386         }
1387
1388         if (ctx->disable_policy_handle_cache) {
1389                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1390                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1391                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1392         }
1393
1394         return werr;
1395 }
1396
1397 /****************************************************************
1398 ****************************************************************/
1399
1400 WERROR NetUserSetInfo_l(struct libnetapi_ctx *ctx,
1401                         struct NetUserSetInfo *r)
1402 {
1403         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetInfo);
1404 }
1405
1406 /****************************************************************
1407 ****************************************************************/
1408
1409 static NTSTATUS query_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
1410                                            struct rpc_pipe_client *pipe_cli,
1411                                            struct policy_handle *domain_handle,
1412                                            struct samr_DomInfo1 *info1,
1413                                            struct samr_DomInfo3 *info3,
1414                                            struct samr_DomInfo5 *info5,
1415                                            struct samr_DomInfo6 *info6,
1416                                            struct samr_DomInfo7 *info7,
1417                                            struct samr_DomInfo12 *info12)
1418 {
1419         NTSTATUS status;
1420         union samr_DomainInfo *dom_info = NULL;
1421
1422         if (info1) {
1423                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1424                                                      domain_handle,
1425                                                      1,
1426                                                      &dom_info);
1427                 NT_STATUS_NOT_OK_RETURN(status);
1428
1429                 *info1 = dom_info->info1;
1430         }
1431
1432         if (info3) {
1433                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1434                                                      domain_handle,
1435                                                      3,
1436                                                      &dom_info);
1437                 NT_STATUS_NOT_OK_RETURN(status);
1438
1439                 *info3 = dom_info->info3;
1440         }
1441
1442         if (info5) {
1443                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1444                                                      domain_handle,
1445                                                      5,
1446                                                      &dom_info);
1447                 NT_STATUS_NOT_OK_RETURN(status);
1448
1449                 *info5 = dom_info->info5;
1450         }
1451
1452         if (info6) {
1453                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1454                                                      domain_handle,
1455                                                      6,
1456                                                      &dom_info);
1457                 NT_STATUS_NOT_OK_RETURN(status);
1458
1459                 *info6 = dom_info->info6;
1460         }
1461
1462         if (info7) {
1463                 status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
1464                                                      domain_handle,
1465                                                      7,
1466                                                      &dom_info);
1467                 NT_STATUS_NOT_OK_RETURN(status);
1468
1469                 *info7 = dom_info->info7;
1470         }
1471
1472         if (info12) {
1473                 status = rpccli_samr_QueryDomainInfo2(pipe_cli, mem_ctx,
1474                                                       domain_handle,
1475                                                       12,
1476                                                       &dom_info);
1477                 NT_STATUS_NOT_OK_RETURN(status);
1478
1479                 *info12 = dom_info->info12;
1480         }
1481
1482         return NT_STATUS_OK;
1483 }
1484
1485 /****************************************************************
1486 ****************************************************************/
1487
1488 static NTSTATUS query_USER_MODALS_INFO_0(TALLOC_CTX *mem_ctx,
1489                                          struct rpc_pipe_client *pipe_cli,
1490                                          struct policy_handle *domain_handle,
1491                                          struct USER_MODALS_INFO_0 *info0)
1492 {
1493         NTSTATUS status;
1494         struct samr_DomInfo1 dom_info1;
1495         struct samr_DomInfo3 dom_info3;
1496
1497         ZERO_STRUCTP(info0);
1498
1499         status = query_USER_MODALS_INFO_rpc(mem_ctx,
1500                                             pipe_cli,
1501                                             domain_handle,
1502                                             &dom_info1,
1503                                             &dom_info3,
1504                                             NULL,
1505                                             NULL,
1506                                             NULL,
1507                                             NULL);
1508         NT_STATUS_NOT_OK_RETURN(status);
1509
1510         info0->usrmod0_min_passwd_len =
1511                 dom_info1.min_password_length;
1512         info0->usrmod0_max_passwd_age =
1513                 nt_time_to_unix_abs((NTTIME *)&dom_info1.max_password_age);
1514         info0->usrmod0_min_passwd_age =
1515                 nt_time_to_unix_abs((NTTIME *)&dom_info1.min_password_age);
1516         info0->usrmod0_password_hist_len =
1517                 dom_info1.password_history_length;
1518
1519         info0->usrmod0_force_logoff =
1520                 nt_time_to_unix_abs(&dom_info3.force_logoff_time);
1521
1522         return NT_STATUS_OK;
1523 }
1524
1525 /****************************************************************
1526 ****************************************************************/
1527
1528 static NTSTATUS query_USER_MODALS_INFO_1(TALLOC_CTX *mem_ctx,
1529                                          struct rpc_pipe_client *pipe_cli,
1530                                          struct policy_handle *domain_handle,
1531                                          struct USER_MODALS_INFO_1 *info1)
1532 {
1533         NTSTATUS status;
1534         struct samr_DomInfo6 dom_info6;
1535         struct samr_DomInfo7 dom_info7;
1536
1537         status = query_USER_MODALS_INFO_rpc(mem_ctx,
1538                                             pipe_cli,
1539                                             domain_handle,
1540                                             NULL,
1541                                             NULL,
1542                                             NULL,
1543                                             &dom_info6,
1544                                             &dom_info7,
1545                                             NULL);
1546         NT_STATUS_NOT_OK_RETURN(status);
1547
1548         info1->usrmod1_primary =
1549                 talloc_strdup(mem_ctx, dom_info6.primary.string);
1550
1551         info1->usrmod1_role = dom_info7.role;
1552
1553         return NT_STATUS_OK;
1554 }
1555
1556 /****************************************************************
1557 ****************************************************************/
1558
1559 static NTSTATUS query_USER_MODALS_INFO_2(TALLOC_CTX *mem_ctx,
1560                                          struct rpc_pipe_client *pipe_cli,
1561                                          struct policy_handle *domain_handle,
1562                                          struct dom_sid *domain_sid,
1563                                          struct USER_MODALS_INFO_2 *info2)
1564 {
1565         NTSTATUS status;
1566         struct samr_DomInfo5 dom_info5;
1567
1568         status = query_USER_MODALS_INFO_rpc(mem_ctx,
1569                                             pipe_cli,
1570                                             domain_handle,
1571                                             NULL,
1572                                             NULL,
1573                                             &dom_info5,
1574                                             NULL,
1575                                             NULL,
1576                                             NULL);
1577         NT_STATUS_NOT_OK_RETURN(status);
1578
1579         info2->usrmod2_domain_name =
1580                 talloc_strdup(mem_ctx, dom_info5.domain_name.string);
1581         info2->usrmod2_domain_id =
1582                 (struct domsid *)sid_dup_talloc(mem_ctx, domain_sid);
1583
1584         NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_name);
1585         NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_id);
1586
1587         return NT_STATUS_OK;
1588 }
1589
1590 /****************************************************************
1591 ****************************************************************/
1592
1593 static NTSTATUS query_USER_MODALS_INFO_3(TALLOC_CTX *mem_ctx,
1594                                          struct rpc_pipe_client *pipe_cli,
1595                                          struct policy_handle *domain_handle,
1596                                          struct USER_MODALS_INFO_3 *info3)
1597 {
1598         NTSTATUS status;
1599         struct samr_DomInfo12 dom_info12;
1600
1601         status = query_USER_MODALS_INFO_rpc(mem_ctx,
1602                                             pipe_cli,
1603                                             domain_handle,
1604                                             NULL,
1605                                             NULL,
1606                                             NULL,
1607                                             NULL,
1608                                             NULL,
1609                                             &dom_info12);
1610         NT_STATUS_NOT_OK_RETURN(status);
1611
1612         info3->usrmod3_lockout_duration =
1613                 nt_time_to_unix_abs(&dom_info12.lockout_duration);
1614         info3->usrmod3_lockout_observation_window =
1615                 nt_time_to_unix_abs(&dom_info12.lockout_window);
1616         info3->usrmod3_lockout_threshold =
1617                 dom_info12.lockout_threshold;
1618
1619         return NT_STATUS_OK;
1620 }
1621
1622 /****************************************************************
1623 ****************************************************************/
1624
1625 static NTSTATUS query_USER_MODALS_INFO_to_buffer(TALLOC_CTX *mem_ctx,
1626                                                  struct rpc_pipe_client *pipe_cli,
1627                                                  uint32_t level,
1628                                                  struct policy_handle *domain_handle,
1629                                                  struct dom_sid *domain_sid,
1630                                                  uint8_t **buffer)
1631 {
1632         NTSTATUS status;
1633
1634         struct USER_MODALS_INFO_0 info0;
1635         struct USER_MODALS_INFO_1 info1;
1636         struct USER_MODALS_INFO_2 info2;
1637         struct USER_MODALS_INFO_3 info3;
1638
1639         if (!buffer) {
1640                 return ERROR_INSUFFICIENT_BUFFER;
1641         }
1642
1643         switch (level) {
1644                 case 0:
1645                         status = query_USER_MODALS_INFO_0(mem_ctx,
1646                                                           pipe_cli,
1647                                                           domain_handle,
1648                                                           &info0);
1649                         NT_STATUS_NOT_OK_RETURN(status);
1650
1651                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0,
1652                                                            sizeof(info0));
1653                         break;
1654
1655                 case 1:
1656                         status = query_USER_MODALS_INFO_1(mem_ctx,
1657                                                           pipe_cli,
1658                                                           domain_handle,
1659                                                           &info1);
1660                         NT_STATUS_NOT_OK_RETURN(status);
1661
1662                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1,
1663                                                            sizeof(info1));
1664                         break;
1665                 case 2:
1666                         status = query_USER_MODALS_INFO_2(mem_ctx,
1667                                                           pipe_cli,
1668                                                           domain_handle,
1669                                                           domain_sid,
1670                                                           &info2);
1671                         NT_STATUS_NOT_OK_RETURN(status);
1672
1673                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2,
1674                                                            sizeof(info2));
1675                         break;
1676                 case 3:
1677                         status = query_USER_MODALS_INFO_3(mem_ctx,
1678                                                           pipe_cli,
1679                                                           domain_handle,
1680                                                           &info3);
1681                         NT_STATUS_NOT_OK_RETURN(status);
1682
1683                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3,
1684                                                            sizeof(info3));
1685                         break;
1686                 default:
1687                         break;
1688         }
1689
1690         NT_STATUS_HAVE_NO_MEMORY(*buffer);
1691
1692         return NT_STATUS_OK;
1693 }
1694
1695 /****************************************************************
1696 ****************************************************************/
1697
1698 WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx,
1699                           struct NetUserModalsGet *r)
1700 {
1701         struct cli_state *cli = NULL;
1702         struct rpc_pipe_client *pipe_cli = NULL;
1703         NTSTATUS status;
1704         WERROR werr;
1705
1706         struct policy_handle connect_handle, domain_handle;
1707         struct dom_sid2 *domain_sid = NULL;
1708         uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
1709
1710         ZERO_STRUCT(connect_handle);
1711         ZERO_STRUCT(domain_handle);
1712
1713         if (!r->out.buffer) {
1714                 return WERR_INVALID_PARAM;
1715         }
1716
1717         switch (r->in.level) {
1718                 case 0:
1719                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
1720                                        SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
1721                         break;
1722                 case 1:
1723                 case 2:
1724                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
1725                         break;
1726                 case 3:
1727                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1;
1728                         break;
1729                 default:
1730                         werr = WERR_UNKNOWN_LEVEL;
1731                         goto done;
1732         }
1733
1734         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1735                                    &ndr_table_samr.syntax_id,
1736                                    &cli,
1737                                    &pipe_cli);
1738         if (!W_ERROR_IS_OK(werr)) {
1739                 goto done;
1740         }
1741
1742         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1743                                           SAMR_ACCESS_ENUM_DOMAINS |
1744                                           SAMR_ACCESS_OPEN_DOMAIN,
1745                                           access_mask,
1746                                           &connect_handle,
1747                                           &domain_handle,
1748                                           &domain_sid);
1749         if (!W_ERROR_IS_OK(werr)) {
1750                 goto done;
1751         }
1752
1753         /* 0:  1 + 3 */
1754         /* 1:  6 + 7 */
1755         /* 2:  5 */
1756         /* 3: 12 (DomainInfo2) */
1757
1758         status = query_USER_MODALS_INFO_to_buffer(ctx,
1759                                                   pipe_cli,
1760                                                   r->in.level,
1761                                                   &domain_handle,
1762                                                   domain_sid,
1763                                                   r->out.buffer);
1764         if (!NT_STATUS_IS_OK(status)) {
1765                 werr = ntstatus_to_werror(status);
1766                 goto done;
1767         }
1768
1769  done:
1770         if (!cli) {
1771                 return werr;
1772         }
1773
1774         if (ctx->disable_policy_handle_cache) {
1775                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1776                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1777         }
1778
1779         return werr;
1780 }
1781
1782 /****************************************************************
1783 ****************************************************************/
1784
1785 WERROR NetUserModalsGet_l(struct libnetapi_ctx *ctx,
1786                           struct NetUserModalsGet *r)
1787 {
1788         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsGet);
1789 }
1790
1791 /****************************************************************
1792 ****************************************************************/
1793
1794 static NTSTATUS set_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
1795                                          struct rpc_pipe_client *pipe_cli,
1796                                          struct policy_handle *domain_handle,
1797                                          struct samr_DomInfo1 *info1,
1798                                          struct samr_DomInfo3 *info3,
1799                                          struct samr_DomInfo12 *info12)
1800 {
1801         NTSTATUS status;
1802         union samr_DomainInfo dom_info;
1803
1804         if (info1) {
1805
1806                 ZERO_STRUCT(dom_info);
1807
1808                 dom_info.info1 = *info1;
1809
1810                 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
1811                                                    domain_handle,
1812                                                    1,
1813                                                    &dom_info);
1814                 NT_STATUS_NOT_OK_RETURN(status);
1815         }
1816
1817         if (info3) {
1818
1819                 ZERO_STRUCT(dom_info);
1820
1821                 dom_info.info3 = *info3;
1822
1823                 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
1824                                                    domain_handle,
1825                                                    3,
1826                                                    &dom_info);
1827
1828                 NT_STATUS_NOT_OK_RETURN(status);
1829         }
1830
1831         if (info12) {
1832
1833                 ZERO_STRUCT(dom_info);
1834
1835                 dom_info.info12 = *info12;
1836
1837                 status = rpccli_samr_SetDomainInfo(pipe_cli, mem_ctx,
1838                                                    domain_handle,
1839                                                    12,
1840                                                    &dom_info);
1841
1842                 NT_STATUS_NOT_OK_RETURN(status);
1843         }
1844
1845         return NT_STATUS_OK;
1846 }
1847
1848 /****************************************************************
1849 ****************************************************************/
1850
1851 static NTSTATUS set_USER_MODALS_INFO_0_buffer(TALLOC_CTX *mem_ctx,
1852                                               struct rpc_pipe_client *pipe_cli,
1853                                               struct policy_handle *domain_handle,
1854                                               struct USER_MODALS_INFO_0 *info0)
1855 {
1856         NTSTATUS status;
1857         struct samr_DomInfo1 dom_info_1;
1858         struct samr_DomInfo3 dom_info_3;
1859
1860         status = query_USER_MODALS_INFO_rpc(mem_ctx,
1861                                             pipe_cli,
1862                                             domain_handle,
1863                                             &dom_info_1,
1864                                             &dom_info_3,
1865                                             NULL,
1866                                             NULL,
1867                                             NULL,
1868                                             NULL);
1869         NT_STATUS_NOT_OK_RETURN(status);
1870
1871         dom_info_1.min_password_length =
1872                 info0->usrmod0_min_passwd_len;
1873         dom_info_1.password_history_length =
1874                 info0->usrmod0_password_hist_len;
1875
1876         unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
1877                 info0->usrmod0_max_passwd_age);
1878         unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
1879                 info0->usrmod0_min_passwd_age);
1880
1881         unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
1882                 info0->usrmod0_force_logoff);
1883
1884         return set_USER_MODALS_INFO_rpc(mem_ctx,
1885                                         pipe_cli,
1886                                         domain_handle,
1887                                         &dom_info_1,
1888                                         &dom_info_3,
1889                                         NULL);
1890 }
1891
1892 /****************************************************************
1893 ****************************************************************/
1894
1895 static NTSTATUS set_USER_MODALS_INFO_3_buffer(TALLOC_CTX *mem_ctx,
1896                                               struct rpc_pipe_client *pipe_cli,
1897                                               struct policy_handle *domain_handle,
1898                                               struct USER_MODALS_INFO_3 *info3)
1899 {
1900         NTSTATUS status;
1901         struct samr_DomInfo12 dom_info_12;
1902
1903         status = query_USER_MODALS_INFO_rpc(mem_ctx,
1904                                             pipe_cli,
1905                                             domain_handle,
1906                                             NULL,
1907                                             NULL,
1908                                             NULL,
1909                                             NULL,
1910                                             NULL,
1911                                             &dom_info_12);
1912         NT_STATUS_NOT_OK_RETURN(status);
1913
1914         unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_duration,
1915                 info3->usrmod3_lockout_duration);
1916         unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_window,
1917                 info3->usrmod3_lockout_observation_window);
1918         dom_info_12.lockout_threshold = info3->usrmod3_lockout_threshold;
1919
1920         return set_USER_MODALS_INFO_rpc(mem_ctx,
1921                                         pipe_cli,
1922                                         domain_handle,
1923                                         NULL,
1924                                         NULL,
1925                                         &dom_info_12);
1926 }
1927
1928 /****************************************************************
1929 ****************************************************************/
1930
1931 static NTSTATUS set_USER_MODALS_INFO_1001_buffer(TALLOC_CTX *mem_ctx,
1932                                                  struct rpc_pipe_client *pipe_cli,
1933                                                  struct policy_handle *domain_handle,
1934                                                  struct USER_MODALS_INFO_1001 *info1001)
1935 {
1936         NTSTATUS status;
1937         struct samr_DomInfo1 dom_info_1;
1938
1939         status = query_USER_MODALS_INFO_rpc(mem_ctx,
1940                                             pipe_cli,
1941                                             domain_handle,
1942                                             &dom_info_1,
1943                                             NULL,
1944                                             NULL,
1945                                             NULL,
1946                                             NULL,
1947                                             NULL);
1948         NT_STATUS_NOT_OK_RETURN(status);
1949
1950         dom_info_1.min_password_length =
1951                 info1001->usrmod1001_min_passwd_len;
1952
1953         return set_USER_MODALS_INFO_rpc(mem_ctx,
1954                                         pipe_cli,
1955                                         domain_handle,
1956                                         &dom_info_1,
1957                                         NULL,
1958                                         NULL);
1959 }
1960
1961 /****************************************************************
1962 ****************************************************************/
1963
1964 static NTSTATUS set_USER_MODALS_INFO_1002_buffer(TALLOC_CTX *mem_ctx,
1965                                                  struct rpc_pipe_client *pipe_cli,
1966                                                  struct policy_handle *domain_handle,
1967                                                  struct USER_MODALS_INFO_1002 *info1002)
1968 {
1969         NTSTATUS status;
1970         struct samr_DomInfo1 dom_info_1;
1971
1972         status = query_USER_MODALS_INFO_rpc(mem_ctx,
1973                                             pipe_cli,
1974                                             domain_handle,
1975                                             &dom_info_1,
1976                                             NULL,
1977                                             NULL,
1978                                             NULL,
1979                                             NULL,
1980                                             NULL);
1981         NT_STATUS_NOT_OK_RETURN(status);
1982
1983         unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
1984                 info1002->usrmod1002_max_passwd_age);
1985
1986         return set_USER_MODALS_INFO_rpc(mem_ctx,
1987                                         pipe_cli,
1988                                         domain_handle,
1989                                         &dom_info_1,
1990                                         NULL,
1991                                         NULL);
1992 }
1993
1994 /****************************************************************
1995 ****************************************************************/
1996
1997 static NTSTATUS set_USER_MODALS_INFO_1003_buffer(TALLOC_CTX *mem_ctx,
1998                                                  struct rpc_pipe_client *pipe_cli,
1999                                                  struct policy_handle *domain_handle,
2000                                                  struct USER_MODALS_INFO_1003 *info1003)
2001 {
2002         NTSTATUS status;
2003         struct samr_DomInfo1 dom_info_1;
2004
2005         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2006                                             pipe_cli,
2007                                             domain_handle,
2008                                             &dom_info_1,
2009                                             NULL,
2010                                             NULL,
2011                                             NULL,
2012                                             NULL,
2013                                             NULL);
2014         NT_STATUS_NOT_OK_RETURN(status);
2015
2016         unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2017                 info1003->usrmod1003_min_passwd_age);
2018
2019         return set_USER_MODALS_INFO_rpc(mem_ctx,
2020                                         pipe_cli,
2021                                         domain_handle,
2022                                         &dom_info_1,
2023                                         NULL,
2024                                         NULL);
2025 }
2026
2027 /****************************************************************
2028 ****************************************************************/
2029
2030 static NTSTATUS set_USER_MODALS_INFO_1004_buffer(TALLOC_CTX *mem_ctx,
2031                                                  struct rpc_pipe_client *pipe_cli,
2032                                                  struct policy_handle *domain_handle,
2033                                                  struct USER_MODALS_INFO_1004 *info1004)
2034 {
2035         NTSTATUS status;
2036         struct samr_DomInfo3 dom_info_3;
2037
2038         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2039                                             pipe_cli,
2040                                             domain_handle,
2041                                             NULL,
2042                                             &dom_info_3,
2043                                             NULL,
2044                                             NULL,
2045                                             NULL,
2046                                             NULL);
2047         NT_STATUS_NOT_OK_RETURN(status);
2048
2049         unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2050                 info1004->usrmod1004_force_logoff);
2051
2052         return set_USER_MODALS_INFO_rpc(mem_ctx,
2053                                         pipe_cli,
2054                                         domain_handle,
2055                                         NULL,
2056                                         &dom_info_3,
2057                                         NULL);
2058 }
2059
2060 /****************************************************************
2061 ****************************************************************/
2062
2063 static NTSTATUS set_USER_MODALS_INFO_1005_buffer(TALLOC_CTX *mem_ctx,
2064                                                  struct rpc_pipe_client *pipe_cli,
2065                                                  struct policy_handle *domain_handle,
2066                                                  struct USER_MODALS_INFO_1005 *info1005)
2067 {
2068         NTSTATUS status;
2069         struct samr_DomInfo1 dom_info_1;
2070
2071         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2072                                             pipe_cli,
2073                                             domain_handle,
2074                                             &dom_info_1,
2075                                             NULL,
2076                                             NULL,
2077                                             NULL,
2078                                             NULL,
2079                                             NULL);
2080         NT_STATUS_NOT_OK_RETURN(status);
2081
2082         dom_info_1.password_history_length =
2083                 info1005->usrmod1005_password_hist_len;
2084
2085         return set_USER_MODALS_INFO_rpc(mem_ctx,
2086                                         pipe_cli,
2087                                         domain_handle,
2088                                         &dom_info_1,
2089                                         NULL,
2090                                         NULL);
2091 }
2092
2093 /****************************************************************
2094 ****************************************************************/
2095
2096 static NTSTATUS set_USER_MODALS_INFO_buffer(TALLOC_CTX *mem_ctx,
2097                                             struct rpc_pipe_client *pipe_cli,
2098                                             uint32_t level,
2099                                             struct policy_handle *domain_handle,
2100                                             struct dom_sid *domain_sid,
2101                                             uint8_t *buffer)
2102 {
2103         struct USER_MODALS_INFO_0 *info0;
2104         struct USER_MODALS_INFO_3 *info3;
2105         struct USER_MODALS_INFO_1001 *info1001;
2106         struct USER_MODALS_INFO_1002 *info1002;
2107         struct USER_MODALS_INFO_1003 *info1003;
2108         struct USER_MODALS_INFO_1004 *info1004;
2109         struct USER_MODALS_INFO_1005 *info1005;
2110
2111         if (!buffer) {
2112                 return ERROR_INSUFFICIENT_BUFFER;
2113         }
2114
2115         switch (level) {
2116                 case 0:
2117                         info0 = (struct USER_MODALS_INFO_0 *)buffer;
2118                         return set_USER_MODALS_INFO_0_buffer(mem_ctx,
2119                                                              pipe_cli,
2120                                                              domain_handle,
2121                                                              info0);
2122                 case 3:
2123                         info3 = (struct USER_MODALS_INFO_3 *)buffer;
2124                         return set_USER_MODALS_INFO_3_buffer(mem_ctx,
2125                                                              pipe_cli,
2126                                                              domain_handle,
2127                                                              info3);
2128                 case 1001:
2129                         info1001 = (struct USER_MODALS_INFO_1001 *)buffer;
2130                         return set_USER_MODALS_INFO_1001_buffer(mem_ctx,
2131                                                                 pipe_cli,
2132                                                                 domain_handle,
2133                                                                 info1001);
2134                 case 1002:
2135                         info1002 = (struct USER_MODALS_INFO_1002 *)buffer;
2136                         return set_USER_MODALS_INFO_1002_buffer(mem_ctx,
2137                                                                 pipe_cli,
2138                                                                 domain_handle,
2139                                                                 info1002);
2140                 case 1003:
2141                         info1003 = (struct USER_MODALS_INFO_1003 *)buffer;
2142                         return set_USER_MODALS_INFO_1003_buffer(mem_ctx,
2143                                                                 pipe_cli,
2144                                                                 domain_handle,
2145                                                                 info1003);
2146                 case 1004:
2147                         info1004 = (struct USER_MODALS_INFO_1004 *)buffer;
2148                         return set_USER_MODALS_INFO_1004_buffer(mem_ctx,
2149                                                                 pipe_cli,
2150                                                                 domain_handle,
2151                                                                 info1004);
2152                 case 1005:
2153                         info1005 = (struct USER_MODALS_INFO_1005 *)buffer;
2154                         return set_USER_MODALS_INFO_1005_buffer(mem_ctx,
2155                                                                 pipe_cli,
2156                                                                 domain_handle,
2157                                                                 info1005);
2158
2159                 default:
2160                         break;
2161         }
2162
2163         return NT_STATUS_OK;
2164 }
2165
2166 /****************************************************************
2167 ****************************************************************/
2168
2169 WERROR NetUserModalsSet_r(struct libnetapi_ctx *ctx,
2170                           struct NetUserModalsSet *r)
2171 {
2172         struct cli_state *cli = NULL;
2173         struct rpc_pipe_client *pipe_cli = NULL;
2174         NTSTATUS status;
2175         WERROR werr;
2176
2177         struct policy_handle connect_handle, domain_handle;
2178         struct dom_sid2 *domain_sid = NULL;
2179         uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2180
2181         ZERO_STRUCT(connect_handle);
2182         ZERO_STRUCT(domain_handle);
2183
2184         if (!r->in.buffer) {
2185                 return WERR_INVALID_PARAM;
2186         }
2187
2188         switch (r->in.level) {
2189                 case 0:
2190                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2191                                        SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2192                                        SAMR_DOMAIN_ACCESS_SET_INFO_1 |
2193                                        SAMR_DOMAIN_ACCESS_SET_INFO_2;
2194                         break;
2195                 case 3:
2196                 case 1001:
2197                 case 1002:
2198                 case 1003:
2199                 case 1005:
2200                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2201                                        SAMR_DOMAIN_ACCESS_SET_INFO_1;
2202                         break;
2203                 case 1004:
2204                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2205                                        SAMR_DOMAIN_ACCESS_SET_INFO_2;
2206                         break;
2207                 case 1:
2208                 case 2:
2209                 case 1006:
2210                 case 1007:
2211                         werr = WERR_NOT_SUPPORTED;
2212                         break;
2213                 default:
2214                         werr = WERR_UNKNOWN_LEVEL;
2215                         goto done;
2216         }
2217
2218         werr = libnetapi_open_pipe(ctx, r->in.server_name,
2219                                    &ndr_table_samr.syntax_id,
2220                                    &cli,
2221                                    &pipe_cli);
2222         if (!W_ERROR_IS_OK(werr)) {
2223                 goto done;
2224         }
2225
2226         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2227                                           SAMR_ACCESS_ENUM_DOMAINS |
2228                                           SAMR_ACCESS_OPEN_DOMAIN,
2229                                           access_mask,
2230                                           &connect_handle,
2231                                           &domain_handle,
2232                                           &domain_sid);
2233         if (!W_ERROR_IS_OK(werr)) {
2234                 goto done;
2235         }
2236
2237         status = set_USER_MODALS_INFO_buffer(ctx,
2238                                              pipe_cli,
2239                                              r->in.level,
2240                                              &domain_handle,
2241                                              domain_sid,
2242                                              r->in.buffer);
2243         if (!NT_STATUS_IS_OK(status)) {
2244                 werr = ntstatus_to_werror(status);
2245                 goto done;
2246         }
2247
2248  done:
2249         if (!cli) {
2250                 return werr;
2251         }
2252
2253         if (ctx->disable_policy_handle_cache) {
2254                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2255                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2256         }
2257
2258         return werr;
2259 }
2260
2261 /****************************************************************
2262 ****************************************************************/
2263
2264 WERROR NetUserModalsSet_l(struct libnetapi_ctx *ctx,
2265                           struct NetUserModalsSet *r)
2266 {
2267         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsSet);
2268 }