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