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