s3-libds: use already existing ../libds/common/flag_mapping.h header.
[ira/wip.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 #include "../librpc/gen_ndr/ndr_samr_c.h"
27 #include "rpc_client/init_samr.h"
28 #include "../libds/common/flags.h"
29 #include "rpc_client/init_lsa.h"
30 #include "../libcli/security/security.h"
31 #include "../libds/common/flag_mapping.h"
32
33 /****************************************************************
34 ****************************************************************/
35
36 static void convert_USER_INFO_X_to_samr_user_info21(struct USER_INFO_X *infoX,
37                                                     struct samr_UserInfo21 *info21)
38 {
39         uint32_t fields_present = 0;
40         struct samr_LogonHours zero_logon_hours;
41         struct lsa_BinaryString zero_parameters;
42         NTTIME password_age;
43
44         ZERO_STRUCTP(info21);
45         ZERO_STRUCT(zero_logon_hours);
46         ZERO_STRUCT(zero_parameters);
47
48         if (infoX->usriX_flags) {
49                 fields_present |= SAMR_FIELD_ACCT_FLAGS;
50         }
51         if (infoX->usriX_name) {
52                 fields_present |= SAMR_FIELD_ACCOUNT_NAME;
53         }
54         if (infoX->usriX_password) {
55                 fields_present |= SAMR_FIELD_NT_PASSWORD_PRESENT;
56         }
57         if (infoX->usriX_flags) {
58                 fields_present |= SAMR_FIELD_ACCT_FLAGS;
59         }
60         if (infoX->usriX_home_dir) {
61                 fields_present |= SAMR_FIELD_HOME_DIRECTORY;
62         }
63         if (infoX->usriX_script_path) {
64                 fields_present |= SAMR_FIELD_LOGON_SCRIPT;
65         }
66         if (infoX->usriX_comment) {
67                 fields_present |= SAMR_FIELD_DESCRIPTION;
68         }
69         if (infoX->usriX_password_age) {
70                 fields_present |= SAMR_FIELD_FORCE_PWD_CHANGE;
71         }
72         if (infoX->usriX_full_name) {
73                 fields_present |= SAMR_FIELD_FULL_NAME;
74         }
75         if (infoX->usriX_usr_comment) {
76                 fields_present |= SAMR_FIELD_COMMENT;
77         }
78         if (infoX->usriX_profile) {
79                 fields_present |= SAMR_FIELD_PROFILE_PATH;
80         }
81         if (infoX->usriX_home_dir_drive) {
82                 fields_present |= SAMR_FIELD_HOME_DRIVE;
83         }
84         if (infoX->usriX_primary_group_id) {
85                 fields_present |= SAMR_FIELD_PRIMARY_GID;
86         }
87         if (infoX->usriX_country_code) {
88                 fields_present |= SAMR_FIELD_COUNTRY_CODE;
89         }
90         if (infoX->usriX_workstations) {
91                 fields_present |= SAMR_FIELD_WORKSTATIONS;
92         }
93
94         unix_to_nt_time_abs(&password_age, infoX->usriX_password_age);
95
96         /* TODO: infoX->usriX_priv */
97
98         info21->last_logon              = 0;
99         info21->last_logoff             = 0;
100         info21->last_password_change    = 0;
101         info21->acct_expiry             = 0;
102         info21->allow_password_change   = 0;
103         info21->force_password_change   = 0;
104         info21->account_name.string     = infoX->usriX_name;
105         info21->full_name.string        = infoX->usriX_full_name;
106         info21->home_directory.string   = infoX->usriX_home_dir;
107         info21->home_drive.string       = infoX->usriX_home_dir_drive;
108         info21->logon_script.string     = infoX->usriX_script_path;
109         info21->profile_path.string     = infoX->usriX_profile;
110         info21->description.string      = infoX->usriX_comment;
111         info21->workstations.string     = infoX->usriX_workstations;
112         info21->comment.string          = infoX->usriX_usr_comment;
113         info21->parameters              = zero_parameters;
114         info21->lm_owf_password         = zero_parameters;
115         info21->nt_owf_password         = zero_parameters;
116         info21->private_data.string     = NULL;
117         info21->buf_count               = 0;
118         info21->buffer                  = NULL;
119         info21->rid                     = infoX->usriX_user_id;
120         info21->primary_gid             = infoX->usriX_primary_group_id;
121         info21->acct_flags              = infoX->usriX_flags;
122         info21->fields_present          = fields_present;
123         info21->logon_hours             = zero_logon_hours;
124         info21->bad_password_count      = infoX->usriX_bad_pw_count;
125         info21->logon_count             = infoX->usriX_num_logons;
126         info21->country_code            = infoX->usriX_country_code;
127         info21->code_page               = infoX->usriX_code_page;
128         info21->lm_password_set         = 0;
129         info21->nt_password_set         = 0;
130         info21->password_expired        = infoX->usriX_password_expired;
131         info21->private_data_sensitive  = 0;
132 }
133
134 /****************************************************************
135 ****************************************************************/
136
137 static NTSTATUS construct_USER_INFO_X(uint32_t level,
138                                       uint8_t *buffer,
139                                       struct USER_INFO_X *uX)
140 {
141         struct USER_INFO_0 *u0 = NULL;
142         struct USER_INFO_1 *u1 = NULL;
143         struct USER_INFO_2 *u2 = NULL;
144         struct USER_INFO_3 *u3 = NULL;
145         struct USER_INFO_1003 *u1003 = NULL;
146         struct USER_INFO_1006 *u1006 = NULL;
147         struct USER_INFO_1007 *u1007 = NULL;
148         struct USER_INFO_1009 *u1009 = NULL;
149         struct USER_INFO_1011 *u1011 = NULL;
150         struct USER_INFO_1012 *u1012 = NULL;
151         struct USER_INFO_1014 *u1014 = NULL;
152         struct USER_INFO_1024 *u1024 = NULL;
153         struct USER_INFO_1051 *u1051 = NULL;
154         struct USER_INFO_1052 *u1052 = NULL;
155         struct USER_INFO_1053 *u1053 = NULL;
156
157         if (!buffer || !uX) {
158                 return NT_STATUS_INVALID_PARAMETER;
159         }
160
161         ZERO_STRUCTP(uX);
162
163         switch (level) {
164                 case 0:
165                         u0 = (struct USER_INFO_0 *)buffer;
166                         uX->usriX_name          = u0->usri0_name;
167                         break;
168                 case 1:
169                         u1 = (struct USER_INFO_1 *)buffer;
170                         uX->usriX_name          = u1->usri1_name;
171                         uX->usriX_password      = u1->usri1_password;
172                         uX->usriX_password_age  = u1->usri1_password_age;
173                         uX->usriX_priv          = u1->usri1_priv;
174                         uX->usriX_home_dir      = u1->usri1_home_dir;
175                         uX->usriX_comment       = u1->usri1_comment;
176                         uX->usriX_flags         = u1->usri1_flags;
177                         uX->usriX_script_path   = u1->usri1_script_path;
178                         break;
179                 case 2:
180                         u2 = (struct USER_INFO_2 *)buffer;
181                         uX->usriX_name          = u2->usri2_name;
182                         uX->usriX_password      = u2->usri2_password;
183                         uX->usriX_password_age  = u2->usri2_password_age;
184                         uX->usriX_priv          = u2->usri2_priv;
185                         uX->usriX_home_dir      = u2->usri2_home_dir;
186                         uX->usriX_comment       = u2->usri2_comment;
187                         uX->usriX_flags         = u2->usri2_flags;
188                         uX->usriX_script_path   = u2->usri2_script_path;
189                         uX->usriX_auth_flags    = u2->usri2_auth_flags;
190                         uX->usriX_full_name     = u2->usri2_full_name;
191                         uX->usriX_usr_comment   = u2->usri2_usr_comment;
192                         uX->usriX_parms         = u2->usri2_parms;
193                         uX->usriX_workstations  = u2->usri2_workstations;
194                         uX->usriX_last_logon    = u2->usri2_last_logon;
195                         uX->usriX_last_logoff   = u2->usri2_last_logoff;
196                         uX->usriX_acct_expires  = u2->usri2_acct_expires;
197                         uX->usriX_max_storage   = u2->usri2_max_storage;
198                         uX->usriX_units_per_week= u2->usri2_units_per_week;
199                         uX->usriX_logon_hours   = u2->usri2_logon_hours;
200                         uX->usriX_bad_pw_count  = u2->usri2_bad_pw_count;
201                         uX->usriX_num_logons    = u2->usri2_num_logons;
202                         uX->usriX_logon_server  = u2->usri2_logon_server;
203                         uX->usriX_country_code  = u2->usri2_country_code;
204                         uX->usriX_code_page     = u2->usri2_code_page;
205                         break;
206                 case 3:
207                         u3 = (struct USER_INFO_3 *)buffer;
208                         uX->usriX_name          = u3->usri3_name;
209                         uX->usriX_password_age  = u3->usri3_password_age;
210                         uX->usriX_priv          = u3->usri3_priv;
211                         uX->usriX_home_dir      = u3->usri3_home_dir;
212                         uX->usriX_comment       = u3->usri3_comment;
213                         uX->usriX_flags         = u3->usri3_flags;
214                         uX->usriX_script_path   = u3->usri3_script_path;
215                         uX->usriX_auth_flags    = u3->usri3_auth_flags;
216                         uX->usriX_full_name     = u3->usri3_full_name;
217                         uX->usriX_usr_comment   = u3->usri3_usr_comment;
218                         uX->usriX_parms         = u3->usri3_parms;
219                         uX->usriX_workstations  = u3->usri3_workstations;
220                         uX->usriX_last_logon    = u3->usri3_last_logon;
221                         uX->usriX_last_logoff   = u3->usri3_last_logoff;
222                         uX->usriX_acct_expires  = u3->usri3_acct_expires;
223                         uX->usriX_max_storage   = u3->usri3_max_storage;
224                         uX->usriX_units_per_week= u3->usri3_units_per_week;
225                         uX->usriX_logon_hours   = u3->usri3_logon_hours;
226                         uX->usriX_bad_pw_count  = u3->usri3_bad_pw_count;
227                         uX->usriX_num_logons    = u3->usri3_num_logons;
228                         uX->usriX_logon_server  = u3->usri3_logon_server;
229                         uX->usriX_country_code  = u3->usri3_country_code;
230                         uX->usriX_code_page     = u3->usri3_code_page;
231                         uX->usriX_user_id       = u3->usri3_user_id;
232                         uX->usriX_primary_group_id = u3->usri3_primary_group_id;
233                         uX->usriX_profile       = u3->usri3_profile;
234                         uX->usriX_home_dir_drive = u3->usri3_home_dir_drive;
235                         uX->usriX_password_expired = u3->usri3_password_expired;
236                         break;
237                 case 1003:
238                         u1003 = (struct USER_INFO_1003 *)buffer;
239                         uX->usriX_password      = u1003->usri1003_password;
240                         break;
241                 case 1006:
242                         u1006 = (struct USER_INFO_1006 *)buffer;
243                         uX->usriX_home_dir      = u1006->usri1006_home_dir;
244                         break;
245                 case 1007:
246                         u1007 = (struct USER_INFO_1007 *)buffer;
247                         uX->usriX_comment       = u1007->usri1007_comment;
248                         break;
249                 case 1009:
250                         u1009 = (struct USER_INFO_1009 *)buffer;
251                         uX->usriX_script_path   = u1009->usri1009_script_path;
252                         break;
253                 case 1011:
254                         u1011 = (struct USER_INFO_1011 *)buffer;
255                         uX->usriX_full_name     = u1011->usri1011_full_name;
256                         break;
257                 case 1012:
258                         u1012 = (struct USER_INFO_1012 *)buffer;
259                         uX->usriX_usr_comment   = u1012->usri1012_usr_comment;
260                         break;
261                 case 1014:
262                         u1014 = (struct USER_INFO_1014 *)buffer;
263                         uX->usriX_workstations  = u1014->usri1014_workstations;
264                         break;
265                 case 1024:
266                         u1024 = (struct USER_INFO_1024 *)buffer;
267                         uX->usriX_country_code  = u1024->usri1024_country_code;
268                         break;
269                 case 1051:
270                         u1051 = (struct USER_INFO_1051 *)buffer;
271                         uX->usriX_primary_group_id = u1051->usri1051_primary_group_id;
272                         break;
273                 case 1052:
274                         u1052 = (struct USER_INFO_1052 *)buffer;
275                         uX->usriX_profile       = u1052->usri1052_profile;
276                         break;
277                 case 1053:
278                         u1053 = (struct USER_INFO_1053 *)buffer;
279                         uX->usriX_home_dir_drive = u1053->usri1053_home_dir_drive;
280                         break;
281                 case 4:
282                 default:
283                         return NT_STATUS_INVALID_INFO_CLASS;
284         }
285
286         return NT_STATUS_OK;
287 }
288
289 /****************************************************************
290 ****************************************************************/
291
292 static NTSTATUS set_user_info_USER_INFO_X(TALLOC_CTX *ctx,
293                                           struct rpc_pipe_client *pipe_cli,
294                                           DATA_BLOB *session_key,
295                                           struct policy_handle *user_handle,
296                                           struct USER_INFO_X *uX)
297 {
298         union samr_UserInfo user_info;
299         struct samr_UserInfo21 info21;
300         NTSTATUS status, result;
301         struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
302
303         if (!uX) {
304                 return NT_STATUS_INVALID_PARAMETER;
305         }
306
307         convert_USER_INFO_X_to_samr_user_info21(uX, &info21);
308
309         ZERO_STRUCT(user_info);
310
311         if (uX->usriX_password) {
312
313                 user_info.info25.info = info21;
314
315                 init_samr_CryptPasswordEx(uX->usriX_password,
316                                           session_key,
317                                           &user_info.info25.password);
318
319                 status = dcerpc_samr_SetUserInfo2(b, talloc_tos(),
320                                                   user_handle,
321                                                   25,
322                                                   &user_info,
323                                                   &result);
324                 if (NT_STATUS_EQUAL(status, NT_STATUS(DCERPC_FAULT_INVALID_TAG))) {
325
326                         user_info.info23.info = info21;
327
328                         init_samr_CryptPassword(uX->usriX_password,
329                                                 session_key,
330                                                 &user_info.info23.password);
331
332                         status = dcerpc_samr_SetUserInfo2(b, talloc_tos(),
333                                                           user_handle,
334                                                           23,
335                                                           &user_info,
336                                                           &result);
337                         if (!NT_STATUS_IS_OK(status)) {
338                                 return status;
339                         }
340                 }
341
342                 if (!NT_STATUS_IS_OK(status)) {
343                         return status;
344                 }
345         } else {
346
347                 user_info.info21 = info21;
348
349                 status = dcerpc_samr_SetUserInfo(b, talloc_tos(),
350                                                  user_handle,
351                                                  21,
352                                                  &user_info,
353                                                  &result);
354                 if (!NT_STATUS_IS_OK(status)) {
355                         return status;
356                 }
357         }
358
359         return result;
360 }
361
362 /****************************************************************
363 ****************************************************************/
364
365 WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
366                     struct NetUserAdd *r)
367 {
368         struct rpc_pipe_client *pipe_cli = NULL;
369         NTSTATUS status, result;
370         WERROR werr;
371         struct policy_handle connect_handle, domain_handle, user_handle;
372         struct lsa_String lsa_account_name;
373         struct dom_sid2 *domain_sid = NULL;
374         union samr_UserInfo *user_info = NULL;
375         struct samr_PwInfo pw_info;
376         uint32_t access_granted = 0;
377         uint32_t rid = 0;
378         struct USER_INFO_X uX;
379         struct dcerpc_binding_handle *b = NULL;
380
381         ZERO_STRUCT(connect_handle);
382         ZERO_STRUCT(domain_handle);
383         ZERO_STRUCT(user_handle);
384
385         if (!r->in.buffer) {
386                 return WERR_INVALID_PARAM;
387         }
388
389         switch (r->in.level) {
390                 case 1:
391                         break;
392                 case 2:
393                 case 3:
394                 case 4:
395                 default:
396                         werr = WERR_NOT_SUPPORTED;
397                         goto done;
398         }
399
400         werr = libnetapi_open_pipe(ctx, r->in.server_name,
401                                    &ndr_table_samr.syntax_id,
402                                    &pipe_cli);
403         if (!W_ERROR_IS_OK(werr)) {
404                 goto done;
405         }
406
407         b = pipe_cli->binding_handle;
408
409         status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
410         if (!NT_STATUS_IS_OK(status)) {
411                 werr = ntstatus_to_werror(status);
412                 goto done;
413         }
414
415         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
416                                           SAMR_ACCESS_ENUM_DOMAINS |
417                                           SAMR_ACCESS_LOOKUP_DOMAIN,
418                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
419                                           SAMR_DOMAIN_ACCESS_CREATE_USER |
420                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
421                                           &connect_handle,
422                                           &domain_handle,
423                                           &domain_sid);
424         if (!W_ERROR_IS_OK(werr)) {
425                 goto done;
426         }
427
428         init_lsa_String(&lsa_account_name, uX.usriX_name);
429
430         status = dcerpc_samr_CreateUser2(b, talloc_tos(),
431                                          &domain_handle,
432                                          &lsa_account_name,
433                                          ACB_NORMAL,
434                                          SEC_STD_WRITE_DAC |
435                                          SEC_STD_DELETE |
436                                          SAMR_USER_ACCESS_SET_PASSWORD |
437                                          SAMR_USER_ACCESS_SET_ATTRIBUTES |
438                                          SAMR_USER_ACCESS_GET_ATTRIBUTES,
439                                          &user_handle,
440                                          &access_granted,
441                                          &rid,
442                                          &result);
443         if (!NT_STATUS_IS_OK(status)) {
444                 werr = ntstatus_to_werror(status);
445                 goto done;
446         }
447         if (!NT_STATUS_IS_OK(result)) {
448                 werr = ntstatus_to_werror(result);
449                 goto done;
450         }
451
452         status = dcerpc_samr_QueryUserInfo(b, talloc_tos(),
453                                            &user_handle,
454                                            16,
455                                            &user_info,
456                                            &result);
457         if (!NT_STATUS_IS_OK(status)) {
458                 werr = ntstatus_to_werror(status);
459                 goto done;
460         }
461         if (!NT_STATUS_IS_OK(result)) {
462                 werr = ntstatus_to_werror(result);
463                 goto done;
464         }
465
466         if (!(user_info->info16.acct_flags & ACB_NORMAL)) {
467                 werr = WERR_INVALID_PARAM;
468                 goto done;
469         }
470
471         status = dcerpc_samr_GetUserPwInfo(b, talloc_tos(),
472                                            &user_handle,
473                                            &pw_info,
474                                            &result);
475         if (!NT_STATUS_IS_OK(status)) {
476                 werr = ntstatus_to_werror(status);
477                 goto done;
478         }
479         if (!NT_STATUS_IS_OK(result)) {
480                 werr = ntstatus_to_werror(result);
481                 goto done;
482         }
483
484         uX.usriX_flags |= ACB_NORMAL;
485
486         status = set_user_info_USER_INFO_X(ctx, pipe_cli,
487                                            &pipe_cli->auth->user_session_key,
488                                            &user_handle,
489                                            &uX);
490         if (!NT_STATUS_IS_OK(status)) {
491                 werr = ntstatus_to_werror(status);
492                 goto failed;
493         }
494
495         werr = WERR_OK;
496         goto done;
497
498  failed:
499         dcerpc_samr_DeleteUser(b, talloc_tos(),
500                                &user_handle,
501                                &result);
502
503  done:
504         if (is_valid_policy_hnd(&user_handle) && b) {
505                 dcerpc_samr_Close(b, talloc_tos(), &user_handle, &result);
506         }
507
508         if (ctx->disable_policy_handle_cache) {
509                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
510                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
511         }
512
513         return werr;
514 }
515
516 /****************************************************************
517 ****************************************************************/
518
519 WERROR NetUserAdd_l(struct libnetapi_ctx *ctx,
520                     struct NetUserAdd *r)
521 {
522         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserAdd);
523 }
524
525 /****************************************************************
526 ****************************************************************/
527
528 WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
529                     struct NetUserDel *r)
530 {
531         struct rpc_pipe_client *pipe_cli = NULL;
532         NTSTATUS status, result;
533         WERROR werr;
534         struct policy_handle connect_handle, builtin_handle, domain_handle, user_handle;
535         struct lsa_String lsa_account_name;
536         struct samr_Ids user_rids, name_types;
537         struct dom_sid2 *domain_sid = NULL;
538         struct dom_sid2 user_sid;
539         struct dcerpc_binding_handle *b = NULL;
540
541         ZERO_STRUCT(connect_handle);
542         ZERO_STRUCT(builtin_handle);
543         ZERO_STRUCT(domain_handle);
544         ZERO_STRUCT(user_handle);
545
546         werr = libnetapi_open_pipe(ctx, r->in.server_name,
547                                    &ndr_table_samr.syntax_id,
548                                    &pipe_cli);
549
550         if (!W_ERROR_IS_OK(werr)) {
551                 goto done;
552         }
553
554         b = pipe_cli->binding_handle;
555
556         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
557                                           SAMR_ACCESS_ENUM_DOMAINS |
558                                           SAMR_ACCESS_LOOKUP_DOMAIN,
559                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
560                                           &connect_handle,
561                                           &domain_handle,
562                                           &domain_sid);
563         if (!W_ERROR_IS_OK(werr)) {
564                 goto done;
565         }
566
567         status = dcerpc_samr_OpenDomain(b, talloc_tos(),
568                                         &connect_handle,
569                                         SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
570                                         CONST_DISCARD(struct dom_sid *, &global_sid_Builtin),
571                                         &builtin_handle,
572                                         &result);
573         if (!NT_STATUS_IS_OK(status)) {
574                 werr = ntstatus_to_werror(status);
575                 goto done;
576         }
577         if (!NT_STATUS_IS_OK(result)) {
578                 werr = ntstatus_to_werror(result);
579                 goto done;
580         }
581
582         init_lsa_String(&lsa_account_name, r->in.user_name);
583
584         status = dcerpc_samr_LookupNames(b, talloc_tos(),
585                                          &domain_handle,
586                                          1,
587                                          &lsa_account_name,
588                                          &user_rids,
589                                          &name_types,
590                                          &result);
591         if (!NT_STATUS_IS_OK(status)) {
592                 werr = ntstatus_to_werror(status);
593                 goto done;
594         }
595         if (!NT_STATUS_IS_OK(result)) {
596                 werr = ntstatus_to_werror(result);
597                 goto done;
598         }
599
600         status = dcerpc_samr_OpenUser(b, talloc_tos(),
601                                       &domain_handle,
602                                       SEC_STD_DELETE,
603                                       user_rids.ids[0],
604                                       &user_handle,
605                                       &result);
606         if (!NT_STATUS_IS_OK(status)) {
607                 werr = ntstatus_to_werror(status);
608                 goto done;
609         }
610         if (!NT_STATUS_IS_OK(result)) {
611                 werr = ntstatus_to_werror(result);
612                 goto done;
613         }
614
615         sid_compose(&user_sid, domain_sid, user_rids.ids[0]);
616
617         status = dcerpc_samr_RemoveMemberFromForeignDomain(b, talloc_tos(),
618                                                            &builtin_handle,
619                                                            &user_sid,
620                                                            &result);
621         if (!NT_STATUS_IS_OK(status)) {
622                 werr = ntstatus_to_werror(status);
623                 goto done;
624         }
625         if (!NT_STATUS_IS_OK(result)) {
626                 werr = ntstatus_to_werror(result);
627                 goto done;
628         }
629
630         status = dcerpc_samr_DeleteUser(b, talloc_tos(),
631                                         &user_handle,
632                                         &result);
633         if (!NT_STATUS_IS_OK(status)) {
634                 werr = ntstatus_to_werror(status);
635                 goto done;
636         }
637         if (!NT_STATUS_IS_OK(result)) {
638                 werr = ntstatus_to_werror(result);
639                 goto done;
640         }
641
642         werr = WERR_OK;
643
644  done:
645         if (is_valid_policy_hnd(&user_handle)) {
646                 dcerpc_samr_Close(b, talloc_tos(), &user_handle, &result);
647         }
648
649         if (ctx->disable_policy_handle_cache) {
650                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
651                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
652                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
653         }
654
655         return werr;
656 }
657
658 /****************************************************************
659 ****************************************************************/
660
661 WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
662                     struct NetUserDel *r)
663 {
664         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserDel);
665 }
666
667 /****************************************************************
668 ****************************************************************/
669
670 static NTSTATUS libnetapi_samr_lookup_user(TALLOC_CTX *mem_ctx,
671                                            struct rpc_pipe_client *pipe_cli,
672                                            struct policy_handle *domain_handle,
673                                            struct policy_handle *builtin_handle,
674                                            const char *user_name,
675                                            const struct dom_sid *domain_sid,
676                                            uint32_t rid,
677                                            uint32_t level,
678                                            struct samr_UserInfo21 **info21,
679                                            struct sec_desc_buf **sec_desc,
680                                            uint32_t *auth_flag_p)
681 {
682         NTSTATUS status, result;
683
684         struct policy_handle user_handle;
685         union samr_UserInfo *user_info = NULL;
686         struct samr_RidWithAttributeArray *rid_array = NULL;
687         uint32_t access_mask = SEC_STD_READ_CONTROL |
688                                SAMR_USER_ACCESS_GET_ATTRIBUTES |
689                                SAMR_USER_ACCESS_GET_NAME_ETC;
690         struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
691
692         ZERO_STRUCT(user_handle);
693
694         switch (level) {
695                 case 0:
696                         break;
697                 case 1:
698                         access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
699                                        SAMR_USER_ACCESS_GET_GROUPS;
700                         break;
701                 case 2:
702                 case 3:
703                 case 4:
704                 case 11:
705                         access_mask |= SAMR_USER_ACCESS_GET_LOGONINFO |
706                                        SAMR_USER_ACCESS_GET_GROUPS |
707                                        SAMR_USER_ACCESS_GET_LOCALE;
708                         break;
709                 case 10:
710                 case 20:
711                 case 23:
712                         break;
713                 default:
714                         return NT_STATUS_INVALID_LEVEL;
715         }
716
717         if (level == 0) {
718                 return NT_STATUS_OK;
719         }
720
721         status = dcerpc_samr_OpenUser(b, mem_ctx,
722                                       domain_handle,
723                                       access_mask,
724                                       rid,
725                                       &user_handle,
726                                       &result);
727         if (!NT_STATUS_IS_OK(status)) {
728                 goto done;
729         }
730         if (!NT_STATUS_IS_OK(result)) {
731                 status = result;
732                 goto done;
733         }
734
735         status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
736                                            &user_handle,
737                                            21,
738                                            &user_info,
739                                            &result);
740         if (!NT_STATUS_IS_OK(status)) {
741                 goto done;
742         }
743         if (!NT_STATUS_IS_OK(result)) {
744                 status = result;
745                 goto done;
746         }
747
748         status = dcerpc_samr_QuerySecurity(b, mem_ctx,
749                                            &user_handle,
750                                            SECINFO_DACL,
751                                            sec_desc,
752                                            &result);
753         if (!NT_STATUS_IS_OK(status)) {
754                 goto done;
755         }
756         if (!NT_STATUS_IS_OK(result)) {
757                 status = result;
758                 goto done;
759         }
760
761         if (access_mask & SAMR_USER_ACCESS_GET_GROUPS) {
762
763                 struct lsa_SidArray sid_array;
764                 struct samr_Ids alias_rids;
765                 int i;
766                 uint32_t auth_flag = 0;
767                 struct dom_sid sid;
768
769                 status = dcerpc_samr_GetGroupsForUser(b, mem_ctx,
770                                                       &user_handle,
771                                                       &rid_array,
772                                                       &result);
773                 if (!NT_STATUS_IS_OK(status)) {
774                         goto done;
775                 }
776                 if (!NT_STATUS_IS_OK(result)) {
777                         status = result;
778                         goto done;
779                 }
780
781                 sid_array.num_sids = rid_array->count + 1;
782                 sid_array.sids = talloc_array(mem_ctx, struct lsa_SidPtr,
783                                               sid_array.num_sids);
784                 NT_STATUS_HAVE_NO_MEMORY(sid_array.sids);
785
786                 for (i=0; i<rid_array->count; i++) {
787                         sid_compose(&sid, domain_sid, rid_array->rids[i].rid);
788                         sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sid);
789                         NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
790                 }
791
792                 sid_compose(&sid, domain_sid, rid);
793                 sid_array.sids[i].sid = dom_sid_dup(mem_ctx, &sid);
794                 NT_STATUS_HAVE_NO_MEMORY(sid_array.sids[i].sid);
795
796                 status = dcerpc_samr_GetAliasMembership(b, mem_ctx,
797                                                         builtin_handle,
798                                                         &sid_array,
799                                                         &alias_rids,
800                                                         &result);
801                 if (!NT_STATUS_IS_OK(status)) {
802                         goto done;
803                 }
804                 if (!NT_STATUS_IS_OK(result)) {
805                         status = result;
806                         goto done;
807                 }
808
809                 for (i=0; i<alias_rids.count; i++) {
810                         switch (alias_rids.ids[i]) {
811                                 case 550: /* Print Operators */
812                                         auth_flag |= AF_OP_PRINT;
813                                         break;
814                                 case 549: /* Server Operators */
815                                         auth_flag |= AF_OP_SERVER;
816                                         break;
817                                 case 548: /* Account Operators */
818                                         auth_flag |= AF_OP_ACCOUNTS;
819                                         break;
820                                 default:
821                                         break;
822                         }
823                 }
824
825                 if (auth_flag_p) {
826                         *auth_flag_p = auth_flag;
827                 }
828         }
829
830         *info21 = &user_info->info21;
831
832  done:
833         if (is_valid_policy_hnd(&user_handle)) {
834                 dcerpc_samr_Close(b, mem_ctx, &user_handle, &result);
835         }
836
837         return status;
838 }
839
840 /****************************************************************
841 ****************************************************************/
842
843 static uint32_t samr_rid_to_priv_level(uint32_t rid)
844 {
845         switch (rid) {
846                 case DOMAIN_RID_ADMINISTRATOR:
847                         return USER_PRIV_ADMIN;
848                 case DOMAIN_RID_GUEST:
849                         return USER_PRIV_GUEST;
850                 default:
851                         return USER_PRIV_USER;
852         }
853 }
854
855 /****************************************************************
856 ****************************************************************/
857
858 static uint32_t samr_acb_flags_to_netapi_flags(uint32_t acb)
859 {
860         uint32_t fl = UF_SCRIPT; /* god knows why */
861
862         fl |= ds_acb2uf(acb);
863
864         return fl;
865 }
866
867 /****************************************************************
868 ****************************************************************/
869
870 static NTSTATUS info21_to_USER_INFO_1(TALLOC_CTX *mem_ctx,
871                                       const struct samr_UserInfo21 *i21,
872                                       struct USER_INFO_1 *i)
873 {
874         ZERO_STRUCTP(i);
875         i->usri1_name           = talloc_strdup(mem_ctx, i21->account_name.string);
876         NT_STATUS_HAVE_NO_MEMORY(i->usri1_name);
877         i->usri1_password       = NULL;
878         i->usri1_password_age   = time(NULL) - nt_time_to_unix(i21->last_password_change);
879         i->usri1_priv           = samr_rid_to_priv_level(i21->rid);
880         i->usri1_home_dir       = talloc_strdup(mem_ctx, i21->home_directory.string);
881         i->usri1_comment        = talloc_strdup(mem_ctx, i21->description.string);
882         i->usri1_flags          = samr_acb_flags_to_netapi_flags(i21->acct_flags);
883         i->usri1_script_path    = talloc_strdup(mem_ctx, i21->logon_script.string);
884
885         return NT_STATUS_OK;
886 }
887
888 /****************************************************************
889 ****************************************************************/
890
891 static NTSTATUS info21_to_USER_INFO_2(TALLOC_CTX *mem_ctx,
892                                       const struct samr_UserInfo21 *i21,
893                                       uint32_t auth_flag,
894                                       struct USER_INFO_2 *i)
895 {
896         ZERO_STRUCTP(i);
897
898         i->usri2_name           = talloc_strdup(mem_ctx, i21->account_name.string);
899         NT_STATUS_HAVE_NO_MEMORY(i->usri2_name);
900         i->usri2_password       = NULL;
901         i->usri2_password_age   = time(NULL) - nt_time_to_unix(i21->last_password_change);
902         i->usri2_priv           = samr_rid_to_priv_level(i21->rid);
903         i->usri2_home_dir       = talloc_strdup(mem_ctx, i21->home_directory.string);
904         i->usri2_comment        = talloc_strdup(mem_ctx, i21->description.string);
905         i->usri2_flags          = samr_acb_flags_to_netapi_flags(i21->acct_flags);
906         i->usri2_script_path    = talloc_strdup(mem_ctx, i21->logon_script.string);
907         i->usri2_auth_flags     = auth_flag;
908         i->usri2_full_name      = talloc_strdup(mem_ctx, i21->full_name.string);
909         i->usri2_usr_comment    = talloc_strdup(mem_ctx, i21->comment.string);
910         i->usri2_parms          = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
911         i->usri2_workstations   = talloc_strdup(mem_ctx, i21->workstations.string);
912         i->usri2_last_logon     = nt_time_to_unix(i21->last_logon);
913         i->usri2_last_logoff    = nt_time_to_unix(i21->last_logoff);
914         i->usri2_acct_expires   = nt_time_to_unix(i21->acct_expiry);
915         i->usri2_max_storage    = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
916         i->usri2_units_per_week = i21->logon_hours.units_per_week;
917         i->usri2_logon_hours    = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
918         i->usri2_bad_pw_count   = i21->bad_password_count;
919         i->usri2_num_logons     = i21->logon_count;
920         i->usri2_logon_server   = talloc_strdup(mem_ctx, "\\\\*");
921         i->usri2_country_code   = i21->country_code;
922         i->usri2_code_page      = i21->code_page;
923
924         return NT_STATUS_OK;
925 }
926
927 /****************************************************************
928 ****************************************************************/
929
930 static NTSTATUS info21_to_USER_INFO_3(TALLOC_CTX *mem_ctx,
931                                       const struct samr_UserInfo21 *i21,
932                                       uint32_t auth_flag,
933                                       struct USER_INFO_3 *i)
934 {
935         ZERO_STRUCTP(i);
936
937         i->usri3_name           = talloc_strdup(mem_ctx, i21->account_name.string);
938         NT_STATUS_HAVE_NO_MEMORY(i->usri3_name);
939         i->usri3_password_age   = time(NULL) - nt_time_to_unix(i21->last_password_change);
940         i->usri3_priv           = samr_rid_to_priv_level(i21->rid);
941         i->usri3_home_dir       = talloc_strdup(mem_ctx, i21->home_directory.string);
942         i->usri3_comment        = talloc_strdup(mem_ctx, i21->description.string);
943         i->usri3_flags          = samr_acb_flags_to_netapi_flags(i21->acct_flags);
944         i->usri3_script_path    = talloc_strdup(mem_ctx, i21->logon_script.string);
945         i->usri3_auth_flags     = auth_flag;
946         i->usri3_full_name      = talloc_strdup(mem_ctx, i21->full_name.string);
947         i->usri3_usr_comment    = talloc_strdup(mem_ctx, i21->comment.string);
948         i->usri3_parms          = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
949         i->usri3_workstations   = talloc_strdup(mem_ctx, i21->workstations.string);
950         i->usri3_last_logon     = nt_time_to_unix(i21->last_logon);
951         i->usri3_last_logoff    = nt_time_to_unix(i21->last_logoff);
952         i->usri3_acct_expires   = nt_time_to_unix(i21->acct_expiry);
953         i->usri3_max_storage    = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
954         i->usri3_units_per_week = i21->logon_hours.units_per_week;
955         i->usri3_logon_hours    = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
956         i->usri3_bad_pw_count   = i21->bad_password_count;
957         i->usri3_num_logons     = i21->logon_count;
958         i->usri3_logon_server   = talloc_strdup(mem_ctx, "\\\\*");
959         i->usri3_country_code   = i21->country_code;
960         i->usri3_code_page      = i21->code_page;
961         i->usri3_user_id        = i21->rid;
962         i->usri3_primary_group_id = i21->primary_gid;
963         i->usri3_profile        = talloc_strdup(mem_ctx, i21->profile_path.string);
964         i->usri3_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
965         i->usri3_password_expired = i21->password_expired;
966
967         return NT_STATUS_OK;
968 }
969
970 /****************************************************************
971 ****************************************************************/
972
973 static NTSTATUS info21_to_USER_INFO_4(TALLOC_CTX *mem_ctx,
974                                       const struct samr_UserInfo21 *i21,
975                                       uint32_t auth_flag,
976                                       struct dom_sid *domain_sid,
977                                       struct USER_INFO_4 *i)
978 {
979         struct dom_sid sid;
980
981         ZERO_STRUCTP(i);
982
983         i->usri4_name           = talloc_strdup(mem_ctx, i21->account_name.string);
984         NT_STATUS_HAVE_NO_MEMORY(i->usri4_name);
985         i->usri4_password_age   = time(NULL) - nt_time_to_unix(i21->last_password_change);
986         i->usri4_password       = NULL;
987         i->usri4_priv           = samr_rid_to_priv_level(i21->rid);
988         i->usri4_home_dir       = talloc_strdup(mem_ctx, i21->home_directory.string);
989         i->usri4_comment        = talloc_strdup(mem_ctx, i21->description.string);
990         i->usri4_flags          = samr_acb_flags_to_netapi_flags(i21->acct_flags);
991         i->usri4_script_path    = talloc_strdup(mem_ctx, i21->logon_script.string);
992         i->usri4_auth_flags     = auth_flag;
993         i->usri4_full_name      = talloc_strdup(mem_ctx, i21->full_name.string);
994         i->usri4_usr_comment    = talloc_strdup(mem_ctx, i21->comment.string);
995         i->usri4_parms          = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
996         i->usri4_workstations   = talloc_strdup(mem_ctx, i21->workstations.string);
997         i->usri4_last_logon     = nt_time_to_unix(i21->last_logon);
998         i->usri4_last_logoff    = nt_time_to_unix(i21->last_logoff);
999         i->usri4_acct_expires   = nt_time_to_unix(i21->acct_expiry);
1000         i->usri4_max_storage    = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
1001         i->usri4_units_per_week = i21->logon_hours.units_per_week;
1002         i->usri4_logon_hours    = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
1003         i->usri4_bad_pw_count   = i21->bad_password_count;
1004         i->usri4_num_logons     = i21->logon_count;
1005         i->usri4_logon_server   = talloc_strdup(mem_ctx, "\\\\*");
1006         i->usri4_country_code   = i21->country_code;
1007         i->usri4_code_page      = i21->code_page;
1008         if (!sid_compose(&sid, domain_sid, i21->rid)) {
1009                 return NT_STATUS_NO_MEMORY;
1010         }
1011         i->usri4_user_sid       = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
1012         i->usri4_primary_group_id = i21->primary_gid;
1013         i->usri4_profile        = talloc_strdup(mem_ctx, i21->profile_path.string);
1014         i->usri4_home_dir_drive = talloc_strdup(mem_ctx, i21->home_drive.string);
1015         i->usri4_password_expired = i21->password_expired;
1016
1017         return NT_STATUS_OK;
1018 }
1019
1020 /****************************************************************
1021 ****************************************************************/
1022
1023 static NTSTATUS info21_to_USER_INFO_10(TALLOC_CTX *mem_ctx,
1024                                        const struct samr_UserInfo21 *i21,
1025                                        struct USER_INFO_10 *i)
1026 {
1027         ZERO_STRUCTP(i);
1028
1029         i->usri10_name          = talloc_strdup(mem_ctx, i21->account_name.string);
1030         NT_STATUS_HAVE_NO_MEMORY(i->usri10_name);
1031         i->usri10_comment       = talloc_strdup(mem_ctx, i21->description.string);
1032         i->usri10_full_name     = talloc_strdup(mem_ctx, i21->full_name.string);
1033         i->usri10_usr_comment   = talloc_strdup(mem_ctx, i21->comment.string);
1034
1035         return NT_STATUS_OK;
1036 }
1037
1038 /****************************************************************
1039 ****************************************************************/
1040
1041 static NTSTATUS info21_to_USER_INFO_11(TALLOC_CTX *mem_ctx,
1042                                        const struct samr_UserInfo21 *i21,
1043                                        uint32_t auth_flag,
1044                                        struct USER_INFO_11 *i)
1045 {
1046         ZERO_STRUCTP(i);
1047
1048         i->usri11_name          = talloc_strdup(mem_ctx, i21->account_name.string);
1049         NT_STATUS_HAVE_NO_MEMORY(i->usri11_name);
1050         i->usri11_comment       = talloc_strdup(mem_ctx, i21->description.string);
1051         i->usri11_usr_comment   = talloc_strdup(mem_ctx, i21->comment.string);
1052         i->usri11_full_name     = talloc_strdup(mem_ctx, i21->full_name.string);
1053         i->usri11_priv          = samr_rid_to_priv_level(i21->rid);
1054         i->usri11_auth_flags    = auth_flag;
1055         i->usri11_password_age  = time(NULL) - nt_time_to_unix(i21->last_password_change);
1056         i->usri11_home_dir      = talloc_strdup(mem_ctx, i21->home_directory.string);
1057         i->usri11_parms         = talloc_strndup(mem_ctx, (const char *)i21->parameters.array, i21->parameters.size/2);
1058         i->usri11_last_logon    = nt_time_to_unix(i21->last_logon);
1059         i->usri11_last_logoff   = nt_time_to_unix(i21->last_logoff);
1060         i->usri11_bad_pw_count  = i21->bad_password_count;
1061         i->usri11_num_logons    = i21->logon_count;
1062         i->usri11_logon_server  = talloc_strdup(mem_ctx, "\\\\*");
1063         i->usri11_country_code  = i21->country_code;
1064         i->usri11_workstations  = talloc_strdup(mem_ctx, i21->workstations.string);
1065         i->usri11_max_storage   = USER_MAXSTORAGE_UNLIMITED; /* FIXME */
1066         i->usri11_units_per_week = i21->logon_hours.units_per_week;
1067         i->usri11_logon_hours   = (uint8_t *)talloc_memdup(mem_ctx, i21->logon_hours.bits, 21);
1068         i->usri11_code_page     = i21->code_page;
1069
1070         return NT_STATUS_OK;
1071 }
1072
1073 /****************************************************************
1074 ****************************************************************/
1075
1076 static NTSTATUS info21_to_USER_INFO_20(TALLOC_CTX *mem_ctx,
1077                                        const struct samr_UserInfo21 *i21,
1078                                        struct USER_INFO_20 *i)
1079 {
1080         ZERO_STRUCTP(i);
1081
1082         i->usri20_name          = talloc_strdup(mem_ctx, i21->account_name.string);
1083         NT_STATUS_HAVE_NO_MEMORY(i->usri20_name);
1084         i->usri20_comment       = talloc_strdup(mem_ctx, i21->description.string);
1085         i->usri20_full_name     = talloc_strdup(mem_ctx, i21->full_name.string);
1086         i->usri20_flags         = samr_acb_flags_to_netapi_flags(i21->acct_flags);
1087         i->usri20_user_id       = i21->rid;
1088
1089         return NT_STATUS_OK;
1090 }
1091
1092 /****************************************************************
1093 ****************************************************************/
1094
1095 static NTSTATUS info21_to_USER_INFO_23(TALLOC_CTX *mem_ctx,
1096                                        const struct samr_UserInfo21 *i21,
1097                                        struct dom_sid *domain_sid,
1098                                        struct USER_INFO_23 *i)
1099 {
1100         struct dom_sid sid;
1101
1102         ZERO_STRUCTP(i);
1103
1104         i->usri23_name          = talloc_strdup(mem_ctx, i21->account_name.string);
1105         NT_STATUS_HAVE_NO_MEMORY(i->usri23_name);
1106         i->usri23_comment       = talloc_strdup(mem_ctx, i21->description.string);
1107         i->usri23_full_name     = talloc_strdup(mem_ctx, i21->full_name.string);
1108         i->usri23_flags         = samr_acb_flags_to_netapi_flags(i21->acct_flags);
1109         if (!sid_compose(&sid, domain_sid, i21->rid)) {
1110                 return NT_STATUS_NO_MEMORY;
1111         }
1112         i->usri23_user_sid      = (struct domsid *)dom_sid_dup(mem_ctx, &sid);
1113
1114         return NT_STATUS_OK;
1115 }
1116
1117 /****************************************************************
1118 ****************************************************************/
1119
1120 static NTSTATUS libnetapi_samr_lookup_user_map_USER_INFO(TALLOC_CTX *mem_ctx,
1121                                                          struct rpc_pipe_client *pipe_cli,
1122                                                          struct dom_sid *domain_sid,
1123                                                          struct policy_handle *domain_handle,
1124                                                          struct policy_handle *builtin_handle,
1125                                                          const char *user_name,
1126                                                          uint32_t rid,
1127                                                          uint32_t level,
1128                                                          uint8_t **buffer,
1129                                                          uint32_t *num_entries)
1130 {
1131         NTSTATUS status;
1132
1133         struct samr_UserInfo21 *info21 = NULL;
1134         struct sec_desc_buf *sec_desc = NULL;
1135         uint32_t auth_flag = 0;
1136
1137         struct USER_INFO_0 info0;
1138         struct USER_INFO_1 info1;
1139         struct USER_INFO_2 info2;
1140         struct USER_INFO_3 info3;
1141         struct USER_INFO_4 info4;
1142         struct USER_INFO_10 info10;
1143         struct USER_INFO_11 info11;
1144         struct USER_INFO_20 info20;
1145         struct USER_INFO_23 info23;
1146
1147         switch (level) {
1148                 case 0:
1149                 case 1:
1150                 case 2:
1151                 case 3:
1152                 case 4:
1153                 case 10:
1154                 case 11:
1155                 case 20:
1156                 case 23:
1157                         break;
1158                 default:
1159                         return NT_STATUS_INVALID_LEVEL;
1160         }
1161
1162         if (level == 0) {
1163                 info0.usri0_name = talloc_strdup(mem_ctx, user_name);
1164                 NT_STATUS_HAVE_NO_MEMORY(info0.usri0_name);
1165
1166                 ADD_TO_ARRAY(mem_ctx, struct USER_INFO_0, info0,
1167                              (struct USER_INFO_0 **)buffer, num_entries);
1168
1169                 return NT_STATUS_OK;
1170         }
1171
1172         status = libnetapi_samr_lookup_user(mem_ctx, pipe_cli,
1173                                             domain_handle,
1174                                             builtin_handle,
1175                                             user_name,
1176                                             domain_sid,
1177                                             rid,
1178                                             level,
1179                                             &info21,
1180                                             &sec_desc,
1181                                             &auth_flag);
1182
1183         if (!NT_STATUS_IS_OK(status)) {
1184                 goto done;
1185         }
1186
1187         switch (level) {
1188                 case 0:
1189                         /* already returned above */
1190                         break;
1191                 case 1:
1192                         status = info21_to_USER_INFO_1(mem_ctx, info21, &info1);
1193                         NT_STATUS_NOT_OK_RETURN(status);
1194
1195                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_1, info1,
1196                                      (struct USER_INFO_1 **)buffer, num_entries);
1197
1198                         break;
1199                 case 2:
1200                         status = info21_to_USER_INFO_2(mem_ctx, info21, auth_flag, &info2);
1201                         NT_STATUS_NOT_OK_RETURN(status);
1202
1203                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_2, info2,
1204                                      (struct USER_INFO_2 **)buffer, num_entries);
1205
1206                         break;
1207                 case 3:
1208                         status = info21_to_USER_INFO_3(mem_ctx, info21, auth_flag, &info3);
1209                         NT_STATUS_NOT_OK_RETURN(status);
1210
1211                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_3, info3,
1212                                      (struct USER_INFO_3 **)buffer, num_entries);
1213
1214                         break;
1215                 case 4:
1216                         status = info21_to_USER_INFO_4(mem_ctx, info21, auth_flag, domain_sid, &info4);
1217                         NT_STATUS_NOT_OK_RETURN(status);
1218
1219                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_4, info4,
1220                                      (struct USER_INFO_4 **)buffer, num_entries);
1221
1222                         break;
1223                 case 10:
1224                         status = info21_to_USER_INFO_10(mem_ctx, info21, &info10);
1225                         NT_STATUS_NOT_OK_RETURN(status);
1226
1227                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_10, info10,
1228                                      (struct USER_INFO_10 **)buffer, num_entries);
1229
1230                         break;
1231                 case 11:
1232                         status = info21_to_USER_INFO_11(mem_ctx, info21, auth_flag, &info11);
1233                         NT_STATUS_NOT_OK_RETURN(status);
1234
1235                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_11, info11,
1236                                      (struct USER_INFO_11 **)buffer, num_entries);
1237
1238                         break;
1239                 case 20:
1240                         status = info21_to_USER_INFO_20(mem_ctx, info21, &info20);
1241                         NT_STATUS_NOT_OK_RETURN(status);
1242
1243                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_20, info20,
1244                                      (struct USER_INFO_20 **)buffer, num_entries);
1245
1246                         break;
1247                 case 23:
1248                         status = info21_to_USER_INFO_23(mem_ctx, info21, domain_sid, &info23);
1249                         NT_STATUS_NOT_OK_RETURN(status);
1250
1251                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_23, info23,
1252                                      (struct USER_INFO_23 **)buffer, num_entries);
1253                         break;
1254                 default:
1255                         return NT_STATUS_INVALID_LEVEL;
1256         }
1257
1258  done:
1259         return status;
1260 }
1261
1262 /****************************************************************
1263 ****************************************************************/
1264
1265 WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
1266                      struct NetUserEnum *r)
1267 {
1268         struct rpc_pipe_client *pipe_cli = NULL;
1269         struct policy_handle connect_handle;
1270         struct dom_sid2 *domain_sid = NULL;
1271         struct policy_handle domain_handle, builtin_handle;
1272         struct samr_SamArray *sam = NULL;
1273         uint32_t filter = ACB_NORMAL;
1274         int i;
1275         uint32_t entries_read = 0;
1276
1277         NTSTATUS status = NT_STATUS_OK;
1278         NTSTATUS result = NT_STATUS_OK;
1279         WERROR werr;
1280         struct dcerpc_binding_handle *b = NULL;
1281
1282         ZERO_STRUCT(connect_handle);
1283         ZERO_STRUCT(domain_handle);
1284         ZERO_STRUCT(builtin_handle);
1285
1286         if (!r->out.buffer) {
1287                 return WERR_INVALID_PARAM;
1288         }
1289
1290         *r->out.buffer = NULL;
1291         *r->out.entries_read = 0;
1292
1293         switch (r->in.level) {
1294                 case 0:
1295                 case 1:
1296                 case 2:
1297                 case 3:
1298                 case 4:
1299                 case 10:
1300                 case 11:
1301                 case 20:
1302                 case 23:
1303                         break;
1304                 default:
1305                         return WERR_UNKNOWN_LEVEL;
1306         }
1307
1308         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1309                                    &ndr_table_samr.syntax_id,
1310                                    &pipe_cli);
1311         if (!W_ERROR_IS_OK(werr)) {
1312                 goto done;
1313         }
1314
1315         b = pipe_cli->binding_handle;
1316
1317         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1318                                                   SAMR_ACCESS_ENUM_DOMAINS |
1319                                                   SAMR_ACCESS_LOOKUP_DOMAIN,
1320                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1321                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1322                                                   &connect_handle,
1323                                                   &builtin_handle);
1324         if (!W_ERROR_IS_OK(werr)) {
1325                 goto done;
1326         }
1327
1328         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1329                                           SAMR_ACCESS_ENUM_DOMAINS |
1330                                           SAMR_ACCESS_LOOKUP_DOMAIN,
1331                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1332                                           SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1333                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1334                                           &connect_handle,
1335                                           &domain_handle,
1336                                           &domain_sid);
1337         if (!W_ERROR_IS_OK(werr)) {
1338                 goto done;
1339         }
1340
1341         switch (r->in.filter) {
1342                 case FILTER_NORMAL_ACCOUNT:
1343                         filter = ACB_NORMAL;
1344                         break;
1345                 case FILTER_TEMP_DUPLICATE_ACCOUNT:
1346                         filter = ACB_TEMPDUP;
1347                         break;
1348                 case FILTER_INTERDOMAIN_TRUST_ACCOUNT:
1349                         filter = ACB_DOMTRUST;
1350                         break;
1351                 case FILTER_WORKSTATION_TRUST_ACCOUNT:
1352                         filter = ACB_WSTRUST;
1353                         break;
1354                 case FILTER_SERVER_TRUST_ACCOUNT:
1355                         filter = ACB_SVRTRUST;
1356                         break;
1357                 default:
1358                         break;
1359         }
1360
1361         status = dcerpc_samr_EnumDomainUsers(b,
1362                                              ctx,
1363                                              &domain_handle,
1364                                              r->in.resume_handle,
1365                                              filter,
1366                                              &sam,
1367                                              r->in.prefmaxlen,
1368                                              &entries_read,
1369                                              &result);
1370         if (!NT_STATUS_IS_OK(status)) {
1371                 werr = ntstatus_to_werror(status);
1372                 goto done;
1373         }
1374         werr = ntstatus_to_werror(result);
1375         if (NT_STATUS_IS_ERR(result)) {
1376                 goto done;
1377         }
1378
1379         for (i=0; i < sam->count; i++) {
1380
1381                 status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1382                                                                   domain_sid,
1383                                                                   &domain_handle,
1384                                                                   &builtin_handle,
1385                                                                   sam->entries[i].name.string,
1386                                                                   sam->entries[i].idx,
1387                                                                   r->in.level,
1388                                                                   r->out.buffer,
1389                                                                   r->out.entries_read);
1390                 if (!NT_STATUS_IS_OK(status)) {
1391                         werr = ntstatus_to_werror(status);
1392                         goto done;
1393                 }
1394         }
1395
1396  done:
1397         /* if last query */
1398         if (NT_STATUS_IS_OK(result) ||
1399             NT_STATUS_IS_ERR(result)) {
1400
1401                 if (ctx->disable_policy_handle_cache) {
1402                         libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1403                         libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1404                         libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1405                 }
1406         }
1407
1408         return werr;
1409 }
1410
1411 /****************************************************************
1412 ****************************************************************/
1413
1414 WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
1415                      struct NetUserEnum *r)
1416 {
1417         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserEnum);
1418 }
1419
1420 /****************************************************************
1421 ****************************************************************/
1422
1423 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_USER(TALLOC_CTX *mem_ctx,
1424                                                         struct samr_DispInfoGeneral *info,
1425                                                         uint32_t *entries_read,
1426                                                         void **buffer)
1427 {
1428         struct NET_DISPLAY_USER *user = NULL;
1429         int i;
1430
1431         user = TALLOC_ZERO_ARRAY(mem_ctx,
1432                                  struct NET_DISPLAY_USER,
1433                                  info->count);
1434         W_ERROR_HAVE_NO_MEMORY(user);
1435
1436         for (i = 0; i < info->count; i++) {
1437                 user[i].usri1_name = talloc_strdup(mem_ctx,
1438                         info->entries[i].account_name.string);
1439                 user[i].usri1_comment = talloc_strdup(mem_ctx,
1440                         info->entries[i].description.string);
1441                 user[i].usri1_flags =
1442                         info->entries[i].acct_flags;
1443                 user[i].usri1_full_name = talloc_strdup(mem_ctx,
1444                         info->entries[i].full_name.string);
1445                 user[i].usri1_user_id =
1446                         info->entries[i].rid;
1447                 user[i].usri1_next_index =
1448                         info->entries[i].idx;
1449
1450                 if (!user[i].usri1_name) {
1451                         return WERR_NOMEM;
1452                 }
1453         }
1454
1455         *buffer = talloc_memdup(mem_ctx, user,
1456                 sizeof(struct NET_DISPLAY_USER) * info->count);
1457         W_ERROR_HAVE_NO_MEMORY(*buffer);
1458
1459         *entries_read = info->count;
1460
1461         return WERR_OK;
1462 }
1463
1464 /****************************************************************
1465 ****************************************************************/
1466
1467 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(TALLOC_CTX *mem_ctx,
1468                                                            struct samr_DispInfoFull *info,
1469                                                            uint32_t *entries_read,
1470                                                            void **buffer)
1471 {
1472         struct NET_DISPLAY_MACHINE *machine = NULL;
1473         int i;
1474
1475         machine = TALLOC_ZERO_ARRAY(mem_ctx,
1476                                     struct NET_DISPLAY_MACHINE,
1477                                     info->count);
1478         W_ERROR_HAVE_NO_MEMORY(machine);
1479
1480         for (i = 0; i < info->count; i++) {
1481                 machine[i].usri2_name = talloc_strdup(mem_ctx,
1482                         info->entries[i].account_name.string);
1483                 machine[i].usri2_comment = talloc_strdup(mem_ctx,
1484                         info->entries[i].description.string);
1485                 machine[i].usri2_flags =
1486                         info->entries[i].acct_flags;
1487                 machine[i].usri2_user_id =
1488                         info->entries[i].rid;
1489                 machine[i].usri2_next_index =
1490                         info->entries[i].idx;
1491
1492                 if (!machine[i].usri2_name) {
1493                         return WERR_NOMEM;
1494                 }
1495         }
1496
1497         *buffer = talloc_memdup(mem_ctx, machine,
1498                 sizeof(struct NET_DISPLAY_MACHINE) * info->count);
1499         W_ERROR_HAVE_NO_MEMORY(*buffer);
1500
1501         *entries_read = info->count;
1502
1503         return WERR_OK;
1504 }
1505
1506 /****************************************************************
1507 ****************************************************************/
1508
1509 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_GROUP(TALLOC_CTX *mem_ctx,
1510                                                          struct samr_DispInfoFullGroups *info,
1511                                                          uint32_t *entries_read,
1512                                                          void **buffer)
1513 {
1514         struct NET_DISPLAY_GROUP *group = NULL;
1515         int i;
1516
1517         group = TALLOC_ZERO_ARRAY(mem_ctx,
1518                                   struct NET_DISPLAY_GROUP,
1519                                   info->count);
1520         W_ERROR_HAVE_NO_MEMORY(group);
1521
1522         for (i = 0; i < info->count; i++) {
1523                 group[i].grpi3_name = talloc_strdup(mem_ctx,
1524                         info->entries[i].account_name.string);
1525                 group[i].grpi3_comment = talloc_strdup(mem_ctx,
1526                         info->entries[i].description.string);
1527                 group[i].grpi3_group_id =
1528                         info->entries[i].rid;
1529                 group[i].grpi3_attributes =
1530                         info->entries[i].acct_flags;
1531                 group[i].grpi3_next_index =
1532                         info->entries[i].idx;
1533
1534                 if (!group[i].grpi3_name) {
1535                         return WERR_NOMEM;
1536                 }
1537         }
1538
1539         *buffer = talloc_memdup(mem_ctx, group,
1540                 sizeof(struct NET_DISPLAY_GROUP) * info->count);
1541         W_ERROR_HAVE_NO_MEMORY(*buffer);
1542
1543         *entries_read = info->count;
1544
1545         return WERR_OK;
1546
1547 }
1548
1549 /****************************************************************
1550 ****************************************************************/
1551
1552 static WERROR convert_samr_dispinfo_to_NET_DISPLAY(TALLOC_CTX *mem_ctx,
1553                                                    union samr_DispInfo *info,
1554                                                    uint32_t level,
1555                                                    uint32_t *entries_read,
1556                                                    void **buffer)
1557 {
1558         switch (level) {
1559                 case 1:
1560                         return convert_samr_dispinfo_to_NET_DISPLAY_USER(mem_ctx,
1561                                                                          &info->info1,
1562                                                                          entries_read,
1563                                                                          buffer);
1564                 case 2:
1565                         return convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(mem_ctx,
1566                                                                             &info->info2,
1567                                                                             entries_read,
1568                                                                             buffer);
1569                 case 3:
1570                         return convert_samr_dispinfo_to_NET_DISPLAY_GROUP(mem_ctx,
1571                                                                           &info->info3,
1572                                                                           entries_read,
1573                                                                           buffer);
1574                 default:
1575                         break;
1576         }
1577
1578         return WERR_UNKNOWN_LEVEL;
1579 }
1580
1581 /****************************************************************
1582 ****************************************************************/
1583
1584 WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
1585                                     struct NetQueryDisplayInformation *r)
1586 {
1587         struct rpc_pipe_client *pipe_cli = NULL;
1588         struct policy_handle connect_handle;
1589         struct dom_sid2 *domain_sid = NULL;
1590         struct policy_handle domain_handle;
1591         union samr_DispInfo info;
1592         struct dcerpc_binding_handle *b = NULL;
1593
1594         uint32_t total_size = 0;
1595         uint32_t returned_size = 0;
1596
1597         NTSTATUS status = NT_STATUS_OK;
1598         NTSTATUS result = NT_STATUS_OK;
1599         WERROR werr;
1600         WERROR werr_tmp;
1601
1602         *r->out.entries_read = 0;
1603
1604         ZERO_STRUCT(connect_handle);
1605         ZERO_STRUCT(domain_handle);
1606
1607         switch (r->in.level) {
1608                 case 1:
1609                 case 2:
1610                 case 3:
1611                         break;
1612                 default:
1613                         return WERR_UNKNOWN_LEVEL;
1614         }
1615
1616         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1617                                    &ndr_table_samr.syntax_id,
1618                                    &pipe_cli);
1619         if (!W_ERROR_IS_OK(werr)) {
1620                 goto done;
1621         }
1622
1623         b = pipe_cli->binding_handle;
1624
1625         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1626                                           SAMR_ACCESS_ENUM_DOMAINS |
1627                                           SAMR_ACCESS_LOOKUP_DOMAIN,
1628                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1629                                           SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1630                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1631                                           &connect_handle,
1632                                           &domain_handle,
1633                                           &domain_sid);
1634         if (!W_ERROR_IS_OK(werr)) {
1635                 goto done;
1636         }
1637
1638         status = dcerpc_samr_QueryDisplayInfo2(b,
1639                                                ctx,
1640                                                &domain_handle,
1641                                                r->in.level,
1642                                                r->in.idx,
1643                                                r->in.entries_requested,
1644                                                r->in.prefmaxlen,
1645                                                &total_size,
1646                                                &returned_size,
1647                                                &info,
1648                                                &result);
1649         if (!NT_STATUS_IS_OK(status)) {
1650                 werr = ntstatus_to_werror(status);
1651                 goto done;
1652         }
1653         werr = ntstatus_to_werror(result);
1654         if (NT_STATUS_IS_ERR(result)) {
1655                 goto done;
1656         }
1657
1658         werr_tmp = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info,
1659                                                         r->in.level,
1660                                                         r->out.entries_read,
1661                                                         r->out.buffer);
1662         if (!W_ERROR_IS_OK(werr_tmp)) {
1663                 werr = werr_tmp;
1664         }
1665  done:
1666         /* if last query */
1667         if (NT_STATUS_IS_OK(result) ||
1668             NT_STATUS_IS_ERR(result)) {
1669
1670                 if (ctx->disable_policy_handle_cache) {
1671                         libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1672                         libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1673                 }
1674         }
1675
1676         return werr;
1677
1678 }
1679
1680 /****************************************************************
1681 ****************************************************************/
1682
1683
1684 WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
1685                                     struct NetQueryDisplayInformation *r)
1686 {
1687         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetQueryDisplayInformation);
1688 }
1689
1690 /****************************************************************
1691 ****************************************************************/
1692
1693 WERROR NetUserChangePassword_r(struct libnetapi_ctx *ctx,
1694                                struct NetUserChangePassword *r)
1695 {
1696         return WERR_NOT_SUPPORTED;
1697 }
1698
1699 /****************************************************************
1700 ****************************************************************/
1701
1702 WERROR NetUserChangePassword_l(struct libnetapi_ctx *ctx,
1703                                struct NetUserChangePassword *r)
1704 {
1705         return WERR_NOT_SUPPORTED;
1706 }
1707
1708 /****************************************************************
1709 ****************************************************************/
1710
1711 WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx,
1712                         struct NetUserGetInfo *r)
1713 {
1714         struct rpc_pipe_client *pipe_cli = NULL;
1715         NTSTATUS status, result;
1716         WERROR werr;
1717
1718         struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1719         struct lsa_String lsa_account_name;
1720         struct dom_sid2 *domain_sid = NULL;
1721         struct samr_Ids user_rids, name_types;
1722         uint32_t num_entries = 0;
1723         struct dcerpc_binding_handle *b = NULL;
1724
1725         ZERO_STRUCT(connect_handle);
1726         ZERO_STRUCT(domain_handle);
1727         ZERO_STRUCT(builtin_handle);
1728         ZERO_STRUCT(user_handle);
1729
1730         if (!r->out.buffer) {
1731                 return WERR_INVALID_PARAM;
1732         }
1733
1734         switch (r->in.level) {
1735                 case 0:
1736                 case 1:
1737                 case 2:
1738                 case 3:
1739                 case 4:
1740                 case 10:
1741                 case 11:
1742                 case 20:
1743                 case 23:
1744                         break;
1745                 default:
1746                         werr = WERR_UNKNOWN_LEVEL;
1747                         goto done;
1748         }
1749
1750         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1751                                    &ndr_table_samr.syntax_id,
1752                                    &pipe_cli);
1753         if (!W_ERROR_IS_OK(werr)) {
1754                 goto done;
1755         }
1756
1757         b = pipe_cli->binding_handle;
1758
1759         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1760                                           SAMR_ACCESS_ENUM_DOMAINS |
1761                                           SAMR_ACCESS_LOOKUP_DOMAIN,
1762                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1763                                           &connect_handle,
1764                                           &domain_handle,
1765                                           &domain_sid);
1766         if (!W_ERROR_IS_OK(werr)) {
1767                 goto done;
1768         }
1769
1770         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1771                                                   SAMR_ACCESS_ENUM_DOMAINS |
1772                                                   SAMR_ACCESS_LOOKUP_DOMAIN,
1773                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1774                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1775                                                   &connect_handle,
1776                                                   &builtin_handle);
1777         if (!W_ERROR_IS_OK(werr)) {
1778                 goto done;
1779         }
1780
1781         init_lsa_String(&lsa_account_name, r->in.user_name);
1782
1783         status = dcerpc_samr_LookupNames(b, talloc_tos(),
1784                                          &domain_handle,
1785                                          1,
1786                                          &lsa_account_name,
1787                                          &user_rids,
1788                                          &name_types,
1789                                          &result);
1790         if (!NT_STATUS_IS_OK(status)) {
1791                 werr = ntstatus_to_werror(status);
1792                 goto done;
1793         }
1794         if (!NT_STATUS_IS_OK(result)) {
1795                 werr = ntstatus_to_werror(result);
1796                 goto done;
1797         }
1798
1799         status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1800                                                           domain_sid,
1801                                                           &domain_handle,
1802                                                           &builtin_handle,
1803                                                           r->in.user_name,
1804                                                           user_rids.ids[0],
1805                                                           r->in.level,
1806                                                           r->out.buffer,
1807                                                           &num_entries);
1808         if (!NT_STATUS_IS_OK(status)) {
1809                 werr = ntstatus_to_werror(status);
1810                 goto done;
1811         }
1812
1813  done:
1814         if (is_valid_policy_hnd(&user_handle) && b) {
1815                 dcerpc_samr_Close(b, talloc_tos(), &user_handle, &result);
1816         }
1817
1818         if (ctx->disable_policy_handle_cache) {
1819                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1820                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1821         }
1822
1823         return werr;
1824 }
1825
1826 /****************************************************************
1827 ****************************************************************/
1828
1829 WERROR NetUserGetInfo_l(struct libnetapi_ctx *ctx,
1830                         struct NetUserGetInfo *r)
1831 {
1832         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetInfo);
1833 }
1834
1835 /****************************************************************
1836 ****************************************************************/
1837
1838 WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
1839                         struct NetUserSetInfo *r)
1840 {
1841         struct rpc_pipe_client *pipe_cli = NULL;
1842         NTSTATUS status, result;
1843         WERROR werr;
1844
1845         struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1846         struct lsa_String lsa_account_name;
1847         struct dom_sid2 *domain_sid = NULL;
1848         struct samr_Ids user_rids, name_types;
1849         uint32_t user_mask = 0;
1850
1851         struct USER_INFO_X uX;
1852         struct dcerpc_binding_handle *b = NULL;
1853
1854         ZERO_STRUCT(connect_handle);
1855         ZERO_STRUCT(domain_handle);
1856         ZERO_STRUCT(builtin_handle);
1857         ZERO_STRUCT(user_handle);
1858
1859         if (!r->in.buffer) {
1860                 return WERR_INVALID_PARAM;
1861         }
1862
1863         switch (r->in.level) {
1864                 case 0:
1865                         user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
1866                         break;
1867                 case 1003:
1868                         user_mask = SAMR_USER_ACCESS_SET_PASSWORD;
1869                         break;
1870                 case 1006:
1871                 case 1007:
1872                 case 1009:
1873                 case 1011:
1874                 case 1014:
1875                 case 1052:
1876                 case 1053:
1877                         user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
1878                         break;
1879                 case 1012:
1880                 case 1024:
1881                         user_mask = SAMR_USER_ACCESS_SET_LOC_COM;
1882                 case 1051:
1883                         user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES |
1884                                     SAMR_USER_ACCESS_GET_GROUPS;
1885                         break;
1886                 case 3:
1887                         user_mask = SEC_STD_READ_CONTROL |
1888                                     SEC_STD_WRITE_DAC |
1889                                     SAMR_USER_ACCESS_GET_GROUPS |
1890                                     SAMR_USER_ACCESS_SET_PASSWORD |
1891                                     SAMR_USER_ACCESS_SET_ATTRIBUTES |
1892                                     SAMR_USER_ACCESS_GET_ATTRIBUTES |
1893                                     SAMR_USER_ACCESS_SET_LOC_COM;
1894                         break;
1895                 case 1:
1896                 case 2:
1897                 case 4:
1898                 case 21:
1899                 case 22:
1900                 case 1005:
1901                 case 1008:
1902                 case 1010:
1903                 case 1017:
1904                 case 1020:
1905                         werr = WERR_NOT_SUPPORTED;
1906                         goto done;
1907                 default:
1908                         werr = WERR_UNKNOWN_LEVEL;
1909                         goto done;
1910         }
1911
1912         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1913                                    &ndr_table_samr.syntax_id,
1914                                    &pipe_cli);
1915         if (!W_ERROR_IS_OK(werr)) {
1916                 goto done;
1917         }
1918
1919         b = pipe_cli->binding_handle;
1920
1921         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1922                                           SAMR_ACCESS_ENUM_DOMAINS |
1923                                           SAMR_ACCESS_LOOKUP_DOMAIN,
1924                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
1925                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1926                                           &connect_handle,
1927                                           &domain_handle,
1928                                           &domain_sid);
1929         if (!W_ERROR_IS_OK(werr)) {
1930                 goto done;
1931         }
1932
1933         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1934                                                   SAMR_ACCESS_ENUM_DOMAINS |
1935                                                   SAMR_ACCESS_LOOKUP_DOMAIN,
1936                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1937                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1938                                                   &connect_handle,
1939                                                   &builtin_handle);
1940         if (!W_ERROR_IS_OK(werr)) {
1941                 goto done;
1942         }
1943
1944         init_lsa_String(&lsa_account_name, r->in.user_name);
1945
1946         status = dcerpc_samr_LookupNames(b, talloc_tos(),
1947                                          &domain_handle,
1948                                          1,
1949                                          &lsa_account_name,
1950                                          &user_rids,
1951                                          &name_types,
1952                                          &result);
1953         if (!NT_STATUS_IS_OK(status)) {
1954                 werr = ntstatus_to_werror(status);
1955                 goto done;
1956         }
1957         if (!NT_STATUS_IS_OK(result)) {
1958                 werr = ntstatus_to_werror(result);
1959                 goto done;
1960         }
1961
1962         status = dcerpc_samr_OpenUser(b, talloc_tos(),
1963                                       &domain_handle,
1964                                       user_mask,
1965                                       user_rids.ids[0],
1966                                       &user_handle,
1967                                       &result);
1968         if (!NT_STATUS_IS_OK(status)) {
1969                 werr = ntstatus_to_werror(status);
1970                 goto done;
1971         }
1972         if (!NT_STATUS_IS_OK(result)) {
1973                 werr = ntstatus_to_werror(result);
1974                 goto done;
1975         }
1976
1977         status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
1978         if (!NT_STATUS_IS_OK(status)) {
1979                 werr = ntstatus_to_werror(status);
1980                 goto done;
1981         }
1982
1983         status = set_user_info_USER_INFO_X(ctx, pipe_cli,
1984                                            &pipe_cli->auth->user_session_key,
1985                                            &user_handle,
1986                                            &uX);
1987         if (!NT_STATUS_IS_OK(status)) {
1988                 werr = ntstatus_to_werror(status);
1989                 goto done;
1990         }
1991
1992         werr = WERR_OK;
1993
1994  done:
1995         if (is_valid_policy_hnd(&user_handle) && b) {
1996                 dcerpc_samr_Close(b, talloc_tos(), &user_handle, &result);
1997         }
1998
1999         if (ctx->disable_policy_handle_cache) {
2000                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2001                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
2002                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2003         }
2004
2005         return werr;
2006 }
2007
2008 /****************************************************************
2009 ****************************************************************/
2010
2011 WERROR NetUserSetInfo_l(struct libnetapi_ctx *ctx,
2012                         struct NetUserSetInfo *r)
2013 {
2014         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetInfo);
2015 }
2016
2017 /****************************************************************
2018 ****************************************************************/
2019
2020 static NTSTATUS query_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
2021                                            struct rpc_pipe_client *pipe_cli,
2022                                            struct policy_handle *domain_handle,
2023                                            struct samr_DomInfo1 *info1,
2024                                            struct samr_DomInfo3 *info3,
2025                                            struct samr_DomInfo5 *info5,
2026                                            struct samr_DomInfo6 *info6,
2027                                            struct samr_DomInfo7 *info7,
2028                                            struct samr_DomInfo12 *info12)
2029 {
2030         NTSTATUS status, result;
2031         union samr_DomainInfo *dom_info = NULL;
2032         struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
2033
2034         if (info1) {
2035                 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
2036                                                      domain_handle,
2037                                                      1,
2038                                                      &dom_info,
2039                                                      &result);
2040                 NT_STATUS_NOT_OK_RETURN(status);
2041                 NT_STATUS_NOT_OK_RETURN(result);
2042
2043                 *info1 = dom_info->info1;
2044         }
2045
2046         if (info3) {
2047                 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
2048                                                      domain_handle,
2049                                                      3,
2050                                                      &dom_info,
2051                                                      &result);
2052                 NT_STATUS_NOT_OK_RETURN(status);
2053                 NT_STATUS_NOT_OK_RETURN(result);
2054
2055                 *info3 = dom_info->info3;
2056         }
2057
2058         if (info5) {
2059                 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
2060                                                      domain_handle,
2061                                                      5,
2062                                                      &dom_info,
2063                                                      &result);
2064                 NT_STATUS_NOT_OK_RETURN(status);
2065                 NT_STATUS_NOT_OK_RETURN(result);
2066
2067                 *info5 = dom_info->info5;
2068         }
2069
2070         if (info6) {
2071                 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
2072                                                      domain_handle,
2073                                                      6,
2074                                                      &dom_info,
2075                                                      &result);
2076                 NT_STATUS_NOT_OK_RETURN(status);
2077                 NT_STATUS_NOT_OK_RETURN(result);
2078
2079                 *info6 = dom_info->info6;
2080         }
2081
2082         if (info7) {
2083                 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
2084                                                      domain_handle,
2085                                                      7,
2086                                                      &dom_info,
2087                                                      &result);
2088                 NT_STATUS_NOT_OK_RETURN(status);
2089                 NT_STATUS_NOT_OK_RETURN(result);
2090
2091                 *info7 = dom_info->info7;
2092         }
2093
2094         if (info12) {
2095                 status = dcerpc_samr_QueryDomainInfo2(b, mem_ctx,
2096                                                       domain_handle,
2097                                                       12,
2098                                                       &dom_info,
2099                                                       &result);
2100                 NT_STATUS_NOT_OK_RETURN(status);
2101                 NT_STATUS_NOT_OK_RETURN(result);
2102
2103                 *info12 = dom_info->info12;
2104         }
2105
2106         return NT_STATUS_OK;
2107 }
2108
2109 /****************************************************************
2110 ****************************************************************/
2111
2112 static NTSTATUS query_USER_MODALS_INFO_0(TALLOC_CTX *mem_ctx,
2113                                          struct rpc_pipe_client *pipe_cli,
2114                                          struct policy_handle *domain_handle,
2115                                          struct USER_MODALS_INFO_0 *info0)
2116 {
2117         NTSTATUS status;
2118         struct samr_DomInfo1 dom_info1;
2119         struct samr_DomInfo3 dom_info3;
2120
2121         ZERO_STRUCTP(info0);
2122
2123         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2124                                             pipe_cli,
2125                                             domain_handle,
2126                                             &dom_info1,
2127                                             &dom_info3,
2128                                             NULL,
2129                                             NULL,
2130                                             NULL,
2131                                             NULL);
2132         NT_STATUS_NOT_OK_RETURN(status);
2133
2134         info0->usrmod0_min_passwd_len =
2135                 dom_info1.min_password_length;
2136         info0->usrmod0_max_passwd_age =
2137                 nt_time_to_unix_abs((NTTIME *)&dom_info1.max_password_age);
2138         info0->usrmod0_min_passwd_age =
2139                 nt_time_to_unix_abs((NTTIME *)&dom_info1.min_password_age);
2140         info0->usrmod0_password_hist_len =
2141                 dom_info1.password_history_length;
2142
2143         info0->usrmod0_force_logoff =
2144                 nt_time_to_unix_abs(&dom_info3.force_logoff_time);
2145
2146         return NT_STATUS_OK;
2147 }
2148
2149 /****************************************************************
2150 ****************************************************************/
2151
2152 static NTSTATUS query_USER_MODALS_INFO_1(TALLOC_CTX *mem_ctx,
2153                                          struct rpc_pipe_client *pipe_cli,
2154                                          struct policy_handle *domain_handle,
2155                                          struct USER_MODALS_INFO_1 *info1)
2156 {
2157         NTSTATUS status;
2158         struct samr_DomInfo6 dom_info6;
2159         struct samr_DomInfo7 dom_info7;
2160
2161         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2162                                             pipe_cli,
2163                                             domain_handle,
2164                                             NULL,
2165                                             NULL,
2166                                             NULL,
2167                                             &dom_info6,
2168                                             &dom_info7,
2169                                             NULL);
2170         NT_STATUS_NOT_OK_RETURN(status);
2171
2172         info1->usrmod1_primary =
2173                 talloc_strdup(mem_ctx, dom_info6.primary.string);
2174
2175         info1->usrmod1_role = dom_info7.role;
2176
2177         return NT_STATUS_OK;
2178 }
2179
2180 /****************************************************************
2181 ****************************************************************/
2182
2183 static NTSTATUS query_USER_MODALS_INFO_2(TALLOC_CTX *mem_ctx,
2184                                          struct rpc_pipe_client *pipe_cli,
2185                                          struct policy_handle *domain_handle,
2186                                          struct dom_sid *domain_sid,
2187                                          struct USER_MODALS_INFO_2 *info2)
2188 {
2189         NTSTATUS status;
2190         struct samr_DomInfo5 dom_info5;
2191
2192         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2193                                             pipe_cli,
2194                                             domain_handle,
2195                                             NULL,
2196                                             NULL,
2197                                             &dom_info5,
2198                                             NULL,
2199                                             NULL,
2200                                             NULL);
2201         NT_STATUS_NOT_OK_RETURN(status);
2202
2203         info2->usrmod2_domain_name =
2204                 talloc_strdup(mem_ctx, dom_info5.domain_name.string);
2205         info2->usrmod2_domain_id =
2206                 (struct domsid *)dom_sid_dup(mem_ctx, domain_sid);
2207
2208         NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_name);
2209         NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_id);
2210
2211         return NT_STATUS_OK;
2212 }
2213
2214 /****************************************************************
2215 ****************************************************************/
2216
2217 static NTSTATUS query_USER_MODALS_INFO_3(TALLOC_CTX *mem_ctx,
2218                                          struct rpc_pipe_client *pipe_cli,
2219                                          struct policy_handle *domain_handle,
2220                                          struct USER_MODALS_INFO_3 *info3)
2221 {
2222         NTSTATUS status;
2223         struct samr_DomInfo12 dom_info12;
2224
2225         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2226                                             pipe_cli,
2227                                             domain_handle,
2228                                             NULL,
2229                                             NULL,
2230                                             NULL,
2231                                             NULL,
2232                                             NULL,
2233                                             &dom_info12);
2234         NT_STATUS_NOT_OK_RETURN(status);
2235
2236         info3->usrmod3_lockout_duration =
2237                 nt_time_to_unix_abs(&dom_info12.lockout_duration);
2238         info3->usrmod3_lockout_observation_window =
2239                 nt_time_to_unix_abs(&dom_info12.lockout_window);
2240         info3->usrmod3_lockout_threshold =
2241                 dom_info12.lockout_threshold;
2242
2243         return NT_STATUS_OK;
2244 }
2245
2246 /****************************************************************
2247 ****************************************************************/
2248
2249 static NTSTATUS query_USER_MODALS_INFO_to_buffer(TALLOC_CTX *mem_ctx,
2250                                                  struct rpc_pipe_client *pipe_cli,
2251                                                  uint32_t level,
2252                                                  struct policy_handle *domain_handle,
2253                                                  struct dom_sid *domain_sid,
2254                                                  uint8_t **buffer)
2255 {
2256         NTSTATUS status;
2257
2258         struct USER_MODALS_INFO_0 info0;
2259         struct USER_MODALS_INFO_1 info1;
2260         struct USER_MODALS_INFO_2 info2;
2261         struct USER_MODALS_INFO_3 info3;
2262
2263         if (!buffer) {
2264                 return ERROR_INSUFFICIENT_BUFFER;
2265         }
2266
2267         switch (level) {
2268                 case 0:
2269                         status = query_USER_MODALS_INFO_0(mem_ctx,
2270                                                           pipe_cli,
2271                                                           domain_handle,
2272                                                           &info0);
2273                         NT_STATUS_NOT_OK_RETURN(status);
2274
2275                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0,
2276                                                            sizeof(info0));
2277                         break;
2278
2279                 case 1:
2280                         status = query_USER_MODALS_INFO_1(mem_ctx,
2281                                                           pipe_cli,
2282                                                           domain_handle,
2283                                                           &info1);
2284                         NT_STATUS_NOT_OK_RETURN(status);
2285
2286                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1,
2287                                                            sizeof(info1));
2288                         break;
2289                 case 2:
2290                         status = query_USER_MODALS_INFO_2(mem_ctx,
2291                                                           pipe_cli,
2292                                                           domain_handle,
2293                                                           domain_sid,
2294                                                           &info2);
2295                         NT_STATUS_NOT_OK_RETURN(status);
2296
2297                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2,
2298                                                            sizeof(info2));
2299                         break;
2300                 case 3:
2301                         status = query_USER_MODALS_INFO_3(mem_ctx,
2302                                                           pipe_cli,
2303                                                           domain_handle,
2304                                                           &info3);
2305                         NT_STATUS_NOT_OK_RETURN(status);
2306
2307                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3,
2308                                                            sizeof(info3));
2309                         break;
2310                 default:
2311                         break;
2312         }
2313
2314         NT_STATUS_HAVE_NO_MEMORY(*buffer);
2315
2316         return NT_STATUS_OK;
2317 }
2318
2319 /****************************************************************
2320 ****************************************************************/
2321
2322 WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx,
2323                           struct NetUserModalsGet *r)
2324 {
2325         struct rpc_pipe_client *pipe_cli = NULL;
2326         NTSTATUS status;
2327         WERROR werr;
2328
2329         struct policy_handle connect_handle, domain_handle;
2330         struct dom_sid2 *domain_sid = NULL;
2331         uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2332
2333         ZERO_STRUCT(connect_handle);
2334         ZERO_STRUCT(domain_handle);
2335
2336         if (!r->out.buffer) {
2337                 return WERR_INVALID_PARAM;
2338         }
2339
2340         switch (r->in.level) {
2341                 case 0:
2342                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2343                                        SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2344                         break;
2345                 case 1:
2346                 case 2:
2347                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2348                         break;
2349                 case 3:
2350                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1;
2351                         break;
2352                 default:
2353                         werr = WERR_UNKNOWN_LEVEL;
2354                         goto done;
2355         }
2356
2357         werr = libnetapi_open_pipe(ctx, r->in.server_name,
2358                                    &ndr_table_samr.syntax_id,
2359                                    &pipe_cli);
2360         if (!W_ERROR_IS_OK(werr)) {
2361                 goto done;
2362         }
2363
2364         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2365                                           SAMR_ACCESS_ENUM_DOMAINS |
2366                                           SAMR_ACCESS_LOOKUP_DOMAIN,
2367                                           access_mask,
2368                                           &connect_handle,
2369                                           &domain_handle,
2370                                           &domain_sid);
2371         if (!W_ERROR_IS_OK(werr)) {
2372                 goto done;
2373         }
2374
2375         /* 0:  1 + 3 */
2376         /* 1:  6 + 7 */
2377         /* 2:  5 */
2378         /* 3: 12 (DomainInfo2) */
2379
2380         status = query_USER_MODALS_INFO_to_buffer(ctx,
2381                                                   pipe_cli,
2382                                                   r->in.level,
2383                                                   &domain_handle,
2384                                                   domain_sid,
2385                                                   r->out.buffer);
2386         if (!NT_STATUS_IS_OK(status)) {
2387                 werr = ntstatus_to_werror(status);
2388                 goto done;
2389         }
2390
2391  done:
2392         if (ctx->disable_policy_handle_cache) {
2393                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2394                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2395         }
2396
2397         return werr;
2398 }
2399
2400 /****************************************************************
2401 ****************************************************************/
2402
2403 WERROR NetUserModalsGet_l(struct libnetapi_ctx *ctx,
2404                           struct NetUserModalsGet *r)
2405 {
2406         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsGet);
2407 }
2408
2409 /****************************************************************
2410 ****************************************************************/
2411
2412 static NTSTATUS set_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
2413                                          struct rpc_pipe_client *pipe_cli,
2414                                          struct policy_handle *domain_handle,
2415                                          struct samr_DomInfo1 *info1,
2416                                          struct samr_DomInfo3 *info3,
2417                                          struct samr_DomInfo12 *info12)
2418 {
2419         NTSTATUS status, result;
2420         union samr_DomainInfo dom_info;
2421         struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
2422
2423         if (info1) {
2424
2425                 ZERO_STRUCT(dom_info);
2426
2427                 dom_info.info1 = *info1;
2428
2429                 status = dcerpc_samr_SetDomainInfo(b, mem_ctx,
2430                                                    domain_handle,
2431                                                    1,
2432                                                    &dom_info,
2433                                                    &result);
2434                 NT_STATUS_NOT_OK_RETURN(status);
2435                 NT_STATUS_NOT_OK_RETURN(result);
2436         }
2437
2438         if (info3) {
2439
2440                 ZERO_STRUCT(dom_info);
2441
2442                 dom_info.info3 = *info3;
2443
2444                 status = dcerpc_samr_SetDomainInfo(b, mem_ctx,
2445                                                    domain_handle,
2446                                                    3,
2447                                                    &dom_info,
2448                                                    &result);
2449
2450                 NT_STATUS_NOT_OK_RETURN(status);
2451                 NT_STATUS_NOT_OK_RETURN(result);
2452         }
2453
2454         if (info12) {
2455
2456                 ZERO_STRUCT(dom_info);
2457
2458                 dom_info.info12 = *info12;
2459
2460                 status = dcerpc_samr_SetDomainInfo(b, mem_ctx,
2461                                                    domain_handle,
2462                                                    12,
2463                                                    &dom_info,
2464                                                    &result);
2465
2466                 NT_STATUS_NOT_OK_RETURN(status);
2467                 NT_STATUS_NOT_OK_RETURN(result);
2468         }
2469
2470         return NT_STATUS_OK;
2471 }
2472
2473 /****************************************************************
2474 ****************************************************************/
2475
2476 static NTSTATUS set_USER_MODALS_INFO_0_buffer(TALLOC_CTX *mem_ctx,
2477                                               struct rpc_pipe_client *pipe_cli,
2478                                               struct policy_handle *domain_handle,
2479                                               struct USER_MODALS_INFO_0 *info0)
2480 {
2481         NTSTATUS status;
2482         struct samr_DomInfo1 dom_info_1;
2483         struct samr_DomInfo3 dom_info_3;
2484
2485         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2486                                             pipe_cli,
2487                                             domain_handle,
2488                                             &dom_info_1,
2489                                             &dom_info_3,
2490                                             NULL,
2491                                             NULL,
2492                                             NULL,
2493                                             NULL);
2494         NT_STATUS_NOT_OK_RETURN(status);
2495
2496         dom_info_1.min_password_length =
2497                 info0->usrmod0_min_passwd_len;
2498         dom_info_1.password_history_length =
2499                 info0->usrmod0_password_hist_len;
2500
2501         unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2502                 info0->usrmod0_max_passwd_age);
2503         unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2504                 info0->usrmod0_min_passwd_age);
2505
2506         unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2507                 info0->usrmod0_force_logoff);
2508
2509         return set_USER_MODALS_INFO_rpc(mem_ctx,
2510                                         pipe_cli,
2511                                         domain_handle,
2512                                         &dom_info_1,
2513                                         &dom_info_3,
2514                                         NULL);
2515 }
2516
2517 /****************************************************************
2518 ****************************************************************/
2519
2520 static NTSTATUS set_USER_MODALS_INFO_3_buffer(TALLOC_CTX *mem_ctx,
2521                                               struct rpc_pipe_client *pipe_cli,
2522                                               struct policy_handle *domain_handle,
2523                                               struct USER_MODALS_INFO_3 *info3)
2524 {
2525         NTSTATUS status;
2526         struct samr_DomInfo12 dom_info_12;
2527
2528         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2529                                             pipe_cli,
2530                                             domain_handle,
2531                                             NULL,
2532                                             NULL,
2533                                             NULL,
2534                                             NULL,
2535                                             NULL,
2536                                             &dom_info_12);
2537         NT_STATUS_NOT_OK_RETURN(status);
2538
2539         unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_duration,
2540                 info3->usrmod3_lockout_duration);
2541         unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_window,
2542                 info3->usrmod3_lockout_observation_window);
2543         dom_info_12.lockout_threshold = info3->usrmod3_lockout_threshold;
2544
2545         return set_USER_MODALS_INFO_rpc(mem_ctx,
2546                                         pipe_cli,
2547                                         domain_handle,
2548                                         NULL,
2549                                         NULL,
2550                                         &dom_info_12);
2551 }
2552
2553 /****************************************************************
2554 ****************************************************************/
2555
2556 static NTSTATUS set_USER_MODALS_INFO_1001_buffer(TALLOC_CTX *mem_ctx,
2557                                                  struct rpc_pipe_client *pipe_cli,
2558                                                  struct policy_handle *domain_handle,
2559                                                  struct USER_MODALS_INFO_1001 *info1001)
2560 {
2561         NTSTATUS status;
2562         struct samr_DomInfo1 dom_info_1;
2563
2564         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2565                                             pipe_cli,
2566                                             domain_handle,
2567                                             &dom_info_1,
2568                                             NULL,
2569                                             NULL,
2570                                             NULL,
2571                                             NULL,
2572                                             NULL);
2573         NT_STATUS_NOT_OK_RETURN(status);
2574
2575         dom_info_1.min_password_length =
2576                 info1001->usrmod1001_min_passwd_len;
2577
2578         return set_USER_MODALS_INFO_rpc(mem_ctx,
2579                                         pipe_cli,
2580                                         domain_handle,
2581                                         &dom_info_1,
2582                                         NULL,
2583                                         NULL);
2584 }
2585
2586 /****************************************************************
2587 ****************************************************************/
2588
2589 static NTSTATUS set_USER_MODALS_INFO_1002_buffer(TALLOC_CTX *mem_ctx,
2590                                                  struct rpc_pipe_client *pipe_cli,
2591                                                  struct policy_handle *domain_handle,
2592                                                  struct USER_MODALS_INFO_1002 *info1002)
2593 {
2594         NTSTATUS status;
2595         struct samr_DomInfo1 dom_info_1;
2596
2597         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2598                                             pipe_cli,
2599                                             domain_handle,
2600                                             &dom_info_1,
2601                                             NULL,
2602                                             NULL,
2603                                             NULL,
2604                                             NULL,
2605                                             NULL);
2606         NT_STATUS_NOT_OK_RETURN(status);
2607
2608         unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2609                 info1002->usrmod1002_max_passwd_age);
2610
2611         return set_USER_MODALS_INFO_rpc(mem_ctx,
2612                                         pipe_cli,
2613                                         domain_handle,
2614                                         &dom_info_1,
2615                                         NULL,
2616                                         NULL);
2617 }
2618
2619 /****************************************************************
2620 ****************************************************************/
2621
2622 static NTSTATUS set_USER_MODALS_INFO_1003_buffer(TALLOC_CTX *mem_ctx,
2623                                                  struct rpc_pipe_client *pipe_cli,
2624                                                  struct policy_handle *domain_handle,
2625                                                  struct USER_MODALS_INFO_1003 *info1003)
2626 {
2627         NTSTATUS status;
2628         struct samr_DomInfo1 dom_info_1;
2629
2630         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2631                                             pipe_cli,
2632                                             domain_handle,
2633                                             &dom_info_1,
2634                                             NULL,
2635                                             NULL,
2636                                             NULL,
2637                                             NULL,
2638                                             NULL);
2639         NT_STATUS_NOT_OK_RETURN(status);
2640
2641         unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2642                 info1003->usrmod1003_min_passwd_age);
2643
2644         return set_USER_MODALS_INFO_rpc(mem_ctx,
2645                                         pipe_cli,
2646                                         domain_handle,
2647                                         &dom_info_1,
2648                                         NULL,
2649                                         NULL);
2650 }
2651
2652 /****************************************************************
2653 ****************************************************************/
2654
2655 static NTSTATUS set_USER_MODALS_INFO_1004_buffer(TALLOC_CTX *mem_ctx,
2656                                                  struct rpc_pipe_client *pipe_cli,
2657                                                  struct policy_handle *domain_handle,
2658                                                  struct USER_MODALS_INFO_1004 *info1004)
2659 {
2660         NTSTATUS status;
2661         struct samr_DomInfo3 dom_info_3;
2662
2663         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2664                                             pipe_cli,
2665                                             domain_handle,
2666                                             NULL,
2667                                             &dom_info_3,
2668                                             NULL,
2669                                             NULL,
2670                                             NULL,
2671                                             NULL);
2672         NT_STATUS_NOT_OK_RETURN(status);
2673
2674         unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2675                 info1004->usrmod1004_force_logoff);
2676
2677         return set_USER_MODALS_INFO_rpc(mem_ctx,
2678                                         pipe_cli,
2679                                         domain_handle,
2680                                         NULL,
2681                                         &dom_info_3,
2682                                         NULL);
2683 }
2684
2685 /****************************************************************
2686 ****************************************************************/
2687
2688 static NTSTATUS set_USER_MODALS_INFO_1005_buffer(TALLOC_CTX *mem_ctx,
2689                                                  struct rpc_pipe_client *pipe_cli,
2690                                                  struct policy_handle *domain_handle,
2691                                                  struct USER_MODALS_INFO_1005 *info1005)
2692 {
2693         NTSTATUS status;
2694         struct samr_DomInfo1 dom_info_1;
2695
2696         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2697                                             pipe_cli,
2698                                             domain_handle,
2699                                             &dom_info_1,
2700                                             NULL,
2701                                             NULL,
2702                                             NULL,
2703                                             NULL,
2704                                             NULL);
2705         NT_STATUS_NOT_OK_RETURN(status);
2706
2707         dom_info_1.password_history_length =
2708                 info1005->usrmod1005_password_hist_len;
2709
2710         return set_USER_MODALS_INFO_rpc(mem_ctx,
2711                                         pipe_cli,
2712                                         domain_handle,
2713                                         &dom_info_1,
2714                                         NULL,
2715                                         NULL);
2716 }
2717
2718 /****************************************************************
2719 ****************************************************************/
2720
2721 static NTSTATUS set_USER_MODALS_INFO_buffer(TALLOC_CTX *mem_ctx,
2722                                             struct rpc_pipe_client *pipe_cli,
2723                                             uint32_t level,
2724                                             struct policy_handle *domain_handle,
2725                                             struct dom_sid *domain_sid,
2726                                             uint8_t *buffer)
2727 {
2728         struct USER_MODALS_INFO_0 *info0;
2729         struct USER_MODALS_INFO_3 *info3;
2730         struct USER_MODALS_INFO_1001 *info1001;
2731         struct USER_MODALS_INFO_1002 *info1002;
2732         struct USER_MODALS_INFO_1003 *info1003;
2733         struct USER_MODALS_INFO_1004 *info1004;
2734         struct USER_MODALS_INFO_1005 *info1005;
2735
2736         if (!buffer) {
2737                 return ERROR_INSUFFICIENT_BUFFER;
2738         }
2739
2740         switch (level) {
2741                 case 0:
2742                         info0 = (struct USER_MODALS_INFO_0 *)buffer;
2743                         return set_USER_MODALS_INFO_0_buffer(mem_ctx,
2744                                                              pipe_cli,
2745                                                              domain_handle,
2746                                                              info0);
2747                 case 3:
2748                         info3 = (struct USER_MODALS_INFO_3 *)buffer;
2749                         return set_USER_MODALS_INFO_3_buffer(mem_ctx,
2750                                                              pipe_cli,
2751                                                              domain_handle,
2752                                                              info3);
2753                 case 1001:
2754                         info1001 = (struct USER_MODALS_INFO_1001 *)buffer;
2755                         return set_USER_MODALS_INFO_1001_buffer(mem_ctx,
2756                                                                 pipe_cli,
2757                                                                 domain_handle,
2758                                                                 info1001);
2759                 case 1002:
2760                         info1002 = (struct USER_MODALS_INFO_1002 *)buffer;
2761                         return set_USER_MODALS_INFO_1002_buffer(mem_ctx,
2762                                                                 pipe_cli,
2763                                                                 domain_handle,
2764                                                                 info1002);
2765                 case 1003:
2766                         info1003 = (struct USER_MODALS_INFO_1003 *)buffer;
2767                         return set_USER_MODALS_INFO_1003_buffer(mem_ctx,
2768                                                                 pipe_cli,
2769                                                                 domain_handle,
2770                                                                 info1003);
2771                 case 1004:
2772                         info1004 = (struct USER_MODALS_INFO_1004 *)buffer;
2773                         return set_USER_MODALS_INFO_1004_buffer(mem_ctx,
2774                                                                 pipe_cli,
2775                                                                 domain_handle,
2776                                                                 info1004);
2777                 case 1005:
2778                         info1005 = (struct USER_MODALS_INFO_1005 *)buffer;
2779                         return set_USER_MODALS_INFO_1005_buffer(mem_ctx,
2780                                                                 pipe_cli,
2781                                                                 domain_handle,
2782                                                                 info1005);
2783
2784                 default:
2785                         break;
2786         }
2787
2788         return NT_STATUS_OK;
2789 }
2790
2791 /****************************************************************
2792 ****************************************************************/
2793
2794 WERROR NetUserModalsSet_r(struct libnetapi_ctx *ctx,
2795                           struct NetUserModalsSet *r)
2796 {
2797         struct rpc_pipe_client *pipe_cli = NULL;
2798         NTSTATUS status;
2799         WERROR werr;
2800
2801         struct policy_handle connect_handle, domain_handle;
2802         struct dom_sid2 *domain_sid = NULL;
2803         uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2804
2805         ZERO_STRUCT(connect_handle);
2806         ZERO_STRUCT(domain_handle);
2807
2808         if (!r->in.buffer) {
2809                 return WERR_INVALID_PARAM;
2810         }
2811
2812         switch (r->in.level) {
2813                 case 0:
2814                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2815                                        SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2816                                        SAMR_DOMAIN_ACCESS_SET_INFO_1 |
2817                                        SAMR_DOMAIN_ACCESS_SET_INFO_2;
2818                         break;
2819                 case 3:
2820                 case 1001:
2821                 case 1002:
2822                 case 1003:
2823                 case 1005:
2824                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2825                                        SAMR_DOMAIN_ACCESS_SET_INFO_1;
2826                         break;
2827                 case 1004:
2828                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2829                                        SAMR_DOMAIN_ACCESS_SET_INFO_2;
2830                         break;
2831                 case 1:
2832                 case 2:
2833                 case 1006:
2834                 case 1007:
2835                         werr = WERR_NOT_SUPPORTED;
2836                         break;
2837                 default:
2838                         werr = WERR_UNKNOWN_LEVEL;
2839                         goto done;
2840         }
2841
2842         werr = libnetapi_open_pipe(ctx, r->in.server_name,
2843                                    &ndr_table_samr.syntax_id,
2844                                    &pipe_cli);
2845         if (!W_ERROR_IS_OK(werr)) {
2846                 goto done;
2847         }
2848
2849         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2850                                           SAMR_ACCESS_ENUM_DOMAINS |
2851                                           SAMR_ACCESS_LOOKUP_DOMAIN,
2852                                           access_mask,
2853                                           &connect_handle,
2854                                           &domain_handle,
2855                                           &domain_sid);
2856         if (!W_ERROR_IS_OK(werr)) {
2857                 goto done;
2858         }
2859
2860         status = set_USER_MODALS_INFO_buffer(ctx,
2861                                              pipe_cli,
2862                                              r->in.level,
2863                                              &domain_handle,
2864                                              domain_sid,
2865                                              r->in.buffer);
2866         if (!NT_STATUS_IS_OK(status)) {
2867                 werr = ntstatus_to_werror(status);
2868                 goto done;
2869         }
2870
2871  done:
2872         if (ctx->disable_policy_handle_cache) {
2873                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2874                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2875         }
2876
2877         return werr;
2878 }
2879
2880 /****************************************************************
2881 ****************************************************************/
2882
2883 WERROR NetUserModalsSet_l(struct libnetapi_ctx *ctx,
2884                           struct NetUserModalsSet *r)
2885 {
2886         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsSet);
2887 }
2888
2889 /****************************************************************
2890 ****************************************************************/
2891
2892 NTSTATUS add_GROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
2893                                        uint32_t level,
2894                                        const char *group_name,
2895                                        uint32_t attributes,
2896                                        uint8_t **buffer,
2897                                        uint32_t *num_entries)
2898 {
2899         struct GROUP_USERS_INFO_0 u0;
2900         struct GROUP_USERS_INFO_1 u1;
2901
2902         switch (level) {
2903                 case 0:
2904                         if (group_name) {
2905                                 u0.grui0_name = talloc_strdup(mem_ctx, group_name);
2906                                 NT_STATUS_HAVE_NO_MEMORY(u0.grui0_name);
2907                         } else {
2908                                 u0.grui0_name = NULL;
2909                         }
2910
2911                         ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_0, u0,
2912                                      (struct GROUP_USERS_INFO_0 **)buffer, num_entries);
2913                         break;
2914                 case 1:
2915                         if (group_name) {
2916                                 u1.grui1_name = talloc_strdup(mem_ctx, group_name);
2917                                 NT_STATUS_HAVE_NO_MEMORY(u1.grui1_name);
2918                         } else {
2919                                 u1.grui1_name = NULL;
2920                         }
2921
2922                         u1.grui1_attributes = attributes;
2923
2924                         ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_1, u1,
2925                                      (struct GROUP_USERS_INFO_1 **)buffer, num_entries);
2926                         break;
2927                 default:
2928                         return NT_STATUS_INVALID_INFO_CLASS;
2929         }
2930
2931         return NT_STATUS_OK;
2932 }
2933
2934 /****************************************************************
2935 ****************************************************************/
2936
2937 WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
2938                           struct NetUserGetGroups *r)
2939 {
2940         struct rpc_pipe_client *pipe_cli = NULL;
2941         struct policy_handle connect_handle, domain_handle, user_handle;
2942         struct lsa_String lsa_account_name;
2943         struct dom_sid2 *domain_sid = NULL;
2944         struct samr_Ids user_rids, name_types;
2945         struct samr_RidWithAttributeArray *rid_array = NULL;
2946         struct lsa_Strings names;
2947         struct samr_Ids types;
2948         uint32_t *rids = NULL;
2949
2950         int i;
2951         uint32_t entries_read = 0;
2952
2953         NTSTATUS status = NT_STATUS_OK;
2954         NTSTATUS result = NT_STATUS_OK;
2955         WERROR werr;
2956         struct dcerpc_binding_handle *b = NULL;
2957
2958         ZERO_STRUCT(connect_handle);
2959         ZERO_STRUCT(domain_handle);
2960
2961         if (!r->out.buffer) {
2962                 return WERR_INVALID_PARAM;
2963         }
2964
2965         *r->out.buffer = NULL;
2966         *r->out.entries_read = 0;
2967         *r->out.total_entries = 0;
2968
2969         switch (r->in.level) {
2970                 case 0:
2971                 case 1:
2972                         break;
2973                 default:
2974                         return WERR_UNKNOWN_LEVEL;
2975         }
2976
2977         werr = libnetapi_open_pipe(ctx, r->in.server_name,
2978                                    &ndr_table_samr.syntax_id,
2979                                    &pipe_cli);
2980         if (!W_ERROR_IS_OK(werr)) {
2981                 goto done;
2982         }
2983
2984         b = pipe_cli->binding_handle;
2985
2986         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2987                                           SAMR_ACCESS_ENUM_DOMAINS |
2988                                           SAMR_ACCESS_LOOKUP_DOMAIN,
2989                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2990                                           &connect_handle,
2991                                           &domain_handle,
2992                                           &domain_sid);
2993         if (!W_ERROR_IS_OK(werr)) {
2994                 goto done;
2995         }
2996
2997         init_lsa_String(&lsa_account_name, r->in.user_name);
2998
2999         status = dcerpc_samr_LookupNames(b, talloc_tos(),
3000                                          &domain_handle,
3001                                          1,
3002                                          &lsa_account_name,
3003                                          &user_rids,
3004                                          &name_types,
3005                                          &result);
3006         if (!NT_STATUS_IS_OK(status)) {
3007                 werr = ntstatus_to_werror(status);
3008                 goto done;
3009         }
3010         if (!NT_STATUS_IS_OK(result)) {
3011                 werr = ntstatus_to_werror(result);
3012                 goto done;
3013         }
3014
3015         status = dcerpc_samr_OpenUser(b, talloc_tos(),
3016                                       &domain_handle,
3017                                       SAMR_USER_ACCESS_GET_GROUPS,
3018                                       user_rids.ids[0],
3019                                       &user_handle,
3020                                       &result);
3021         if (!NT_STATUS_IS_OK(status)) {
3022                 werr = ntstatus_to_werror(status);
3023                 goto done;
3024         }
3025         if (!NT_STATUS_IS_OK(result)) {
3026                 werr = ntstatus_to_werror(result);
3027                 goto done;
3028         }
3029
3030         status = dcerpc_samr_GetGroupsForUser(b, talloc_tos(),
3031                                               &user_handle,
3032                                               &rid_array,
3033                                               &result);
3034         if (!NT_STATUS_IS_OK(status)) {
3035                 werr = ntstatus_to_werror(status);
3036                 goto done;
3037         }
3038         if (!NT_STATUS_IS_OK(result)) {
3039                 werr = ntstatus_to_werror(result);
3040                 goto done;
3041         }
3042
3043         rids = talloc_array(ctx, uint32_t, rid_array->count);
3044         if (!rids) {
3045                 werr = WERR_NOMEM;
3046                 goto done;
3047         }
3048
3049         for (i=0; i < rid_array->count; i++) {
3050                 rids[i] = rid_array->rids[i].rid;
3051         }
3052
3053         status = dcerpc_samr_LookupRids(b, talloc_tos(),
3054                                         &domain_handle,
3055                                         rid_array->count,
3056                                         rids,
3057                                         &names,
3058                                         &types,
3059                                         &result);
3060         if (!NT_STATUS_IS_OK(status)) {
3061                 werr = ntstatus_to_werror(status);
3062                 goto done;
3063         }
3064         if (!NT_STATUS_IS_OK(result) &&
3065             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
3066                 werr = ntstatus_to_werror(result);
3067                 goto done;
3068         }
3069
3070         for (i=0; i < names.count; i++) {
3071                 status = add_GROUP_USERS_INFO_X_buffer(ctx,
3072                                                        r->in.level,
3073                                                        names.names[i].string,
3074                                                        rid_array->rids[i].attributes,
3075                                                        r->out.buffer,
3076                                                        &entries_read);
3077                 if (!NT_STATUS_IS_OK(status)) {
3078                         werr = ntstatus_to_werror(status);
3079                         goto done;
3080                 }
3081         }
3082
3083         *r->out.entries_read = entries_read;
3084         *r->out.total_entries = entries_read;
3085
3086  done:
3087         if (ctx->disable_policy_handle_cache) {
3088                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3089                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3090         }
3091
3092         return werr;
3093 }
3094
3095 /****************************************************************
3096 ****************************************************************/
3097
3098 WERROR NetUserGetGroups_l(struct libnetapi_ctx *ctx,
3099                           struct NetUserGetGroups *r)
3100 {
3101         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetGroups);
3102 }
3103
3104 /****************************************************************
3105 ****************************************************************/
3106
3107 WERROR NetUserSetGroups_r(struct libnetapi_ctx *ctx,
3108                           struct NetUserSetGroups *r)
3109 {
3110         struct rpc_pipe_client *pipe_cli = NULL;
3111         struct policy_handle connect_handle, domain_handle, user_handle, group_handle;
3112         struct lsa_String lsa_account_name;
3113         struct dom_sid2 *domain_sid = NULL;
3114         struct samr_Ids user_rids, name_types;
3115         struct samr_Ids group_rids;
3116         struct samr_RidWithAttributeArray *rid_array = NULL;
3117         struct lsa_String *lsa_names = NULL;
3118
3119         uint32_t *add_rids = NULL;
3120         uint32_t *del_rids = NULL;
3121         size_t num_add_rids = 0;
3122         size_t num_del_rids = 0;
3123
3124         uint32_t *member_rids = NULL;
3125         size_t num_member_rids = 0;
3126
3127         struct GROUP_USERS_INFO_0 *i0 = NULL;
3128         struct GROUP_USERS_INFO_1 *i1 = NULL;
3129
3130         int i, k;
3131
3132         NTSTATUS status = NT_STATUS_OK;
3133         NTSTATUS result = NT_STATUS_OK;
3134         WERROR werr;
3135         struct dcerpc_binding_handle *b = NULL;
3136
3137         ZERO_STRUCT(connect_handle);
3138         ZERO_STRUCT(domain_handle);
3139
3140         if (!r->in.buffer) {
3141                 return WERR_INVALID_PARAM;
3142         }
3143
3144         switch (r->in.level) {
3145                 case 0:
3146                 case 1:
3147                         break;
3148                 default:
3149                         return WERR_UNKNOWN_LEVEL;
3150         }
3151
3152         werr = libnetapi_open_pipe(ctx, r->in.server_name,
3153                                    &ndr_table_samr.syntax_id,
3154                                    &pipe_cli);
3155         if (!W_ERROR_IS_OK(werr)) {
3156                 goto done;
3157         }
3158
3159         b = pipe_cli->binding_handle;
3160
3161         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
3162                                           SAMR_ACCESS_ENUM_DOMAINS |
3163                                           SAMR_ACCESS_LOOKUP_DOMAIN,
3164                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
3165                                           &connect_handle,
3166                                           &domain_handle,
3167                                           &domain_sid);
3168         if (!W_ERROR_IS_OK(werr)) {
3169                 goto done;
3170         }
3171
3172         init_lsa_String(&lsa_account_name, r->in.user_name);
3173
3174         status = dcerpc_samr_LookupNames(b, talloc_tos(),
3175                                          &domain_handle,
3176                                          1,
3177                                          &lsa_account_name,
3178                                          &user_rids,
3179                                          &name_types,
3180                                          &result);
3181         if (!NT_STATUS_IS_OK(status)) {
3182                 werr = ntstatus_to_werror(status);
3183                 goto done;
3184         }
3185         if (!NT_STATUS_IS_OK(result)) {
3186                 werr = ntstatus_to_werror(result);
3187                 goto done;
3188         }
3189
3190         status = dcerpc_samr_OpenUser(b, talloc_tos(),
3191                                       &domain_handle,
3192                                       SAMR_USER_ACCESS_GET_GROUPS,
3193                                       user_rids.ids[0],
3194                                       &user_handle,
3195                                       &result);
3196         if (!NT_STATUS_IS_OK(status)) {
3197                 werr = ntstatus_to_werror(status);
3198                 goto done;
3199         }
3200         if (!NT_STATUS_IS_OK(result)) {
3201                 werr = ntstatus_to_werror(result);
3202                 goto done;
3203         }
3204
3205         switch (r->in.level) {
3206                 case 0:
3207                         i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
3208                         break;
3209                 case 1:
3210                         i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
3211                         break;
3212         }
3213
3214         lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
3215         if (!lsa_names) {
3216                 werr = WERR_NOMEM;
3217                 goto done;
3218         }
3219
3220         for (i=0; i < r->in.num_entries; i++) {
3221
3222                 switch (r->in.level) {
3223                         case 0:
3224                                 init_lsa_String(&lsa_names[i], i0->grui0_name);
3225                                 i0++;
3226                                 break;
3227                         case 1:
3228                                 init_lsa_String(&lsa_names[i], i1->grui1_name);
3229                                 i1++;
3230                                 break;
3231                 }
3232         }
3233
3234         status = dcerpc_samr_LookupNames(b, talloc_tos(),
3235                                          &domain_handle,
3236                                          r->in.num_entries,
3237                                          lsa_names,
3238                                          &group_rids,
3239                                          &name_types,
3240                                          &result);
3241         if (!NT_STATUS_IS_OK(status)) {
3242                 werr = ntstatus_to_werror(status);
3243                 goto done;
3244         }
3245         if (!NT_STATUS_IS_OK(result)) {
3246                 werr = ntstatus_to_werror(result);
3247                 goto done;
3248         }
3249
3250         member_rids = group_rids.ids;
3251         num_member_rids = group_rids.count;
3252
3253         status = dcerpc_samr_GetGroupsForUser(b, talloc_tos(),
3254                                               &user_handle,
3255                                               &rid_array,
3256                                               &result);
3257         if (!NT_STATUS_IS_OK(status)) {
3258                 werr = ntstatus_to_werror(status);
3259                 goto done;
3260         }
3261         if (!NT_STATUS_IS_OK(result)) {
3262                 werr = ntstatus_to_werror(result);
3263                 goto done;
3264         }
3265
3266         /* add list */
3267
3268         for (i=0; i < r->in.num_entries; i++) {
3269                 bool already_member = false;
3270                 for (k=0; k < rid_array->count; k++) {
3271                         if (member_rids[i] == rid_array->rids[k].rid) {
3272                                 already_member = true;
3273                                 break;
3274                         }
3275                 }
3276                 if (!already_member) {
3277                         if (!add_rid_to_array_unique(ctx,
3278                                                      member_rids[i],
3279                                                      &add_rids, &num_add_rids)) {
3280                                 werr = WERR_GENERAL_FAILURE;
3281                                 goto done;
3282                         }
3283                 }
3284         }
3285
3286         /* del list */
3287
3288         for (k=0; k < rid_array->count; k++) {
3289                 bool keep_member = false;
3290                 for (i=0; i < r->in.num_entries; i++) {
3291                         if (member_rids[i] == rid_array->rids[k].rid) {
3292                                 keep_member = true;
3293                                 break;
3294                         }
3295                 }
3296                 if (!keep_member) {
3297                         if (!add_rid_to_array_unique(ctx,
3298                                                      rid_array->rids[k].rid,
3299                                                      &del_rids, &num_del_rids)) {
3300                                 werr = WERR_GENERAL_FAILURE;
3301                                 goto done;
3302                         }
3303                 }
3304         }
3305
3306         /* add list */
3307
3308         for (i=0; i < num_add_rids; i++) {
3309                 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
3310                                                &domain_handle,
3311                                                SAMR_GROUP_ACCESS_ADD_MEMBER,
3312                                                add_rids[i],
3313                                                &group_handle,
3314                                                &result);
3315                 if (!NT_STATUS_IS_OK(status)) {
3316                         werr = ntstatus_to_werror(status);
3317                         goto done;
3318                 }
3319                 if (!NT_STATUS_IS_OK(result)) {
3320                         werr = ntstatus_to_werror(result);
3321                         goto done;
3322                 }
3323
3324                 status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
3325                                                     &group_handle,
3326                                                     user_rids.ids[0],
3327                                                     7 /* ? */,
3328                                                     &result);
3329                 if (!NT_STATUS_IS_OK(status)) {
3330                         werr = ntstatus_to_werror(status);
3331                         goto done;
3332                 }
3333                 if (!NT_STATUS_IS_OK(result)) {
3334                         werr = ntstatus_to_werror(result);
3335                         goto done;
3336                 }
3337
3338                 if (is_valid_policy_hnd(&group_handle)) {
3339                         dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
3340                 }
3341         }
3342
3343         /* del list */
3344
3345         for (i=0; i < num_del_rids; i++) {
3346                 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
3347                                                &domain_handle,
3348                                                SAMR_GROUP_ACCESS_REMOVE_MEMBER,
3349                                                del_rids[i],
3350                                                &group_handle,
3351                                                &result);
3352                 if (!NT_STATUS_IS_OK(status)) {
3353                         werr = ntstatus_to_werror(status);
3354                         goto done;
3355                 }
3356                 if (!NT_STATUS_IS_OK(result)) {
3357                         werr = ntstatus_to_werror(result);
3358                         goto done;
3359                 }
3360
3361                 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
3362                                                        &group_handle,
3363                                                        user_rids.ids[0],
3364                                                        &result);
3365                 if (!NT_STATUS_IS_OK(status)) {
3366                         werr = ntstatus_to_werror(status);
3367                         goto done;
3368                 }
3369                 if (!NT_STATUS_IS_OK(result)) {
3370                         werr = ntstatus_to_werror(result);
3371                         goto done;
3372                 }
3373
3374                 if (is_valid_policy_hnd(&group_handle)) {
3375                         dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
3376                 }
3377         }
3378
3379         werr = WERR_OK;
3380
3381  done:
3382         if (is_valid_policy_hnd(&group_handle)) {
3383                 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
3384         }
3385
3386         if (ctx->disable_policy_handle_cache) {
3387                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3388                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3389         }
3390
3391         return werr;
3392 }
3393
3394 /****************************************************************
3395 ****************************************************************/
3396
3397 WERROR NetUserSetGroups_l(struct libnetapi_ctx *ctx,
3398                           struct NetUserSetGroups *r)
3399 {
3400         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetGroups);
3401 }
3402
3403 /****************************************************************
3404 ****************************************************************/
3405
3406 static NTSTATUS add_LOCALGROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
3407                                                    uint32_t level,
3408                                                    const char *group_name,
3409                                                    uint8_t **buffer,
3410                                                    uint32_t *num_entries)
3411 {
3412         struct LOCALGROUP_USERS_INFO_0 u0;
3413
3414         switch (level) {
3415                 case 0:
3416                         u0.lgrui0_name = talloc_strdup(mem_ctx, group_name);
3417                         NT_STATUS_HAVE_NO_MEMORY(u0.lgrui0_name);
3418
3419                         ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_USERS_INFO_0, u0,
3420                                      (struct LOCALGROUP_USERS_INFO_0 **)buffer, num_entries);
3421                         break;
3422                 default:
3423                         return NT_STATUS_INVALID_INFO_CLASS;
3424         }
3425
3426         return NT_STATUS_OK;
3427 }
3428
3429 /****************************************************************
3430 ****************************************************************/
3431
3432 WERROR NetUserGetLocalGroups_r(struct libnetapi_ctx *ctx,
3433                                struct NetUserGetLocalGroups *r)
3434 {
3435         struct rpc_pipe_client *pipe_cli = NULL;
3436         struct policy_handle connect_handle, domain_handle, user_handle,
3437         builtin_handle;
3438         struct lsa_String lsa_account_name;
3439         struct dom_sid2 *domain_sid = NULL;
3440         struct samr_Ids user_rids, name_types;
3441         struct samr_RidWithAttributeArray *rid_array = NULL;
3442         struct lsa_Strings names;
3443         struct samr_Ids types;
3444         uint32_t *rids = NULL;
3445         size_t num_rids = 0;
3446         struct dom_sid user_sid;
3447         struct lsa_SidArray sid_array;
3448         struct samr_Ids domain_rids;
3449         struct samr_Ids builtin_rids;
3450
3451         int i;
3452         uint32_t entries_read = 0;
3453
3454         NTSTATUS status = NT_STATUS_OK;
3455         NTSTATUS result = NT_STATUS_OK;
3456         WERROR werr;
3457         struct dcerpc_binding_handle *b = NULL;
3458
3459         ZERO_STRUCT(connect_handle);
3460         ZERO_STRUCT(domain_handle);
3461
3462         if (!r->out.buffer) {
3463                 return WERR_INVALID_PARAM;
3464         }
3465
3466         *r->out.buffer = NULL;
3467         *r->out.entries_read = 0;
3468         *r->out.total_entries = 0;
3469
3470         switch (r->in.level) {
3471                 case 0:
3472                 case 1:
3473                         break;
3474                 default:
3475                         return WERR_UNKNOWN_LEVEL;
3476         }
3477
3478         werr = libnetapi_open_pipe(ctx, r->in.server_name,
3479                                    &ndr_table_samr.syntax_id,
3480                                    &pipe_cli);
3481         if (!W_ERROR_IS_OK(werr)) {
3482                 goto done;
3483         }
3484
3485         b = pipe_cli->binding_handle;
3486
3487         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
3488                                           SAMR_ACCESS_ENUM_DOMAINS |
3489                                           SAMR_ACCESS_LOOKUP_DOMAIN,
3490                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
3491                                           SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
3492                                           &connect_handle,
3493                                           &domain_handle,
3494                                           &domain_sid);
3495         if (!W_ERROR_IS_OK(werr)) {
3496                 goto done;
3497         }
3498
3499         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
3500                                                   SAMR_ACCESS_ENUM_DOMAINS |
3501                                                   SAMR_ACCESS_LOOKUP_DOMAIN,
3502                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
3503                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
3504                                                   &connect_handle,
3505                                                   &builtin_handle);
3506         if (!W_ERROR_IS_OK(werr)) {
3507                 goto done;
3508         }
3509
3510         init_lsa_String(&lsa_account_name, r->in.user_name);
3511
3512         status = dcerpc_samr_LookupNames(b, talloc_tos(),
3513                                          &domain_handle,
3514                                          1,
3515                                          &lsa_account_name,
3516                                          &user_rids,
3517                                          &name_types,
3518                                          &result);
3519         if (!NT_STATUS_IS_OK(status)) {
3520                 werr = ntstatus_to_werror(status);
3521                 goto done;
3522         }
3523         if (!NT_STATUS_IS_OK(result)) {
3524                 werr = ntstatus_to_werror(result);
3525                 goto done;
3526         }
3527
3528         status = dcerpc_samr_OpenUser(b, talloc_tos(),
3529                                       &domain_handle,
3530                                       SAMR_USER_ACCESS_GET_GROUPS,
3531                                       user_rids.ids[0],
3532                                       &user_handle,
3533                                       &result);
3534         if (!NT_STATUS_IS_OK(status)) {
3535                 werr = ntstatus_to_werror(status);
3536                 goto done;
3537         }
3538         if (!NT_STATUS_IS_OK(result)) {
3539                 werr = ntstatus_to_werror(result);
3540                 goto done;
3541         }
3542
3543         status = dcerpc_samr_GetGroupsForUser(b, talloc_tos(),
3544                                               &user_handle,
3545                                               &rid_array,
3546                                               &result);
3547         if (!NT_STATUS_IS_OK(status)) {
3548                 werr = ntstatus_to_werror(status);
3549                 goto done;
3550         }
3551         if (!NT_STATUS_IS_OK(result)) {
3552                 werr = ntstatus_to_werror(result);
3553                 goto done;
3554         }
3555
3556         if (!sid_compose(&user_sid, domain_sid, user_rids.ids[0])) {
3557                 werr = WERR_NOMEM;
3558                 goto done;
3559         }
3560
3561         sid_array.num_sids = rid_array->count + 1;
3562         sid_array.sids = TALLOC_ARRAY(ctx, struct lsa_SidPtr, sid_array.num_sids);
3563         if (!sid_array.sids) {
3564                 werr = WERR_NOMEM;
3565                 goto done;
3566         }
3567
3568         sid_array.sids[0].sid = dom_sid_dup(ctx, &user_sid);
3569         if (!sid_array.sids[0].sid) {
3570                 werr = WERR_NOMEM;
3571                 goto done;
3572         }
3573
3574         for (i=0; i < rid_array->count; i++) {
3575                 struct dom_sid sid;
3576
3577                 if (!sid_compose(&sid, domain_sid, rid_array->rids[i].rid)) {
3578                         werr = WERR_NOMEM;
3579                         goto done;
3580                 }
3581
3582                 sid_array.sids[i+1].sid = dom_sid_dup(ctx, &sid);
3583                 if (!sid_array.sids[i+1].sid) {
3584                         werr = WERR_NOMEM;
3585                         goto done;
3586                 }
3587         }
3588
3589         status = dcerpc_samr_GetAliasMembership(b, talloc_tos(),
3590                                                 &domain_handle,
3591                                                 &sid_array,
3592                                                 &domain_rids,
3593                                                 &result);
3594         if (!NT_STATUS_IS_OK(status)) {
3595                 werr = ntstatus_to_werror(status);
3596                 goto done;
3597         }
3598         if (!NT_STATUS_IS_OK(result)) {
3599                 werr = ntstatus_to_werror(result);
3600                 goto done;
3601         }
3602
3603         for (i=0; i < domain_rids.count; i++) {
3604                 if (!add_rid_to_array_unique(ctx, domain_rids.ids[i],
3605                                              &rids, &num_rids)) {
3606                         werr = WERR_NOMEM;
3607                         goto done;
3608                 }
3609         }
3610
3611         status = dcerpc_samr_GetAliasMembership(b, talloc_tos(),
3612                                                 &builtin_handle,
3613                                                 &sid_array,
3614                                                 &builtin_rids,
3615                                                 &result);
3616         if (!NT_STATUS_IS_OK(status)) {
3617                 werr = ntstatus_to_werror(status);
3618                 goto done;
3619         }
3620         if (!NT_STATUS_IS_OK(result)) {
3621                 werr = ntstatus_to_werror(result);
3622                 goto done;
3623         }
3624
3625         for (i=0; i < builtin_rids.count; i++) {
3626                 if (!add_rid_to_array_unique(ctx, builtin_rids.ids[i],
3627                                              &rids, &num_rids)) {
3628                         werr = WERR_NOMEM;
3629                         goto done;
3630                 }
3631         }
3632
3633         status = dcerpc_samr_LookupRids(b, talloc_tos(),
3634                                         &builtin_handle,
3635                                         num_rids,
3636                                         rids,
3637                                         &names,
3638                                         &types,
3639                                         &result);
3640         if (!NT_STATUS_IS_OK(status)) {
3641                 werr = ntstatus_to_werror(status);
3642                 goto done;
3643         }
3644         if (!NT_STATUS_IS_OK(result)) {
3645                 werr = ntstatus_to_werror(result);
3646                 goto done;
3647         }
3648
3649         for (i=0; i < names.count; i++) {
3650                 status = add_LOCALGROUP_USERS_INFO_X_buffer(ctx,
3651                                                             r->in.level,
3652                                                             names.names[i].string,
3653                                                             r->out.buffer,
3654                                                             &entries_read);
3655                 if (!NT_STATUS_IS_OK(status)) {
3656                         werr = ntstatus_to_werror(status);
3657                         goto done;
3658                 }
3659         }
3660
3661         *r->out.entries_read = entries_read;
3662         *r->out.total_entries = entries_read;
3663
3664  done:
3665         if (ctx->disable_policy_handle_cache) {
3666                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3667                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3668         }
3669
3670         return werr;
3671 }
3672
3673 /****************************************************************
3674 ****************************************************************/
3675
3676 WERROR NetUserGetLocalGroups_l(struct libnetapi_ctx *ctx,
3677                                struct NetUserGetLocalGroups *r)
3678 {
3679         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetLocalGroups);
3680 }