libnetapi: Fix 241166 Fixing logically dead code
[amitay/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_EXPIRED_FLAG;
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 1:
1205                         status = info21_to_USER_INFO_1(mem_ctx, info21, &info1);
1206                         NT_STATUS_NOT_OK_RETURN(status);
1207
1208                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_1, info1,
1209                                      (struct USER_INFO_1 **)buffer, num_entries);
1210
1211                         break;
1212                 case 2:
1213                         status = info21_to_USER_INFO_2(mem_ctx, info21, auth_flag, &info2);
1214                         NT_STATUS_NOT_OK_RETURN(status);
1215
1216                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_2, info2,
1217                                      (struct USER_INFO_2 **)buffer, num_entries);
1218
1219                         break;
1220                 case 3:
1221                         status = info21_to_USER_INFO_3(mem_ctx, info21, auth_flag, &info3);
1222                         NT_STATUS_NOT_OK_RETURN(status);
1223
1224                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_3, info3,
1225                                      (struct USER_INFO_3 **)buffer, num_entries);
1226
1227                         break;
1228                 case 4:
1229                         status = info21_to_USER_INFO_4(mem_ctx, info21, auth_flag, domain_sid, &info4);
1230                         NT_STATUS_NOT_OK_RETURN(status);
1231
1232                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_4, info4,
1233                                      (struct USER_INFO_4 **)buffer, num_entries);
1234
1235                         break;
1236                 case 10:
1237                         status = info21_to_USER_INFO_10(mem_ctx, info21, &info10);
1238                         NT_STATUS_NOT_OK_RETURN(status);
1239
1240                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_10, info10,
1241                                      (struct USER_INFO_10 **)buffer, num_entries);
1242
1243                         break;
1244                 case 11:
1245                         status = info21_to_USER_INFO_11(mem_ctx, info21, auth_flag, &info11);
1246                         NT_STATUS_NOT_OK_RETURN(status);
1247
1248                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_11, info11,
1249                                      (struct USER_INFO_11 **)buffer, num_entries);
1250
1251                         break;
1252                 case 20:
1253                         status = info21_to_USER_INFO_20(mem_ctx, info21, &info20);
1254                         NT_STATUS_NOT_OK_RETURN(status);
1255
1256                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_20, info20,
1257                                      (struct USER_INFO_20 **)buffer, num_entries);
1258
1259                         break;
1260                 case 23:
1261                         status = info21_to_USER_INFO_23(mem_ctx, info21, domain_sid, &info23);
1262                         NT_STATUS_NOT_OK_RETURN(status);
1263
1264                         ADD_TO_ARRAY(mem_ctx, struct USER_INFO_23, info23,
1265                                      (struct USER_INFO_23 **)buffer, num_entries);
1266                         break;
1267                 default:
1268                         return NT_STATUS_INVALID_LEVEL;
1269         }
1270
1271  done:
1272         return status;
1273 }
1274
1275 /****************************************************************
1276 ****************************************************************/
1277
1278 WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
1279                      struct NetUserEnum *r)
1280 {
1281         struct rpc_pipe_client *pipe_cli = NULL;
1282         struct policy_handle connect_handle;
1283         struct dom_sid2 *domain_sid = NULL;
1284         struct policy_handle domain_handle, builtin_handle;
1285         struct samr_SamArray *sam = NULL;
1286         uint32_t filter = ACB_NORMAL;
1287         int i;
1288         uint32_t entries_read = 0;
1289
1290         NTSTATUS status = NT_STATUS_OK;
1291         NTSTATUS result = NT_STATUS_OK;
1292         WERROR werr;
1293         struct dcerpc_binding_handle *b = NULL;
1294
1295         ZERO_STRUCT(connect_handle);
1296         ZERO_STRUCT(domain_handle);
1297         ZERO_STRUCT(builtin_handle);
1298
1299         if (!r->out.buffer) {
1300                 return WERR_INVALID_PARAM;
1301         }
1302
1303         *r->out.buffer = NULL;
1304         *r->out.entries_read = 0;
1305
1306         switch (r->in.level) {
1307                 case 0:
1308                 case 1:
1309                 case 2:
1310                 case 3:
1311                 case 4:
1312                 case 10:
1313                 case 11:
1314                 case 20:
1315                 case 23:
1316                         break;
1317                 default:
1318                         return WERR_UNKNOWN_LEVEL;
1319         }
1320
1321         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1322                                    &ndr_table_samr,
1323                                    &pipe_cli);
1324         if (!W_ERROR_IS_OK(werr)) {
1325                 goto done;
1326         }
1327
1328         b = pipe_cli->binding_handle;
1329
1330         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1331                                                   SAMR_ACCESS_ENUM_DOMAINS |
1332                                                   SAMR_ACCESS_LOOKUP_DOMAIN,
1333                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1334                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1335                                                   &connect_handle,
1336                                                   &builtin_handle);
1337         if (!W_ERROR_IS_OK(werr)) {
1338                 goto done;
1339         }
1340
1341         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1342                                           SAMR_ACCESS_ENUM_DOMAINS |
1343                                           SAMR_ACCESS_LOOKUP_DOMAIN,
1344                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1345                                           SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1346                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1347                                           &connect_handle,
1348                                           &domain_handle,
1349                                           &domain_sid);
1350         if (!W_ERROR_IS_OK(werr)) {
1351                 goto done;
1352         }
1353
1354         switch (r->in.filter) {
1355                 case FILTER_NORMAL_ACCOUNT:
1356                         filter = ACB_NORMAL;
1357                         break;
1358                 case FILTER_TEMP_DUPLICATE_ACCOUNT:
1359                         filter = ACB_TEMPDUP;
1360                         break;
1361                 case FILTER_INTERDOMAIN_TRUST_ACCOUNT:
1362                         filter = ACB_DOMTRUST;
1363                         break;
1364                 case FILTER_WORKSTATION_TRUST_ACCOUNT:
1365                         filter = ACB_WSTRUST;
1366                         break;
1367                 case FILTER_SERVER_TRUST_ACCOUNT:
1368                         filter = ACB_SVRTRUST;
1369                         break;
1370                 default:
1371                         break;
1372         }
1373
1374         status = dcerpc_samr_EnumDomainUsers(b,
1375                                              ctx,
1376                                              &domain_handle,
1377                                              r->in.resume_handle,
1378                                              filter,
1379                                              &sam,
1380                                              r->in.prefmaxlen,
1381                                              &entries_read,
1382                                              &result);
1383         if (!NT_STATUS_IS_OK(status)) {
1384                 werr = ntstatus_to_werror(status);
1385                 goto done;
1386         }
1387         werr = ntstatus_to_werror(result);
1388         if (NT_STATUS_IS_ERR(result)) {
1389                 goto done;
1390         }
1391
1392         for (i=0; i < sam->count; i++) {
1393
1394                 status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1395                                                                   domain_sid,
1396                                                                   &domain_handle,
1397                                                                   &builtin_handle,
1398                                                                   sam->entries[i].name.string,
1399                                                                   sam->entries[i].idx,
1400                                                                   r->in.level,
1401                                                                   r->out.buffer,
1402                                                                   r->out.entries_read);
1403                 if (!NT_STATUS_IS_OK(status)) {
1404                         werr = ntstatus_to_werror(status);
1405                         goto done;
1406                 }
1407         }
1408
1409  done:
1410         /* if last query */
1411         if (NT_STATUS_IS_OK(result) ||
1412             NT_STATUS_IS_ERR(result)) {
1413
1414                 if (ctx->disable_policy_handle_cache) {
1415                         libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1416                         libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
1417                         libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1418                 }
1419         }
1420
1421         return werr;
1422 }
1423
1424 /****************************************************************
1425 ****************************************************************/
1426
1427 WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
1428                      struct NetUserEnum *r)
1429 {
1430         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserEnum);
1431 }
1432
1433 /****************************************************************
1434 ****************************************************************/
1435
1436 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_USER(TALLOC_CTX *mem_ctx,
1437                                                         struct samr_DispInfoGeneral *info,
1438                                                         uint32_t *entries_read,
1439                                                         void **buffer)
1440 {
1441         struct NET_DISPLAY_USER *user = NULL;
1442         int i;
1443
1444         user = talloc_zero_array(mem_ctx,
1445                                  struct NET_DISPLAY_USER,
1446                                  info->count);
1447         W_ERROR_HAVE_NO_MEMORY(user);
1448
1449         for (i = 0; i < info->count; i++) {
1450                 user[i].usri1_name = talloc_strdup(mem_ctx,
1451                         info->entries[i].account_name.string);
1452                 user[i].usri1_comment = talloc_strdup(mem_ctx,
1453                         info->entries[i].description.string);
1454                 user[i].usri1_flags =
1455                         info->entries[i].acct_flags;
1456                 user[i].usri1_full_name = talloc_strdup(mem_ctx,
1457                         info->entries[i].full_name.string);
1458                 user[i].usri1_user_id =
1459                         info->entries[i].rid;
1460                 user[i].usri1_next_index =
1461                         info->entries[i].idx;
1462
1463                 if (!user[i].usri1_name) {
1464                         return WERR_NOMEM;
1465                 }
1466         }
1467
1468         *buffer = talloc_memdup(mem_ctx, user,
1469                 sizeof(struct NET_DISPLAY_USER) * info->count);
1470         W_ERROR_HAVE_NO_MEMORY(*buffer);
1471
1472         *entries_read = info->count;
1473
1474         return WERR_OK;
1475 }
1476
1477 /****************************************************************
1478 ****************************************************************/
1479
1480 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(TALLOC_CTX *mem_ctx,
1481                                                            struct samr_DispInfoFull *info,
1482                                                            uint32_t *entries_read,
1483                                                            void **buffer)
1484 {
1485         struct NET_DISPLAY_MACHINE *machine = NULL;
1486         int i;
1487
1488         machine = talloc_zero_array(mem_ctx,
1489                                     struct NET_DISPLAY_MACHINE,
1490                                     info->count);
1491         W_ERROR_HAVE_NO_MEMORY(machine);
1492
1493         for (i = 0; i < info->count; i++) {
1494                 machine[i].usri2_name = talloc_strdup(mem_ctx,
1495                         info->entries[i].account_name.string);
1496                 machine[i].usri2_comment = talloc_strdup(mem_ctx,
1497                         info->entries[i].description.string);
1498                 machine[i].usri2_flags =
1499                         info->entries[i].acct_flags;
1500                 machine[i].usri2_user_id =
1501                         info->entries[i].rid;
1502                 machine[i].usri2_next_index =
1503                         info->entries[i].idx;
1504
1505                 if (!machine[i].usri2_name) {
1506                         return WERR_NOMEM;
1507                 }
1508         }
1509
1510         *buffer = talloc_memdup(mem_ctx, machine,
1511                 sizeof(struct NET_DISPLAY_MACHINE) * info->count);
1512         W_ERROR_HAVE_NO_MEMORY(*buffer);
1513
1514         *entries_read = info->count;
1515
1516         return WERR_OK;
1517 }
1518
1519 /****************************************************************
1520 ****************************************************************/
1521
1522 static WERROR convert_samr_dispinfo_to_NET_DISPLAY_GROUP(TALLOC_CTX *mem_ctx,
1523                                                          struct samr_DispInfoFullGroups *info,
1524                                                          uint32_t *entries_read,
1525                                                          void **buffer)
1526 {
1527         struct NET_DISPLAY_GROUP *group = NULL;
1528         int i;
1529
1530         group = talloc_zero_array(mem_ctx,
1531                                   struct NET_DISPLAY_GROUP,
1532                                   info->count);
1533         W_ERROR_HAVE_NO_MEMORY(group);
1534
1535         for (i = 0; i < info->count; i++) {
1536                 group[i].grpi3_name = talloc_strdup(mem_ctx,
1537                         info->entries[i].account_name.string);
1538                 group[i].grpi3_comment = talloc_strdup(mem_ctx,
1539                         info->entries[i].description.string);
1540                 group[i].grpi3_group_id =
1541                         info->entries[i].rid;
1542                 group[i].grpi3_attributes =
1543                         info->entries[i].acct_flags;
1544                 group[i].grpi3_next_index =
1545                         info->entries[i].idx;
1546
1547                 if (!group[i].grpi3_name) {
1548                         return WERR_NOMEM;
1549                 }
1550         }
1551
1552         *buffer = talloc_memdup(mem_ctx, group,
1553                 sizeof(struct NET_DISPLAY_GROUP) * info->count);
1554         W_ERROR_HAVE_NO_MEMORY(*buffer);
1555
1556         *entries_read = info->count;
1557
1558         return WERR_OK;
1559
1560 }
1561
1562 /****************************************************************
1563 ****************************************************************/
1564
1565 static WERROR convert_samr_dispinfo_to_NET_DISPLAY(TALLOC_CTX *mem_ctx,
1566                                                    union samr_DispInfo *info,
1567                                                    uint32_t level,
1568                                                    uint32_t *entries_read,
1569                                                    void **buffer)
1570 {
1571         switch (level) {
1572                 case 1:
1573                         return convert_samr_dispinfo_to_NET_DISPLAY_USER(mem_ctx,
1574                                                                          &info->info1,
1575                                                                          entries_read,
1576                                                                          buffer);
1577                 case 2:
1578                         return convert_samr_dispinfo_to_NET_DISPLAY_MACHINE(mem_ctx,
1579                                                                             &info->info2,
1580                                                                             entries_read,
1581                                                                             buffer);
1582                 case 3:
1583                         return convert_samr_dispinfo_to_NET_DISPLAY_GROUP(mem_ctx,
1584                                                                           &info->info3,
1585                                                                           entries_read,
1586                                                                           buffer);
1587                 default:
1588                         break;
1589         }
1590
1591         return WERR_UNKNOWN_LEVEL;
1592 }
1593
1594 /****************************************************************
1595 ****************************************************************/
1596
1597 WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
1598                                     struct NetQueryDisplayInformation *r)
1599 {
1600         struct rpc_pipe_client *pipe_cli = NULL;
1601         struct policy_handle connect_handle;
1602         struct dom_sid2 *domain_sid = NULL;
1603         struct policy_handle domain_handle;
1604         union samr_DispInfo info;
1605         struct dcerpc_binding_handle *b = NULL;
1606
1607         uint32_t total_size = 0;
1608         uint32_t returned_size = 0;
1609
1610         NTSTATUS status = NT_STATUS_OK;
1611         NTSTATUS result = NT_STATUS_OK;
1612         WERROR werr;
1613         WERROR werr_tmp;
1614
1615         *r->out.entries_read = 0;
1616
1617         ZERO_STRUCT(connect_handle);
1618         ZERO_STRUCT(domain_handle);
1619
1620         switch (r->in.level) {
1621                 case 1:
1622                 case 2:
1623                 case 3:
1624                         break;
1625                 default:
1626                         return WERR_UNKNOWN_LEVEL;
1627         }
1628
1629         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1630                                    &ndr_table_samr,
1631                                    &pipe_cli);
1632         if (!W_ERROR_IS_OK(werr)) {
1633                 goto done;
1634         }
1635
1636         b = pipe_cli->binding_handle;
1637
1638         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1639                                           SAMR_ACCESS_ENUM_DOMAINS |
1640                                           SAMR_ACCESS_LOOKUP_DOMAIN,
1641                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
1642                                           SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
1643                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1644                                           &connect_handle,
1645                                           &domain_handle,
1646                                           &domain_sid);
1647         if (!W_ERROR_IS_OK(werr)) {
1648                 goto done;
1649         }
1650
1651         status = dcerpc_samr_QueryDisplayInfo2(b,
1652                                                ctx,
1653                                                &domain_handle,
1654                                                r->in.level,
1655                                                r->in.idx,
1656                                                r->in.entries_requested,
1657                                                r->in.prefmaxlen,
1658                                                &total_size,
1659                                                &returned_size,
1660                                                &info,
1661                                                &result);
1662         if (!NT_STATUS_IS_OK(status)) {
1663                 werr = ntstatus_to_werror(status);
1664                 goto done;
1665         }
1666         werr = ntstatus_to_werror(result);
1667         if (NT_STATUS_IS_ERR(result)) {
1668                 goto done;
1669         }
1670
1671         werr_tmp = convert_samr_dispinfo_to_NET_DISPLAY(ctx, &info,
1672                                                         r->in.level,
1673                                                         r->out.entries_read,
1674                                                         r->out.buffer);
1675         if (!W_ERROR_IS_OK(werr_tmp)) {
1676                 werr = werr_tmp;
1677         }
1678  done:
1679         /* if last query */
1680         if (NT_STATUS_IS_OK(result) ||
1681             NT_STATUS_IS_ERR(result)) {
1682
1683                 if (ctx->disable_policy_handle_cache) {
1684                         libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1685                         libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1686                 }
1687         }
1688
1689         return werr;
1690
1691 }
1692
1693 /****************************************************************
1694 ****************************************************************/
1695
1696
1697 WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
1698                                     struct NetQueryDisplayInformation *r)
1699 {
1700         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetQueryDisplayInformation);
1701 }
1702
1703 /****************************************************************
1704 ****************************************************************/
1705
1706 WERROR NetUserChangePassword_r(struct libnetapi_ctx *ctx,
1707                                struct NetUserChangePassword *r)
1708 {
1709         return WERR_NOT_SUPPORTED;
1710 }
1711
1712 /****************************************************************
1713 ****************************************************************/
1714
1715 WERROR NetUserChangePassword_l(struct libnetapi_ctx *ctx,
1716                                struct NetUserChangePassword *r)
1717 {
1718         return WERR_NOT_SUPPORTED;
1719 }
1720
1721 /****************************************************************
1722 ****************************************************************/
1723
1724 WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx,
1725                         struct NetUserGetInfo *r)
1726 {
1727         struct rpc_pipe_client *pipe_cli = NULL;
1728         NTSTATUS status, result;
1729         WERROR werr;
1730
1731         struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1732         struct lsa_String lsa_account_name;
1733         struct dom_sid2 *domain_sid = NULL;
1734         struct samr_Ids user_rids, name_types;
1735         uint32_t num_entries = 0;
1736         struct dcerpc_binding_handle *b = NULL;
1737
1738         ZERO_STRUCT(connect_handle);
1739         ZERO_STRUCT(domain_handle);
1740         ZERO_STRUCT(builtin_handle);
1741         ZERO_STRUCT(user_handle);
1742
1743         if (!r->out.buffer) {
1744                 return WERR_INVALID_PARAM;
1745         }
1746
1747         switch (r->in.level) {
1748                 case 0:
1749                 case 1:
1750                 case 2:
1751                 case 3:
1752                 case 4:
1753                 case 10:
1754                 case 11:
1755                 case 20:
1756                 case 23:
1757                         break;
1758                 default:
1759                         werr = WERR_UNKNOWN_LEVEL;
1760                         goto done;
1761         }
1762
1763         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1764                                    &ndr_table_samr,
1765                                    &pipe_cli);
1766         if (!W_ERROR_IS_OK(werr)) {
1767                 goto done;
1768         }
1769
1770         b = pipe_cli->binding_handle;
1771
1772         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1773                                           SAMR_ACCESS_ENUM_DOMAINS |
1774                                           SAMR_ACCESS_LOOKUP_DOMAIN,
1775                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1776                                           &connect_handle,
1777                                           &domain_handle,
1778                                           &domain_sid);
1779         if (!W_ERROR_IS_OK(werr)) {
1780                 goto done;
1781         }
1782
1783         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1784                                                   SAMR_ACCESS_ENUM_DOMAINS |
1785                                                   SAMR_ACCESS_LOOKUP_DOMAIN,
1786                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1787                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1788                                                   &connect_handle,
1789                                                   &builtin_handle);
1790         if (!W_ERROR_IS_OK(werr)) {
1791                 goto done;
1792         }
1793
1794         init_lsa_String(&lsa_account_name, r->in.user_name);
1795
1796         status = dcerpc_samr_LookupNames(b, talloc_tos(),
1797                                          &domain_handle,
1798                                          1,
1799                                          &lsa_account_name,
1800                                          &user_rids,
1801                                          &name_types,
1802                                          &result);
1803         if (!NT_STATUS_IS_OK(status)) {
1804                 werr = ntstatus_to_werror(status);
1805                 goto done;
1806         }
1807         if (!NT_STATUS_IS_OK(result)) {
1808                 werr = ntstatus_to_werror(result);
1809                 goto done;
1810         }
1811         if (user_rids.count != 1) {
1812                 werr = WERR_BAD_NET_RESP;
1813                 goto done;
1814         }
1815         if (name_types.count != 1) {
1816                 werr = WERR_BAD_NET_RESP;
1817                 goto done;
1818         }
1819
1820         status = libnetapi_samr_lookup_user_map_USER_INFO(ctx, pipe_cli,
1821                                                           domain_sid,
1822                                                           &domain_handle,
1823                                                           &builtin_handle,
1824                                                           r->in.user_name,
1825                                                           user_rids.ids[0],
1826                                                           r->in.level,
1827                                                           r->out.buffer,
1828                                                           &num_entries);
1829         if (!NT_STATUS_IS_OK(status)) {
1830                 werr = ntstatus_to_werror(status);
1831                 goto done;
1832         }
1833
1834  done:
1835         if (is_valid_policy_hnd(&user_handle) && b) {
1836                 dcerpc_samr_Close(b, talloc_tos(), &user_handle, &result);
1837         }
1838
1839         if (ctx->disable_policy_handle_cache) {
1840                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
1841                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
1842         }
1843
1844         return werr;
1845 }
1846
1847 /****************************************************************
1848 ****************************************************************/
1849
1850 WERROR NetUserGetInfo_l(struct libnetapi_ctx *ctx,
1851                         struct NetUserGetInfo *r)
1852 {
1853         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetInfo);
1854 }
1855
1856 /****************************************************************
1857 ****************************************************************/
1858
1859 WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx,
1860                         struct NetUserSetInfo *r)
1861 {
1862         struct rpc_pipe_client *pipe_cli = NULL;
1863         NTSTATUS status, result;
1864         WERROR werr;
1865
1866         struct policy_handle connect_handle, domain_handle, builtin_handle, user_handle;
1867         struct lsa_String lsa_account_name;
1868         struct dom_sid2 *domain_sid = NULL;
1869         struct samr_Ids user_rids, name_types;
1870         uint32_t user_mask = 0;
1871
1872         struct USER_INFO_X uX;
1873         struct dcerpc_binding_handle *b = NULL;
1874         DATA_BLOB session_key;
1875
1876         ZERO_STRUCT(connect_handle);
1877         ZERO_STRUCT(domain_handle);
1878         ZERO_STRUCT(builtin_handle);
1879         ZERO_STRUCT(user_handle);
1880
1881         if (!r->in.buffer) {
1882                 return WERR_INVALID_PARAM;
1883         }
1884
1885         switch (r->in.level) {
1886                 case 0:
1887                         user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
1888                         break;
1889                 case 1003:
1890                         user_mask = SAMR_USER_ACCESS_SET_PASSWORD;
1891                         break;
1892                 case 1006:
1893                 case 1007:
1894                 case 1009:
1895                 case 1011:
1896                 case 1014:
1897                 case 1052:
1898                 case 1053:
1899                         user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES;
1900                         break;
1901                 case 1012:
1902                 case 1024:
1903                         user_mask = SAMR_USER_ACCESS_SET_LOC_COM;
1904                         break;
1905                 case 1051:
1906                         user_mask = SAMR_USER_ACCESS_SET_ATTRIBUTES |
1907                                     SAMR_USER_ACCESS_GET_GROUPS;
1908                         break;
1909                 case 3:
1910                         user_mask = SEC_STD_READ_CONTROL |
1911                                     SEC_STD_WRITE_DAC |
1912                                     SAMR_USER_ACCESS_GET_GROUPS |
1913                                     SAMR_USER_ACCESS_SET_PASSWORD |
1914                                     SAMR_USER_ACCESS_SET_ATTRIBUTES |
1915                                     SAMR_USER_ACCESS_GET_ATTRIBUTES |
1916                                     SAMR_USER_ACCESS_SET_LOC_COM;
1917                         break;
1918                 case 1:
1919                 case 2:
1920                 case 4:
1921                 case 21:
1922                 case 22:
1923                 case 1005:
1924                 case 1008:
1925                 case 1010:
1926                 case 1017:
1927                 case 1020:
1928                         werr = WERR_NOT_SUPPORTED;
1929                         goto done;
1930                 default:
1931                         werr = WERR_UNKNOWN_LEVEL;
1932                         goto done;
1933         }
1934
1935         werr = libnetapi_open_pipe(ctx, r->in.server_name,
1936                                    &ndr_table_samr,
1937                                    &pipe_cli);
1938         if (!W_ERROR_IS_OK(werr)) {
1939                 goto done;
1940         }
1941
1942         b = pipe_cli->binding_handle;
1943
1944         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
1945                                           SAMR_ACCESS_ENUM_DOMAINS |
1946                                           SAMR_ACCESS_LOOKUP_DOMAIN,
1947                                           SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
1948                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1949                                           &connect_handle,
1950                                           &domain_handle,
1951                                           &domain_sid);
1952         if (!W_ERROR_IS_OK(werr)) {
1953                 goto done;
1954         }
1955
1956         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
1957                                                   SAMR_ACCESS_ENUM_DOMAINS |
1958                                                   SAMR_ACCESS_LOOKUP_DOMAIN,
1959                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
1960                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
1961                                                   &connect_handle,
1962                                                   &builtin_handle);
1963         if (!W_ERROR_IS_OK(werr)) {
1964                 goto done;
1965         }
1966
1967         init_lsa_String(&lsa_account_name, r->in.user_name);
1968
1969         status = dcerpc_samr_LookupNames(b, talloc_tos(),
1970                                          &domain_handle,
1971                                          1,
1972                                          &lsa_account_name,
1973                                          &user_rids,
1974                                          &name_types,
1975                                          &result);
1976         if (!NT_STATUS_IS_OK(status)) {
1977                 werr = ntstatus_to_werror(status);
1978                 goto done;
1979         }
1980         if (!NT_STATUS_IS_OK(result)) {
1981                 werr = ntstatus_to_werror(result);
1982                 goto done;
1983         }
1984         if (user_rids.count != 1) {
1985                 werr = WERR_BAD_NET_RESP;
1986                 goto done;
1987         }
1988         if (name_types.count != 1) {
1989                 werr = WERR_BAD_NET_RESP;
1990                 goto done;
1991         }
1992
1993         status = dcerpc_samr_OpenUser(b, talloc_tos(),
1994                                       &domain_handle,
1995                                       user_mask,
1996                                       user_rids.ids[0],
1997                                       &user_handle,
1998                                       &result);
1999         if (!NT_STATUS_IS_OK(status)) {
2000                 werr = ntstatus_to_werror(status);
2001                 goto done;
2002         }
2003         if (!NT_STATUS_IS_OK(result)) {
2004                 werr = ntstatus_to_werror(result);
2005                 goto done;
2006         }
2007
2008         status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX);
2009         if (!NT_STATUS_IS_OK(status)) {
2010                 werr = ntstatus_to_werror(status);
2011                 goto done;
2012         }
2013
2014         status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
2015         if (!NT_STATUS_IS_OK(status)) {
2016                 werr = ntstatus_to_werror(status);
2017                 goto done;
2018         }
2019
2020         status = set_user_info_USER_INFO_X(ctx, pipe_cli,
2021                                            &session_key,
2022                                            &user_handle,
2023                                            &uX);
2024         if (!NT_STATUS_IS_OK(status)) {
2025                 werr = ntstatus_to_werror(status);
2026                 goto done;
2027         }
2028
2029         werr = WERR_OK;
2030
2031  done:
2032         if (is_valid_policy_hnd(&user_handle) && b) {
2033                 dcerpc_samr_Close(b, talloc_tos(), &user_handle, &result);
2034         }
2035
2036         if (ctx->disable_policy_handle_cache) {
2037                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2038                 libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
2039                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2040         }
2041
2042         return werr;
2043 }
2044
2045 /****************************************************************
2046 ****************************************************************/
2047
2048 WERROR NetUserSetInfo_l(struct libnetapi_ctx *ctx,
2049                         struct NetUserSetInfo *r)
2050 {
2051         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetInfo);
2052 }
2053
2054 /****************************************************************
2055 ****************************************************************/
2056
2057 static NTSTATUS query_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
2058                                            struct rpc_pipe_client *pipe_cli,
2059                                            struct policy_handle *domain_handle,
2060                                            struct samr_DomInfo1 *info1,
2061                                            struct samr_DomInfo3 *info3,
2062                                            struct samr_DomInfo5 *info5,
2063                                            struct samr_DomInfo6 *info6,
2064                                            struct samr_DomInfo7 *info7,
2065                                            struct samr_DomInfo12 *info12)
2066 {
2067         NTSTATUS status, result;
2068         union samr_DomainInfo *dom_info = NULL;
2069         struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
2070
2071         if (info1) {
2072                 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
2073                                                      domain_handle,
2074                                                      1,
2075                                                      &dom_info,
2076                                                      &result);
2077                 NT_STATUS_NOT_OK_RETURN(status);
2078                 NT_STATUS_NOT_OK_RETURN(result);
2079
2080                 *info1 = dom_info->info1;
2081         }
2082
2083         if (info3) {
2084                 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
2085                                                      domain_handle,
2086                                                      3,
2087                                                      &dom_info,
2088                                                      &result);
2089                 NT_STATUS_NOT_OK_RETURN(status);
2090                 NT_STATUS_NOT_OK_RETURN(result);
2091
2092                 *info3 = dom_info->info3;
2093         }
2094
2095         if (info5) {
2096                 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
2097                                                      domain_handle,
2098                                                      5,
2099                                                      &dom_info,
2100                                                      &result);
2101                 NT_STATUS_NOT_OK_RETURN(status);
2102                 NT_STATUS_NOT_OK_RETURN(result);
2103
2104                 *info5 = dom_info->info5;
2105         }
2106
2107         if (info6) {
2108                 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
2109                                                      domain_handle,
2110                                                      6,
2111                                                      &dom_info,
2112                                                      &result);
2113                 NT_STATUS_NOT_OK_RETURN(status);
2114                 NT_STATUS_NOT_OK_RETURN(result);
2115
2116                 *info6 = dom_info->info6;
2117         }
2118
2119         if (info7) {
2120                 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
2121                                                      domain_handle,
2122                                                      7,
2123                                                      &dom_info,
2124                                                      &result);
2125                 NT_STATUS_NOT_OK_RETURN(status);
2126                 NT_STATUS_NOT_OK_RETURN(result);
2127
2128                 *info7 = dom_info->info7;
2129         }
2130
2131         if (info12) {
2132                 status = dcerpc_samr_QueryDomainInfo2(b, mem_ctx,
2133                                                       domain_handle,
2134                                                       12,
2135                                                       &dom_info,
2136                                                       &result);
2137                 NT_STATUS_NOT_OK_RETURN(status);
2138                 NT_STATUS_NOT_OK_RETURN(result);
2139
2140                 *info12 = dom_info->info12;
2141         }
2142
2143         return NT_STATUS_OK;
2144 }
2145
2146 /****************************************************************
2147 ****************************************************************/
2148
2149 static NTSTATUS query_USER_MODALS_INFO_0(TALLOC_CTX *mem_ctx,
2150                                          struct rpc_pipe_client *pipe_cli,
2151                                          struct policy_handle *domain_handle,
2152                                          struct USER_MODALS_INFO_0 *info0)
2153 {
2154         NTSTATUS status;
2155         struct samr_DomInfo1 dom_info1;
2156         struct samr_DomInfo3 dom_info3;
2157
2158         ZERO_STRUCTP(info0);
2159
2160         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2161                                             pipe_cli,
2162                                             domain_handle,
2163                                             &dom_info1,
2164                                             &dom_info3,
2165                                             NULL,
2166                                             NULL,
2167                                             NULL,
2168                                             NULL);
2169         NT_STATUS_NOT_OK_RETURN(status);
2170
2171         info0->usrmod0_min_passwd_len =
2172                 dom_info1.min_password_length;
2173         info0->usrmod0_max_passwd_age =
2174                 nt_time_to_unix_abs((NTTIME *)&dom_info1.max_password_age);
2175         info0->usrmod0_min_passwd_age =
2176                 nt_time_to_unix_abs((NTTIME *)&dom_info1.min_password_age);
2177         info0->usrmod0_password_hist_len =
2178                 dom_info1.password_history_length;
2179
2180         info0->usrmod0_force_logoff =
2181                 nt_time_to_unix_abs(&dom_info3.force_logoff_time);
2182
2183         return NT_STATUS_OK;
2184 }
2185
2186 /****************************************************************
2187 ****************************************************************/
2188
2189 static NTSTATUS query_USER_MODALS_INFO_1(TALLOC_CTX *mem_ctx,
2190                                          struct rpc_pipe_client *pipe_cli,
2191                                          struct policy_handle *domain_handle,
2192                                          struct USER_MODALS_INFO_1 *info1)
2193 {
2194         NTSTATUS status;
2195         struct samr_DomInfo6 dom_info6;
2196         struct samr_DomInfo7 dom_info7;
2197
2198         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2199                                             pipe_cli,
2200                                             domain_handle,
2201                                             NULL,
2202                                             NULL,
2203                                             NULL,
2204                                             &dom_info6,
2205                                             &dom_info7,
2206                                             NULL);
2207         NT_STATUS_NOT_OK_RETURN(status);
2208
2209         info1->usrmod1_primary =
2210                 talloc_strdup(mem_ctx, dom_info6.primary.string);
2211
2212         info1->usrmod1_role = dom_info7.role;
2213
2214         return NT_STATUS_OK;
2215 }
2216
2217 /****************************************************************
2218 ****************************************************************/
2219
2220 static NTSTATUS query_USER_MODALS_INFO_2(TALLOC_CTX *mem_ctx,
2221                                          struct rpc_pipe_client *pipe_cli,
2222                                          struct policy_handle *domain_handle,
2223                                          struct dom_sid *domain_sid,
2224                                          struct USER_MODALS_INFO_2 *info2)
2225 {
2226         NTSTATUS status;
2227         struct samr_DomInfo5 dom_info5;
2228
2229         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2230                                             pipe_cli,
2231                                             domain_handle,
2232                                             NULL,
2233                                             NULL,
2234                                             &dom_info5,
2235                                             NULL,
2236                                             NULL,
2237                                             NULL);
2238         NT_STATUS_NOT_OK_RETURN(status);
2239
2240         info2->usrmod2_domain_name =
2241                 talloc_strdup(mem_ctx, dom_info5.domain_name.string);
2242         info2->usrmod2_domain_id =
2243                 (struct domsid *)dom_sid_dup(mem_ctx, domain_sid);
2244
2245         NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_name);
2246         NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_id);
2247
2248         return NT_STATUS_OK;
2249 }
2250
2251 /****************************************************************
2252 ****************************************************************/
2253
2254 static NTSTATUS query_USER_MODALS_INFO_3(TALLOC_CTX *mem_ctx,
2255                                          struct rpc_pipe_client *pipe_cli,
2256                                          struct policy_handle *domain_handle,
2257                                          struct USER_MODALS_INFO_3 *info3)
2258 {
2259         NTSTATUS status;
2260         struct samr_DomInfo12 dom_info12;
2261
2262         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2263                                             pipe_cli,
2264                                             domain_handle,
2265                                             NULL,
2266                                             NULL,
2267                                             NULL,
2268                                             NULL,
2269                                             NULL,
2270                                             &dom_info12);
2271         NT_STATUS_NOT_OK_RETURN(status);
2272
2273         info3->usrmod3_lockout_duration =
2274                 nt_time_to_unix_abs(&dom_info12.lockout_duration);
2275         info3->usrmod3_lockout_observation_window =
2276                 nt_time_to_unix_abs(&dom_info12.lockout_window);
2277         info3->usrmod3_lockout_threshold =
2278                 dom_info12.lockout_threshold;
2279
2280         return NT_STATUS_OK;
2281 }
2282
2283 /****************************************************************
2284 ****************************************************************/
2285
2286 static NTSTATUS query_USER_MODALS_INFO_to_buffer(TALLOC_CTX *mem_ctx,
2287                                                  struct rpc_pipe_client *pipe_cli,
2288                                                  uint32_t level,
2289                                                  struct policy_handle *domain_handle,
2290                                                  struct dom_sid *domain_sid,
2291                                                  uint8_t **buffer)
2292 {
2293         NTSTATUS status;
2294
2295         struct USER_MODALS_INFO_0 info0;
2296         struct USER_MODALS_INFO_1 info1;
2297         struct USER_MODALS_INFO_2 info2;
2298         struct USER_MODALS_INFO_3 info3;
2299
2300         if (!buffer) {
2301                 return ERROR_INSUFFICIENT_BUFFER;
2302         }
2303
2304         switch (level) {
2305                 case 0:
2306                         status = query_USER_MODALS_INFO_0(mem_ctx,
2307                                                           pipe_cli,
2308                                                           domain_handle,
2309                                                           &info0);
2310                         NT_STATUS_NOT_OK_RETURN(status);
2311
2312                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0,
2313                                                            sizeof(info0));
2314                         break;
2315
2316                 case 1:
2317                         status = query_USER_MODALS_INFO_1(mem_ctx,
2318                                                           pipe_cli,
2319                                                           domain_handle,
2320                                                           &info1);
2321                         NT_STATUS_NOT_OK_RETURN(status);
2322
2323                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1,
2324                                                            sizeof(info1));
2325                         break;
2326                 case 2:
2327                         status = query_USER_MODALS_INFO_2(mem_ctx,
2328                                                           pipe_cli,
2329                                                           domain_handle,
2330                                                           domain_sid,
2331                                                           &info2);
2332                         NT_STATUS_NOT_OK_RETURN(status);
2333
2334                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2,
2335                                                            sizeof(info2));
2336                         break;
2337                 case 3:
2338                         status = query_USER_MODALS_INFO_3(mem_ctx,
2339                                                           pipe_cli,
2340                                                           domain_handle,
2341                                                           &info3);
2342                         NT_STATUS_NOT_OK_RETURN(status);
2343
2344                         *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3,
2345                                                            sizeof(info3));
2346                         break;
2347                 default:
2348                         break;
2349         }
2350
2351         NT_STATUS_HAVE_NO_MEMORY(*buffer);
2352
2353         return NT_STATUS_OK;
2354 }
2355
2356 /****************************************************************
2357 ****************************************************************/
2358
2359 WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx,
2360                           struct NetUserModalsGet *r)
2361 {
2362         struct rpc_pipe_client *pipe_cli = NULL;
2363         NTSTATUS status;
2364         WERROR werr;
2365
2366         struct policy_handle connect_handle, domain_handle;
2367         struct dom_sid2 *domain_sid = NULL;
2368         uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2369
2370         ZERO_STRUCT(connect_handle);
2371         ZERO_STRUCT(domain_handle);
2372
2373         if (!r->out.buffer) {
2374                 return WERR_INVALID_PARAM;
2375         }
2376
2377         switch (r->in.level) {
2378                 case 0:
2379                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2380                                        SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2381                         break;
2382                 case 1:
2383                 case 2:
2384                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
2385                         break;
2386                 case 3:
2387                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1;
2388                         break;
2389                 default:
2390                         werr = WERR_UNKNOWN_LEVEL;
2391                         goto done;
2392         }
2393
2394         werr = libnetapi_open_pipe(ctx, r->in.server_name,
2395                                    &ndr_table_samr,
2396                                    &pipe_cli);
2397         if (!W_ERROR_IS_OK(werr)) {
2398                 goto done;
2399         }
2400
2401         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2402                                           SAMR_ACCESS_ENUM_DOMAINS |
2403                                           SAMR_ACCESS_LOOKUP_DOMAIN,
2404                                           access_mask,
2405                                           &connect_handle,
2406                                           &domain_handle,
2407                                           &domain_sid);
2408         if (!W_ERROR_IS_OK(werr)) {
2409                 goto done;
2410         }
2411
2412         /* 0:  1 + 3 */
2413         /* 1:  6 + 7 */
2414         /* 2:  5 */
2415         /* 3: 12 (DomainInfo2) */
2416
2417         status = query_USER_MODALS_INFO_to_buffer(ctx,
2418                                                   pipe_cli,
2419                                                   r->in.level,
2420                                                   &domain_handle,
2421                                                   domain_sid,
2422                                                   r->out.buffer);
2423         if (!NT_STATUS_IS_OK(status)) {
2424                 werr = ntstatus_to_werror(status);
2425                 goto done;
2426         }
2427
2428  done:
2429         if (ctx->disable_policy_handle_cache) {
2430                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2431                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2432         }
2433
2434         return werr;
2435 }
2436
2437 /****************************************************************
2438 ****************************************************************/
2439
2440 WERROR NetUserModalsGet_l(struct libnetapi_ctx *ctx,
2441                           struct NetUserModalsGet *r)
2442 {
2443         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsGet);
2444 }
2445
2446 /****************************************************************
2447 ****************************************************************/
2448
2449 static NTSTATUS set_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
2450                                          struct rpc_pipe_client *pipe_cli,
2451                                          struct policy_handle *domain_handle,
2452                                          struct samr_DomInfo1 *info1,
2453                                          struct samr_DomInfo3 *info3,
2454                                          struct samr_DomInfo12 *info12)
2455 {
2456         NTSTATUS status, result;
2457         union samr_DomainInfo dom_info;
2458         struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
2459
2460         if (info1) {
2461
2462                 ZERO_STRUCT(dom_info);
2463
2464                 dom_info.info1 = *info1;
2465
2466                 status = dcerpc_samr_SetDomainInfo(b, mem_ctx,
2467                                                    domain_handle,
2468                                                    1,
2469                                                    &dom_info,
2470                                                    &result);
2471                 NT_STATUS_NOT_OK_RETURN(status);
2472                 NT_STATUS_NOT_OK_RETURN(result);
2473         }
2474
2475         if (info3) {
2476
2477                 ZERO_STRUCT(dom_info);
2478
2479                 dom_info.info3 = *info3;
2480
2481                 status = dcerpc_samr_SetDomainInfo(b, mem_ctx,
2482                                                    domain_handle,
2483                                                    3,
2484                                                    &dom_info,
2485                                                    &result);
2486
2487                 NT_STATUS_NOT_OK_RETURN(status);
2488                 NT_STATUS_NOT_OK_RETURN(result);
2489         }
2490
2491         if (info12) {
2492
2493                 ZERO_STRUCT(dom_info);
2494
2495                 dom_info.info12 = *info12;
2496
2497                 status = dcerpc_samr_SetDomainInfo(b, mem_ctx,
2498                                                    domain_handle,
2499                                                    12,
2500                                                    &dom_info,
2501                                                    &result);
2502
2503                 NT_STATUS_NOT_OK_RETURN(status);
2504                 NT_STATUS_NOT_OK_RETURN(result);
2505         }
2506
2507         return NT_STATUS_OK;
2508 }
2509
2510 /****************************************************************
2511 ****************************************************************/
2512
2513 static NTSTATUS set_USER_MODALS_INFO_0_buffer(TALLOC_CTX *mem_ctx,
2514                                               struct rpc_pipe_client *pipe_cli,
2515                                               struct policy_handle *domain_handle,
2516                                               struct USER_MODALS_INFO_0 *info0)
2517 {
2518         NTSTATUS status;
2519         struct samr_DomInfo1 dom_info_1;
2520         struct samr_DomInfo3 dom_info_3;
2521
2522         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2523                                             pipe_cli,
2524                                             domain_handle,
2525                                             &dom_info_1,
2526                                             &dom_info_3,
2527                                             NULL,
2528                                             NULL,
2529                                             NULL,
2530                                             NULL);
2531         NT_STATUS_NOT_OK_RETURN(status);
2532
2533         dom_info_1.min_password_length =
2534                 info0->usrmod0_min_passwd_len;
2535         dom_info_1.password_history_length =
2536                 info0->usrmod0_password_hist_len;
2537
2538         unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2539                 info0->usrmod0_max_passwd_age);
2540         unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2541                 info0->usrmod0_min_passwd_age);
2542
2543         unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2544                 info0->usrmod0_force_logoff);
2545
2546         return set_USER_MODALS_INFO_rpc(mem_ctx,
2547                                         pipe_cli,
2548                                         domain_handle,
2549                                         &dom_info_1,
2550                                         &dom_info_3,
2551                                         NULL);
2552 }
2553
2554 /****************************************************************
2555 ****************************************************************/
2556
2557 static NTSTATUS set_USER_MODALS_INFO_3_buffer(TALLOC_CTX *mem_ctx,
2558                                               struct rpc_pipe_client *pipe_cli,
2559                                               struct policy_handle *domain_handle,
2560                                               struct USER_MODALS_INFO_3 *info3)
2561 {
2562         NTSTATUS status;
2563         struct samr_DomInfo12 dom_info_12;
2564
2565         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2566                                             pipe_cli,
2567                                             domain_handle,
2568                                             NULL,
2569                                             NULL,
2570                                             NULL,
2571                                             NULL,
2572                                             NULL,
2573                                             &dom_info_12);
2574         NT_STATUS_NOT_OK_RETURN(status);
2575
2576         unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_duration,
2577                 info3->usrmod3_lockout_duration);
2578         unix_to_nt_time_abs((NTTIME *)&dom_info_12.lockout_window,
2579                 info3->usrmod3_lockout_observation_window);
2580         dom_info_12.lockout_threshold = info3->usrmod3_lockout_threshold;
2581
2582         return set_USER_MODALS_INFO_rpc(mem_ctx,
2583                                         pipe_cli,
2584                                         domain_handle,
2585                                         NULL,
2586                                         NULL,
2587                                         &dom_info_12);
2588 }
2589
2590 /****************************************************************
2591 ****************************************************************/
2592
2593 static NTSTATUS set_USER_MODALS_INFO_1001_buffer(TALLOC_CTX *mem_ctx,
2594                                                  struct rpc_pipe_client *pipe_cli,
2595                                                  struct policy_handle *domain_handle,
2596                                                  struct USER_MODALS_INFO_1001 *info1001)
2597 {
2598         NTSTATUS status;
2599         struct samr_DomInfo1 dom_info_1;
2600
2601         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2602                                             pipe_cli,
2603                                             domain_handle,
2604                                             &dom_info_1,
2605                                             NULL,
2606                                             NULL,
2607                                             NULL,
2608                                             NULL,
2609                                             NULL);
2610         NT_STATUS_NOT_OK_RETURN(status);
2611
2612         dom_info_1.min_password_length =
2613                 info1001->usrmod1001_min_passwd_len;
2614
2615         return set_USER_MODALS_INFO_rpc(mem_ctx,
2616                                         pipe_cli,
2617                                         domain_handle,
2618                                         &dom_info_1,
2619                                         NULL,
2620                                         NULL);
2621 }
2622
2623 /****************************************************************
2624 ****************************************************************/
2625
2626 static NTSTATUS set_USER_MODALS_INFO_1002_buffer(TALLOC_CTX *mem_ctx,
2627                                                  struct rpc_pipe_client *pipe_cli,
2628                                                  struct policy_handle *domain_handle,
2629                                                  struct USER_MODALS_INFO_1002 *info1002)
2630 {
2631         NTSTATUS status;
2632         struct samr_DomInfo1 dom_info_1;
2633
2634         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2635                                             pipe_cli,
2636                                             domain_handle,
2637                                             &dom_info_1,
2638                                             NULL,
2639                                             NULL,
2640                                             NULL,
2641                                             NULL,
2642                                             NULL);
2643         NT_STATUS_NOT_OK_RETURN(status);
2644
2645         unix_to_nt_time_abs((NTTIME *)&dom_info_1.max_password_age,
2646                 info1002->usrmod1002_max_passwd_age);
2647
2648         return set_USER_MODALS_INFO_rpc(mem_ctx,
2649                                         pipe_cli,
2650                                         domain_handle,
2651                                         &dom_info_1,
2652                                         NULL,
2653                                         NULL);
2654 }
2655
2656 /****************************************************************
2657 ****************************************************************/
2658
2659 static NTSTATUS set_USER_MODALS_INFO_1003_buffer(TALLOC_CTX *mem_ctx,
2660                                                  struct rpc_pipe_client *pipe_cli,
2661                                                  struct policy_handle *domain_handle,
2662                                                  struct USER_MODALS_INFO_1003 *info1003)
2663 {
2664         NTSTATUS status;
2665         struct samr_DomInfo1 dom_info_1;
2666
2667         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2668                                             pipe_cli,
2669                                             domain_handle,
2670                                             &dom_info_1,
2671                                             NULL,
2672                                             NULL,
2673                                             NULL,
2674                                             NULL,
2675                                             NULL);
2676         NT_STATUS_NOT_OK_RETURN(status);
2677
2678         unix_to_nt_time_abs((NTTIME *)&dom_info_1.min_password_age,
2679                 info1003->usrmod1003_min_passwd_age);
2680
2681         return set_USER_MODALS_INFO_rpc(mem_ctx,
2682                                         pipe_cli,
2683                                         domain_handle,
2684                                         &dom_info_1,
2685                                         NULL,
2686                                         NULL);
2687 }
2688
2689 /****************************************************************
2690 ****************************************************************/
2691
2692 static NTSTATUS set_USER_MODALS_INFO_1004_buffer(TALLOC_CTX *mem_ctx,
2693                                                  struct rpc_pipe_client *pipe_cli,
2694                                                  struct policy_handle *domain_handle,
2695                                                  struct USER_MODALS_INFO_1004 *info1004)
2696 {
2697         NTSTATUS status;
2698         struct samr_DomInfo3 dom_info_3;
2699
2700         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2701                                             pipe_cli,
2702                                             domain_handle,
2703                                             NULL,
2704                                             &dom_info_3,
2705                                             NULL,
2706                                             NULL,
2707                                             NULL,
2708                                             NULL);
2709         NT_STATUS_NOT_OK_RETURN(status);
2710
2711         unix_to_nt_time_abs(&dom_info_3.force_logoff_time,
2712                 info1004->usrmod1004_force_logoff);
2713
2714         return set_USER_MODALS_INFO_rpc(mem_ctx,
2715                                         pipe_cli,
2716                                         domain_handle,
2717                                         NULL,
2718                                         &dom_info_3,
2719                                         NULL);
2720 }
2721
2722 /****************************************************************
2723 ****************************************************************/
2724
2725 static NTSTATUS set_USER_MODALS_INFO_1005_buffer(TALLOC_CTX *mem_ctx,
2726                                                  struct rpc_pipe_client *pipe_cli,
2727                                                  struct policy_handle *domain_handle,
2728                                                  struct USER_MODALS_INFO_1005 *info1005)
2729 {
2730         NTSTATUS status;
2731         struct samr_DomInfo1 dom_info_1;
2732
2733         status = query_USER_MODALS_INFO_rpc(mem_ctx,
2734                                             pipe_cli,
2735                                             domain_handle,
2736                                             &dom_info_1,
2737                                             NULL,
2738                                             NULL,
2739                                             NULL,
2740                                             NULL,
2741                                             NULL);
2742         NT_STATUS_NOT_OK_RETURN(status);
2743
2744         dom_info_1.password_history_length =
2745                 info1005->usrmod1005_password_hist_len;
2746
2747         return set_USER_MODALS_INFO_rpc(mem_ctx,
2748                                         pipe_cli,
2749                                         domain_handle,
2750                                         &dom_info_1,
2751                                         NULL,
2752                                         NULL);
2753 }
2754
2755 /****************************************************************
2756 ****************************************************************/
2757
2758 static NTSTATUS set_USER_MODALS_INFO_buffer(TALLOC_CTX *mem_ctx,
2759                                             struct rpc_pipe_client *pipe_cli,
2760                                             uint32_t level,
2761                                             struct policy_handle *domain_handle,
2762                                             struct dom_sid *domain_sid,
2763                                             uint8_t *buffer)
2764 {
2765         struct USER_MODALS_INFO_0 *info0;
2766         struct USER_MODALS_INFO_3 *info3;
2767         struct USER_MODALS_INFO_1001 *info1001;
2768         struct USER_MODALS_INFO_1002 *info1002;
2769         struct USER_MODALS_INFO_1003 *info1003;
2770         struct USER_MODALS_INFO_1004 *info1004;
2771         struct USER_MODALS_INFO_1005 *info1005;
2772
2773         if (!buffer) {
2774                 return ERROR_INSUFFICIENT_BUFFER;
2775         }
2776
2777         switch (level) {
2778                 case 0:
2779                         info0 = (struct USER_MODALS_INFO_0 *)buffer;
2780                         return set_USER_MODALS_INFO_0_buffer(mem_ctx,
2781                                                              pipe_cli,
2782                                                              domain_handle,
2783                                                              info0);
2784                 case 3:
2785                         info3 = (struct USER_MODALS_INFO_3 *)buffer;
2786                         return set_USER_MODALS_INFO_3_buffer(mem_ctx,
2787                                                              pipe_cli,
2788                                                              domain_handle,
2789                                                              info3);
2790                 case 1001:
2791                         info1001 = (struct USER_MODALS_INFO_1001 *)buffer;
2792                         return set_USER_MODALS_INFO_1001_buffer(mem_ctx,
2793                                                                 pipe_cli,
2794                                                                 domain_handle,
2795                                                                 info1001);
2796                 case 1002:
2797                         info1002 = (struct USER_MODALS_INFO_1002 *)buffer;
2798                         return set_USER_MODALS_INFO_1002_buffer(mem_ctx,
2799                                                                 pipe_cli,
2800                                                                 domain_handle,
2801                                                                 info1002);
2802                 case 1003:
2803                         info1003 = (struct USER_MODALS_INFO_1003 *)buffer;
2804                         return set_USER_MODALS_INFO_1003_buffer(mem_ctx,
2805                                                                 pipe_cli,
2806                                                                 domain_handle,
2807                                                                 info1003);
2808                 case 1004:
2809                         info1004 = (struct USER_MODALS_INFO_1004 *)buffer;
2810                         return set_USER_MODALS_INFO_1004_buffer(mem_ctx,
2811                                                                 pipe_cli,
2812                                                                 domain_handle,
2813                                                                 info1004);
2814                 case 1005:
2815                         info1005 = (struct USER_MODALS_INFO_1005 *)buffer;
2816                         return set_USER_MODALS_INFO_1005_buffer(mem_ctx,
2817                                                                 pipe_cli,
2818                                                                 domain_handle,
2819                                                                 info1005);
2820
2821                 default:
2822                         break;
2823         }
2824
2825         return NT_STATUS_OK;
2826 }
2827
2828 /****************************************************************
2829 ****************************************************************/
2830
2831 WERROR NetUserModalsSet_r(struct libnetapi_ctx *ctx,
2832                           struct NetUserModalsSet *r)
2833 {
2834         struct rpc_pipe_client *pipe_cli = NULL;
2835         NTSTATUS status;
2836         WERROR werr;
2837
2838         struct policy_handle connect_handle, domain_handle;
2839         struct dom_sid2 *domain_sid = NULL;
2840         uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
2841
2842         ZERO_STRUCT(connect_handle);
2843         ZERO_STRUCT(domain_handle);
2844
2845         if (!r->in.buffer) {
2846                 return WERR_INVALID_PARAM;
2847         }
2848
2849         switch (r->in.level) {
2850                 case 0:
2851                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2852                                        SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2853                                        SAMR_DOMAIN_ACCESS_SET_INFO_1 |
2854                                        SAMR_DOMAIN_ACCESS_SET_INFO_2;
2855                         break;
2856                 case 3:
2857                 case 1001:
2858                 case 1002:
2859                 case 1003:
2860                 case 1005:
2861                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
2862                                        SAMR_DOMAIN_ACCESS_SET_INFO_1;
2863                         break;
2864                 case 1004:
2865                         access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
2866                                        SAMR_DOMAIN_ACCESS_SET_INFO_2;
2867                         break;
2868                 case 1:
2869                 case 2:
2870                 case 1006:
2871                 case 1007:
2872                         werr = WERR_NOT_SUPPORTED;
2873                         break;
2874                 default:
2875                         werr = WERR_UNKNOWN_LEVEL;
2876                         goto done;
2877         }
2878
2879         werr = libnetapi_open_pipe(ctx, r->in.server_name,
2880                                    &ndr_table_samr,
2881                                    &pipe_cli);
2882         if (!W_ERROR_IS_OK(werr)) {
2883                 goto done;
2884         }
2885
2886         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
2887                                           SAMR_ACCESS_ENUM_DOMAINS |
2888                                           SAMR_ACCESS_LOOKUP_DOMAIN,
2889                                           access_mask,
2890                                           &connect_handle,
2891                                           &domain_handle,
2892                                           &domain_sid);
2893         if (!W_ERROR_IS_OK(werr)) {
2894                 goto done;
2895         }
2896
2897         status = set_USER_MODALS_INFO_buffer(ctx,
2898                                              pipe_cli,
2899                                              r->in.level,
2900                                              &domain_handle,
2901                                              domain_sid,
2902                                              r->in.buffer);
2903         if (!NT_STATUS_IS_OK(status)) {
2904                 werr = ntstatus_to_werror(status);
2905                 goto done;
2906         }
2907
2908  done:
2909         if (ctx->disable_policy_handle_cache) {
2910                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
2911                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
2912         }
2913
2914         return werr;
2915 }
2916
2917 /****************************************************************
2918 ****************************************************************/
2919
2920 WERROR NetUserModalsSet_l(struct libnetapi_ctx *ctx,
2921                           struct NetUserModalsSet *r)
2922 {
2923         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserModalsSet);
2924 }
2925
2926 /****************************************************************
2927 ****************************************************************/
2928
2929 NTSTATUS add_GROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
2930                                        uint32_t level,
2931                                        const char *group_name,
2932                                        uint32_t attributes,
2933                                        uint8_t **buffer,
2934                                        uint32_t *num_entries)
2935 {
2936         struct GROUP_USERS_INFO_0 u0;
2937         struct GROUP_USERS_INFO_1 u1;
2938
2939         switch (level) {
2940                 case 0:
2941                         if (group_name) {
2942                                 u0.grui0_name = talloc_strdup(mem_ctx, group_name);
2943                                 NT_STATUS_HAVE_NO_MEMORY(u0.grui0_name);
2944                         } else {
2945                                 u0.grui0_name = NULL;
2946                         }
2947
2948                         ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_0, u0,
2949                                      (struct GROUP_USERS_INFO_0 **)buffer, num_entries);
2950                         break;
2951                 case 1:
2952                         if (group_name) {
2953                                 u1.grui1_name = talloc_strdup(mem_ctx, group_name);
2954                                 NT_STATUS_HAVE_NO_MEMORY(u1.grui1_name);
2955                         } else {
2956                                 u1.grui1_name = NULL;
2957                         }
2958
2959                         u1.grui1_attributes = attributes;
2960
2961                         ADD_TO_ARRAY(mem_ctx, struct GROUP_USERS_INFO_1, u1,
2962                                      (struct GROUP_USERS_INFO_1 **)buffer, num_entries);
2963                         break;
2964                 default:
2965                         return NT_STATUS_INVALID_INFO_CLASS;
2966         }
2967
2968         return NT_STATUS_OK;
2969 }
2970
2971 /****************************************************************
2972 ****************************************************************/
2973
2974 WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx,
2975                           struct NetUserGetGroups *r)
2976 {
2977         struct rpc_pipe_client *pipe_cli = NULL;
2978         struct policy_handle connect_handle, domain_handle, user_handle;
2979         struct lsa_String lsa_account_name;
2980         struct dom_sid2 *domain_sid = NULL;
2981         struct samr_Ids user_rids, name_types;
2982         struct samr_RidWithAttributeArray *rid_array = NULL;
2983         struct lsa_Strings names;
2984         struct samr_Ids types;
2985         uint32_t *rids = NULL;
2986
2987         int i;
2988         uint32_t entries_read = 0;
2989
2990         NTSTATUS status = NT_STATUS_OK;
2991         NTSTATUS result = NT_STATUS_OK;
2992         WERROR werr;
2993         struct dcerpc_binding_handle *b = NULL;
2994
2995         ZERO_STRUCT(connect_handle);
2996         ZERO_STRUCT(domain_handle);
2997
2998         if (!r->out.buffer) {
2999                 return WERR_INVALID_PARAM;
3000         }
3001
3002         *r->out.buffer = NULL;
3003         *r->out.entries_read = 0;
3004         *r->out.total_entries = 0;
3005
3006         switch (r->in.level) {
3007                 case 0:
3008                 case 1:
3009                         break;
3010                 default:
3011                         return WERR_UNKNOWN_LEVEL;
3012         }
3013
3014         werr = libnetapi_open_pipe(ctx, r->in.server_name,
3015                                    &ndr_table_samr,
3016                                    &pipe_cli);
3017         if (!W_ERROR_IS_OK(werr)) {
3018                 goto done;
3019         }
3020
3021         b = pipe_cli->binding_handle;
3022
3023         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
3024                                           SAMR_ACCESS_ENUM_DOMAINS |
3025                                           SAMR_ACCESS_LOOKUP_DOMAIN,
3026                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
3027                                           &connect_handle,
3028                                           &domain_handle,
3029                                           &domain_sid);
3030         if (!W_ERROR_IS_OK(werr)) {
3031                 goto done;
3032         }
3033
3034         init_lsa_String(&lsa_account_name, r->in.user_name);
3035
3036         status = dcerpc_samr_LookupNames(b, talloc_tos(),
3037                                          &domain_handle,
3038                                          1,
3039                                          &lsa_account_name,
3040                                          &user_rids,
3041                                          &name_types,
3042                                          &result);
3043         if (!NT_STATUS_IS_OK(status)) {
3044                 werr = ntstatus_to_werror(status);
3045                 goto done;
3046         }
3047         if (!NT_STATUS_IS_OK(result)) {
3048                 werr = ntstatus_to_werror(result);
3049                 goto done;
3050         }
3051         if (user_rids.count != 1) {
3052                 werr = WERR_BAD_NET_RESP;
3053                 goto done;
3054         }
3055         if (name_types.count != 1) {
3056                 werr = WERR_BAD_NET_RESP;
3057                 goto done;
3058         }
3059
3060         status = dcerpc_samr_OpenUser(b, talloc_tos(),
3061                                       &domain_handle,
3062                                       SAMR_USER_ACCESS_GET_GROUPS,
3063                                       user_rids.ids[0],
3064                                       &user_handle,
3065                                       &result);
3066         if (!NT_STATUS_IS_OK(status)) {
3067                 werr = ntstatus_to_werror(status);
3068                 goto done;
3069         }
3070         if (!NT_STATUS_IS_OK(result)) {
3071                 werr = ntstatus_to_werror(result);
3072                 goto done;
3073         }
3074
3075         status = dcerpc_samr_GetGroupsForUser(b, talloc_tos(),
3076                                               &user_handle,
3077                                               &rid_array,
3078                                               &result);
3079         if (!NT_STATUS_IS_OK(status)) {
3080                 werr = ntstatus_to_werror(status);
3081                 goto done;
3082         }
3083         if (!NT_STATUS_IS_OK(result)) {
3084                 werr = ntstatus_to_werror(result);
3085                 goto done;
3086         }
3087
3088         rids = talloc_array(ctx, uint32_t, rid_array->count);
3089         if (!rids) {
3090                 werr = WERR_NOMEM;
3091                 goto done;
3092         }
3093
3094         for (i=0; i < rid_array->count; i++) {
3095                 rids[i] = rid_array->rids[i].rid;
3096         }
3097
3098         status = dcerpc_samr_LookupRids(b, talloc_tos(),
3099                                         &domain_handle,
3100                                         rid_array->count,
3101                                         rids,
3102                                         &names,
3103                                         &types,
3104                                         &result);
3105         if (!NT_STATUS_IS_OK(status)) {
3106                 werr = ntstatus_to_werror(status);
3107                 goto done;
3108         }
3109         if (!NT_STATUS_IS_OK(result) &&
3110             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
3111                 werr = ntstatus_to_werror(result);
3112                 goto done;
3113         }
3114         if (names.count != rid_array->count) {
3115                 werr = WERR_BAD_NET_RESP;
3116                 goto done;
3117         }
3118         if (types.count != rid_array->count) {
3119                 werr = WERR_BAD_NET_RESP;
3120                 goto done;
3121         }
3122
3123         for (i=0; i < names.count; i++) {
3124                 status = add_GROUP_USERS_INFO_X_buffer(ctx,
3125                                                        r->in.level,
3126                                                        names.names[i].string,
3127                                                        rid_array->rids[i].attributes,
3128                                                        r->out.buffer,
3129                                                        &entries_read);
3130                 if (!NT_STATUS_IS_OK(status)) {
3131                         werr = ntstatus_to_werror(status);
3132                         goto done;
3133                 }
3134         }
3135
3136         *r->out.entries_read = entries_read;
3137         *r->out.total_entries = entries_read;
3138
3139  done:
3140         if (ctx->disable_policy_handle_cache) {
3141                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3142                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3143         }
3144
3145         return werr;
3146 }
3147
3148 /****************************************************************
3149 ****************************************************************/
3150
3151 WERROR NetUserGetGroups_l(struct libnetapi_ctx *ctx,
3152                           struct NetUserGetGroups *r)
3153 {
3154         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetGroups);
3155 }
3156
3157 /****************************************************************
3158 ****************************************************************/
3159
3160 WERROR NetUserSetGroups_r(struct libnetapi_ctx *ctx,
3161                           struct NetUserSetGroups *r)
3162 {
3163         struct rpc_pipe_client *pipe_cli = NULL;
3164         struct policy_handle connect_handle, domain_handle, user_handle, group_handle;
3165         struct lsa_String lsa_account_name;
3166         struct dom_sid2 *domain_sid = NULL;
3167         struct samr_Ids user_rids, name_types;
3168         struct samr_Ids group_rids;
3169         struct samr_RidWithAttributeArray *rid_array = NULL;
3170         struct lsa_String *lsa_names = NULL;
3171
3172         uint32_t *add_rids = NULL;
3173         uint32_t *del_rids = NULL;
3174         size_t num_add_rids = 0;
3175         size_t num_del_rids = 0;
3176
3177         uint32_t *member_rids = NULL;
3178
3179         struct GROUP_USERS_INFO_0 *i0 = NULL;
3180         struct GROUP_USERS_INFO_1 *i1 = NULL;
3181
3182         int i, k;
3183
3184         NTSTATUS status = NT_STATUS_OK;
3185         NTSTATUS result = NT_STATUS_OK;
3186         WERROR werr;
3187         struct dcerpc_binding_handle *b = NULL;
3188
3189         ZERO_STRUCT(connect_handle);
3190         ZERO_STRUCT(domain_handle);
3191         ZERO_STRUCT(group_handle);
3192
3193         if (!r->in.buffer) {
3194                 return WERR_INVALID_PARAM;
3195         }
3196
3197         switch (r->in.level) {
3198                 case 0:
3199                 case 1:
3200                         break;
3201                 default:
3202                         return WERR_UNKNOWN_LEVEL;
3203         }
3204
3205         werr = libnetapi_open_pipe(ctx, r->in.server_name,
3206                                    &ndr_table_samr,
3207                                    &pipe_cli);
3208         if (!W_ERROR_IS_OK(werr)) {
3209                 goto done;
3210         }
3211
3212         b = pipe_cli->binding_handle;
3213
3214         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
3215                                           SAMR_ACCESS_ENUM_DOMAINS |
3216                                           SAMR_ACCESS_LOOKUP_DOMAIN,
3217                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
3218                                           &connect_handle,
3219                                           &domain_handle,
3220                                           &domain_sid);
3221         if (!W_ERROR_IS_OK(werr)) {
3222                 goto done;
3223         }
3224
3225         init_lsa_String(&lsa_account_name, r->in.user_name);
3226
3227         status = dcerpc_samr_LookupNames(b, talloc_tos(),
3228                                          &domain_handle,
3229                                          1,
3230                                          &lsa_account_name,
3231                                          &user_rids,
3232                                          &name_types,
3233                                          &result);
3234         if (!NT_STATUS_IS_OK(status)) {
3235                 werr = ntstatus_to_werror(status);
3236                 goto done;
3237         }
3238         if (!NT_STATUS_IS_OK(result)) {
3239                 werr = ntstatus_to_werror(result);
3240                 goto done;
3241         }
3242         if (user_rids.count != 1) {
3243                 werr = WERR_BAD_NET_RESP;
3244                 goto done;
3245         }
3246         if (name_types.count != 1) {
3247                 werr = WERR_BAD_NET_RESP;
3248                 goto done;
3249         }
3250
3251         status = dcerpc_samr_OpenUser(b, talloc_tos(),
3252                                       &domain_handle,
3253                                       SAMR_USER_ACCESS_GET_GROUPS,
3254                                       user_rids.ids[0],
3255                                       &user_handle,
3256                                       &result);
3257         if (!NT_STATUS_IS_OK(status)) {
3258                 werr = ntstatus_to_werror(status);
3259                 goto done;
3260         }
3261         if (!NT_STATUS_IS_OK(result)) {
3262                 werr = ntstatus_to_werror(result);
3263                 goto done;
3264         }
3265
3266         switch (r->in.level) {
3267                 case 0:
3268                         i0 = (struct GROUP_USERS_INFO_0 *)r->in.buffer;
3269                         break;
3270                 case 1:
3271                         i1 = (struct GROUP_USERS_INFO_1 *)r->in.buffer;
3272                         break;
3273         }
3274
3275         lsa_names = talloc_array(ctx, struct lsa_String, r->in.num_entries);
3276         if (!lsa_names) {
3277                 werr = WERR_NOMEM;
3278                 goto done;
3279         }
3280
3281         for (i=0; i < r->in.num_entries; i++) {
3282
3283                 switch (r->in.level) {
3284                         case 0:
3285                                 init_lsa_String(&lsa_names[i], i0->grui0_name);
3286                                 i0++;
3287                                 break;
3288                         case 1:
3289                                 init_lsa_String(&lsa_names[i], i1->grui1_name);
3290                                 i1++;
3291                                 break;
3292                 }
3293         }
3294
3295         status = dcerpc_samr_LookupNames(b, talloc_tos(),
3296                                          &domain_handle,
3297                                          r->in.num_entries,
3298                                          lsa_names,
3299                                          &group_rids,
3300                                          &name_types,
3301                                          &result);
3302         if (!NT_STATUS_IS_OK(status)) {
3303                 werr = ntstatus_to_werror(status);
3304                 goto done;
3305         }
3306         if (!NT_STATUS_IS_OK(result)) {
3307                 werr = ntstatus_to_werror(result);
3308                 goto done;
3309         }
3310         if (group_rids.count != r->in.num_entries) {
3311                 werr = WERR_BAD_NET_RESP;
3312                 goto done;
3313         }
3314         if (name_types.count != r->in.num_entries) {
3315                 werr = WERR_BAD_NET_RESP;
3316                 goto done;
3317         }
3318
3319         member_rids = group_rids.ids;
3320
3321         status = dcerpc_samr_GetGroupsForUser(b, talloc_tos(),
3322                                               &user_handle,
3323                                               &rid_array,
3324                                               &result);
3325         if (!NT_STATUS_IS_OK(status)) {
3326                 werr = ntstatus_to_werror(status);
3327                 goto done;
3328         }
3329         if (!NT_STATUS_IS_OK(result)) {
3330                 werr = ntstatus_to_werror(result);
3331                 goto done;
3332         }
3333
3334         /* add list */
3335
3336         for (i=0; i < r->in.num_entries; i++) {
3337                 bool already_member = false;
3338                 for (k=0; k < rid_array->count; k++) {
3339                         if (member_rids[i] == rid_array->rids[k].rid) {
3340                                 already_member = true;
3341                                 break;
3342                         }
3343                 }
3344                 if (!already_member) {
3345                         if (!add_rid_to_array_unique(ctx,
3346                                                      member_rids[i],
3347                                                      &add_rids, &num_add_rids)) {
3348                                 werr = WERR_GENERAL_FAILURE;
3349                                 goto done;
3350                         }
3351                 }
3352         }
3353
3354         /* del list */
3355
3356         for (k=0; k < rid_array->count; k++) {
3357                 bool keep_member = false;
3358                 for (i=0; i < r->in.num_entries; i++) {
3359                         if (member_rids[i] == rid_array->rids[k].rid) {
3360                                 keep_member = true;
3361                                 break;
3362                         }
3363                 }
3364                 if (!keep_member) {
3365                         if (!add_rid_to_array_unique(ctx,
3366                                                      rid_array->rids[k].rid,
3367                                                      &del_rids, &num_del_rids)) {
3368                                 werr = WERR_GENERAL_FAILURE;
3369                                 goto done;
3370                         }
3371                 }
3372         }
3373
3374         /* add list */
3375
3376         for (i=0; i < num_add_rids; i++) {
3377                 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
3378                                                &domain_handle,
3379                                                SAMR_GROUP_ACCESS_ADD_MEMBER,
3380                                                add_rids[i],
3381                                                &group_handle,
3382                                                &result);
3383                 if (!NT_STATUS_IS_OK(status)) {
3384                         werr = ntstatus_to_werror(status);
3385                         goto done;
3386                 }
3387                 if (!NT_STATUS_IS_OK(result)) {
3388                         werr = ntstatus_to_werror(result);
3389                         goto done;
3390                 }
3391
3392                 status = dcerpc_samr_AddGroupMember(b, talloc_tos(),
3393                                                     &group_handle,
3394                                                     user_rids.ids[0],
3395                                                     7 /* ? */,
3396                                                     &result);
3397                 if (!NT_STATUS_IS_OK(status)) {
3398                         werr = ntstatus_to_werror(status);
3399                         goto done;
3400                 }
3401                 if (!NT_STATUS_IS_OK(result)) {
3402                         werr = ntstatus_to_werror(result);
3403                         goto done;
3404                 }
3405
3406                 if (is_valid_policy_hnd(&group_handle)) {
3407                         dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
3408                 }
3409         }
3410
3411         /* del list */
3412
3413         for (i=0; i < num_del_rids; i++) {
3414                 status = dcerpc_samr_OpenGroup(b, talloc_tos(),
3415                                                &domain_handle,
3416                                                SAMR_GROUP_ACCESS_REMOVE_MEMBER,
3417                                                del_rids[i],
3418                                                &group_handle,
3419                                                &result);
3420                 if (!NT_STATUS_IS_OK(status)) {
3421                         werr = ntstatus_to_werror(status);
3422                         goto done;
3423                 }
3424                 if (!NT_STATUS_IS_OK(result)) {
3425                         werr = ntstatus_to_werror(result);
3426                         goto done;
3427                 }
3428
3429                 status = dcerpc_samr_DeleteGroupMember(b, talloc_tos(),
3430                                                        &group_handle,
3431                                                        user_rids.ids[0],
3432                                                        &result);
3433                 if (!NT_STATUS_IS_OK(status)) {
3434                         werr = ntstatus_to_werror(status);
3435                         goto done;
3436                 }
3437                 if (!NT_STATUS_IS_OK(result)) {
3438                         werr = ntstatus_to_werror(result);
3439                         goto done;
3440                 }
3441
3442                 if (is_valid_policy_hnd(&group_handle)) {
3443                         dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
3444                 }
3445         }
3446
3447         werr = WERR_OK;
3448
3449  done:
3450         if (is_valid_policy_hnd(&group_handle)) {
3451                 dcerpc_samr_Close(b, talloc_tos(), &group_handle, &result);
3452         }
3453
3454         if (ctx->disable_policy_handle_cache) {
3455                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3456                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3457         }
3458
3459         return werr;
3460 }
3461
3462 /****************************************************************
3463 ****************************************************************/
3464
3465 WERROR NetUserSetGroups_l(struct libnetapi_ctx *ctx,
3466                           struct NetUserSetGroups *r)
3467 {
3468         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserSetGroups);
3469 }
3470
3471 /****************************************************************
3472 ****************************************************************/
3473
3474 static NTSTATUS add_LOCALGROUP_USERS_INFO_X_buffer(TALLOC_CTX *mem_ctx,
3475                                                    uint32_t level,
3476                                                    const char *group_name,
3477                                                    uint8_t **buffer,
3478                                                    uint32_t *num_entries)
3479 {
3480         struct LOCALGROUP_USERS_INFO_0 u0;
3481
3482         switch (level) {
3483                 case 0:
3484                         u0.lgrui0_name = talloc_strdup(mem_ctx, group_name);
3485                         NT_STATUS_HAVE_NO_MEMORY(u0.lgrui0_name);
3486
3487                         ADD_TO_ARRAY(mem_ctx, struct LOCALGROUP_USERS_INFO_0, u0,
3488                                      (struct LOCALGROUP_USERS_INFO_0 **)buffer, num_entries);
3489                         break;
3490                 default:
3491                         return NT_STATUS_INVALID_INFO_CLASS;
3492         }
3493
3494         return NT_STATUS_OK;
3495 }
3496
3497 /****************************************************************
3498 ****************************************************************/
3499
3500 WERROR NetUserGetLocalGroups_r(struct libnetapi_ctx *ctx,
3501                                struct NetUserGetLocalGroups *r)
3502 {
3503         struct rpc_pipe_client *pipe_cli = NULL;
3504         struct policy_handle connect_handle, domain_handle, user_handle,
3505         builtin_handle;
3506         struct lsa_String lsa_account_name;
3507         struct dom_sid2 *domain_sid = NULL;
3508         struct samr_Ids user_rids, name_types;
3509         struct samr_RidWithAttributeArray *rid_array = NULL;
3510         struct lsa_Strings names;
3511         struct samr_Ids types;
3512         uint32_t *rids = NULL;
3513         size_t num_rids = 0;
3514         struct dom_sid user_sid;
3515         struct lsa_SidArray sid_array;
3516         struct samr_Ids domain_rids;
3517         struct samr_Ids builtin_rids;
3518
3519         int i;
3520         uint32_t entries_read = 0;
3521
3522         NTSTATUS status = NT_STATUS_OK;
3523         NTSTATUS result = NT_STATUS_OK;
3524         WERROR werr;
3525         struct dcerpc_binding_handle *b = NULL;
3526
3527         ZERO_STRUCT(connect_handle);
3528         ZERO_STRUCT(domain_handle);
3529
3530         if (!r->out.buffer) {
3531                 return WERR_INVALID_PARAM;
3532         }
3533
3534         *r->out.buffer = NULL;
3535         *r->out.entries_read = 0;
3536         *r->out.total_entries = 0;
3537
3538         switch (r->in.level) {
3539                 case 0:
3540                 case 1:
3541                         break;
3542                 default:
3543                         return WERR_UNKNOWN_LEVEL;
3544         }
3545
3546         werr = libnetapi_open_pipe(ctx, r->in.server_name,
3547                                    &ndr_table_samr,
3548                                    &pipe_cli);
3549         if (!W_ERROR_IS_OK(werr)) {
3550                 goto done;
3551         }
3552
3553         b = pipe_cli->binding_handle;
3554
3555         werr = libnetapi_samr_open_domain(ctx, pipe_cli,
3556                                           SAMR_ACCESS_ENUM_DOMAINS |
3557                                           SAMR_ACCESS_LOOKUP_DOMAIN,
3558                                           SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
3559                                           SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
3560                                           &connect_handle,
3561                                           &domain_handle,
3562                                           &domain_sid);
3563         if (!W_ERROR_IS_OK(werr)) {
3564                 goto done;
3565         }
3566
3567         werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
3568                                                   SAMR_ACCESS_ENUM_DOMAINS |
3569                                                   SAMR_ACCESS_LOOKUP_DOMAIN,
3570                                                   SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
3571                                                   SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS,
3572                                                   &connect_handle,
3573                                                   &builtin_handle);
3574         if (!W_ERROR_IS_OK(werr)) {
3575                 goto done;
3576         }
3577
3578         init_lsa_String(&lsa_account_name, r->in.user_name);
3579
3580         status = dcerpc_samr_LookupNames(b, talloc_tos(),
3581                                          &domain_handle,
3582                                          1,
3583                                          &lsa_account_name,
3584                                          &user_rids,
3585                                          &name_types,
3586                                          &result);
3587         if (!NT_STATUS_IS_OK(status)) {
3588                 werr = ntstatus_to_werror(status);
3589                 goto done;
3590         }
3591         if (!NT_STATUS_IS_OK(result)) {
3592                 werr = ntstatus_to_werror(result);
3593                 goto done;
3594         }
3595         if (user_rids.count != 1) {
3596                 werr = WERR_BAD_NET_RESP;
3597                 goto done;
3598         }
3599         if (name_types.count != 1) {
3600                 werr = WERR_BAD_NET_RESP;
3601                 goto done;
3602         }
3603
3604         status = dcerpc_samr_OpenUser(b, talloc_tos(),
3605                                       &domain_handle,
3606                                       SAMR_USER_ACCESS_GET_GROUPS,
3607                                       user_rids.ids[0],
3608                                       &user_handle,
3609                                       &result);
3610         if (!NT_STATUS_IS_OK(status)) {
3611                 werr = ntstatus_to_werror(status);
3612                 goto done;
3613         }
3614         if (!NT_STATUS_IS_OK(result)) {
3615                 werr = ntstatus_to_werror(result);
3616                 goto done;
3617         }
3618
3619         status = dcerpc_samr_GetGroupsForUser(b, talloc_tos(),
3620                                               &user_handle,
3621                                               &rid_array,
3622                                               &result);
3623         if (!NT_STATUS_IS_OK(status)) {
3624                 werr = ntstatus_to_werror(status);
3625                 goto done;
3626         }
3627         if (!NT_STATUS_IS_OK(result)) {
3628                 werr = ntstatus_to_werror(result);
3629                 goto done;
3630         }
3631
3632         if (!sid_compose(&user_sid, domain_sid, user_rids.ids[0])) {
3633                 werr = WERR_NOMEM;
3634                 goto done;
3635         }
3636
3637         sid_array.num_sids = rid_array->count + 1;
3638         sid_array.sids = talloc_array(ctx, struct lsa_SidPtr, sid_array.num_sids);
3639         if (!sid_array.sids) {
3640                 werr = WERR_NOMEM;
3641                 goto done;
3642         }
3643
3644         sid_array.sids[0].sid = dom_sid_dup(ctx, &user_sid);
3645         if (!sid_array.sids[0].sid) {
3646                 werr = WERR_NOMEM;
3647                 goto done;
3648         }
3649
3650         for (i=0; i < rid_array->count; i++) {
3651                 struct dom_sid sid;
3652
3653                 if (!sid_compose(&sid, domain_sid, rid_array->rids[i].rid)) {
3654                         werr = WERR_NOMEM;
3655                         goto done;
3656                 }
3657
3658                 sid_array.sids[i+1].sid = dom_sid_dup(ctx, &sid);
3659                 if (!sid_array.sids[i+1].sid) {
3660                         werr = WERR_NOMEM;
3661                         goto done;
3662                 }
3663         }
3664
3665         status = dcerpc_samr_GetAliasMembership(b, talloc_tos(),
3666                                                 &domain_handle,
3667                                                 &sid_array,
3668                                                 &domain_rids,
3669                                                 &result);
3670         if (!NT_STATUS_IS_OK(status)) {
3671                 werr = ntstatus_to_werror(status);
3672                 goto done;
3673         }
3674         if (!NT_STATUS_IS_OK(result)) {
3675                 werr = ntstatus_to_werror(result);
3676                 goto done;
3677         }
3678
3679         for (i=0; i < domain_rids.count; i++) {
3680                 if (!add_rid_to_array_unique(ctx, domain_rids.ids[i],
3681                                              &rids, &num_rids)) {
3682                         werr = WERR_NOMEM;
3683                         goto done;
3684                 }
3685         }
3686
3687         status = dcerpc_samr_GetAliasMembership(b, talloc_tos(),
3688                                                 &builtin_handle,
3689                                                 &sid_array,
3690                                                 &builtin_rids,
3691                                                 &result);
3692         if (!NT_STATUS_IS_OK(status)) {
3693                 werr = ntstatus_to_werror(status);
3694                 goto done;
3695         }
3696         if (!NT_STATUS_IS_OK(result)) {
3697                 werr = ntstatus_to_werror(result);
3698                 goto done;
3699         }
3700
3701         for (i=0; i < builtin_rids.count; i++) {
3702                 if (!add_rid_to_array_unique(ctx, builtin_rids.ids[i],
3703                                              &rids, &num_rids)) {
3704                         werr = WERR_NOMEM;
3705                         goto done;
3706                 }
3707         }
3708
3709         status = dcerpc_samr_LookupRids(b, talloc_tos(),
3710                                         &builtin_handle,
3711                                         num_rids,
3712                                         rids,
3713                                         &names,
3714                                         &types,
3715                                         &result);
3716         if (!NT_STATUS_IS_OK(status)) {
3717                 werr = ntstatus_to_werror(status);
3718                 goto done;
3719         }
3720         if (!NT_STATUS_IS_OK(result)) {
3721                 werr = ntstatus_to_werror(result);
3722                 goto done;
3723         }
3724         if (names.count != num_rids) {
3725                 werr = WERR_BAD_NET_RESP;
3726                 goto done;
3727         }
3728         if (types.count != num_rids) {
3729                 werr = WERR_BAD_NET_RESP;
3730                 goto done;
3731         }
3732
3733         for (i=0; i < names.count; i++) {
3734                 status = add_LOCALGROUP_USERS_INFO_X_buffer(ctx,
3735                                                             r->in.level,
3736                                                             names.names[i].string,
3737                                                             r->out.buffer,
3738                                                             &entries_read);
3739                 if (!NT_STATUS_IS_OK(status)) {
3740                         werr = ntstatus_to_werror(status);
3741                         goto done;
3742                 }
3743         }
3744
3745         *r->out.entries_read = entries_read;
3746         *r->out.total_entries = entries_read;
3747
3748  done:
3749         if (ctx->disable_policy_handle_cache) {
3750                 libnetapi_samr_close_domain_handle(ctx, &domain_handle);
3751                 libnetapi_samr_close_connect_handle(ctx, &connect_handle);
3752         }
3753
3754         return werr;
3755 }
3756
3757 /****************************************************************
3758 ****************************************************************/
3759
3760 WERROR NetUserGetLocalGroups_l(struct libnetapi_ctx *ctx,
3761                                struct NetUserGetLocalGroups *r)
3762 {
3763         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetUserGetLocalGroups);
3764 }