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