netapi: fix libnetapi_samr_lookup_user_map_USER_INFO.
[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_1007 *u1007 = NULL;
115
116         if (!buffer || !uX) {
117                 return NT_STATUS_INVALID_PARAMETER;
118         }
119
120         ZERO_STRUCTP(uX);
121
122         switch (level) {
123                 case 0:
124                         u0 = (struct USER_INFO_0 *)buffer;
125                         uX->usriX_name          = u0->usri0_name;
126                         break;
127                 case 1:
128                         u1 = (struct USER_INFO_1 *)buffer;
129                         uX->usriX_name          = u1->usri1_name;
130                         uX->usriX_password      = u1->usri1_password;
131                         uX->usriX_password_age  = u1->usri1_password_age;
132                         uX->usriX_priv          = u1->usri1_priv;
133                         uX->usriX_home_dir      = u1->usri1_home_dir;
134                         uX->usriX_comment       = u1->usri1_comment;
135                         uX->usriX_flags         = u1->usri1_flags;
136                         uX->usriX_script_path   = u1->usri1_script_path;
137                         break;
138                 case 2:
139                         u2 = (struct USER_INFO_2 *)buffer;
140                         uX->usriX_name          = u2->usri2_name;
141                         uX->usriX_password      = u2->usri2_password;
142                         uX->usriX_password_age  = u2->usri2_password_age;
143                         uX->usriX_priv          = u2->usri2_priv;
144                         uX->usriX_home_dir      = u2->usri2_home_dir;
145                         uX->usriX_comment       = u2->usri2_comment;
146                         uX->usriX_flags         = u2->usri2_flags;
147                         uX->usriX_script_path   = u2->usri2_script_path;
148                         uX->usriX_auth_flags    = u2->usri2_auth_flags;
149                         uX->usriX_full_name     = u2->usri2_full_name;
150                         uX->usriX_usr_comment   = u2->usri2_usr_comment;
151                         uX->usriX_parms         = u2->usri2_parms;
152                         uX->usriX_workstations  = u2->usri2_workstations;
153                         uX->usriX_last_logon    = u2->usri2_last_logon;
154                         uX->usriX_last_logoff   = u2->usri2_last_logoff;
155                         uX->usriX_acct_expires  = u2->usri2_acct_expires;
156                         uX->usriX_max_storage   = u2->usri2_max_storage;
157                         uX->usriX_units_per_week= u2->usri2_units_per_week;
158                         uX->usriX_logon_hours   = u2->usri2_logon_hours;
159                         uX->usriX_bad_pw_count  = u2->usri2_bad_pw_count;
160                         uX->usriX_num_logons    = u2->usri2_num_logons;
161                         uX->usriX_logon_server  = u2->usri2_logon_server;
162                         uX->usriX_country_code  = u2->usri2_country_code;
163                         uX->usriX_code_page     = u2->usri2_code_page;
164                         break;
165                 case 1007:
166                         u1007 = (struct USER_INFO_1007 *)buffer;
167                         uX->usriX_comment       = u1007->usri1007_comment;
168                         break;
169                 case 3:
170                 case 4:
171                 default:
172                         return NT_STATUS_INVALID_INFO_CLASS;
173         }
174
175         return NT_STATUS_OK;
176 }
177
178 /****************************************************************
179 ****************************************************************/
180
181 WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
182                     struct NetUserAdd *r)
183 {
184         struct cli_state *cli = NULL;
185         struct rpc_pipe_client *pipe_cli = NULL;
186         NTSTATUS status;
187         WERROR werr;
188         POLICY_HND connect_handle, domain_handle, user_handle;
189         struct lsa_String lsa_account_name;
190         struct dom_sid2 *domain_sid = NULL;
191         struct samr_UserInfo21 info21;
192         union samr_UserInfo *user_info = NULL;
193         struct samr_PwInfo pw_info;
194         uint32_t access_granted = 0;
195         uint32_t rid = 0;
196         struct USER_INFO_X uX;
197
198         ZERO_STRUCT(connect_handle);
199         ZERO_STRUCT(domain_handle);
200         ZERO_STRUCT(user_handle);
201
202         if (!r->in.buffer) {
203                 return WERR_INVALID_PARAM;
204         }
205
206         switch (r->in.level) {
207                 case 1:
208                         break;
209                 case 2:
210                 case 3:
211                 case 4:
212                 default:
213                         werr = WERR_NOT_SUPPORTED;
214                         goto done;
215         }
216
217         werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
218         if (!W_ERROR_IS_OK(werr)) {
219                 goto done;
220         }
221
222         werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
223                                    &pipe_cli);
224         if (!W_ERROR_IS_OK(werr)) {
225                 goto done;
226         }
227
228         status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
229         if (!NT_STATUS_IS_OK(status)) {
230                 werr = ntstatus_to_werror(status);
231                 goto done;
232         }
233
234         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
235                                           SAMR_ACCESS_ENUM_DOMAINS |
236                                           SAMR_ACCESS_OPEN_DOMAIN,
237                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
238                                           SAMR_DOMAIN_ACCESS_CREATE_USER |
239                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
240                                           &connect_handle,
241                                           &domain_handle,
242                                           &domain_sid);
243         if (!W_ERROR_IS_OK(werr)) {
244                 goto done;
245         }
246
247         init_lsa_String(&lsa_account_name, uX.usriX_name);
248
249         status = rpccli_samr_CreateUser2(pipe_cli, ctx,
250                                          &domain_handle,
251                                          &lsa_account_name,
252                                          ACB_NORMAL,
253                                          SEC_STD_WRITE_DAC |
254                                          SEC_STD_DELETE |
255                                          SAMR_USER_ACCESS_SET_PASSWORD |
256                                          SAMR_USER_ACCESS_SET_ATTRIBUTES |
257                                          SAMR_USER_ACCESS_GET_ATTRIBUTES,
258                                          &user_handle,
259                                          &access_granted,
260                                          &rid);
261         if (!NT_STATUS_IS_OK(status)) {
262                 werr = ntstatus_to_werror(status);
263                 goto done;
264         }
265
266         status = rpccli_samr_QueryUserInfo(pipe_cli, ctx,
267                                            &user_handle,
268                                            16,
269                                            &user_info);
270         if (!NT_STATUS_IS_OK(status)) {
271                 werr = ntstatus_to_werror(status);
272                 goto done;
273         }
274
275         if (!(user_info->info16.acct_flags & ACB_NORMAL)) {
276                 werr = WERR_INVALID_PARAM;
277                 goto done;
278         }
279
280         status = rpccli_samr_GetUserPwInfo(pipe_cli, ctx,
281                                            &user_handle,
282                                            &pw_info);
283         if (!NT_STATUS_IS_OK(status)) {
284                 werr = ntstatus_to_werror(status);
285                 goto done;
286         }
287
288         convert_USER_INFO_X_to_samr_user_info21(&uX,
289                                                 &info21);
290
291         ZERO_STRUCTP(user_info);
292
293         if (uX.usriX_password) {
294
295                 user_info->info25.info = info21;
296
297                 init_samr_CryptPasswordEx(uX.usriX_password,
298                                           &cli->user_session_key,
299                                           &user_info->info25.password);
300
301                 status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
302                                                   &user_handle,
303                                                   25,
304                                                   user_info);
305
306                 if (NT_STATUS_EQUAL(status, NT_STATUS(DCERPC_FAULT_INVALID_TAG))) {
307
308                         user_info->info23.info = info21;
309
310                         init_samr_CryptPassword(uX.usriX_password,
311                                                 &cli->user_session_key,
312                                                 &user_info->info23.password);
313
314                         status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
315                                                           &user_handle,
316                                                           23,
317                                                           user_info);
318                 }
319         } else {
320
321                 user_info->info21 = info21;
322
323                 status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
324                                                  &user_handle,
325                                                  21,
326                                                  user_info);
327
328         }
329         if (!NT_STATUS_IS_OK(status)) {
330                 werr = ntstatus_to_werror(status);
331                 goto failed;
332         }
333
334         werr = WERR_OK;
335         goto done;
336
337  failed:
338         rpccli_samr_DeleteUser(pipe_cli, ctx,
339                                &user_handle);
340
341  done:
342         if (!cli) {
343                 return werr;
344         }
345
346         if (is_valid_policy_hnd(&user_handle)) {
347                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
348         }
349
350         if (ctx->disable_policy_handle_cache) {
351                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
352                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
353         }
354
355         return werr;
356 }
357
358 /****************************************************************
359 ****************************************************************/
360
361 WERROR NetUserAdd_l(struct libnetapi_ctx *ctx,
362                     struct NetUserAdd *r)
363 {
364         /* for now just talk to local RPC server */
365         if (!r->in.server_name) {
366                 r->in.server_name = "localhost";
367         }
368
369         return NetUserAdd_r(ctx, r);
370 }
371
372 /****************************************************************
373 ****************************************************************/
374
375 WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
376                     struct NetUserDel *r)
377 {
378         struct cli_state *cli = NULL;
379         struct rpc_pipe_client *pipe_cli = NULL;
380         NTSTATUS status;
381         WERROR werr;
382         POLICY_HND connect_handle, builtin_handle, domain_handle, user_handle;
383         struct lsa_String lsa_account_name;
384         struct samr_Ids user_rids, name_types;
385         struct dom_sid2 *domain_sid = NULL;
386         struct dom_sid2 user_sid;
387
388         ZERO_STRUCT(connect_handle);
389         ZERO_STRUCT(builtin_handle);
390         ZERO_STRUCT(domain_handle);
391         ZERO_STRUCT(user_handle);
392
393         werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
394         if (!W_ERROR_IS_OK(werr)) {
395                 goto done;
396         }
397
398         werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
399                                    &pipe_cli);
400         if (!W_ERROR_IS_OK(werr)) {
401                 goto done;
402         }
403
404         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
405                                           SAMR_ACCESS_ENUM_DOMAINS |
406                                           SAMR_ACCESS_OPEN_DOMAIN,
407                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
408                                           &connect_handle,
409                                           &domain_handle,
410                                           &domain_sid);
411         if (!W_ERROR_IS_OK(werr)) {
412                 goto done;
413         }
414
415         status = rpccli_samr_OpenDomain(pipe_cli, ctx,
416                                         &connect_handle,
417                                         SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
418                                         CONST_DISCARD(DOM_SID *, &global_sid_Builtin),
419                                         &builtin_handle);
420         if (!NT_STATUS_IS_OK(status)) {
421                 werr = ntstatus_to_werror(status);
422                 goto done;
423         }
424
425         init_lsa_String(&lsa_account_name, r->in.user_name);
426
427         status = rpccli_samr_LookupNames(pipe_cli, ctx,
428                                          &domain_handle,
429                                          1,
430                                          &lsa_account_name,
431                                          &user_rids,
432                                          &name_types);
433         if (!NT_STATUS_IS_OK(status)) {
434                 werr = ntstatus_to_werror(status);
435                 goto done;
436         }
437
438         status = rpccli_samr_OpenUser(pipe_cli, ctx,
439                                       &domain_handle,
440                                       STD_RIGHT_DELETE_ACCESS,
441                                       user_rids.ids[0],
442                                       &user_handle);
443         if (!NT_STATUS_IS_OK(status)) {
444                 werr = ntstatus_to_werror(status);
445                 goto done;
446         }
447
448         sid_compose(&user_sid, domain_sid, user_rids.ids[0]);
449
450         status = rpccli_samr_RemoveMemberFromForeignDomain(pipe_cli, ctx,
451                                                            &builtin_handle,
452                                                            &user_sid);
453         if (!NT_STATUS_IS_OK(status)) {
454                 werr = ntstatus_to_werror(status);
455                 goto done;
456         }
457
458         status = rpccli_samr_DeleteUser(pipe_cli, ctx,
459                                         &user_handle);
460         if (!NT_STATUS_IS_OK(status)) {
461                 werr = ntstatus_to_werror(status);
462                 goto done;
463         }
464
465         werr = WERR_OK;
466
467  done:
468         if (!cli) {
469                 return werr;
470         }
471
472         if (is_valid_policy_hnd(&user_handle)) {
473                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
474         }
475
476         if (ctx->disable_policy_handle_cache) {
477                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
478                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
479                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
480         }
481
482         return werr;
483 }
484
485 /****************************************************************
486 ****************************************************************/
487
488 WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
489                     struct NetUserDel *r)
490 {
491         /* for now just talk to local RPC server */
492         if (!r->in.server_name) {
493                 r->in.server_name = "localhost";
494         }
495
496         return NetUserDel_r(ctx, r);
497 }
498
499 /****************************************************************
500 ****************************************************************/
501
502 static NTSTATUS libnetapi_samr_lookup_user(TALLOC_CTX *mem_ctx,
503                                            struct rpc_pipe_client *pipe_cli,
504                                            struct policy_handle *domain_handle,
505                                            struct policy_handle *builtin_handle,
506                                            const char *user_name,
507                                            uint32_t rid,
508                                            uint32_t level,
509                                            struct samr_UserInfo21 **info21,
510                                            struct sec_desc_buf **sec_desc)
511 {
512         NTSTATUS status;
513
514         struct policy_handle user_handle;
515         union samr_UserInfo *user_info = NULL;
516         struct samr_RidWithAttributeArray *rid_array = NULL;
517         uint32_t access_mask = SEC_STD_READ_CONTROL |
518                                SAMR_USER_ACCESS_GET_ATTRIBUTES |
519                                SAMR_USER_ACCESS_GET_NAME_ETC;
520
521         ZERO_STRUCT(user_handle);
522
523         switch (level) {
524                 case 0:
525                 case 1:
526                 case 2:
527                 case 3:
528                 case 10:
529                 case 11:
530                 case 20:
531                 case 23:
532                         break;
533                 default:
534                         return NT_STATUS_INVALID_LEVEL;
535         }
536
537         if (level == 0) {
538                 return NT_STATUS_OK;
539         }
540
541         status = rpccli_samr_OpenUser(pipe_cli, mem_ctx,
542                                       domain_handle,
543                                       access_mask,
544                                       rid,
545                                       &user_handle);
546         if (!NT_STATUS_IS_OK(status)) {
547                 goto done;
548         }
549
550         status = rpccli_samr_QueryUserInfo(pipe_cli, mem_ctx,
551                                            &user_handle,
552                                            21,
553                                            &user_info);
554         if (!NT_STATUS_IS_OK(status)) {
555                 goto done;
556         }
557
558         status = rpccli_samr_QuerySecurity(pipe_cli, mem_ctx,
559                                            &user_handle,
560                                            SECINFO_DACL,
561                                            sec_desc);
562         if (!NT_STATUS_IS_OK(status)) {
563                 goto done;
564         }
565
566         if (level == 1) {
567                 status = rpccli_samr_GetGroupsForUser(pipe_cli, mem_ctx,
568                                                       &user_handle,
569                                                       &rid_array);
570                 if (!NT_STATUS_IS_OK(status)) {
571                         goto done;
572                 }
573
574 #if 0
575                 status = rpccli_samr_GetAliasMembership(pipe_cli, ctx,
576                                                         &builtin_handle,
577                                                         &sids,
578                                                         &rids);
579                 if (!NT_STATUS_IS_OK(status)) {
580                         goto done;
581                 }
582 #endif
583         }
584
585         *info21 = &user_info->info21;
586
587  done:
588         if (is_valid_policy_hnd(&user_handle)) {
589                 rpccli_samr_Close(pipe_cli, mem_ctx, &user_handle);
590         }
591
592         return status;
593 }
594
595 /****************************************************************
596 ****************************************************************/
597
598 static NTSTATUS libnetapi_samr_lookup_user_map_USER_INFO(TALLOC_CTX *mem_ctx,
599                                                          struct rpc_pipe_client *pipe_cli,
600                                                          struct dom_sid *domain_sid,
601                                                          struct policy_handle *domain_handle,
602                                                          struct policy_handle *builtin_handle,
603                                                          const char *user_name,
604                                                          uint32_t rid,
605                                                          uint32_t level,
606                                                          uint8_t **buffer,
607                                                          uint32_t *num_entries)
608 {
609         NTSTATUS status;
610
611         struct samr_UserInfo21 *info21 = NULL;
612         struct sec_desc_buf *sec_desc = NULL;
613         struct dom_sid sid;
614
615         struct USER_INFO_0 info0;
616         struct USER_INFO_10 info10;
617         struct USER_INFO_20 info20;
618         struct USER_INFO_23 info23;
619
620         switch (level) {
621                 case 0:
622                 case 1:
623                 case 2:
624                 case 3:
625                 case 10:
626                 case 11:
627                 case 20:
628                 case 23:
629                         break;
630                 default:
631                         return NT_STATUS_INVALID_LEVEL;
632         }
633
634         if (level == 0) {
635                 info0.usri0_name = talloc_strdup(mem_ctx, user_name);
636                 NT_STATUS_HAVE_NO_MEMORY(info0.usri0_name);
637
638                 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_0, info0,
639                              (struct USER_INFO_0 **)buffer, num_entries);
640
641                 return NT_STATUS_OK;
642         }
643
644         status = libnetapi_samr_lookup_user(mem_ctx, pipe_cli,
645                                             domain_handle,
646                                             builtin_handle,
647                                             user_name,
648                                             rid,
649                                             level,
650                                             &info21,
651                                             &sec_desc);
652
653         if (!NT_STATUS_IS_OK(status)) {
654                 goto done;
655         }
656
657         switch (level) {
658                 case 10:
659                         info10.usri10_name = talloc_strdup(mem_ctx, user_name);
660                         NT_STATUS_HAVE_NO_MEMORY(info10.usri10_name);
661
662                         info10.usri10_comment = talloc_strdup(mem_ctx,
663                                 info21->description.string);
664
665                         info10.usri10_full_name = talloc_strdup(mem_ctx,
666                                 info21->full_name.string);
667
668                         info10.usri10_usr_comment = talloc_strdup(mem_ctx,
669                                 info21->comment.string);
670
671                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_10, info10,
672                                      (struct USER_INFO_10 **)buffer, num_entries);
673
674                         break;
675
676                 case 20:
677                         info20.usri20_name = talloc_strdup(mem_ctx, user_name);
678                         NT_STATUS_HAVE_NO_MEMORY(info20.usri20_name);
679
680                         info20.usri20_comment = talloc_strdup(mem_ctx,
681                                 info21->description.string);
682
683                         info20.usri20_full_name = talloc_strdup(mem_ctx,
684                                 info21->full_name.string);
685
686                         info20.usri20_flags = info21->acct_flags;
687                         info20.usri20_user_id = rid;
688
689                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_20, info20,
690                                      (struct USER_INFO_20 **)buffer, num_entries);
691
692                         break;
693                 case 23:
694                         info23.usri23_name = talloc_strdup(mem_ctx, user_name);
695                         NT_STATUS_HAVE_NO_MEMORY(info23.usri23_name);
696
697                         info23.usri23_comment = talloc_strdup(mem_ctx,
698                                 info21->description.string);
699
700                         info23.usri23_full_name = talloc_strdup(mem_ctx,
701                                 info21->full_name.string);
702
703                         info23.usri23_flags = info21->acct_flags;
704
705                         if (!sid_compose(&sid, domain_sid, rid)) {
706                                 return NT_STATUS_NO_MEMORY;
707                         }
708
709                         info23.usri23_user_sid =
710                                 (struct domsid *)sid_dup_talloc(mem_ctx, &sid);
711
712                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_23, info23,
713                                      (struct USER_INFO_23 **)buffer, num_entries);
714                         break;
715         }
716
717  done:
718         return status;
719 }
720
721 /****************************************************************
722 ****************************************************************/
723
724 WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
725                      struct NetUserEnum *r)
726 {
727         struct cli_state *cli = NULL;
728         struct rpc_pipe_client *pipe_cli = NULL;
729         struct policy_handle connect_handle;
730         struct dom_sid2 *domain_sid = NULL;
731         struct policy_handle domain_handle;
732         struct samr_SamArray *sam = NULL;
733         uint32_t filter = ACB_NORMAL;
734         int i;
735         uint32_t entries_read = 0;
736
737         NTSTATUS status = NT_STATUS_OK;
738         WERROR werr;
739
740         ZERO_STRUCT(connect_handle);
741         ZERO_STRUCT(domain_handle);
742
743         if (!r->out.buffer) {
744                 return WERR_INVALID_PARAM;
745         }
746
747         *r->out.buffer = NULL;
748         *r->out.entries_read = 0;
749
750         switch (r->in.level) {
751                 case 0:
752                 case 10:
753                 case 20:
754                 case 23:
755                         break;
756                 case 1:
757                 case 2:
758                 case 3:
759                 case 11:
760                 default:
761                         return WERR_NOT_SUPPORTED;
762         }
763
764         werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
765         if (!W_ERROR_IS_OK(werr)) {
766                 goto done;
767         }
768
769         werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
770                                    &pipe_cli);
771         if (!W_ERROR_IS_OK(werr)) {
772                 goto done;
773         }
774
775         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
776                                           SAMR_ACCESS_ENUM_DOMAINS |
777                                           SAMR_ACCESS_OPEN_DOMAIN,
778                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
779                                           SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
780                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
781                                           &connect_handle,
782                                           &domain_handle,
783                                           &domain_sid);
784         if (!W_ERROR_IS_OK(werr)) {
785                 goto done;
786         }
787
788         switch (r->in.filter) {
789                 case FILTER_NORMAL_ACCOUNT:
790                         filter = ACB_NORMAL;
791                         break;
792                 case FILTER_TEMP_DUPLICATE_ACCOUNT:
793                         filter = ACB_TEMPDUP;
794                         break;
795                 case FILTER_INTERDOMAIN_TRUST_ACCOUNT:
796                         filter = ACB_DOMTRUST;
797                         break;
798                 case FILTER_WORKSTATION_TRUST_ACCOUNT:
799                         filter = ACB_WSTRUST;
800                         break;
801                 case FILTER_SERVER_TRUST_ACCOUNT:
802                         filter = ACB_SVRTRUST;
803                         break;
804                 default:
805                         break;
806         }
807
808         status = rpccli_samr_EnumDomainUsers(pipe_cli,
809                                              ctx,
810                                              &domain_handle,
811                                              r->in.resume_handle,
812                                              filter,
813                                              &sam,
814                                              r->in.prefmaxlen,
815                                              &entries_read);
816         werr = ntstatus_to_werror(status);
817         if (NT_STATUS_IS_ERR(status)) {
818                 goto done;
819         }
820
821         for (i=0; i < sam->count; i++) {
822
823                 status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
824                                                                   domain_sid,
825                                                                   &domain_handle,
826                                                                   NULL, /*&builtin_handle, */
827                                                                   sam->entries[i].name.string,
828                                                                   sam->entries[i].idx,
829                                                                   r->in.level,
830                                                                   r->out.buffer,
831                                                                   r->out.entries_read);
832                 if (!NT_STATUS_IS_OK(status)) {
833                         werr = ntstatus_to_werror(status);
834                         goto done;
835                 }
836         }
837
838  done:
839         if (!cli) {
840                 return werr;
841         }
842
843         /* if last query */
844         if (NT_STATUS_IS_OK(status) ||
845             NT_STATUS_IS_ERR(status)) {
846
847                 if (ctx->disable_policy_handle_cache) {
848                         libnetapi_samr_close_domain_handle(ctx, &domain_handle);
849                         libnetapi_samr_close_connect_handle(ctx, &connect_handle);
850                 }
851         }
852
853         return werr;
854 }
855
856 /****************************************************************
857 ****************************************************************/
858
859 WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
860                      struct NetUserEnum *r)
861 {
862         return WERR_NOT_SUPPORTED;
863 }
864
865 /****************************************************************
866 ****************************************************************/
867
868 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_USER(TALLOC_CTX *mem_ctx,
869                                                         struct samr_DispInfoGeneral *info,
870                                                         uint32_t *entries_read,
871                                                         void **buffer)
872 {
873         struct NET_DISPLAY_USER *user = NULL;
874         int i;
875
876         user = TALLOC_ZERO_ARRAY(mem_ctx,
877                                  struct NET_DISPLAY_USER,
878                                  info->count);
879         W_ERROR_HAVE_NO_MEMORY(user);
880
881         for (i = 0; i < info->count; i++) {
882                 user[i].usri1_name = talloc_strdup(mem_ctx,
883                         info->entries[i].account_name.string);
884                 user[i].usri1_comment = talloc_strdup(mem_ctx,
885                         info->entries[i].description.string);
886                 user[i].usri1_flags =
887                         info->entries[i].acct_flags;
888                 user[i].usri1_full_name = talloc_strdup(mem_ctx,
889                         info->entries[i].full_name.string);
890                 user[i].usri1_user_id =
891                         info->entries[i].rid;
892                 user[i].usri1_next_index =
893                         info->entries[i].idx;
894
895                 if (!user[i].usri1_name) {
896                         return WERR_NOMEM;
897                 }
898         }
899
900         *buffer = talloc_memdup(mem_ctx, user,
901                 sizeof(struct NET_DISPLAY_USER) * info->count);
902         W_ERROR_HAVE_NO_MEMORY(*buffer);
903
904         *entries_read = info->count;
905
906         return WERR_OK;
907 }
908
909 /****************************************************************
910 ****************************************************************/
911
912 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(TALLOC_CTX *mem_ctx,
913                                                            struct samr_DispInfoFull *info,
914                                                            uint32_t *entries_read,
915                                                            void **buffer)
916 {
917         struct NET_DISPLAY_MACHINE *machine = NULL;
918         int i;
919
920         machine = TALLOC_ZERO_ARRAY(mem_ctx,
921                                     struct NET_DISPLAY_MACHINE,
922                                     info->count);
923         W_ERROR_HAVE_NO_MEMORY(machine);
924
925         for (i = 0; i < info->count; i++) {
926                 machine[i].usri2_name = talloc_strdup(mem_ctx,
927                         info->entries[i].account_name.string);
928                 machine[i].usri2_comment = talloc_strdup(mem_ctx,
929                         info->entries[i].description.string);
930                 machine[i].usri2_flags =
931                         info->entries[i].acct_flags;
932                 machine[i].usri2_user_id =
933                         info->entries[i].rid;
934                 machine[i].usri2_next_index =
935                         info->entries[i].idx;
936
937                 if (!machine[i].usri2_name) {
938                         return WERR_NOMEM;
939                 }
940         }
941
942         *buffer = talloc_memdup(mem_ctx, machine,
943                 sizeof(struct NET_DISPLAY_MACHINE) * info->count);
944         W_ERROR_HAVE_NO_MEMORY(*buffer);
945
946         *entries_read = info->count;
947
948         return WERR_OK;
949 }
950
951 /****************************************************************
952 ****************************************************************/
953
954 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_GROUP(TALLOC_CTX *mem_ctx,
955                                                          struct samr_DispInfoFullGroups *info,
956                                                          uint32_t *entries_read,
957                                                          void **buffer)
958 {
959         struct NET_DISPLAY_GROUP *group = NULL;
960         int i;
961
962         group = TALLOC_ZERO_ARRAY(mem_ctx,
963                                   struct NET_DISPLAY_GROUP,
964                                   info->count);
965         W_ERROR_HAVE_NO_MEMORY(group);
966
967         for (i = 0; i < info->count; i++) {
968                 group[i].grpi3_name = talloc_strdup(mem_ctx,
969                         info->entries[i].account_name.string);
970                 group[i].grpi3_comment = talloc_strdup(mem_ctx,
971                         info->entries[i].description.string);
972                 group[i].grpi3_group_id =
973                         info->entries[i].rid;
974                 group[i].grpi3_attributes =
975                         info->entries[i].acct_flags;
976                 group[i].grpi3_next_index =
977                         info->entries[i].idx;
978
979                 if (!group[i].grpi3_name) {
980                         return WERR_NOMEM;
981                 }
982         }
983
984         *buffer = talloc_memdup(mem_ctx, group,
985                 sizeof(struct NET_DISPLAY_GROUP) * info->count);
986         W_ERROR_HAVE_NO_MEMORY(*buffer);
987
988         *entries_read = info->count;
989
990         return WERR_OK;
991
992 }
993
994 /****************************************************************
995 ****************************************************************/
996
997 static WERROR convert_samr_dispinfo_to_NET_DISPLAY(TALLOC_CTX *mem_ctx,
998                                                    union samr_DispInfo *info,
999                                                    uint32_t level,
1000                                                    uint32_t *entries_read,
1001                                                    void **buffer)
1002 {
1003         switch (level) {
1004                 case 1:
1005                         return convert_samr_dispinfo_to_NET_DISPLAY_USER(mem_ctx,
1006                                                                          &info->info1,
1007                                                                          entries_read,
1008                                                                          buffer);
1009                 case 2:
1010                         return convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(mem_ctx,
1011                                                                             &info->info2,
1012                                                                             entries_read,
1013                                                                             buffer);
1014                 case 3:
1015                         return convert_samr_dispinfo_to_NET_DISPLAY_GROUP(mem_ctx,
1016                                                                           &info->info3,
1017                                                                           entries_read,
1018                                                                           buffer);
1019                 default:
1020                         return WERR_UNKNOWN_LEVEL;
1021         }
1022
1023         return WERR_OK;
1024 }
1025
1026 /****************************************************************
1027 ****************************************************************/
1028
1029 WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
1030                                     struct NetQueryDisplayInformation *r)
1031 {
1032         struct cli_state *cli = NULL;
1033         struct rpc_pipe_client *pipe_cli = NULL;
1034         struct policy_handle connect_handle;
1035         struct dom_sid2 *domain_sid = NULL;
1036         struct policy_handle domain_handle;
1037         union samr_DispInfo info;
1038
1039         uint32_t total_size = 0;
1040         uint32_t returned_size = 0;
1041
1042         NTSTATUS status = NT_STATUS_OK;
1043         WERROR werr;
1044
1045         ZERO_STRUCT(connect_handle);
1046         ZERO_STRUCT(domain_handle);
1047
1048         switch (r->in.level) {
1049                 case 1:
1050                 case 2:
1051                 case 3:
1052                         break;
1053                 default:
1054                         return WERR_UNKNOWN_LEVEL;
1055         }
1056
1057         werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
1058         if (!W_ERROR_IS_OK(werr)) {
1059                 goto done;
1060         }
1061
1062         werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
1063                                    &pipe_cli);
1064         if (!W_ERROR_IS_OK(werr)) {
1065                 goto done;
1066         }
1067
1068         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1069                                           SAMR_ACCESS_ENUM_DOMAINS |
1070                                           SAMR_ACCESS_OPEN_DOMAIN,
1071                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1072                                           SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1073                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1074                                           &connect_handle,
1075                                           &domain_handle,
1076                                           &domain_sid);
1077         if (!W_ERROR_IS_OK(werr)) {
1078                 goto done;
1079         }
1080
1081         status = rpccli_samr_QueryDisplayInfo2(pipe_cli,
1082                                                ctx,
1083                                                &domain_handle,
1084                                                r->in.level,
1085                                                r->in.idx,
1086                                                r->in.entries_requested,
1087                                                r->in.prefmaxlen,
1088                                                &total_size,
1089                                                &returned_size,
1090                                                &info);
1091         if (!NT_STATUS_IS_OK(status)) {
1092                 werr = ntstatus_to_werror(status);
1093                 goto done;
1094         }
1095
1096         werr = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info,
1097                                                     r->in.level,
1098                                                     r->out.entries_read,
1099                                                     r->out.buffer);
1100  done:
1101         if (!cli) {
1102                 return werr;
1103         }
1104
1105         /* if last query */
1106         if (NT_STATUS_IS_OK(status) ||
1107             NT_STATUS_IS_ERR(status)) {
1108
1109                 if (ctx->disable_policy_handle_cache) {
1110                         libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1111                         libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1112                 }
1113         }
1114
1115         return werr;
1116
1117 }
1118
1119 /****************************************************************
1120 ****************************************************************/
1121
1122
1123 WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
1124                                     struct NetQueryDisplayInformation *r)
1125 {
1126         return WERR_NOT_SUPPORTED;
1127 }
1128
1129 /****************************************************************
1130 ****************************************************************/
1131
1132 WERROR NetUserChangePassword_r(struct libnetapi_ctx *ctx,
1133                                struct NetUserChangePassword *r)
1134 {
1135         return WERR_NOT_SUPPORTED;
1136 }
1137
1138 /****************************************************************
1139 ****************************************************************/
1140
1141 WERROR NetUserChangePassword_l(struct libnetapi_ctx *ctx,
1142                                struct NetUserChangePassword *r)
1143 {
1144         return WERR_NOT_SUPPORTED;
1145 }
1146
1147 /****************************************************************
1148 ****************************************************************/
1149
1150 WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx,
1151                         struct NetUserGetInfo *r)
1152 {
1153         struct cli_state *cli = NULL;
1154         struct rpc_pipe_client *pipe_cli = NULL;
1155         NTSTATUS status;
1156         WERROR werr;
1157
1158         struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1159         struct lsa_String lsa_account_name;
1160         struct dom_sid2 *domain_sid = NULL;
1161         struct samr_Ids user_rids, name_types;
1162         uint32_t num_entries = 0;
1163
1164         ZERO_STRUCT(connect_handle);
1165         ZERO_STRUCT(domain_handle);
1166         ZERO_STRUCT(builtin_handle);
1167         ZERO_STRUCT(user_handle);
1168
1169         if (!r->out.buffer) {
1170                 return WERR_INVALID_PARAM;
1171         }
1172
1173         switch (r->in.level) {
1174                 case 0:
1175                 /* case 1: */
1176                 case 10:
1177                 case 20:
1178                 case 23:
1179                         break;
1180                 default:
1181                         werr = WERR_NOT_SUPPORTED;
1182                         goto done;
1183         }
1184
1185         werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
1186         if (!W_ERROR_IS_OK(werr)) {
1187                 goto done;
1188         }
1189
1190         werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
1191                                    &pipe_cli);
1192         if (!W_ERROR_IS_OK(werr)) {
1193                 goto done;
1194         }
1195
1196         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1197                                           SAMR_ACCESS_ENUM_DOMAINS |
1198                                           SAMR_ACCESS_OPEN_DOMAIN,
1199                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1200                                           &connect_handle,
1201                                           &domain_handle,
1202                                           &domain_sid);
1203         if (!W_ERROR_IS_OK(werr)) {
1204                 goto done;
1205         }
1206
1207         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1208                                                   SAMR_ACCESS_ENUM_DOMAINS |
1209                                                   SAMR_ACCESS_OPEN_DOMAIN,
1210                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1211                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1212                                                   &connect_handle,
1213                                                   &builtin_handle);
1214         if (!W_ERROR_IS_OK(werr)) {
1215                 goto done;
1216         }
1217
1218         init_lsa_String(&lsa_account_name, r->in.user_name);
1219
1220         status = rpccli_samr_LookupNames(pipe_cli, ctx,
1221                                          &domain_handle,
1222                                          1,
1223                                          &lsa_account_name,
1224                                          &user_rids,
1225                                          &name_types);
1226         if (!NT_STATUS_IS_OK(status)) {
1227                 werr = ntstatus_to_werror(status);
1228                 goto done;
1229         }
1230
1231         status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1232                                                           domain_sid,
1233                                                           &domain_handle,
1234                                                           &builtin_handle,
1235                                                           r->in.user_name,
1236                                                           user_rids.ids[0],
1237                                                           r->in.level,
1238                                                           r->out.buffer,
1239                                                           &num_entries);
1240         if (!NT_STATUS_IS_OK(status)) {
1241                 werr = ntstatus_to_werror(status);
1242                 goto done;
1243         }
1244
1245  done:
1246         if (!cli) {
1247                 return werr;
1248         }
1249
1250         if (is_valid_policy_hnd(&user_handle)) {
1251                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
1252         }
1253
1254         if (ctx->disable_policy_handle_cache) {
1255                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1256                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1257         }
1258
1259         return werr;
1260 }
1261
1262 /****************************************************************
1263 ****************************************************************/
1264
1265 WERROR NetUserGetInfo_l(struct libnetapi_ctx *ctx,
1266                         struct NetUserGetInfo *r)
1267 {
1268         return WERR_NOT_SUPPORTED;
1269 }
1270
1271 /****************************************************************
1272 ****************************************************************/
1273
1274 WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
1275                         struct NetUserSetInfo *r)
1276 {
1277         struct cli_state *cli = NULL;
1278         struct rpc_pipe_client *pipe_cli = NULL;
1279         NTSTATUS status;
1280         WERROR werr;
1281
1282         struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1283         struct lsa_String lsa_account_name;
1284         struct dom_sid2 *domain_sid = NULL;
1285         struct samr_Ids user_rids, name_types;
1286         union samr_UserInfo user_info;
1287
1288         struct USER_INFO_X uX;
1289
1290         ZERO_STRUCT(connect_handle);
1291         ZERO_STRUCT(domain_handle);
1292         ZERO_STRUCT(builtin_handle);
1293         ZERO_STRUCT(user_handle);
1294
1295         if (!r->in.buffer) {
1296                 return WERR_INVALID_PARAM;
1297         }
1298
1299         switch (r->in.level) {
1300                 case 0:
1301                 case 1007:
1302                         break;
1303                 default:
1304                         werr = WERR_NOT_SUPPORTED;
1305                         goto done;
1306         }
1307
1308         werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
1309         if (!W_ERROR_IS_OK(werr)) {
1310                 goto done;
1311         }
1312
1313         werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
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         return WERR_NOT_SUPPORTED;
1409 }
1410