Add NetUserEnum to libnetapi.
[kai/samba.git] / source / lib / netapi / user.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  NetApi User Support
4  *  Copyright (C) Guenther Deschner 2008
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "includes.h"
21
22 #include "librpc/gen_ndr/libnetapi.h"
23 #include "lib/netapi/netapi.h"
24 #include "lib/netapi/libnetapi.h"
25
26 /****************************************************************
27 ****************************************************************/
28
29 WERROR NetUserAdd_l(struct libnetapi_ctx *ctx,
30                     struct NetUserAdd *r)
31 {
32         return WERR_NOT_SUPPORTED;
33 }
34
35 /****************************************************************
36 ****************************************************************/
37
38 static void convert_USER_INFO_1_to_samr_user_info25(struct USER_INFO_1 *info1,
39                                                     DATA_BLOB *user_session_key,
40                                                     struct samr_UserInfo25 *info25)
41 {
42         uint32_t fields_present = SAMR_FIELD_ACCT_FLAGS;
43         struct samr_LogonHours zero_logon_hours;
44         struct lsa_BinaryString zero_parameters;
45         uint32_t acct_flags = 0;
46         NTTIME password_age;
47
48         ZERO_STRUCTP(info25);
49         ZERO_STRUCT(zero_logon_hours);
50         ZERO_STRUCT(zero_parameters);
51
52         if (info1->usri1_name) {
53                 fields_present |= SAMR_FIELD_FULL_NAME;
54         }
55         if (info1->usri1_password) {
56                 fields_present |= SAMR_FIELD_PASSWORD;
57         }
58         if (info1->usri1_flags) {
59                 fields_present |= SAMR_FIELD_ACCT_FLAGS;
60         }
61         if (info1->usri1_name) {
62                 fields_present |= SAMR_FIELD_FULL_NAME;
63         }
64         if (info1->usri1_home_dir) {
65                 fields_present |= SAMR_FIELD_HOME_DIRECTORY;
66         }
67         if (info1->usri1_script_path) {
68                 fields_present |= SAMR_FIELD_LOGON_SCRIPT;
69         }
70         if (info1->usri1_comment) {
71                 fields_present |= SAMR_FIELD_DESCRIPTION;
72         }
73         if (info1->usri1_password_age) {
74                 fields_present |= SAMR_FIELD_FORCE_PWD_CHANGE;
75         }
76
77         acct_flags |= info1->usri1_flags | ACB_NORMAL;
78
79         unix_to_nt_time_abs(&password_age, info1->usri1_password_age);
80
81         /* TODO: info1->usri1_priv */
82         init_samr_user_info21(&info25->info,
83                               0,
84                               0,
85                               0,
86                               0,
87                               0,
88                               password_age,
89                               NULL,
90                               info1->usri1_name,
91                               info1->usri1_home_dir,
92                               NULL,
93                               info1->usri1_script_path,
94                               NULL,
95                               info1->usri1_comment,
96                               NULL,
97                               NULL,
98                               &zero_parameters,
99                               0,
100                               0,
101                               acct_flags,
102                               fields_present,
103                               zero_logon_hours,
104                               0,
105                               0,
106                               0,
107                               0,
108                               0,
109                               0,
110                               0);
111
112         if (info1->usri1_password) {
113                 uchar pwbuf[532];
114                 struct MD5Context ctx;
115                 uint8_t confounder[16];
116                 DATA_BLOB confounded_session_key = data_blob(NULL, 16);
117
118                 encode_pw_buffer(pwbuf, info1->usri1_password, STR_UNICODE);
119
120                 generate_random_buffer((uint8_t *)confounder, 16);
121
122                 MD5Init(&ctx);
123                 MD5Update(&ctx, confounder, 16);
124                 MD5Update(&ctx, user_session_key->data,
125                                 user_session_key->length);
126                 MD5Final(confounded_session_key.data, &ctx);
127
128                 SamOEMhashBlob(pwbuf, 516, &confounded_session_key);
129                 memcpy(&pwbuf[516], confounder, 16);
130
131                 memcpy(info25->password.data, pwbuf, sizeof(pwbuf));
132                 data_blob_free(&confounded_session_key);
133         }
134 }
135
136 /****************************************************************
137 ****************************************************************/
138
139 WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
140                     struct NetUserAdd *r)
141 {
142         struct cli_state *cli = NULL;
143         struct rpc_pipe_client *pipe_cli = NULL;
144         NTSTATUS status;
145         WERROR werr;
146         uint32_t resume_handle = 0;
147         uint32_t num_entries = 0;
148         POLICY_HND connect_handle, domain_handle, user_handle;
149         struct samr_SamArray *sam = NULL;
150         const char *domain_name = NULL;
151         struct lsa_String lsa_domain_name, lsa_account_name;
152         struct dom_sid2 *domain_sid = NULL;
153         struct samr_UserInfo25 info25;
154         union samr_UserInfo *user_info = NULL;
155         struct samr_PwInfo pw_info;
156         uint32_t access_granted = 0;
157         uint32_t rid = 0;
158         bool domain_found = true;
159         int i;
160         struct USER_INFO_1 *info1;
161
162         ZERO_STRUCT(connect_handle);
163         ZERO_STRUCT(domain_handle);
164         ZERO_STRUCT(user_handle);
165
166         if (!r->in.buffer) {
167                 return WERR_INVALID_PARAM;
168         }
169
170         switch (r->in.level) {
171                 case 1:
172                         info1 = (struct USER_INFO_1 *)r->in.buffer;
173                         break;
174                 case 2:
175                 case 3:
176                 case 4:
177                 default:
178                         werr = WERR_NOT_SUPPORTED;
179                         goto done;
180         }
181
182         status = cli_full_connection(&cli, NULL, r->in.server_name,
183                                      NULL, 0,
184                                      "IPC$", "IPC",
185                                      ctx->username,
186                                      ctx->workgroup,
187                                      ctx->password,
188                                      CLI_FULL_CONNECTION_USE_KERBEROS |
189                                      CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS,
190                                      Undefined, NULL);
191
192         if (!NT_STATUS_IS_OK(status)) {
193                 werr = ntstatus_to_werror(status);
194                 goto done;
195         }
196
197         pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &status);
198         if (!pipe_cli) {
199                 werr = ntstatus_to_werror(status);
200                 goto done;
201         }
202
203         status = rpccli_try_samr_connects(pipe_cli, ctx,
204                                           SAMR_ACCESS_ENUM_DOMAINS |
205                                           SAMR_ACCESS_OPEN_DOMAIN,
206                                           &connect_handle);
207         if (!NT_STATUS_IS_OK(status)) {
208                 werr = ntstatus_to_werror(status);
209                 goto done;
210         }
211
212         status = rpccli_samr_EnumDomains(pipe_cli, ctx,
213                                          &connect_handle,
214                                          &resume_handle,
215                                          &sam,
216                                          0xffffffff,
217                                          &num_entries);
218         if (!NT_STATUS_IS_OK(status)) {
219                 werr = ntstatus_to_werror(status);
220                 goto done;
221         }
222
223         for (i=0; i<num_entries; i++) {
224
225                 domain_name = sam->entries[i].name.string;
226
227                 if (strequal(domain_name, builtin_domain_name())) {
228                         continue;
229                 }
230
231                 domain_found = true;
232                 break;
233         }
234
235         if (!domain_found) {
236                 werr = WERR_NO_SUCH_DOMAIN;
237                 goto done;
238         }
239
240         init_lsa_String(&lsa_domain_name, domain_name);
241
242         status = rpccli_samr_LookupDomain(pipe_cli, ctx,
243                                           &connect_handle,
244                                           &lsa_domain_name,
245                                           &domain_sid);
246         if (!NT_STATUS_IS_OK(status)) {
247                 werr = ntstatus_to_werror(status);
248                 goto done;
249         }
250
251         status = rpccli_samr_OpenDomain(pipe_cli, ctx,
252                                         &connect_handle,
253                                         SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
254                                         SAMR_DOMAIN_ACCESS_CREATE_USER |
255                                         SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
256                                         domain_sid,
257                                         &domain_handle);
258         if (!NT_STATUS_IS_OK(status)) {
259                 werr = ntstatus_to_werror(status);
260                 goto done;
261         }
262
263         init_lsa_String(&lsa_account_name, info1->usri1_name);
264
265         status = rpccli_samr_CreateUser2(pipe_cli, ctx,
266                                          &domain_handle,
267                                          &lsa_account_name,
268                                          ACB_NORMAL,
269                                          SEC_STD_WRITE_DAC |
270                                          SEC_STD_DELETE |
271                                          SAMR_USER_ACCESS_SET_PASSWORD |
272                                          SAMR_USER_ACCESS_SET_ATTRIBUTES |
273                                          SAMR_USER_ACCESS_GET_ATTRIBUTES,
274                                          &user_handle,
275                                          &access_granted,
276                                          &rid);
277         if (!NT_STATUS_IS_OK(status)) {
278                 werr = ntstatus_to_werror(status);
279                 goto done;
280         }
281
282         status = rpccli_samr_QueryUserInfo(pipe_cli, ctx,
283                                            &user_handle,
284                                            16,
285                                            &user_info);
286         if (!NT_STATUS_IS_OK(status)) {
287                 werr = ntstatus_to_werror(status);
288                 goto done;
289         }
290
291         if (!(user_info->info16.acct_flags & ACB_NORMAL)) {
292                 werr = WERR_INVALID_PARAM;
293                 goto done;
294         }
295
296         status = rpccli_samr_GetUserPwInfo(pipe_cli, ctx,
297                                            &user_handle,
298                                            &pw_info);
299         if (!NT_STATUS_IS_OK(status)) {
300                 werr = ntstatus_to_werror(status);
301                 goto done;
302         }
303
304         ZERO_STRUCTP(user_info);
305
306         convert_USER_INFO_1_to_samr_user_info25(info1,
307                                                 &cli->user_session_key,
308                                                 &info25);
309
310         if (info1->usri1_password) {
311                 user_info->info25 = info25;
312                 status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
313                                                   &user_handle,
314                                                   25,
315                                                   user_info);
316         } else {
317                 user_info->info21 = info25.info;
318                 status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
319                                                  &user_handle,
320                                                  21,
321                                                  user_info);
322
323         }
324         if (!NT_STATUS_IS_OK(status)) {
325                 werr = ntstatus_to_werror(status);
326                 goto failed;
327         }
328
329         werr = WERR_OK;
330         goto done;
331
332  failed:
333         status = rpccli_samr_DeleteUser(pipe_cli, ctx,
334                                         &user_handle);
335         if (!NT_STATUS_IS_OK(status)) {
336                 werr = ntstatus_to_werror(status);
337                 goto done;
338         }
339
340  done:
341         if (!cli) {
342                 return werr;
343         }
344
345         if (is_valid_policy_hnd(&user_handle)) {
346                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
347         }
348         if (is_valid_policy_hnd(&domain_handle)) {
349                 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
350         }
351         if (is_valid_policy_hnd(&connect_handle)) {
352                 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
353         }
354
355         cli_shutdown(cli);
356
357         return werr;
358 }
359
360 /****************************************************************
361 ****************************************************************/
362
363 WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
364                     struct NetUserDel *r)
365 {
366         struct cli_state *cli = NULL;
367         struct rpc_pipe_client *pipe_cli = NULL;
368         NTSTATUS status;
369         WERROR werr;
370         uint32_t resume_handle = 0;
371         uint32_t num_entries = 0;
372         POLICY_HND connect_handle, builtin_handle, domain_handle, user_handle;
373         struct samr_SamArray *sam = NULL;
374         const char *domain_name = NULL;
375         struct lsa_String lsa_domain_name, lsa_account_name;
376         struct samr_Ids user_rids, name_types;
377         struct dom_sid2 *domain_sid = NULL;
378         struct dom_sid2 user_sid;
379         bool domain_found = true;
380         int i;
381
382         ZERO_STRUCT(connect_handle);
383         ZERO_STRUCT(builtin_handle);
384         ZERO_STRUCT(domain_handle);
385         ZERO_STRUCT(user_handle);
386
387         status = cli_full_connection(&cli, NULL, r->in.server_name,
388                                      NULL, 0,
389                                      "IPC$", "IPC",
390                                      ctx->username,
391                                      ctx->workgroup,
392                                      ctx->password,
393                                      CLI_FULL_CONNECTION_USE_KERBEROS |
394                                      CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS,
395                                      Undefined, NULL);
396
397         if (!NT_STATUS_IS_OK(status)) {
398                 werr = ntstatus_to_werror(status);
399                 goto done;
400         }
401
402         pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &status);
403         if (!pipe_cli) {
404                 werr = ntstatus_to_werror(status);
405                 goto done;
406         }
407
408         status = rpccli_try_samr_connects(pipe_cli, ctx,
409                                           SAMR_ACCESS_ENUM_DOMAINS |
410                                           SAMR_ACCESS_OPEN_DOMAIN,
411                                           &connect_handle);
412         if (!NT_STATUS_IS_OK(status)) {
413                 werr = ntstatus_to_werror(status);
414                 goto done;
415         }
416
417         status = rpccli_samr_EnumDomains(pipe_cli, ctx,
418                                          &connect_handle,
419                                          &resume_handle,
420                                          &sam,
421                                          0xffffffff,
422                                          &num_entries);
423         if (!NT_STATUS_IS_OK(status)) {
424                 werr = ntstatus_to_werror(status);
425                 goto done;
426         }
427
428         for (i=0; i<num_entries; i++) {
429
430                 domain_name = sam->entries[i].name.string;
431
432                 if (strequal(domain_name, builtin_domain_name())) {
433                         continue;
434                 }
435
436                 domain_found = true;
437                 break;
438         }
439
440         if (!domain_found) {
441                 werr = WERR_NO_SUCH_DOMAIN;
442                 goto done;
443         }
444
445         init_lsa_String(&lsa_domain_name, domain_name);
446
447         status = rpccli_samr_LookupDomain(pipe_cli, ctx,
448                                           &connect_handle,
449                                           &lsa_domain_name,
450                                           &domain_sid);
451         if (!NT_STATUS_IS_OK(status)) {
452                 werr = ntstatus_to_werror(status);
453                 goto done;
454         }
455
456         status = rpccli_samr_OpenDomain(pipe_cli, ctx,
457                                         &connect_handle,
458                                         SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
459                                         domain_sid,
460                                         &domain_handle);
461         if (!NT_STATUS_IS_OK(status)) {
462                 werr = ntstatus_to_werror(status);
463                 goto done;
464         }
465
466         status = rpccli_samr_OpenDomain(pipe_cli, ctx,
467                                         &connect_handle,
468                                         SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
469                                         CONST_DISCARD(DOM_SID *, &global_sid_Builtin),
470                                         &builtin_handle);
471         if (!NT_STATUS_IS_OK(status)) {
472                 werr = ntstatus_to_werror(status);
473                 goto done;
474         }
475
476         init_lsa_String(&lsa_account_name, r->in.user_name);
477
478         status = rpccli_samr_LookupNames(pipe_cli, ctx,
479                                          &domain_handle,
480                                          1,
481                                          &lsa_account_name,
482                                          &user_rids,
483                                          &name_types);
484         if (!NT_STATUS_IS_OK(status)) {
485                 werr = ntstatus_to_werror(status);
486                 goto done;
487         }
488
489         status = rpccli_samr_OpenUser(pipe_cli, ctx,
490                                       &domain_handle,
491                                       STD_RIGHT_DELETE_ACCESS,
492                                       user_rids.ids[0],
493                                       &user_handle);
494         if (!NT_STATUS_IS_OK(status)) {
495                 werr = ntstatus_to_werror(status);
496                 goto done;
497         }
498
499         sid_compose(&user_sid, domain_sid, user_rids.ids[0]);
500
501         status = rpccli_samr_RemoveMemberFromForeignDomain(pipe_cli, ctx,
502                                                            &builtin_handle,
503                                                            &user_sid);
504         if (!NT_STATUS_IS_OK(status)) {
505                 werr = ntstatus_to_werror(status);
506                 goto done;
507         }
508
509         status = rpccli_samr_DeleteUser(pipe_cli, ctx,
510                                         &user_handle);
511         if (!NT_STATUS_IS_OK(status)) {
512                 werr = ntstatus_to_werror(status);
513                 goto done;
514         }
515
516         werr = WERR_OK;
517
518  done:
519         if (!cli) {
520                 return werr;
521         }
522
523         if (is_valid_policy_hnd(&user_handle)) {
524                 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
525         }
526         if (is_valid_policy_hnd(&builtin_handle)) {
527                 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
528         }
529         if (is_valid_policy_hnd(&domain_handle)) {
530                 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
531         }
532         if (is_valid_policy_hnd(&connect_handle)) {
533                 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
534         }
535
536         cli_shutdown(cli);
537
538         return werr;
539 }
540
541 /****************************************************************
542 ****************************************************************/
543
544 WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
545                     struct NetUserDel *r)
546 {
547         return WERR_NOT_SUPPORTED;
548 }
549
550 /****************************************************************
551 ****************************************************************/
552
553 static WERROR convert_samr_samarray_to_USER_INFO_buffer(TALLOC_CTX *mem_ctx,
554                                                         struct samr_SamArray *sam_array,
555                                                         uint32_t level,
556                                                         uint8_t **buffer)
557 {
558         struct USER_INFO_0 *info0 = NULL;
559         int i;
560
561         switch (level) {
562                 case 0:
563                         info0 = TALLOC_ZERO_ARRAY(mem_ctx, struct USER_INFO_0,
564                                                   sam_array->count);
565                         W_ERROR_HAVE_NO_MEMORY(info0);
566
567                         for (i=0; i<sam_array->count; i++) {
568                                 info0[i].usri0_name = talloc_strdup(mem_ctx,
569                                         sam_array->entries[i].name.string);
570                                 W_ERROR_HAVE_NO_MEMORY(info0[i].usri0_name);
571                         }
572
573                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, info0,
574                                 sizeof(struct USER_INFO_0) * sam_array->count);
575                         W_ERROR_HAVE_NO_MEMORY(*buffer);
576                         break;
577                 default:
578                         return WERR_NOT_SUPPORTED;
579         }
580
581         return WERR_OK;
582 }
583
584 /****************************************************************
585 ****************************************************************/
586
587 WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
588                      struct NetUserEnum *r)
589 {
590         struct cli_state *cli = NULL;
591         struct rpc_pipe_client *pipe_cli = NULL;
592         struct policy_handle connect_handle;
593         struct dom_sid2 *domain_sid = NULL;
594         struct policy_handle domain_handle;
595         struct samr_SamArray *sam = NULL;
596         uint32_t num_entries = 0;
597         int i;
598         const char *domain_name = NULL;
599         bool domain_found = true;
600         uint32_t dom_resume_handle = 0;
601         struct lsa_String lsa_domain_name;
602
603         NTSTATUS status;
604         WERROR werr;
605
606         ZERO_STRUCT(connect_handle);
607         ZERO_STRUCT(domain_handle);
608
609         switch (r->in.level) {
610                 case 0:
611                         break;
612                 case 1:
613                 case 2:
614                 case 3:
615                 case 10:
616                 case 11:
617                 case 20:
618                 case 23:
619                 default:
620                         return WERR_NOT_SUPPORTED;
621         }
622
623         status = cli_full_connection(&cli, NULL, r->in.server_name,
624                                      NULL, 0,
625                                      "IPC$", "IPC",
626                                      ctx->username,
627                                      ctx->workgroup,
628                                      ctx->password,
629                                      CLI_FULL_CONNECTION_USE_KERBEROS |
630                                      CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS,
631                                      Undefined, NULL);
632
633         if (!NT_STATUS_IS_OK(status)) {
634                 werr = ntstatus_to_werror(status);
635                 goto done;
636         }
637
638         pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &status);
639         if (!pipe_cli) {
640                 werr = ntstatus_to_werror(status);
641                 goto done;
642         }
643
644         status = rpccli_try_samr_connects(pipe_cli, ctx,
645                                           SAMR_ACCESS_OPEN_DOMAIN |
646                                           SAMR_ACCESS_ENUM_DOMAINS,
647                                           &connect_handle);
648         if (!NT_STATUS_IS_OK(status)) {
649                 werr = ntstatus_to_werror(status);
650                 goto done;
651         }
652
653         status = rpccli_samr_EnumDomains(pipe_cli, ctx,
654                                          &connect_handle,
655                                          &dom_resume_handle,
656                                          &sam,
657                                          0xffffffff,
658                                          &num_entries);
659         if (!NT_STATUS_IS_OK(status)) {
660                 werr = ntstatus_to_werror(status);
661                 goto done;
662         }
663
664         for (i=0; i<num_entries; i++) {
665
666                 domain_name = sam->entries[i].name.string;
667
668                 if (strequal(domain_name, builtin_domain_name())) {
669                         continue;
670                 }
671
672                 domain_found = true;
673                 break;
674         }
675
676         if (!domain_found) {
677                 werr = WERR_NO_SUCH_DOMAIN;
678                 goto done;
679         }
680
681         init_lsa_String(&lsa_domain_name, domain_name);
682
683         status = rpccli_samr_LookupDomain(pipe_cli, ctx,
684                                           &connect_handle,
685                                           &lsa_domain_name,
686                                           &domain_sid);
687         if (!NT_STATUS_IS_OK(status)) {
688                 werr = ntstatus_to_werror(status);
689                 goto done;
690         }
691
692         status = rpccli_samr_OpenDomain(pipe_cli,
693                                         ctx,
694                                         &connect_handle,
695                                         SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
696                                         SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
697                                         SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
698                                         domain_sid,
699                                         &domain_handle);
700         if (!NT_STATUS_IS_OK(status)) {
701                 werr = ntstatus_to_werror(status);
702                 goto done;
703         }
704
705         status = rpccli_samr_EnumDomainUsers(pipe_cli,
706                                              ctx,
707                                              &domain_handle,
708                                              r->in.resume_handle,
709                                              r->in.filter,
710                                              &sam,
711                                              r->in.prefmaxlen,
712                                              r->out.entries_read);
713         if (!NT_STATUS_IS_OK(status)) {
714                 werr = ntstatus_to_werror(status);
715                 goto done;
716         }
717
718         werr = convert_samr_samarray_to_USER_INFO_buffer(ctx, sam,
719                                                          r->in.level,
720                                                          r->out.buffer);
721
722  done:
723         if (is_valid_policy_hnd(&domain_handle)) {
724                 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
725         }
726         if (is_valid_policy_hnd(&connect_handle)) {
727                 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
728         }
729
730         if (cli) {
731                 cli_shutdown(cli);
732         }
733
734         return werr;
735 }
736
737 /****************************************************************
738 ****************************************************************/
739
740 WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
741                      struct NetUserEnum *r)
742 {
743         return WERR_NOT_SUPPORTED;
744 }
745