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