root/source3/lib/netapi/user.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. convert_USER_INFO_X_to_samr_user_info21
  2. construct_USER_INFO_X
  3. set_user_info_USER_INFO_X
  4. NetUserAdd_r
  5. NetUserAdd_l
  6. NetUserDel_r
  7. NetUserDel_l
  8. libnetapi_samr_lookup_user
  9. samr_rid_to_priv_level
  10. samr_acb_flags_to_netapi_flags
  11. info21_to_USER_INFO_1
  12. info21_to_USER_INFO_2
  13. info21_to_USER_INFO_3
  14. info21_to_USER_INFO_4
  15. info21_to_USER_INFO_10
  16. info21_to_USER_INFO_11
  17. info21_to_USER_INFO_20
  18. info21_to_USER_INFO_23
  19. libnetapi_samr_lookup_user_map_USER_INFO
  20. NetUserEnum_r
  21. NetUserEnum_l
  22. convert_samr_dispinfo_to_NET_DISPLAY_USER
  23. convert_samr_dispinfo_to_NET_DISPLAY_MACHINE
  24. convert_samr_dispinfo_to_NET_DISPLAY_GROUP
  25. convert_samr_dispinfo_to_NET_DISPLAY
  26. NetQueryDisplayInformation_r
  27. NetQueryDisplayInformation_l
  28. NetUserChangePassword_r
  29. NetUserChangePassword_l
  30. NetUserGetInfo_r
  31. NetUserGetInfo_l
  32. NetUserSetInfo_r
  33. NetUserSetInfo_l
  34. query_USER_MODALS_INFO_rpc
  35. query_USER_MODALS_INFO_0
  36. query_USER_MODALS_INFO_1
  37. query_USER_MODALS_INFO_2
  38. query_USER_MODALS_INFO_3
  39. query_USER_MODALS_INFO_to_buffer
  40. NetUserModalsGet_r
  41. NetUserModalsGet_l
  42. set_USER_MODALS_INFO_rpc
  43. set_USER_MODALS_INFO_0_buffer
  44. set_USER_MODALS_INFO_3_buffer
  45. set_USER_MODALS_INFO_1001_buffer
  46. set_USER_MODALS_INFO_1002_buffer
  47. set_USER_MODALS_INFO_1003_buffer
  48. set_USER_MODALS_INFO_1004_buffer
  49. set_USER_MODALS_INFO_1005_buffer
  50. set_USER_MODALS_INFO_buffer
  51. NetUserModalsSet_r
  52. NetUserModalsSet_l
  53. add_GROUP_USERS_INFO_X_buffer
  54. NetUserGetGroups_r
  55. NetUserGetGroups_l
  56. NetUserSetGroups_r
  57. NetUserSetGroups_l
  58. add_LOCALGROUP_USERS_INFO_X_buffer
  59. NetUserGetLocalGroups_r
  60. NetUserGetLocalGroups_l

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

/* [<][>][^][v][top][bottom][index][help] */